FFplay外部时钟分析

FFplay 播放器有 3 个时间:

1,视频流的播放时刻,(视频时钟)

2,音频流的播放时刻,(音频时钟)

3,预定的时间,预定的播放时刻,实际上就是物理世界的自然时间,(外部时钟)

上图中的 14:00:00:123 就是其中一个预定的时间,完全准确的情况下,会在 14:00:00:123 播放第 4 帧视频 ,播放第 7 帧音频。

但是,计算机系统是分时系统,大部分情况不会那么准确,有可能发生以下的情况。

在 14:00:00:133 的时候才播放第 4 帧视频。

在 14:00:00:143 的时候才播放第 7 帧音频。

因此:

在 14:00:00:133 的时候,视频时钟比外部时钟慢 0.01s。

在 14:00:00:143 ` 的时候,音频时钟比外部时钟慢 0.02s。


可以通过以下命令设置 外部时钟为主时钟:

ffplay -sync ext -i juren-30s.mp4

当外部时钟设置为主时钟的时候,在《FFplay视频同步分析》提到的3处视频同步代码,全部都会生效。在 《FFplay音频同步分析》提到的音频同步代码也会生效。

外部时钟只会赋值一次,会取音频时钟,或者视频时钟来赋值,主要看播放的第一帧是音频还是视频。

这是合理的,因为从上面第一张图可以看出来,第一帧的时候,音频时钟或者视频时钟 是跟外部时钟一样的。外部时钟的起始值就是第一帧的时间。

从第一帧开始,外部时钟才开始跑起来。

为什么外部时钟只会赋值一次?

因为只需要把第一帧的 pts + 物理世界里消逝的时间,就能知道当前的外部时钟播放到哪里了。


外部时钟 的赋值在 sdl_audio_callback() 跟 video_refresh() 里,这两个都是播放线程,就看谁先播放第一帧,谁就去赋值外部时钟。

可以看到,赋值 外部时钟的函数是 sync_clock_to_slave() 函数,我们来看一下这个函数的实现,如下:

可以看到,只有外部时钟不为空,才会跑进去 set_clock()当然如果超过 AV_NOSYNC_THRESHOLD 也会跑进去,不过一般这个条件不会成立。


总结,外部时钟,实际上就是记录现在已经到达了哪个预定的播放时刻。

当视频流离自己预定的播放时刻距离太远的时候,超过了同步阈值,就会调整视频的速度。

当音频流离自己预定的播放时刻距离太远的时候,超过了同步阈值,就会调整音频的速度。


推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:

Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

猜你喜欢

转载自blog.csdn.net/u012117034/article/details/129022878