使用FFmpeg进行H.264转换(来自RTP流)

21

环境:

我有一个IP摄像头,它能够以H.264编码格式通过RTP流传输其数据。该原始流从以太网中记录下来,我需要处理这些数据。

目标:

最终,我想要得到一个*.mp4文件,可以使用常见的媒体播放器(如VLC或Windows MP)进行播放。

我已经做了什么:

我拿到了原始的流数据并解析它。由于数据是通过RTP传输的,所以我需要处理NAL字节、SPS和PPS。

1. 写入一个原始文件

首先,我确定每个通过以太网接收到的帧的类型。为此,我解析每个RTP负载的前两个字节,以便获取8个NAL单元位、片段类型位和起始、保留和结束位。在负载中,它们的排列方式如下:

Byte 1: [          3 NAL Unit Bits          | 5 Fragment Type Bits]
Byte 2: [Start Bit | Reserved Bit | End Bit | 5 NAL Unit Bits]

通过这个我可以确定:

  • 视频帧的起始和结束 -> 起始位和结束位
  • 负载类型 -> 5个片段类型位
  • NAL单元字节

在我这种情况下必要的片段类型是:

Fragment Type  7 = SPS
Fragment Type  8 = PPS
Fragment Type 28 = Video Fragment

将字节1和2中的NAL单元位组合在一起,即可创建NAL字节。

现在根据分段类型执行以下操作:

SPS/PPS:

  1. 写入NAL前缀(0x00 0x00 0x01),然后写入SPS或PPS数据

带起始位的分段:

  1. 写入NAL前缀
  2. 写入NAL单元字节
  3. 写入剩余的原始数据

没有起始位的分段:

  1. 直接写入原始数据

这意味着我的原始文件看起来像这样:

[NAL Prefix][SPS][NAL Prefix][PPS][NAL Prefix][NAL Unit Byte][Raw Video Data][Raw Video Data]....[NAL Prefix][NAL Unit Byte][Raw Video Data]...
对于我在流数据中找到的每个PPS和SPS,我只需写一个NAL前缀(0x00 0x00 0x01),然后是SPS / PPS本身。现在我无法使用某些媒体播放器播放此数据,这导致我需要转换文件。由于我想避免与编解码器太多地工作,我只需使用现有的应用程序-> FFmpeg即可。我使用以下参数调用FFmpeg:-f h264 -i -vcodec copy -r 25 .mp4。当我使用这些参数调用FFmpeg时,我得到一个.mp4文件,我可以使用VLC和Windows MP播放它,所以它实际上有效。但是该文件现在看起来与我的原始文件有点不同。因此,我的问题是:我到底做了什么?我的问题不在于它是否有效。我只是想/需要知道调用FFmpeg时我实际上做了什么。我有一个原始的H264文件,我无法播放它。在使用FFmpeg之后,我可以播放它。原始文件和FFmpeg创建的文件之间存在以下差异:1.头:FFmpeg文件大约有0x30字节的头2.页脚:FFmpeg文件还有页脚3.更改的前缀和2个新字节:在原始文件中,新的视频帧始于 [NAL前缀] [NAL单元字节] [原始视频数据],而在新文件中,则看起来像是:
[0x00 0x00][2 "Random" Bytes][NAL Unit Byte][Raw Video Data].....[0x00 0x00[2 other "Random" Bytes][NAL Unit Byte][Raw Video Data]...

我知道视频流需要一个容器格式(如果我错了请纠正我,但我想新的头和尾应该是负责这个的)。但为什么它实际上会改变原始数据中的一些字节呢?这不可能是解码,因为流本身应该由播放器解码而不是 ffmpeg。

你可以看到,我并不需要一个新的解决方案来解决我的问题,更多的是需要一个解释(这样我就可以自己解释)。ffmpeg 到底做了什么?为什么会在视频数据中更改一些字节?


2
你能够实现这个吗?如果可以,你愿意分享解决方案吗?谢谢! - ioan ghip
我也在寻找类似的解决方案。如果您已经解决了这个问题,是否愿意分享一下呢? - Austin
我知道这是一个非常老的问题,但是看起来你在分析有效载荷的“Byte 2”时顺序有误。它应该是“[起始位 | 结束位 | 保留位 | 5个NAL单元位]”-所以你已经重新排列了保留位和结束位。 - Adam Szmyd
3个回答

4
除了添加MP4容器外,ffmpeg将您的H.264 Annex B字节流(带有NAL前缀)转换为长度前缀格式。
[0x00 0x00][2“随机”字节]是一个32位整数,表示以下NAL单元的字节数。

0

看起来流已经被分成了数据包。许多容器格式将比特流分成数据包,并添加一些信息,例如时间戳、数据包长度等。这为解码器提供了钩子,可以在不解码所有内容的情况下跳过文件,当数据包丢失时重新同步,同步音频/视频,组合多个流等。

查看MP4文件格式信息以获取更多信息:
http://en.wikipedia.org/wiki/MPEG-4_Part_14


-2

您可以在开放的h264规范中阅读有关您所做更改的更多信息。请参考附录B章节。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接