将RTP数据包中的h264帧写入MP4文件时遇到问题。使用(例如)avplay / ffplay命令播放视频,但出现以下错误:
[h264 @ 0x7faebc006d40] no frame!0KB vq= 79KB sq= 0B f=0/9
当然看起来有些帧丢失了。
我写数据包的方式如下所示:
等待NAL类型= 8(= SPS)和7(= PPS)的数据包
时间将传入数据包保存在列表中。
如果NAL类型为28,则表示帧已分割-寻找开始
位和结束位,然后创建适当的NAL单元并粘贴
碎片在一起。
如果我们找到了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());
将列表中的等待帧刷新为文件,并在开始时在Big Endian中添加帧大小:
MP4WriteSample(_mp4file, _video, waitingFrame->getDataWithNalSize(), waitingFrame->getSize(), MP4_INVALID_DURATION, 0, 1);
读取RTP数据包并将其循环写入文件:
MP4WriteSample(_mp4file, _video, _videoFrame->getDataWithNalSize(), _videoFrame->getSize(), MP4_INVALID_DURATION, 0, 1);
RTP有效负载包含以下类型的NAL:
-PPS(8)
-SPS(7)
-粘贴后分割的帧(28),我得到了IDR(5)和非IDR(1)视频帧
-SEI(6)
-AUD(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“框架”(使用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(也许是AUD?)NAL写入mp4容器的正确方法是什么?
在我的项目中,我必须使用mp4v2库或任何其他可以免费使用许可证的库(这就是为什么我不能使用libav的原因)
最佳答案
您从RTP数据包收到的NAL以起始码00 00 00 01开头,但是NALS mp4v2需要以4字节的NAL长度开头。