avformat代码在相同参数下产生的输出与ffmpeg略有不同-为什么?

avformat代码在相同参数下产生的输出与ffmpeg略有不同-为什么?,ffmpeg,libavcodec,libavformat,Ffmpeg,Libavcodec,Libavformat,我希望通过代码实现与此ffmpeg命令行调用完全相同的结果: ffmpeg -i CAMERARTSPLINK -c:v copy -an -movflags +frag_keyframe+empty_moov -f mp4 当我运行上述命令时,它会给出以下二进制结果: got 36 bytes: 0, 0, 0, 36, 102, 116, 121, 112, ..., 111, 54, 109, 112, 52, 49, got 512 bytes: 0, 0, 3, 76, 109,

我希望通过代码实现与此ffmpeg命令行调用完全相同的结果:

ffmpeg -i CAMERARTSPLINK -c:v copy -an -movflags +frag_keyframe+empty_moov -f mp4
当我运行上述命令时,它会给出以下二进制结果:

got 36 bytes:  0, 0, 0, 36, 102, 116, 121, 112, ..., 111, 54, 109, 112, 52, 49, 
got 512 bytes: 0, 0, 3, 76, 109, 111, 111, 118, 0, 0, 0, ..., 132, 0, 0, 3, 0, 4, 0, 0, 3, 0, 202,
代码可以利用ffmpeg库和include,但我不想将ffmpeg用作程序调用(也就是说,exec*函数不是首选)

我已经为RTSP H264到MP4 remux创建了一个带有
avformat
的小型演示代码示例。 代码高度重用horgh的nice库

我在pastebin.com(400 loc)上发布了这篇文章。它成功构建,但您需要将其链接到
avformat
avdevice
avcodec
avutil

我尽力达到同样的结果,但是当我运行这段代码时,字节#38后的前几个字节是不同的(可能不仅仅是这些,我没有比较字节#548后的任何内容):

您可以在我的代码输出的第二行中看到,以
0
0
0
0
109
<

而ffmpeg给出了
0
0
3
76
<109

其余的所有数据(即使字节没有粘贴在这里)都是完全相同的(至少前548个字节是如此)


我的代码有什么问题?这两个字节对于解码此流似乎非常重要。

10211612112
在ascii中是
ftyp
这是mp4格式类型框
0,0,0,36是框的大小

ascii中的
109111111118
mdat
这是数据框
0,0,0,0
是框的大小


在这种情况下,
mdat
框的大小未知,因为我们还不知道所有视频和音频帧的大小。所以使用了一个零的占位符。当文件完成时,应该用正确的大小覆盖大小值

这是ffmpeg有限的日志功能加上我在视频编解码器方面的有限知识的愚蠢错误

问题在于ffmpeg(使用h264输入)在将原子写入输出缓冲区时:

  • 首先将原子的大小()
  • 然后填充缓冲区的其余部分
  • 然后在最后,它在缓冲区中查找回atom的大小,并更新大小()
这一切都很好,但在填充缓冲区的其余部分时,它会使用,如果到达缓冲区的末尾,avio_w8将刷新缓冲区

如果您在
avio_alloc_context
中使用自定义IO,并且您没有定义足够大的缓冲区,也没有定义查找操作,并且正在写入的atom大于您的缓冲区大小,那么它将被清除,ffmpeg将无法查找回以更新atom的大小

这可能会导致视频输出文件或流损坏(且无法播放)

因此,解决方案是将缓冲区大小从512增加到4096。在这种情况下,moov原子甚至可以在不进行查找操作的情况下进行拟合


如果您知道moov atom的长度大于512字节,并且查看我的示例代码,那么这是非常简单的。

谢谢。有道理。但ffmpeg命令并没有输出到文件,而是直接输出到标准输出。因此,它无法在打印到标准输出后改变盒子的大小。我需要的是:在不知道mdat框的大小之前,avformat不能打印mdat框。在我的自定义io回调中,没有定义seek函数。或者,为了扭转这个问题:ffmpeg如何知道mdat的大小(在打印到stdout时)而我的代码不知道?ffmpeg在写入mdat框之前无法知道mdat框的大小。将mp4写入标准输出是无效的操作。您必须使用碎片化mp4或其他可流化容器,如mkv。
writeOutput: writing 36 bytes: 0, 0, 0, 36, 102, 116, 121, 112, ..., 111, 54, 109, 112, 52, 49, 
writeOutput: writing 512 bytes: 0, 0, 0, 0, 109, 111, 111, 118, 0, 0, 0, ..., 132, 0, 0, 3, 0, 4, 0, 0, 3, 0, 202,