ffmpeg av libs可以返回准确的PTS吗?
我正在使用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帧)。