我正在使用一个使用IBBP ... GOP序列的mpeg流。前4个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?如果没有,那么同步音频的最佳方法是什么呢?
答案 0 :(得分:10)
我想我终于根据http://www.dranger.com/ffmpeg/tutorial05.html中的评论找出了正在发生的事情:
ffmpeg重新排序数据包,以便avcodec_decode_video()处理的数据包的DTS将始终与它返回的帧的PTS相同
翻译:如果我将数据包输入到具有12的PTS的avcodec_decode_video(),avcodec_decode_video()将不会返回该数据包中包含的解码帧,直到我将其提供给以后的数据包。 DTS为12.如果数据包的PTS与其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
VS。与标准排序(6 - 1)相差5:
| I P B B P B B
| DTS: 0 1 2 3 4 5 6
| decode() result: I B B P
<耸肩/>但那是纯粹的推测。
答案 1 :(得分:1)
好的,抓住我之前的困惑回复。
对于IBBPBBI电影,您希望PTS看起来像这样(按解码顺序)
0, 3, 1, 2, 6, 4, 5, ...
对应框架
I, P, B, B, I, B, B, ...
所以你似乎在序列的开头错过了一个I,但其他时间戳看起来是正确的。
答案 2 :(得分:0)
我很确定你得到了准确的价值观。如果您将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可能只是放弃了第一个共和党的“特殊情况”。
由于前两个B帧没有先前的帧进行操作,因此您应该能够安全地丢弃它们。只需将您的时间戳重新设置为第一个I帧,并调整相同数量的音频流。
这是否会导致帧丢失将取决于FFMPEG的实现,但更糟糕的情况是你丢失了83毫秒(2帧,24帧/秒)。