博客> FFmpeg音视频同步的问题
FFmpeg音视频同步的问题
2017-09-22 18:12 评论:0 阅读:134 lvhahaha
OPenGL

http://www.voidcn.com/blog/EricFantastic/article/p-4919649.html

音视频流里都包含了播放速率的信息,音频使用采样率来表示,而视频则采用f/s来表示,但是我们却不能简单地用这两个数据来对音视频进行同步,我们需要使用DTS(解码时间戳)和PTS(播放时间戳)这两个数据;我们知道影视数据在存储时,会存在多种帧形式,例如MPEG中就采用了I,B和P,由于B帧的存在使得PTS和DTS存在不同(原因见附录),如图1所示为一个简单的例子;当然真正影响我们音视频同步的是PTS。

   我们可以从影视文件中获得包的PTS,但是我们无法直接获得帧(我们真正关心的)的PTS,解决办法是用一帧的第一个包的PTS作为这一帧的PTS,这是可行的,因为当一个包开始一帧时,avcodec_decode_video()会调用为帧申请存储空间的函数,我们可以重写这个函数,在其中加入获取包DTS的方法(这是很容易的),因为ffmpeg会重新给包进行排序,因此被avcodec_decode_video()处理过的包的DTS和返回的帧的PTS是相同的,这样就可以得到帧的PTS了。当然有时我们可能没法得到这个PTS,那样我们使用内部video_clock(记录视频已经过去的时间);

这样我们就可以使用PTS来重新队列化我们的帧(queue_picture);

然后,我们可以去获得音频的播放时间PTS。

get_audio_clock():

把audio_clock作为音频的pts,但是在audio_decode_frame()计算的audio_clock的是假定缓冲满的情况,而实际上可能缓冲是不满的,我们需要减去空闲的部分的时间:pts -= (double)hw_buf_size / bytes_per_sec;

audio_decode_frame():音频解码

读取包时,获取其pts,放入audio_clock中;

播放时根据缓冲大小和播放速率计算播放时间;

获得这两个pts后,我们有三个选择:视频同步音频(计算音视频PTS只差,来决定视频是否有延迟)、音频同步视频(根据音视频PTS差值调整音频取的样值,即改变音频缓冲区的大小)和音频视频同步外部时钟(同前一个)。

附录:

I frame :帧内编码帧 又称intra picture,I 帧通常是每个 GOP(MPEG 所使用的一种视频压缩技术)的第一个帧,经过适度地压缩,做为随机访问的参考点,可以当成图象。I帧可以看成是一个图像经过压缩后的产物。

P frame: 前向预测编码帧 又称predictive-frame,通过充分将低于图像序列中前面已编码帧的时间冗余信息来压缩传输数据量的编码图像,也叫预测帧;

B frame: 双向预测内插编码帧 又称bi-directional interpolated prediction frame,既考虑与源图像序列前面已编码帧,也顾及源图像序列后面已编码帧之间的时间冗余信息来压缩传输数据量的编码图像,也叫双向预测帧;

I frame: 自身可以通过视频解压算法解压成一张单独的完整的图片。

P frame:需要参考其前面的一个I frame 或者B frame来生成一张完整的图片。

B frame:则要参考其前一个I或者P帧及其后面的一个P帧来生成一张完整的图片。

I frame 的解码不依赖于任何的其它的帧.而p frame的解码则依赖于其前面的I frame或者P frame.B frame的解码则依赖于其前的最近的一个I frame或者P frame 及其后的最近的一个P frame.

收藏
0
sina weixin mail 回到顶部