使用SDL和ffmpeg库在C中编写一个非常基本的媒体播放器。最初,按照this页面中的理论来了解整个程序和库的使用。在从头开始编码之后,感谢该教程和许多其他资源,最后我使用最新的ffmpeg和SDL(2.0)库使我的代码工作。但我的代码缺乏适当的同步机制(实际上它没有同步机制!)。
我仍然不清楚如何将音频和视频同步在一起,因为链接中提供的理论只是非常部分正确(至少在使用最新的开发时)库)。
例如,this页面中的句子如下:
然而,ffmpeg重新排序数据包,以便avcodec_decode_video()处理的数据包的DTS将始终与它返回的帧的PTS相同。
我正在使用 avcodec_decode_video2(),并且数据包的DTS绝对与它解码的帧的pts(通常)不同。
我阅读了this非常有用的BBC报告,这完全合情合理。我对PTS和DTS有一个清晰的认识。但是ffmpeg用于数据包和解码帧的PTS和DTS值令人困惑。我希望有一些关于这方面的文件。
有人可以解释同步音频和视频的步骤吗?我只需要这些步骤。我很乐意实现它们。任何帮助是极大的赞赏。谢谢 !
PS:这是我所说的截图:
巨大的负值是,我假设AV_NOPTS_VALUE。
答案 0 :(得分: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
...
但是编码器(在编码过程中,在编码文件的过去的某个时间)将数据包放入视频流中:(这是为了能够解码P
和B
帧)
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)
Next Input Packet ---------> DECODER ----------> Next Output Frame
(pts_PKT, dts_PKT) I1 (pts_I1, dts_PKT)
我想您现在可以注意到,在解码的每一步,解码器已经 其他帧(过去帧或自然显示顺序的未来帧) )成功解码输入数据包。解码器以自然显示顺序输出帧。另据我观察,通常包含I或P帧的访问单元(数据包)的 pts 是AV_NOPTS_VALUE。
PS:我不懂ASCII艺术!对不起,如果插图不太好。希望它能帮助别人。