碎片MP4中的闪光音频或破碎视频



我正在开发用于多路复用音频和视频的小型C++库。这基本上是FFMPEG功能和结构的外观。代码在这里,这里有最小的复制测试代码,到目前为止,它似乎工作得很好。。。几乎

记录在案——我的MP4文件是所谓的";碎片MP4";,将头移到文件的开头,这样就可以流式传输该文件(即在缓冲时在浏览器中播放(。这就是我在Mp4Muxer::writeHeader()中设置的movflags的作用。

在用原始H264视频流和MP3文件(视频长度<1分钟,MP3-几分钟长(测试这个库时,我观察到:

  • 如果我不限制多路复用音频流;前方";对于视频(因为MP3更长,所以最终视频帧停止出现,但音频帧仍然出现(,所有复用器都很好,没有错误,但在几秒钟后用ffplay播放输出MP4会导致以下日志(以及冻结的视频,同时音频继续播放(:
[h264 @ 0x7f90a40ae2c0] Invalid NAL unit size (2162119 > 76779).0
[h264 @ 0x7f90a40ae2c0] Error splitting the input into NAL units.
[mp3float @ 0x7f90a4009540] Header missing  515KB sq=    0B f=0/0
[h264 @ 0x7f90a40cb0c0] Invalid NAL unit size (-860010620 > 17931).
[h264 @ 0x7f90a40cb0c0] Error splitting the input into NAL units.
[h264 @ 0x7f90a42bf440] Invalid NAL unit size (-168012642 > 8000).
[h264 @ 0x7f90a42bf440] Error splitting the input into NAL units.
[h264 @ 0x7f90a42fa780] Invalid NAL unit size (-1843711407 > 5683).
[ and it repeats...]
  • 即使我限制了流可以是多少";前方";另一种,过多地限制它会导致输出中没有多路复用数据
  • 限制一个流在复用器中相对于另一个流可以缓冲多少的任何其他中间级别都会导致音频故障,在ffplay中不时会出现以下错误(限制越严格,打印的频率就越高(:
[mp3float @ 0x7f744c01b640] overread, skip -6 enddists: -1 -1=0/0 

相对于多路复用视频,不限制多路复用音频(完全或足够(也会在我的多路复用应用程序中产生以下消息:

[mp4 @ 0x55d0c6c21940] Delay between the first packet and last packet in the muxing queue is 10004898 > 10000000: forcing output

目前,修复非常丑陋,我甚至不明白为什么它能工作,但在写入MP4标头之前,我手动设置了muxer缓冲帧的限制,如下所示:

formatCtxt->max_interleave_delta = 10000000LL * 10LL;

通过这种方式,复用器可以存储一个流的更多分组;前方";另一个(队列开始和结束时数据包的DTS之间的最大差异设置为比默认值大10倍;它还去掉了上面提到的信息日志(。显然,我想更妥善地解决它,而不是像那样的黑客行为。

我尝试了各种方法,包括手动跳过MP3文件中的ID3标签(但看起来FFMPEG处理得很好,没有改变任何东西(。我还在MP4中试用FLAC,而不是MP3。虽然我知道这是一件相当实验性的事情,但我在音频故障方面遇到了非常类似的问题(不过,当大量音频数据被多路复用时,视频被冻结没有问题(。似乎音频故障或冻结视频的问题在规模上也有所不同,这取决于我给多路复用器提供的输入数据块的大小。老实说,现在我没什么想法。

我在回答我自己的问题,也许有人会从我的错误中吸取教训。顺便说一句,主分支上的代码发生了显著变化,但故障部分仍然可以突出显示。

看起来有问题的代码是Mp4Muxer::muxMediaData()方法中的这个片段:

for(auto packet = mediaCtxt.getNextFrame();
packet.size > 0 && checkLimit(audioAheadOfVideoInCommonTimebase, timeAheadInCommonTimebaseLimit);
packet = mediaCtxt.getNextFrame(), ++packetsMuxedCnt)

在这个循环中,我首先获取媒体数据包,然后检查流是否由于过于超前于其他流而受到限制。如果是,则表示媒体数据包丢失。由于音频几乎总是领先于视频,所以由于样本丢失,它出现了故障。

最新更新