【转】 如何同步视频 2010-07-16 10:18 转载自 fandy 586 最终编辑 fandy 586 如何同步视频 PTS 和DTS 幸运的是,音频和视频流都有一些关于以多快速度和什么时间来播放它们的信息在里面。音频流有采样,视频流有每秒的帧率。然而,如果我们只是简单的通过数帧和乘以帧率的方式来同步视频,那么就很有可能会失去同步。于是作为一种补充,在流中的包有种叫做 DTS(解码时间戳)和PTS(显示时间戳)的机制。为了这两个参数,你需要了解电影存放的方式。像 MPEG 等格式,使用被叫做 B 帧(B 表示双向 bidrectional)的方式。另外两种帧被叫做 I 帧和P 帧(I 表示关键帧,P 表示预测帧)。I 帧包含了某个特定的完整图像。P 帧依赖于前面的I 帧和P 帧并且使用比较或者差分的方式来编码。B 帧与 P 帧有点类似,但是它是依赖于前面和后面的帧的信息的。这也就解释了为什么我们可能在调用 av codec_decode_v ideo 以后会得不到一帧图像。 所以对于一个电影,帧是这样来显示的:I B B P。现在我们需要在显示 B 帧之前知道 P 帧中的信息。因此,帧可能会按照这样的方式来存储:IPBB。这就是为什么我们会有一个解码时间戳和一个显示时间戳的原因。解码时间戳告诉我们什么时候需要解码,显示时间戳告诉我们什么时候需要显示。所以,在这种情况下,我们的流可以是这样的: PTS: 1 4 2 3 DTS: 1 2 3 4 Stream: I P B B 通常 PTS 和DTS 只有在流中有B 帧的时候会不同。 当我们调用 av _read_frame()得到一个包的时候,PTS 和DTS 的信息也会保存在包中。但是我们真正想要的PTS 是我们刚刚解码出来的原始帧的PTS,这样我们才能知道什么时候来显示它。然而,我们从 av codec_decode_v ideo()函数中得到的帧只是一个 AVFrame,其中并没有包含有用的PTS 值(注意:AVFrame 并没有包含时间戳信息,但当我们等到帧的时候并不是我们想要的样子)。然而,ffmpeg 重新排序包以便于被avcodec_decode_video()函数处理的包的DTS 可以总是与其返回的PTS 相同。但是,另外的一个警告是:我们也并不是总能得到这个信息。 不用担心,因为有另外一种办法可以找到帧的PTS,我们可以让程序自己来重新排序包。我们保存一帧的第一个包的PTS:这将作为整个这一帧的 PTS。我们可以通过函数avcodec_decode_video()来计算出哪个包是一帧的第一个包。怎样实现呢?任何时候当一个包开始一帧的时候,avcodec_d...