ffplay分析 (音视频同步:主时钟为音频)

《ffplay的数据结构分析》
《ffplay分析(从启动到读取线程的操作)》
《ffplay分析(视频解码线程的操作)》
《ffplay分析(音频解码线程的操作)》
《ffplay 分析(音频从Frame(解码后)队列取数据到SDL输出)》
《ffplay分析 (视频从Frame(解码后)队列取数据到SDL输出)》
《ffplay分析 (暂停 / 播放处理)》
《ffplay分析 (seek操作处理)》
《ffplay源码(版本:ffmpeg-4.2.1)》

ffplay分析 (音视频同步:主时钟为音频)

一、分析:

因为音频和视频解码时间并不是都能在同一个时间点同时解码完成进行播放,所以如果都在各自解码完成后自主的直接播放就可能数据的时间点匹配不上。所以要有个基准的时间轴让播放的数据匹配对应这个时间轴来进行播放。

ffplay 默认的音视频同步方法就是音频时钟作为主时钟,视频同步音频。音频解码完成直接播放,视频就要实时的检测音频当前的时间点,进行匹配。

视频播放时:
(1)通过一个循环播放和一个休眠时间间隔的判断当前视频时钟和音频时钟的差值。
(2)这个差值有个阀值的范围在范围内都还是示为同步的,不作为处理,让视频帧按照duration显示。如果差值是正数而且超出阀值范围才表示视频快了,此时当前显示的视频帧就要延长显示时间。
(3)如果差值是负数而且超出阀值范围才表示视频慢了,此时当前显示的视频帧就要加快显示时间。一般都是直接下一帧。而且如果还慢了一帧,就连当前将要显示的帧都抛弃,再显示下一帧。

1、refresh_loop_wait_event():在refresh_loop_wait_event()函数内的remaining_time就是间隔判断的休眠时间,这个值有默认值。但如果视频快了这个值就是同步计算后返回的当前这一帧还要继续显示的时间,就会在这里休眠等待,但也不一定是多长时间都会休眠,返回的值要和默认的比较选择一个更小的值进行休眠。这样可以多次判断更精准。

在这里插入图片描述

2、refresh_loop_wait_event():使用remaining_time调用video_fresh()进行视频显示,就会进行操作是接着往下显示视频帧还是保持显示当前帧不变。

在这里插入图片描述

3、refresh_loop_wait_event():从Frame(解码后)队列中取出上一帧显示的帧和将要显示的一帧。并且进行判断序列是否一样,不同直接丢弃,获取下一帧。

在这里插入图片描述

4、refresh_loop_wait_event():判断是否是新的序列开始然后重置is->frame_timer,这个值表示在系统时间里上一帧的显示时间,因为系统时间是变化的,只有使用系统时间才可以判断每帧的显示时长 是否到达了。

在这里插入图片描述

5、refresh_loop_wait_event():调用vp_duration()计算上一帧的持续时间(理论上的)

在这里插入图片描述

6、vp_duration():计算上一帧的持续时间(理论上的)

在这里插入图片描述

7、refresh_loop_wait_event():调用compute_target_delay()计算上一帧的持续时间(同步后实际上的)

在这里插入图片描述

8、compute_target_delay():判断主时钟不是视频才行同步计算,获取视频时钟与主时钟的差值

在这里插入图片描述

9、compute_target_delay():根据delay(理论上的上一帧的显示时长)设置同步阀值

在这里插入图片描述

10、compute_target_delay():使用diff差值和sync_threshold阀值判断当前视频与主时钟相比是否快还是慢,计算上一帧(当前显示的这)

在这里插入图片描述

11、refresh_loop_wait_event():获取当前的系统时间和经过compute_target_delay()计算返回的当前显示的帧的实际持续时长,判断是否保持显示当前的这一帧实行延时就是当前视频快了,或往下走就是

在这里插入图片描述

12、refresh_loop_wait_event():此时可以显示下一帧了,设置is->frame_timer新显示的这一帧的系统时间

在这里插入图片描述

13、refresh_loop_wait_event():更新视频时钟

在这里插入图片描述

14、refresh_loop_wait_event():丢帧处理

在这里插入图片描述

15、refresh_loop_wait_event():到最后可以正常显示新的一帧就是先调用frame_queue_next()移动读索引,然后调用video_display()显示新的一帧了

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_37599645/article/details/113483146