ffmpeg av libs可以返回准确的PTS吗?

时间:2020-03-06 14:23:07  来源:igfitidea点击:

我正在使用IBBP ... GOP序列的mpeg流。前四个AVPackets返回的(DTS,PTS)值如下:I =(0,3)B =(1,1)B =(2,2)P =(3,6)

I帧上的PTS看起来合法,但是B帧上的PTS不能正确,因为B帧不应该在I帧之前显示,因为它们的PTS值指示。我还尝试解码数据包,并在结果AVFrame中使用pts值,将PTS始终设置为零。

有什么办法可以从ffmpeg中获取准确的PTS?如果没有,那么同步音频的最佳方法是什么?

解决方案

好的,请抓取我之前的困惑答复。

对于IBBPBBI电影,我们希望PTS看起来像这样(按解码顺序)

0, 3, 1, 2, 6, 4, 5, ...

对应于框架

I, P, B, B, I, B, B, ...

因此,我们似乎在序列的开头缺少I,但是时间戳看起来正确。

我想我根据http://www.dranger.com/ffmpeg/tutorial05.html中的评论终于弄清楚了发生了什么:

ffmpeg reorders the packets so that the DTS of the packet being processed by avcodec_decode_video() will always be the same as the PTS of the frame it returns

翻译:如果我将数据包输入到PTS为12的avcodec_decode_video()中,则avcodec_decode_video()不会返回该数据包中包含的已解码帧,直到我将其输入的DTS为12的更高数据包为止。与其DTS相同,则给定的数据包与返回的帧相同。如果数据包的PTS比其DTS晚2帧,则avcodec_decode_video()将延迟该帧,直到我再提供2个数据包后才返回。

基于此行为,我猜测av_read_frame()可能会将数据包从IPBB重新排序到IBBP,以便avcodec_decode_video()只需将P帧缓冲为3帧而不是5帧。 P帧按此顺序的输出为3(6 3):

|                  I B B P B B P
|             DTS: 0 1 2 3 4 5 6
| decode() result:       I B B P

与标准顺序(6 1)相差5:

|                  I P B B P B B
|             DTS: 0 1 2 3 4 5 6
| decode() result:       I B B P

<shrug />,但这纯粹是猜测。

我相当确定我们正在获得准确的价值。如果我们将MPEG流也视为流,则可能会有所帮助。在这种情况下,我们通常会在IBBPBB之前看到另一个GOP。也许是这样的(使用与原始问题相同的符号):

P(-3,-2)  B(-2,-1)  B(-1,0)

基本上,I帧之后的B帧基于I帧和上一个GOP中的最后一个P帧。

从视频开始,这样做在逻辑上是合理的:

Start GOP: IPBBPBBPBB...

以后一定是

Start GOP: IBBPBBPBBPBB
Start GOP: IBBPBBPBBPBB
Start GOP: IBB...

请记住,解码任何B帧都需要在其之前和之后的完整帧。因此,每对B帧应在文件中的I或者P帧之前显示。

FFMPEG可能只是放弃了第一个GOP的"特殊情况"。

由于前两个B帧没有前一个要操作的帧,因此我们应该能够安全地丢弃它们。只需从第一个I帧开始重新设置时间戳,并调整音频流相同的数量即可。

这是否会导致实际丢失帧取决于FFMPEG的实现,但更糟的情况是丢失83毫秒(2帧/秒,每秒24帧)。