一般音视频同步有三种方法:视频同步音频、音频同步视频、外部时钟。IjkPlayer 没有实现外部时钟这种方式。所以只介绍视频同步音频和音频同步视频。
音视频同步的核心就是:比较两个的播放时间,然后判断一方是追赶还是等待另一方。所以我们先分析音频和视频更新播放时间的代码:
视频设置时间轴:
其中的vp->pts 为当前帧的显示时间,其他不重要。
set_clock_at:
重点:
- pts:最新视频帧的显示时间;(同步时比较的时间)
- last_updated :更新时间
- pts_drift: 视频帧的显示时间与更新时间差;
音频设置时间轴:
if (!isnan(is->audio_clock)) {
set_clock_at(&is->audclk, is->audio_clock - (double)(is->audio_write_buf_size) / is->audio_tgt.bytes_per_sec - SDL_AoutGetLatencySeconds(ffp->aout), is->audio_clock_serial, ffp->audio_callback_time / 1000000.0);
sync_clock_to_slave(&is->extclk, &is->audclk);
}
也是调用set_clock_at:
重点:
- pts = is->audio_clock - (double)(is->audio_write_buf_size) / is->audio_tgt.bytes_per_sec - SDL_AoutGetLatencySeconds(ffp->aout) 该帧音频播放完成时间 - 该帧还未播放时长 - 延迟时间(同步时比较的时间)
- last_updated = ffp->audio_callback_time / 1000000.0 获取需要播放音频数据的时间
- pts_drift = pts - last_updated
解释下p