今天有时间继续研究ffplay了,之前把重点放在编码解码上了,今天看了一下ffplay的音视频同步的代码,也是看了一个人的博客,但是这个对初学者可能还是有点看不懂,在这里就只对一个方法做解析,这个方法了解就知道音视频同步的原理了。
//一下代码是我从另一个人的博客拷贝过来的,因为需要弄懂的就在这个方法里面,所以直接上他的代码了,不然还要去
static double compute_target_delay(double delay, VideoState *is)
{
double sync_threshold,diff;
/* update delay to followmaster synchronisation source */
/*如果主同步方式不是以视频为主,默认是以audio为主进行同步*/
if(get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) {
/* if video is slave,we try to correct big delays by
duplicating ordeleting a frame */
/*get_clock(&is->vidclk)获取到的实际上是:从处理最后一帧开始到现在的时间加上最后一帧的pts,具体参考set_clock_at 和get_clock的代码
get_clock(&is->vidclk) ==is->vidclk.pts, av_gettime_relative() / 1000000.0 -is->vidclk.last_updated +is->vidclk.pts*/
/*driff实际上就是已经播放的最近一个视频帧和音频帧pts的差值+ 两方系统的一个差值,用公式表达如下:
pre_video_pts: 最近的一个视频帧的pts
video_system_time_diff: 记录最近一个视频pts 到现在的时间,即av_gettime_relative()/ 1000000.0 - is->vidclk.last_updated
pre_audio_pts: 音频已经播放到的时间点,即已经播放的数据所代表的时间,通过已经播放的samples可以计算出已经播放的时间,在sdl_audio_callback中被设置
audio_system_time_diff: 同video_system_time_diff
//我要说的就是这个了,直接看下面的图,如果之前没看过这个博客的先看
//他的博客。
最终视频和音频的diff可以用下面的公式表示:
diff = (pre_video_pts-pre_audio_pts) +(video_system_time_diff - audio_system_time_diff)
如果diff<0, 则说明视频播放太慢了,如果diff>0,
则说明视频播放太快,此时需要通过计算delay来调整视频的播放速度如果
diff
diff =get_clock(&is->vidclk) - get_master_clock(is);
/* skip or repeatframe. We take into account the
delay to computethe threshold. I still don't know
if it is the bestguess */
sync_threshold=FFMAX(AV_SYNC_THRESHOLD_MIN,FFMIN(AV_SYNC_THRESHOLD_MAX,delay));
if (!isnan(diff)&& fabs(diff) < is->max_frame_duration) {
if (diff <=-sync_threshold)
delay =FFMAX(0, delay + diff);
else if (diff >= sync_threshold&& delay > AV_SYNC_FRAMEDUP_THRESHOLD)
delay = delay+ diff;
else if (diff>= sync_threshold)
delay = 2 *delay;
}
}
av_dlog(NULL, "video:delay=%0.3f A-V=%f\n",
delay, -diff);
return delay;
}