ffmpeg解码处理

一、前言采用ffmpeg解码 , 是所有视频监控开发人员必备的技能 , 绕不过去的一个玩意 , 甚至可以说是所有音视频开发人员的必备技能 。FFmpeg是一套可以用来记录、转换数字音频、视频 , 并能将其转化为流的开源计算机程序 。它包括了目前领先的音/视频编码库libavcodec 。FFmpeg是在 linux 下开发出来的 , 但它可以在包括 windows 在内的大多数操作系统中编译 。这个项目是由 Fabrice Bellard 发起的 , 现在由 Michael Niedermayer 主持 。可以轻易地实现多种视频格式之间的相互转换 , 例如可以将摄录下的视频avi等转成现在视频网站所采用的flv格式 。
关于ffmpeg解码 , 网上搜索到的代码绝对是一大堆一大堆 , 而且很多都讲得很详细 , 解码的函数流程图非常清晰 , 关于ffmpeg这块的学习本人推荐雷神的博客 , 分析的相当细致 , 我在很久以前刚用Qt+ffmpeg解码的时候 , 参考的就是雷神的例子 , 当然这些demo其实在ffmpeg的开发包dev下的examples也是非常详细的 , 只不过没有什么分析过程 , 参考雷神的博客可以看到很多分析过程 。
本人总结的解码过程:
1. 注册解码库相关(av_register_all、avformat_network_init等)
2. 初始化各种参数比如缓存大小等(av_dict_set)
3. 打开视频流或者文件(avformat_alloc_context、avformat_open_input)
4. 获取流信息(avformat_find_stream_info)
5. 获取视频流并初始化视频解码器(av_find_best_stream、avcodec_find_decoder)
6. 获取音频流并初始化音频解码器(av_find_best_stream、avcodec_find_decoder、avcodec_open2)
【ffmpeg解码处理】7. 预分配帧内存(av_frame_alloc)
8. 循环读取音视频帧(av_read_frame、av_packet_unref)
9. 解码视频(avcodec_decode_video2或者avcodec_send_packet、avcodec_receive_frame)
10. 解码音频(avcodec_decode_audio4)
11. 处理结束释放资源(sws_freeContext、av_frame_free、av_free)
## 二、功能特点1. 多线程实时播放视频流+本地视频+USB摄像头等 。
2. 支持windows+linux+mac , 支持ffmpeg3和ffmpeg4 , 支持32位和64位 。
3. 多线程显示图像 , 不卡主界面 。
4. 自动重连网络摄像头 。
5. 可设置边框大小即偏移量和边框颜色 。
6. 可设置是否绘制OSD标签即标签文本或图片和标签位置 。
7. 可设置两种OSD位置和风格 。
8. 可设置是否保存到文件以及文件名 。
9. 可直接拖曳文件到ffmpegwidget控件播放 。
10. 支持h265视频流+rtmp等常见视频流 。
11. 可暂停播放和继续播放 。
12. 支持回调模式和句柄两种模式 。
13. 支持线程读取进度等信息和事件回调两种处理模式 。
14. 自动将当前播放位置和音量大小是否静音以信号发出去 。
15. 提供接口设置播放位置和音量及设置静音 。
16. 支持存储单个视频文件和定时存储视频文件 。
17. 自定义顶部悬浮条 , 发送单击信号通知 , 可设置是否启用 。
18. 支持qsv、dxva2、d3d11va等硬解码 。
19. 支持opengl绘制视频数据 , 极低CPU占用 。
20. 支持嵌入式linux 。
## 三、效果图 

ffmpeg解码处理

文章插图
 
 
## 四、相关站点1. 国内站点:[https://gitee.com/feiyangqingyun/QWidgetDemo](https://gitee.com/feiyangqingyun/QWidgetDemo)
2. 国际站点:[https://github.com/feiyangqingyun/QWidgetDemo](https://github.com/feiyangqingyun/QWidgetDemo)
3. 个人主页:[https://blog.csdn.net/feiyangqingyun](https://blog.csdn.net/feiyangqingyun)
4. 知乎主页:[https://www.zhihu.com/people/feiyangqingyun/](https://www.zhihu.com/people/feiyangqingyun/)
5. 体验地址:[https://blog.csdn.net/feiyangqingyun/article/details/97565652](https://blog.csdn.net/feiyangqingyun/article/details/97565652)
## 五、核心代码bool FFmpegThread::init(){//判断该摄像机是否能联通if (checkConn && isRtsp) {if (!checkUrl(url, checkTime)) {return false;}}//初始化参数this->initOption();//初始化输入if (!initInput()) {return false;}//初始化视频if (!initVideo()) {return false;}//初始化音频if (!initAudio()) {return false;}//初始化帧this->initFrame();//输出视频信息//av_dump_format(formatCtx, 0, url.toStdString().data(), 0);//qDebug() << TIMEMS << "init ffmpeg finsh";return true;}void FFmpegThread::initOption(){//在打开码流前指定各种参数比如:探测时间/超时时间/最大延时等//设置缓存大小,1080p可将值调大av_dict_set(&options, "buffer_size", "8192000", 0);//以tcp方式打开,如果以udp方式打开将tcp替换为udpav_dict_set(&options, "rtsp_transport", transport.toLatin1().constData(), 0);//设置超时断开连接时间,单位微秒,3000000表示3秒av_dict_set(&options, "stimeout", "3000000", 0);//设置最大时延,单位微秒,1000000表示1秒av_dict_set(&options, "max_delay", "1000000", 0);//自动开启线程数av_dict_set(&options, "threads", "auto", 0);//设置USB摄像机分辨率if (url.startsWith("video")) {QString size = QString("%1x%2").arg(videoWidth).arg(videoHeight);av_dict_set(&options, "video_size", size.toLatin1().constData(), 0);}}bool FFmpegThread::initInput(){//实例化格式处理上下文formatCtx = avformat_alloc_context();//先判断是否是本地设备(video=设备名字符串),打开的方式不一样int result = -1;if (url.startsWith("video")) {#if defined(Q_OS_WIN)AVInputFormat *ifmt = av_find_input_format("dshow");#elif defined(Q_OS_LINUX)AVInputFormat *ifmt = av_find_input_format("video4linux2");#elif defined(Q_OS_MAC)AVInputFormat *ifmt = av_find_input_format("avfoundation");#endifresult = avformat_open_input(&formatCtx, url.toStdString().data(), ifmt, &options);} else {result = avformat_open_input(&formatCtx, url.toStdString().data(), NULL, &options);}if (result < 0) {qDebug() << TIMEMS << "open input error" << url;return false;}//释放设置参数if (options != NULL) {av_dict_free(&options);}//获取流信息result = avformat_find_stream_info(formatCtx, NULL);if (result < 0) {qDebug() << TIMEMS << "find stream info error";return false;}return true;}


推荐阅读