开发环境:MinGW+QT5.9+FFMPEG20190212
一、开发环境搭建
FFMPEG的开发环境部署比如容易,在官网下载库文件,然后在QT里面指定路径,把相关dll文件放到exe目录下就可以了,不需要根据开发工具重新编译。
(1)下载工具
在https://ffmpeg.zeranoe.com/builds/下载对应版本。链接方式有三种,
Static:这个版本只包含了ffmpeg.exe、ffplay.exe、ffprobe.exe三个可执行程序,没有头文件和库文件。
Shared:这个版本包含了ffmpeg.exe、ffplay.exe、ffprobe.exe三个可执行程序和相关动态库文件。
Dev:开发版,这个包含了头文件和库文件。
我们需要下载Shared和Dev两个版本,Dev有我们程序开发需要的头文件和库文件,这里面包含的库是动态调用的,所依赖的动态库在Shared这个版本里面,所以两个版本都要下载。
(2)添加库
将下载的文件解压缩,然后新建一个QT工程,在pro添加lib目录和include目录的路径。
INCLUDEPATH +="E:\\Lib\\ffmpeg\\include"
LIBS += -LE:\Lib\ffmpeg\lib -lavutil -lavformat -lavcodec -lavdevice -lavfilter -lpostproc -lswresample -lswscale
然后将shared下的动态库添加到exe目录下。
二、代码实现播放功能
在界面上放置一个QLabel和QPushButton控件,当点击按钮时实现以下功能:
#include
extern "C"{
#include
#include
#include
#include
}
void Delay(int msec)
{
QTime dieTime = QTime::currentTime().addMSecs(msec);
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, );
}
void MainWindow::on_btnPlay_clicked()
{
AVFormatContext *pFormatCtx;
int i, videoindex;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame, *pFrameRGB;
unsigned char *out_buffer;
AVPacket *packet;
int ret, got_picture;
struct SwsContext *img_convert_ctx;
char filepath\[\] = "E:\\\\media\\\\1.avi";
//初始化编解码库
av\_register\_all();//创建AVFormatContext对象,与码流相关的结构。
pFormatCtx = avformat\_alloc\_context();
//初始化pFormatCtx结构
if (avformat\_open\_input(&pFormatCtx, filepath, NULL, NULL) != ){
printf("Couldn't open input stream.\\n");
return ;
}
//获取音视频流数据信息
if (avformat\_find\_stream\_info(pFormatCtx, NULL) < ){
printf("Couldn't find stream information.\\n");
return ;
}
videoindex = -;
//nb\_streams视音频流的个数,这里当查找到视频流时就中断了。
for (i = ; i < pFormatCtx->nb\_streams; i++)
if (pFormatCtx->streams\[i\]->codec->codec\_type == AVMEDIA\_TYPE\_VIDEO){
videoindex = i;
break;
}
if (videoindex == -){
printf("Didn't find a video stream.\\n");
return ;
}
//获取视频流编码结构
pCodecCtx = pFormatCtx->streams\[videoindex\]->codec;
//查找解码器
pCodec = avcodec\_find\_decoder(pCodecCtx->codec\_id);
if (pCodec == NULL){
printf("Codec not found.\\n");
return ;
}
//用于初始化pCodecCtx结构
if (avcodec\_open2(pCodecCtx, pCodec, NULL) < ){
printf("Could not open codec.\\n");
return ;
}
//创建帧结构,此函数仅分配基本结构空间,图像数据空间需通过av\_malloc分配
pFrame = av\_frame\_alloc();
pFrameRGB = av\_frame\_alloc();
//创建动态内存,创建存储图像数据的空间
//av\_image\_get\_buffer\_size获取一帧图像需要的大小
out\_buffer = (unsigned char \*)av\_malloc(av\_image\_get\_buffer\_size(AV\_PIX\_FMT\_RGB32, pCodecCtx->width, pCodecCtx->height, ));
av\_image\_fill\_arrays(pFrameRGB->data, pFrameRGB->linesize, out\_buffer,
AV\_PIX\_FMT\_RGB32, pCodecCtx->width, pCodecCtx->height, );
packet = (AVPacket \*)av\_malloc(sizeof(AVPacket));
//Output Info-----------------------------
printf("--------------- File Information ----------------\\n");
//此函数打印输入或输出的详细信息
av\_dump\_format(pFormatCtx, , filepath, );
printf("-------------------------------------------------\\n");
//初始化img\_convert\_ctx结构
img\_convert\_ctx = sws\_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix\_fmt,
pCodecCtx->width, pCodecCtx->height, AV\_PIX\_FMT\_RGB32, SWS\_BICUBIC, NULL, NULL, NULL);
//av\_read\_frame读取一帧未解码的数据
while (av\_read\_frame(pFormatCtx, packet) >= ){
//如果是视频数据
if (packet->stream\_index == videoindex){
//解码一帧视频数据
ret = avcodec\_decode\_video2(pCodecCtx, pFrame, &got\_picture, packet);
if (ret < ){
printf("Decode Error.\\n");
return ;
}
if (got\_picture){
sws\_scale(img\_convert\_ctx, (const unsigned char\* const\*)pFrame->data, pFrame->linesize, , pCodecCtx->height,
pFrameRGB->data, pFrameRGB->linesize);
QImage img((uchar\*)pFrameRGB->data\[\],pCodecCtx->width,pCodecCtx->height,QImage::Format\_RGB32);
ui->label->setPixmap(QPixmap::fromImage(img));
Delay();
}
}
av\_free\_packet(packet);
}
sws\_freeContext(img\_convert\_ctx);
av\_frame\_free(&pFrameRGB);
av\_frame\_free(&pFrame);
avcodec\_close(pCodecCtx);
avformat\_close\_input(&pFormatCtx);
}
以上就是QT显示视频图像的简单例子,对于对FFMPEG感兴趣想学习更多内容的,推荐看看下面博主的博文,对FFMPEG的介绍非常详细:
https://blog.csdn.net/leixiaohua1020/article/details/15811977
手机扫一扫
移动阅读更方便
你可能感兴趣的文章