公司网站设计平台,学广告平面设计哪里好,丹阳企业网站制作,门户网站开发报价## 一、前言用ffmpeg来做音视频同步#xff0c;个人认为这个是ffmpeg基础处理中最难的一个#xff0c;无数人就卡在这里#xff0c;怎么也不准#xff0c;本人也是尝试过网上各种demo#xff0c;基本上都是渣渣#xff0c;要么仅仅支持极其少量的视频文件比如收到的数据包…## 一、前言用ffmpeg来做音视频同步个人认为这个是ffmpeg基础处理中最难的一个无数人就卡在这里怎么也不准本人也是尝试过网上各种demo基本上都是渣渣要么仅仅支持极其少量的视频文件比如收到的数据包是一帧视频一帧音频的要么根本没法同步歪七八糟的要么进度跳过去直接蹦蹦蹦崩溃的其实最完美的音视频同步处理demo就是ffplay我亲测过几十种各种各样的音视频本地文件数十种视频流文件都是非常完美当然啦这是亲生的啦不完美还玩个屁。如果仅仅是播放视频流(不带音频流)可能不需要音视频同步所以最开始只做rtsp视频流播放的时候根本没有考虑同步的问题因为没遇到也不需要等到后期发现各种rtmp、http、m3u8这种视频流的时候问题大了去了他是hls格式的视频流文件一次性过来的一个个小视频文件过来的如果没有同步的话意味着突然之间刷刷刷的图片过去很多下一次来的又是刷刷的这就需要自己计算同步了上次接收到的数据包放入队列到了需要显示的时候就显示。常用的音视频同步方法1. 通过fps来控制fps表示一秒钟播放多少帧比如25帧可以自行计算一帧解码用掉的时间一帧占用(1000/2540毫秒)通过延时来处理这其实是最渣渣的办法。2. 记住开始解码的时间startTime通过av_rescale_q计算pts时间两者的差值就是需要延时的时间调用av_usleep来延时这种只有部分文件正常很多时候不正常。3. 音频同步到视频视频时钟作为主时钟没试过网上很多人说这个办法不好。4. 视频同步到音频音频时钟作为主时钟没试过据说大部分人采用的此办法。5. 音视频同步到外部时钟外部时钟作为主时钟最终采用的办法容易理解互不干扰各自按照外部时钟去同步自己。6. ffplay自身内置了三种同步策略可以通过参数来控制采用何种策略默认是视频同步到音频。## 二、功能特点1. 多线程实时播放视频流本地视频USB摄像头等。2. 支持windowslinuxmac支持ffmpeg3和ffmpeg4支持32位和64位。3. 多线程显示图像不卡主界面。4. 自动重连网络摄像头。5. 可设置边框大小即偏移量和边框颜色。6. 可设置是否绘制OSD标签即标签文本或图片和标签位置。7. 可设置两种OSD位置和风格。8. 可设置是否保存到文件以及文件名。9. 可直接拖曳文件到ffmpegwidget控件播放。10. 支持h265视频流rtmp等常见视频流。11. 可暂停播放和继续播放。12. 支持存储单个视频文件和定时存储视频文件。13. 自定义顶部悬浮条发送单击信号通知可设置是否启用。14. 可设置画面拉伸填充或者等比例填充。15. 可设置解码是速度优先、质量优先、均衡处理。16. 可对视频进行截图(原始图片)和截屏。17. 录像文件存储支持裸流和MP4文件。18. 音视频完美同步采用外部时钟同步策略。19. 支持seek定位播放位置。20. 支持qsv、dxva2、d3d11va等硬解码。21. 支持opengl绘制视频数据极低CPU占用。22. 支持安卓和嵌入式linux交叉编译即可。## 三、效果图## 四、相关站点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)## 五、核心代码void FFmpegSync::run(){ reset(); while (!stopped) { //暂停状态或者队列中没有帧则不处理 if (!thread-isPause packets.count() 0) { mutex.lock(); AVPacket *packet packets.first(); mutex.unlock(); //h264的裸流文件同步有问题,获取不到pts和dts,暂时用最蠢的办法延时解决 if (thread-formatName h264) { int sleepTime (1000 / thread-videoFps) - 5; msleep(sleepTime); } //计算当前帧显示时间 外部时钟同步 ptsTime getPtsTime(thread-formatCtx, packet); if (!this-checkPtsTime()) { msleep(1); continue; } //显示当前的播放进度 checkShowTime(); //0-表示音频 1-表示视频 if (type 0) { thread-decodeAudio(packet); } else if (type 1) { thread-decodeVideo(packet); } //释放资源并移除 thread-free(packet); mutex.lock(); packets.removeFirst(); mutex.unlock(); } msleep(1); } clear(); stopped false;}bool FFmpegSync::checkPtsTime(){ bool ok false; if (ptsTime 0) { if (ptsTime offsetTime 100000) { bufferTime ptsTime - offsetTime 100000; } int offset (type 0 ? 1000 : 5000); offsetTime av_gettime() - startTime bufferTime; if ((offsetTime ptsTime ptsTime - offsetTime offset) || (offsetTime ptsTime)) { ok true; } } else { ok true; } return ok;}