使用mp4v2将h264写入mp4容器的正确方法是什么?

时间:2014-03-08 19:36:46

标签: video mp4 h.264 rtp

我在将从RTP数据包中获取的h264帧写入MP4文件时遇到了问题。视频播放(例如)命令avplay / ffplay,但我收到这些错误:

[h264 @ 0x7faebc006d40] no frame!0KB vq=   79KB sq=    0B f=0/9

当然看起来有些帧错过了。 我正在编写数据包的方式如下:

  1. 等待NAL类型= 8(= SPS)和7(= PPS)的数据包 时间将传入的数据包保留在列表中。
  2. 如果NAL类型为28,则表示帧已分割 - 查找开始 位和结束位然后创建适当的NAL单位并坚持 碎片在一起。
  3. 如果我们找到了PPS和SPS表,那么创建MP4文件:

    char * application_name =“isom”; _mp4file = MP4CreateEx(name,0,1,1,application_name,1);

    然后创建VideoTrack:

     _video = MP4AddH264VideoTrack(_mp4file, _videoTimeScale, _videoTimeScale / _videoSampleDuration, _videoWidth, _videoHeight,
                                                _sps->getData()[1], //sps[1] AVCProfileIndication
                                                _sps->getData()[2], //sps[2] profile_compat
                                                _sps->getData()[3], //sps[3] AVCLevelIndication
    3); // 4 (minusOne) bytes length before each NAL unit 
    

    并设置一些内容:

    MP4SetVideoProfileLevel(_mp4file, 0x7F);
    MP4AddH264SequenceParameterSet(_mp4file, _video, _sps->getData(), _sps->getSize());
    MP4AddH264PictureParameterSet(_mp4file, _video, _pps->getData(), _pps->getSize());
    
  4. 从列表到文件刷新等待帧,在开头的Big Endian中添加了帧大小:

    MP4WriteSample(_mp4file, _video, waitingFrame->getDataWithNalSize(), waitingFrame->getSize(), MP4_INVALID_DURATION, 0, 1);
  5. 读取RTP数据包并将其写入循环到文件:
    MP4WriteSample(_mp4file, _video, _videoFrame->getDataWithNalSize(), _videoFrame->getSize(), MP4_INVALID_DURATION, 0, 1);
  6. RTP有效载荷由这些类型的NAL组成:
    - PPS(8)
    - SPS(7)
    - 分开的框架(28),坚持后我得到IDR(5)和非IDR(1)视频帧
    - SEI(6)
    - 澳元(9)

    奇怪的是,如果我不使用MP4WriteSample函数在文件的开头写PPS和SPS,我会收到这些错误(来自avplay):

    [h264 @ 0x7faebc006d40] non-existing PPS 0 referenced
    [h264 @ 0x7faebc006d40] decode_slice_header error
    [h264 @ 0x7faebc008200] no frame!
    

    但如果我这样做,那就没有错误了。 所以真正的问题是SEI NAL。如果我将它们写入RTP流中(使用MP4WriteSample),我会收到“无帧”错误。但是如果我在文件的开头只写了一个SEI“frame”(使用MP4WriteSample),我就会遇到这种错误:

    [h264 @ 0x7f1e48007d40] error while decoding MB 50 0, bytestream (-48)
    [h264 @ 0x7f1e48007d40] concealing 1499 DC, 1499 AC, 1499 MV errors
    [h264 @ 0x7f1e48008200] error while decoding MB 44 0, bytestream (-25)
    [h264 @ 0x7f1e48008200] concealing 1500 DC, 1500 AC, 1500 MV errors
    [h264 @ 0x7f1e48006d40] top block unavailable for requested intra4x4 mode -1 at 52 0
    

    然后图片失真(但后来我没有“没有帧”错误)。

    所以我的问题是什么是将SEI(也许是澳元?)NAL写入mp4容器的正确方法?

    在我的项目中,我必须使用mp4v2库或任何其他免费使用许可证的库(这就是为什么我不能使用libav)

1 个答案:

答案 0 :(得分:0)

您从RTP数据包收到的NAL以起始码00 00 00 01开始,但NALS mp4v2需要以4字节NAL长度开始。