如何将H.264 UDP数据包转换为可播放的媒体流或文件(碎片整理)

时间:2013-03-14 08:08:11

标签: java udp h.264 rtp sdp

在将SDP会话的UDP流转换为可解码的H.264流时,我遗漏了一些基本的东西。我正在使用支持H.264的摄像头进行测试,可以直接与播放器一起播放流。当我尝试播放翻译的流时,播放器将无法识别(缺少标题错误)。但是我必须解码UDP流才能将它集成到一个Java应用程序中,周围有一些解码器。

我已经看到了以下问题的非常好的答案:

  1. How to process raw UDP packets so that they can be decoded by a decoder filter in a directshow source filter
  2. Problem to Decode H264 video over RTP with ffmpeg (libavcodec)
  3. 两者都有一些令人困惑的小差异(见下文)。

    但首先让我们看看容易的部分。正如我从相机中看到的那样,发送了SPS和PPS数据包。所有剩余的数据包都是索引或未索引的碎片帧。

    对于没有帧的所有数据包(在我的情况下只有NALUnitType 7和8)我剥离RTP报头(12字节)并在前面添加起始字节3 x 0字节和1 x 1(00 00 00 01)。

    对于所有分段的帧数据包,我根据答案1的描述重建它们。所以详细说明这意味着: 剥离RTP标头(仅用于数据验证)。 然后从有效载荷中解码片段信息:

    第一个字节:[3 NAL UNIT BITS | 5个碎片类型位]
    第二个字节:[START BIT |结束位|保留位| 5个NAL单位]

    如果设置了起始位,则有一个新的有效负载头构造如下:[3 NAL UNIT BITS(从第一个字节开始)| 5个NAL单位(从第二个字节开始)]
    这为非idr切片提供了NALUnitType 1,为idr切片提供了5。这是根据规范。

    我使用这个新的有效负载头(1个字节)并将没有2个字节头的有效负载附加到新的包中。以相同的方式添加所有连续片段(12字节RTP标题的条带,2字节单元类型信息的条带),直到看到结束位信息。当看到结束时,我将开始字节(00 00 00 01)放在此数据包的前面并将其写入流中。

    问题是由于未知原因无法解码。我读过的答案的答案2的不同之处在于,有效载荷头的第二个字节也可能被放入翻译的数据包中。但我试过了两次,但仍然没有运气。

    新构建的流可能还有其他缺失的东西吗?或者我在碎片整理中犯了错误?

2 个答案:

答案 0 :(得分: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

也许这就是它遇到麻烦的地方。

答案 1 :(得分:1)

请参阅Problem to Decode H264 video over RTP with ffmpeg (libavcodec)了解答案。它有正确的实现!

和@Thomas,如果有SPS,PPS或SEI NAL,它确实有4个。