如何将 H.264 UDP 数据包转换为可播放的媒体流或文件(碎片整理)
Posted
技术标签:
【中文标题】如何将 H.264 UDP 数据包转换为可播放的媒体流或文件(碎片整理)【英文标题】:How to convert H.264 UDP packets to playable media stream or file (defragmentation) 【发布时间】:2013-03-02 11:50:48 【问题描述】:在将 SDP 会话的 UDP 流转换为可解码的 H.264 流时,我缺少一些基本的东西。我正在使用支持 H.264 的相机进行测试,并且可以直接使用播放器播放流。当我尝试播放翻译后的流时,播放器将无法识别它(缺少标题错误)。但是,我必须对 UDP 流进行解码,以便能够将其集成到 Java 应用程序中,该应用程序周围有一些解码器。
我已经看到以下问题的非常好的答案:
-
How to process raw UDP packets so that they can be decoded by a decoder filter in a directshow source filter
Problem to Decode H264 video over RTP with ffmpeg (libavcodec)
两者都有一些令人困惑的细微差别(见下文)。
但首先让我们看一下简单的部分。正如我从相机看到的,发送了 SPS 和 PPS 数据包。所有剩余的数据包都是索引的碎片帧。
对于所有没有帧的数据包(在我的例子中只有 NALUnitType 7 和 8),我去掉 RTP 标头(12 字节)并在前面添加起始字节 3 x 0 字节和 1 x 1(00 00 00 01)。
对于所有分段的帧数据包,我根据答案 1 的描述重建它们。所以详细地说,这意味着: RTP 标头的剥离(仅用于数据验证)。 然后从payload中解码片段信息:
第一个字节:[ 3 NAL UNIT BITS | 5 片段类型位]第二个字节:[ 起始位 |结束位 |保留位 | 5 NAL 单位位]
如果设置了起始位,则会有一个新的有效负载标头构造如下:[3 NAL UNIT BITS(从第一个字节)| 5 NAL UNIT BITS(从第二个字节开始)] 这为我们提供了 NALUnitType 1 用于非 idr 切片或 5 用于 idr 切片。这是根据规范。
我采用这个新的有效负载标头(1 个字节)并将不带 2 个字节标头的有效负载附加到一个新包中。所有连续的片段都以相同的方式添加(12 字节 RTP 头条,2 字节单元类型信息条),直到看到结束位信息。当看到结束时,我将开始字节(00 00 00 01)放在这个数据包的前面并将它写到流中。
问题是由于未知原因无法解码。我已阅读的答案的答案 2 的不同之处在于,有效载荷标头的第二个字节也可能被放入已转换的数据包中。但我都尝试了,但仍然没有运气。
新构建的流中可能还缺少其他东西?还是我碎片整理有误?
【问题讨论】:
原来组合帧的新payload header是错误的。我会检查那里可能有什么问题。 [3 NAL 单位位(从第一个字节开始)| 5 NAL UNIT BITS(从第二个字节开始)| 0x40] 可以解决问题。我还不知道为什么。 【参考方案1】:请参阅Problem to Decode H264 video over RTP with ffmpeg (libavcodec) 以获取答案。它有正确的实现!
@Thomas,是的,如果存在 SPS、PPS 或 SEI NAL,它确实有 4 个。
【讨论】:
【参考方案2】:托马斯,
我正在尝试自己理解这一切。在我看来,通过阅读以下内容:How to process raw UDP packets so that they can be decoded by a decoder filter in a directshow source filter 您的“起始字节”减少了一个字节。我认为它是 3 个字节,而不是 4 个......如:00 00 01
也许这就是它遇到问题的地方。
【讨论】:
以上是关于如何将 H.264 UDP 数据包转换为可播放的媒体流或文件(碎片整理)的主要内容,如果未能解决你的问题,请参考以下文章
如何将 H264 RTP 流从 PCAP 转换为可播放的视频文件