ffmpeg如何同步音视频解决方案

ffmpeg如何同步音视频解决方案

ID:5322033

大小:43.34 KB

页数:36页

时间:2017-12-08

ffmpeg如何同步音视频解决方案_第1页
ffmpeg如何同步音视频解决方案_第2页
ffmpeg如何同步音视频解决方案_第3页
ffmpeg如何同步音视频解决方案_第4页
ffmpeg如何同步音视频解决方案_第5页
资源描述:

《ffmpeg如何同步音视频解决方案》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库

1、Ffmpeg音视频同步详解PTS和DTS音频和视频流都有一些关于以多快速度和什么时间来播放它们的信息在里面。音频流有采样,视频流有每秒的帧率。然而,如果我们只是简单的通过数帧和乘以帧率的方式来同步视频,那么就很有可能会失去同步。于是作为一种补充,在流中的包有种叫做DTS(解码时间戳)和PTS(显示时间戳)的机制。为了这两个参数,你需要了解电影存放的方式。像MPEG等格式,使用被叫做B帧(B表示双向bidrectional)的方式。另外两种帧被叫做I帧和P帧(I表示关键帧,P表示预测帧)。I帧包含

2、了某个特定的完整图像。P帧依赖于前面的I帧和P帧并且使用比较或者差分的方式来编码。B帧与P帧有点类似,但是它是依赖于前面和后面的帧的信息的。这也就解释了为什么我们可能在调用avcodec_decode_video以后会得不到一帧图像。所以对于一个电影,帧是这样来显示的:IBBP。现在我们需要在显示B帧之前知道P帧中的信息。因此,帧可能会按照这样的方式来存储:IPBB。这就是为什么我们会有一个解码时间戳和一个显示时间戳的原因。解码时间戳告诉我们什么时候需要解码,显示时间戳告诉我们什么时候需要显示。

3、所以,在这种情况下,我们的流可以是这样的:PTS:1423DTS:1234Stream:IPBB通常PTS和DTS只有在流中有B帧的时候会不同。当我们调用av_read_frame()得到一个包的时候,PTS和DTS的信息也会保存在包中。但是我们真正想要的PTS是我们刚刚解码出来的原始帧的PTS,这样我们才能知道什么时候来显示它。然而,我们从avcodec_decode_video()函数中得到的帧只是一个AVFrame,其中并没有包含有用的PTS值(注意:AVFrame并没有包含时间戳信息,但

4、当我们等到帧的时候并不是我们想要的样子)。然而,ffmpeg重新排序包以便于被avcodec_decode_video()函数处理的包的DTS可以总是与其返回的PTS相同。但是,另外的一个警告是:我们也并不是总能得到这个信息。不用担心,因为有另外一种办法可以找到帧的PTS,我们可以让程序自己来重新排序包。我们保存一帧的第一个包的PTS:这将作为整个这一帧的PTS。我们可以通过函数avcodec_decode_video()来计算出哪个包是一帧的第一个包。怎样实现呢?任何时候当一个包开始一帧的时候

5、,avcodec_decode_video()将调用一个函数来为一帧申请一个缓冲。当然,ffmpeg允许我们重新定义那个分配内存的函数。所以我们制作了一个新的函数来保存一个包的时间戳。当然,尽管那样,我们可能还是得不到一个正确的时间戳。我们将在后面处理这个问题。同步现在,知道了什么时候来显示一个视频帧真好,但是我们怎样来实际操作呢?这里有个主意:当我们显示了一帧以后,我们计算出下一帧显示的时间。然后我们简单的设置一个新的定时器来。你可能会想,我们检查下一帧的PTS值而不是系统时钟来看超时是否会到

6、。这种方式可以工作,但是有两种情况要处理。首先,要知道下一个PTS是什么。现在我们能添加视频速率到我们的PTS中--太对了!然而,有些电影需要帧重复。这意味着我们重复播放当前的帧。这将导致程序显示下一帧太快了。所以我们需要计算它们。第二,正如程序现在这样,视频和音频播放很欢快,一点也不受同步的影响。如果一切都工作得很好的话,我们不必担心。但是,你的电脑并不是最好的,很多视频文件也不是完好的。所以,我们有三种选择:同步音频到视频,同步视频到音频,或者都同步到外部时钟(例如你的电脑时钟)。从现在开始

7、,我们将同步视频到音频。写代码:获得帧的时间戳现在让我们到代码中来做这些事情。我们将需要为我们的大结构体添加一些成员,但是我们会根据需要来做。首先,让我们看一下视频线程。记住,在这里我们得到了解码线程输出到队列中的包。这里我们需要的是从avcodec_decode_video函数中得到帧的时间戳。我们讨论的第一种方式是从上次处理的包中得到DTS,这是很容易的:doublepts;for(;;){if(packet_queue_get(&is->videoq,packet,1)<0){//mean

8、swequitgettingpacketsbreak;}pts=0;//Decodevideoframelen1=avcodec_decode_video(is->video_st->codec,pFrame,&frameFinished,packet->data,packet->size);if(packet->dts!=AV_NOPTS_VALUE){pts=packet->dts;}else{pts=0;}pts*=av_q2d(is->video_st->time_base);如果我们得

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。