ffmpeg音视频同步

音视频同步简单介绍

一般来说,视频同步指的是视频和音频同步,也就是说播放的声音要和当前显示的画面保持一致。
在视频流和音频流中已包含了其以怎样的速度播放的相关数据,视频的帧率(Frame Rate)指示视频一秒显示的帧数(图像数);音频的采样率(Sample Rate)表示音频一秒播放的样本(Sample)的个数。可以使用以上数据通过简单的计算得到其在某一Frame(Sample)的播放时间,以这样的速度音频和视频各自播放互不影响,在理想条件下,其应该是同步的,不会出现偏差。但,理想条件是什么大家都懂得。如果用上面那种简单的计算方式,慢慢的就会出现音视频不同步的情况。要不是视频播放快了,要么是音频播放快了,很难准确的同步。这就需要一种随着时间会线性增长的量,视频和音频的播放速度都以该量为标准,播放快了就减慢播放速度;播放快了就加快播放的速度。所以呢,视频和音频的同步实际上是一个动态的过程,同步是暂时的,不同步则是常态。以选择的播放速度量为标准,快的等待慢的,慢的则加快速度,是一个你等我赶的过程。

播放速度标准量的的选择一般来说有以下三种:

将视频同步到音频上,就是以音频的播放速度为基准来同步视频。视频比音频播放慢了,加快其播放速度;快了,则延迟播放。
将音频同步到视频上,就是以视频的播放速度为基准来同步音频。
将视频和音频同步外部的时钟上,选择一个外部时钟为基准,视频和音频的播放速度都以该时钟为标准。

DTS和PTS

上面提到,视频和音频的同步过程是一个你等我赶的过程,快了则等待,慢了就加快速度。这就需要一个量来判断(和选择基准比较),到底是播放的快了还是慢了,或者正以同步的速度播放。在视音频流中的包中都含有DTS和PTS,就是这样的量(准确来说是PTS)。

DTS,Decoding Time Stamp,解码时间戳,告诉解码器packet的解码顺序;

PTS,Presentation Time Stamp,显示时间戳,指示从packet中解码出来的数据的显示顺序。
音视频都是顺序播放的,其解码的顺序不应该就是其播放的顺序么,为啥还要有DTS和PTS之分呢。对于音频来说,DTS和PTS是相同的,也就是其解码的顺序和解码的顺序是相同的,但对于视频来说情况就有些不同了。视频的编码要比音频复杂一些,特别的是预测编码是视频编码的基本工具,这就会造成视频的DTS和PTS的不同。这样视频编码后会有三种不同类型的帧:

I帧 关键帧,包含了一帧的完整数据,解码时只需要本帧的数据,不需要参考其他帧。
P帧 P是向前搜索,该帧的数据不完全的,解码时需要参考其前一帧的数据。
B帧 B是双向搜索,解码这种类型的帧是最复杂,不但需要参考其一帧的数据,还需要其后一帧的数据。

I帧的解码是最简单的,只需要本帧的数据;P帧也不是很复杂,值需要缓存上一帧的数据即可,总体来说都是线性,其解码顺序和显示顺序是一致的。B帧就比较复杂了,需要前后两帧的顺序,并且不是线性的,也是造成了DTS和PTS的不同的“元凶”,也是在解码后有可能得不到完整Frame的原因。(更多I,B,P帧的信息可参考)
假如一个视频序列,要这样显示I B B P,但是需要在B帧之前得到P帧的信息,因此帧可能以这样的顺序来存储I P B B,这样其解码顺序和显示的顺序就不同了,这也是DTS和PTS同时存在的原因。DTS指示解码顺序,PTS指示显示顺序。所以流中可以是这样的:

Stream : I P B B
DTS      1 2 3 4
PTS      1 4 2 3

I帧/IDR帧/P帧/B帧

I帧:I帧(Intra-coded picture, 帧内编码帧,常称为关键帧)包含一幅完整的图像信息,属于帧内编码图像,不含运动矢量,在解码时不需要参考其他帧图像。因此在I帧图像处可以切换频道,而不会导致图像丢失或无法解码。I帧图像用于阻止误差的累积和扩散。在闭合式GOP中,每个GOP的第一个帧一定是I帧,且当前GOP的数据不会参考前后GOP的数据。

IDR帧:IDR帧(Instantaneous Decoding Refresh picture, 即时解码刷新帧)是一种特殊的I帧。当解码器解码到IDR帧时,会将DPB(Decoded Picture Buffer,指前后向参考帧列表)清空,将已解码的数据全部输出或抛弃,然后开始一次全新的解码序列。IDR帧之后的图像不会参考IDR帧之前的图像,因此IDR帧可以阻止视频流中的错误传播,同时IDR帧也是解码器、播放器的一个安全访问点。

P帧:P帧(Predictive-coded picture, 预测编码图像帧)是帧间编码帧,利用之前的I帧或P帧进行预测编码。

B帧:B帧(Bi-directionally predicted picture, 双向预测编码图像帧)是帧间编码帧,利用之前和(或)之后的I帧或P帧进行双向预测编码。B帧不可以作为参考帧。B帧具有更高的压缩率,但需要更多的缓冲时间以及更高的CPU占用率,因此B帧适合本地存储以及视频点播,而不适用对实时性要求较高的直播系统。

avcodec_send_packet() 按解码顺序发送 packet。
avcodec_receive_frame() 按显示顺序输出 frame 

播放器对音频和视频的播放没有绝对的静态的同步,只有相对的动态的同步,实际上音视频同步就是一个“你追我赶”的过程。

音视频的同步方式有 3 种,即:音视频分别向系统时钟同步、音频向视频同步及视频向音频同步

通常来说只有在流中含有B帧的时候,PTS和DTS才会不同。

time_base

time_base 是 PTS 和 DTS 的时间单位,也称时间基。

不同的封装格式time_base不一样,转码过程中的不同阶段time_base也不一样。

以 mpegts 封装格式为例,假设视频帧率为 25 FPS。编码数据包 packet(数据结构 AVPacket) 对应的 time_base 为 AVRational{1,90000}。原始数据帧 frame(数据结构 AVFrame) 对应的 time_base 为 AVRational{1,25}。在解码或播放过程中,我们关注的是 frame 的 time_base,定义在 AVStream 结构体中,其表示形式 AVRational{1,25} 是一个分数,值为 1/25,单位是秒。在旧的 FFmpeg 版本中,AVStream 中的 time_base 成员有如下注释:

For fixed-fps content, time base should be 1/framerate and timestamp increments should be 1.

FFmpeg简易播放器的实现5-音视频同步 - 叶余 - 博客园 (cnblogs.com)

(289条消息) FFmpeg 播放器实现音视频同步的三种方式_ffmpeg音视频同步_金戈鐡馬的博客-CSDN博客

(289条消息) FFmpeg学习:视音频同步-CSDN博客

ffmpeg音视频同步---视频同步到音频时钟_13306945的技术博客_51CTO博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaowang_lj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值