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

时间:2012-07-18 14:34:27

标签: video stream ffmpeg h.264 rtp

环境:

我有一台IP摄像机,能够通过RTP以H.264编码格式传输数据。从以太网记录该原始流。有了这些数据,我必须工作。

目标:

最后我想要一个* .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数据
  2. 使用起始位碎片

    1. 编写NAL前缀
    2. 写NAL单位字节
    3. 写下剩余的原始数据
    4. 没有开始位的碎片

      1. 写原始数据
      2. 这意味着我的原始文件看起来像这样:

        [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本身。

        现在我无法使用某些媒体播放器播放这些数据,这导致我:

        2。转换文件

        由于我想避免使用编解码器,我只是去使用现有的应用程序 - > FFmpeg的。这是我用这些参数调用的:

        ffmpeg.exe -f h264 -i <RawInputFile> -vcodec copy -r 25 <OutPutFilename>.mp4

        -f h264:这应该告诉ffmpeg我有一个h264编码流

        -vcodec copy:从联系人页面引用:

        Force video codec to codec. Use the "copy" special value to tell that the raw codec data must be copied as is.

        -r 25:将帧速率设置为25 FPS。

        当我用这些参数调用ffmpeg时,我得到一个.mp4文件,我可以用VLC和Windows MP播放,所以它实际上有效。但是该文件现在看起来与我的原始文件有点不同。

        这引出了我的问题:

        我到底做了什么?

        我的问题不在于它不起作用。我只是想/需要知道我调用ffmpeg实际上做了什么。我有一个原始H264文件,我无法播放。使用FFmpeg后我可以播放它。

        原始文件(我写的)与FFmpeg写的文件有以下区别:

        1. 标题:FFmpeg文件大约有0x30字节的标题
        2. 页脚:FFmpeg文件也有一个页脚
        3. 更改了前缀和2个新字节:
        4. 原始文件中的新视频帧开始时 新文件中的[NAL Prefix][NAL Unit Byte][Raw Video Data]看起来像这样:

          [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实际上做了什么?为什么它会改变视频数据中的某些字节?

3 个答案:

答案 0 :(得分:3)

除了添加MP4容器外,ffmpeg还将您的H.264附件B字节流(带有NAL前缀)转换为长度前缀格式。

你的[0x00 0x00] [2“随机”字节]是一个32位整数,给出以下NAL单位的长度,以字节为单位。

答案 1 :(得分:0)

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

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

答案 2 :(得分:-1)

您可以在开放式h264 specs中详细了解您的更改。第二章附录B.