2

坚持使用 SDL 和 ffmpeg 库用 C 语言编写一个非常基本的媒体播放器。最初,按照本页中的理论了解整个程序和库的使用。在从头开始编码之后,感谢该教程和许多其他资源,最后我使用最新的 ffmpeg 和 SDL (2.0) 库完成了我的代码工作。但是我的代码缺少适当的同步机制(实际上它缺少同步机制!)。

我仍然不清楚如何将音频和视频同步在一起,因为链接中提供的理论只是部分正确(至少在使用最新的开发库时)。
例如,本页中的一句话如下

但是,ffmpeg 对数据包重新排序,以便 avcodec_decode_video() 正在处理的数据包的 DTS 将始终与其返回的帧的 PTS 相同。

我正在使用avcodec_decode_video2()并且数据包的 DTS 绝对与它解码的帧的 pts 不同(通常)。

我读了这篇内容非常丰富的 BBC 报道,它完全有道理。我对 PTS 和 DTS 有一个清晰的认识。但是 ffmpeg 用于数据包和解码帧的 PTS 和 DTS 值令人困惑。我希望有一些关于这方面的文件。

有人可以解释同步音频和视频的步骤吗?我只需要步骤。我很乐意实施它们。任何帮助是极大的赞赏。谢谢 !

PS:这是我正在谈论的截图:

在此处输入图像描述

巨大的负值是,我假设 AV_NOPTS_VALUE。

4

1 回答 1

3

这不是一个直接的答案,但对于上述问题有很多有用的信息。在浏览了更多信息和编码之后,以下是我的观察:

我提供了一个.mpg文件作为输入,这些是我的观察结果:

BBC RD 1996/3 在其内容丰富的报告中说:

为了能够从未来帧进行反向预测,编码器将图片从自然显示顺序重新排序为“传输”(或“比特流”)顺序,以便在它引用的过去和未来图片之后传输 B 图像。(见图 14)。这引入了取决于连续 B 图像数量的延迟。

  • 提供的输入文件的前几个视频帧如下:(按自然显示顺序)

    I0 B0 B1 P0 B2 B3 P1 B4 B5 P2 B6 B7 P3 B8 B9 I1...

  • 但是编码器(在编码过程中,在过去的某个时间,当文件被编码时)将数据包放入视频流中:(这是为了启用PB帧的解码)

    I0 P0 B0 B1 P1 B2 B3 P2 B4 B5 P3 B6 B7 I1 B8 B9...

  • 现在,当 av_read_frame()从视频流中读取数据包时,它们的获取顺序与上述相同:

    I0 P0 B0 B1 P1 B2 B3 P2 B4 B5 P3 B6 B7 I1 B8 B9...

  • 这就是avcodec_decode_video2()(或至少在这种情况下正在做的):

    输入 I0 (pts_I0, dts_I0)-----> DECODER---->无输出帧
    输入 P0 (pts_P0, dts_P0)-----> DECODER---->输出 I0 (pts_I0, dts_P0)
    输入 B0 (pts_B0, dts_B0)-----> DECODER---->输出 B0 (pts_B0, dts_B0)
    输入 B1 (pts_B1, dts_B1)-----> DECODER-- -->输出 B1 (pts_B1, dts_B1)
    输入 P1 (pts_P1, dts_P1)-----> DECODER---->输出 P0 (pts_P0, dts_P1)
    输入 B2 (pts_B2, dts_B2)-----> DECODER---->输出 B2 (pts_B2, dts_B2)
    输入 B3 (pts_B3, dts_B3)-----> DECODER---->输出 B3 (pts_B3, dts_B3)
    输入 P2 (pts_P2, dts_P2)-----> DECODER---->输出 P1 (pts_P1, dts_P2)
    输入 B4 (pts_B4, dts_B4)-----> DECODER---->输出 B4 (pts_B4, dts_B4)
    输入 B5 (pts_B5, dts_B5)-----> DECODER---->输出 B5 (pts_B5, dts_B5)
    输入 P3 (pts_P3, dts_P3)-----> DECODER---->输出 P2 (pts_P2, dts_P3)
    输入 B6 (pts_B6, dts_B6)-----> DECODER---->输出 B6 (pts_B6, dts_B6)
    输入 B7 (pts_B7, dts_B7)-----> DECODER---->输出 B7 (pts_B7, dts_B7)
    输入 I1 (pts_I1, dts_I1)-----> DECODER---->输出 P3 (pts_P3, dts_I1)
    输入 B8 (pts_B8, dts_B8)-----> DECODER--- ->输出 B8 (pts_B8, dts_B8)
    输入 B9 (pts_B9, dts_B9)-----> DECODER---->输出 B9 (pts_B9, dts_B9)

      下一个输入包 ---------> 解码器 ----------> 下一个输出帧   
    (pts_PKT, dts_PKT) I1 (pts_I1, dts_PKT)

我想你现在可以注意到,在解码的每一步,解码器已经有其他(自然显示顺序的过去帧或未来帧)来成功解码输入数据包。解码器以自然显示顺序输出帧。同样据我观察,通常包含 I 或 P 帧的访问单元(数据包)的pts是 AV_NOPTS_VALUE。

PS:我不懂ASCII艺术!如果插图不太好,请见谅。希望它对其他人有所帮助。
现在知道这一点后,我想它有助于更​​好地理解 pts 和 dts。
此链接此链接是我发现有用的其他链接。

于 2013-10-19T13:23:31.907 回答