为什么我不能使手动修改的 MPEG-4 扩展框(块)大小起作用?

Why can't I get a manually modified MPEG-4 extended box (chunk) size to work?

概览

作为编写 MPEG-4 (MP4) 文件解析器的项目的一部分,我需要了解如何在 MP4 文件中处理扩展框(或块)大小。当我尝试手动模拟具有扩展框大小的 MP4 文件时,媒体播放器报告该文件无效。

技术信息

解释MPEG-4 specification

一个 MP4 文件由一系列 objects 组成,称为 'boxes'。所有数据都包含在框中,文件中没有其他数据。

这是第 4.2 节的屏幕截图:Object 结构,它描述了方框 header 及其大小和类型字段:

大多数 MP4 框 header 包含两个字段:32 位压缩框大小和 32 位框类型。紧凑的盒子尺寸支持高达 4 GB 的盒子数据。有时 MP4 盒可能有比这更多的数据(例如,一个大视频文件)。在这种情况下,紧凑盒大小设置为 1,并且紧跟在盒类型之后添加八 (8) 个八位字节。这个 64 位数字被称为 'extended box size',并支持最大 2^64 的框大小。

为了更好地理解扩展框大小,我拿了一个简单的 MP4 文件,想修改 moov/trak/mdia 框以使用扩展框大小,而不是紧凑大小。

这是 MP4 文件在修改之前的样子。三个框 header 以红色突出显示:

我的计划如下:

  1. 修改moov/trak/mdia
    • moov/trak/mdia 中,紧跟框类型 ('mdia') 插入八 (8) 个八位字节。这最终将成为我们扩展的盒子尺寸。
    • 将紧凑框大小复制到 newly-inserted 扩展框大小,将大小增加 8 以补偿新插入的八位字节。大小按big-endian顺序插入。
    • 将紧凑大小设置为 1。
  2. 修改moov/trak
    • 将 8 添加到现有的紧凑框大小(以补偿添加到 mdia 的八个八位字节)。
  3. 修改moov
    • 将 8 添加到现有的压缩框大小(同样,以补偿 mdia 中的八个八位字节)

这是 MP4 文件现在的样子,修改后的八位字节为红色:

我们做了什么?

我们已经告诉 MP4 parser/player 从扩展字段而不是紧凑大小字段中获取 moov/trak/mdia 框大小,并将所有 parent 框增加八个(8 ) 以补偿 mdia 框中的 newly-inserted 扩展框大小。

有什么问题?

当我尝试播放修改后的 MP4 文件时,我收到来自不同媒体播放器的错误消息:

为什么媒体播放器将修改后的文件视为无效 MP4?

感谢@Alan Birtles 指出块偏移量也需要修改。实际上,stco(示例 table 块偏移量?)框包含 绝对 文件偏移到 mdat 框中的数据块(而不是 relative 框内的偏移量)。这个可以看规范文档:

块偏移量需要增加我们在 mdat 框之前添加到文件中的八位字节数。在我们的例子中,这是插入 mdia 框中的八 (8) 个八位字节扩展框大小。

剩下的就是手动更改在两个 stco 框(视频和音频轨道)中找到的块偏移量,为每个块偏移量添加八 (8) 个。这是 stco 个方块,然后将 8 添加到它们的块偏移量:

现在文件通过了两个ffmpeg and ffprobe 工具的有效性测试。有趣的是,虽然 VLC 成功播放修改后的文件,但其他媒体播放器(例如 Windows Media Player、MS Photos、MS Movies & TV、MS MovieMaker)报告文件已损坏。目前尚不清楚为什么他们无法播放该文件。未经证实的可能性包括:

  • 不支持 mdat
  • 以外的任何框的扩展框尺寸
  • 如果扩展框大小小于 2^32 则犹豫不决

总而言之,如果将任何字段添加到框(例如,扩展框大小),stco 块偏移量需要增加每个 [=10] 之前插入 MP4 文件中的八位字节数=] 框.