video - 如何使用 ffmpeg 库同步音频和视频?

标签 video ffmpeg sync pts

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

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

However, 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.



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

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

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

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

enter image description here

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

最佳答案

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

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

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

To enable backward prediction from a future frame, the coder re-orders the pictures from natural display order to ‘transmission’ (or ‘bitstream’) order so that the B-picture is transmitted after the past and future pictures which it references. (See Fig. 14). This introduces a delay which depends upon the number of consecutive B-pictures.


  • 提供的输入文件的前几个视频帧如下:(按自然显示顺序)
    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)

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

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

    关于video - 如何使用 ffmpeg 库同步音频和视频?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19463550/

    相关文章:

    javascript - 如何使用静音 Prop 取消静音 html5 视频

    video - 具有 H.264 的 mpeg-4 容器所需的最小 Atom/Box 集(一个流,渐进式视频,无音频)

    android - 将图像编码为电影文件

    Android 多个同步适配器项目,如 Google 帐户?

    JavaScript 同步两个数组(对象)/查找增量

    image - 如何通过使用ffmpeg从目录循环到图像来转换视频?

    ffmpeg - 如何安装 FFmpeg 让我的机器人播放音乐?

    android - 根据我的需要减少编译后的 ffmpeg 库大小

    iphone - 进行移动和服务器同步的最佳方式是什么?

    javascript - 如何让我的视频在点击锚定链接宽度目标="_blank"后的某个时间自动播放