一、音视频为什么会不同步?
在音视频处理中,经常会出现不同步的现象,常见的原因如下
-
录制设备差异:音频和视频可能使用不同的设备进行录制,这可能会导致录制的音频和视频之间存在时间差。
-
编码和传输延迟:音频和视频在编码、传输和解码过程中可能会引入延迟,导致音频和视频不同步。
-
系统时钟漂移:音频和视频设备可能使用不同的系统时钟,导致时钟漂移,从而影响音视频同步。
-
解码和渲染延迟:音频和视频在解码和渲染过程中可能会产生不同的延迟,导致不同步。在ffplay中,音视频的输出有自己的线程。音频的输出线程是sdl的回调线程,视频的输出是程序的主线程。这两个线程调度过程中不一定那么准确。
二、音视频同步策略
小时后很多同学都有电子手表。当发现自己的手表和别人的手表的时间不一样的时候,我们会去对表。
音视频同步就是一个对表的过程。
但是大家的时钟都走的好好的,以谁的为准呢?
无所谓,只要设定一个基准,大家一致就行了。
在ffplay中,根据基准的不同,三种同步方式,分别以不同的时间为基准。
-
以音频为基准,同步视频到音频(AV_SYNC_AUDIO_MASTER)
- 视频慢了,丢帧或快放
- 视频快了,继续渲染上一帧
-
以视频为基准,同步音频到视频(AV_SYNC_VIDEO_MASTER)
- 音频慢了,加快播放速度(或丢弃部分帧,但极容易听出断音)
- 音频快了,降低播放速度(或重复上一帧)
-
以外部时钟为基准,同步音频和视频到外部时钟(AV_SYNC_EXTERNAL_CLOCK)
- 选择一个外部时钟为基准,视频和音频的播放速度都以该时钟为标准。
这三种是最基本的策略,考虑到人对声音的敏感度要强于视频,一般情况下我们会采取视频去同步音频的策略。
但实际还是要根据情况调整的。比如一个没有声音的视频,或者刚播放的只有音频没有视频,视频比较晚到,那前面的音频也可以先丢弃。
三、ffplay中的音视频同步
由于大部分的场景都是视频去同步音频,其它的几乎不怎么用。
所以这里只看视频同步音频的方法。
ffplay中的音视频同步主要是在video_refresh中去同步的。
video_refresh 是刷新视频帧的结构体,分析这个函数的时候,先不用考虑音视频同步,只要考虑一帧需要显示多久
//事件循环
static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) {
double remaining_time = 0.0;
//收集事件
SDL_PumpEvents();
//检查是否有事件
while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
//隐藏鼠标的操作
if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) {
SDL_ShowCursor(0);
cursor_hidden = 1;
}
if (remaining_time > 0.0)
av_usleep((int64_t)(remaining_time * 1000000.0));
//
remaining_time = REFRESH_RATE;
if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
video_refresh(is, &remaining_time);
SDL_PumpEvents();
}
}
/* called to display each frame */
static void video_refresh(void *opaque, double *remaining_time)
{
VideoState *is = opaque;
double time;
Frame *sp, *sp2;
if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime)
check_external_clock_speed(is

本文解析了ffplay中音视频不同步的原因,如设备差异、编码延迟等,并介绍了音视频同步的基本策略,重点讲解了视频同步音频的方法,包括使用audio基准、video基准以及外部时钟基准。同时,详细剖析了ffplay中如何通过compute_target_delay函数来计算延迟并调整播放速度以实现同步。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



