此文章讲的seek测率有一定缺陷,即用户非常快速点击seek操作,主线程会卡,下一篇ffmpeg音视频同步,seek策略总结是对这篇的改进,若想直接了解较好的策略,直接移步到我的下一篇中。
音视频同步一般有三种方式,
1、设置共同时间标志。这种多用于多视频播放中。
2、音频同步视频,(由于人耳对音频比视频敏感,比较少用)
3、视频同步音频
下面就介绍一种视频同步音频的方法。
视频同步音频
1、音频的解码和重采样相对于视频解码来说,只占很小的比率,因此这里只需要在解析音频的时候开启一个线程专门解码视频。
2、现在手机配置越来越高,因此视频要同步音频,只需要在解码视频后,看当前frame的帧率的pts和 当前播放的 音频的 currentaudioPts 比较,如果 Vpts 大于currentaudioPts,就停止显示 1ms,然后继续判断。这样音视频的相差就会在2ms内。人是感觉不出来的。
详细看下面的流程图
一共有三个线程:
- 蓝色的为解封装和音频重采样线程,并且在解封装过程中,将视频的packet存入video packet list当中
- 红色为音频播放线程,在回调函数中,不停取出audio data(重采样数据)、pts list 来播放音频,并且当前压入播放队列的data 对应pts就为 currentAudiopts。
- 绿色为视频显示线程,不停的从video packet list 取出packet解码,然后currentAudiopts小于 当前解码完的视频的pts时候,就显示视频,否则就等等显示。
node:
1、从流程图可以看出,同步的关键在:pts的精装计算。还有就是音频的pts和视频额pts的basetime不一样,因此在packet的时候就计算出音视频的分别的basetime,然后将音视频的pts 计算到同时间单位上。
2、对list操作时候,注意枷锁,一个音频锁、一个视频锁。
3、无法用来针对电视频道如:
http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8
进行同步,因为发现音频pts 总视为0.
seek策略
基于上面的流程,在seek的时候很容易导致(特别从后往前退时候),因为pts问题,导致视频卡住,等待音频pts更新,而视频的pts一直是seek前的比较大的pts,无论怎么更新,都是等待。因此要保证一下几条测率:
1、在seek的时候,设置seek锁,锁住的时候清理掉 audio data list ,audio pts list、 videoPacket list,并且清理掉解封装缓存、音频解码器缓存,视频解码器缓存,将seek结束时候,currentPts 置为duration,防止线程堵塞中存在一帧,导致堵塞视频显示:
void DataManager::clearData()
{
videoLock.lock();
while(videoP