3

我正在生成 MP4 文件(带有 h.264 视频和 AAC 音频),方法是从 JavaScript 中的 MPEG-TS 进行转换,以通过 blob URL 在浏览器中播放。在 Chrome 中一切正常,如果我从开发人员控制台中获取 blob URL 并下载它们,生成的文件也可以在 Windows Media Player 上正常播放。然而,Firefox 声称它们已损坏。

我已将问题缩小到音频元数据中的 ESDS 框的问题。如果我通过其他方式(如 ffmpeg)重新打包源 MPEG-TS 文件,并在十六进制编辑器中手动编辑我生成的文件,以将其他软件生成的等效文件粘贴到 ESDS 框中,那么 Firefox 很高兴。

构建 ESDS 盒的代码。(我正在跟踪这个问题

我试图通过一个非常简单的从 MPEG-specs 中转录材料的过程来编写它,但这并不能保证我没有把它搞砸。由于 Chrome 和 Windows Media 可以很好地播放我的文件,我不确定这是否真的是我的文件中的错误,他们能够以某种方式忽略,或者这是否是 Firefox 的问题。我怀疑前者,但我不确定。

任何人都对如何构建合适的 ESDS 盒有任何见解,或者可能是一个简单易懂的参考?

编辑:以下是为同一个输入文件生成的一些不同的 ESDS 部分(作为十六进制字节,从我的十六进制编辑器中复制出来):

矿:

00 00 00 27 65 73 64 73 00 00 00 00 03 22 00 00
02 04 14 40 15 00 00 00 00 00 3a f1 00 00 2d e6
05 02 12 10 06 01 02

mpegts

00 00 00 33 65 73 64 73 00 00 00 00 03 80 80 80
22 00 02 00 04 80 80 80 14 40 15 00 00 00 00 00
00 00 00 00 00 00 05 80 80 80 02 12 10 06 80 80
80 01 02

ffmpeg:

00 00 00 2c 65 73 64 73 00 00 00 00 03 80 80 80
1b 00 02 00 04 80 80 80 0d 40 15 00 00 00 00 01
5f 42 00 00 00 00 06 80 80 80 01 02

奇怪的是,我之前没有注意到这一点,Firefox 将使用 ffmpeg 的输出播放视频,但 Firefox 和 Windows Media 都不会真正播放声音(Chrome 会)。不过,Firefox 和 Windows Media 都乐于使用 mpegts 的输出来播放有声视频。使用我的,Chrome 和 Windows Media 将播放有声视频,但 Firefox 根本不播放,并声称视频已损坏。

4

4 回答 4

2

好吧,我找到了我自己问题的答案。在思考我的 ESDS 盒与其他软件生成的 ESDS 盒之间的差异后,很明显,最大的差异是这些 0x80 填充字节的存在——每个 ES Descriptor 标记号之后的三个填充字节。把它们加进去,大多数其他东西都排成一行,看起来几乎一样。

我在 MP4 文件或 ISOBMFF 的 MPEG 规范中没有提到为什么这些字节应该存在,但是添加它们可以使它工作 - Firefox 不再认为文件已损坏。

于 2015-06-24T04:14:42.530 回答
2

您现在通过在 ES Descriptor Tag 编号后添加三个字节的 0x80找到了您的解决方案。很高兴这适用于所有浏览器。

让我分享一个可以帮助您或您的代码的未来用户的见解:

“..我在 MP4 文件或 ISOBMFF 的 MPEG 规范中没有提到为什么这些字节应该在那里,但是添加它们使它工作..”

看看这个mp4ESDSbox.java的链接,我们看到 ESDS atom 被分成五个部分,每个部分都用字节填充80 80 80。这三个字节被描述为“可选的扩展描述符类型标记字符串”,可能的类型值为.. 8081FE

您走在正确的道路上,但您只填充了第一部分。

MP4Muxer.js: (A) 你目前拥有的...

00 00 00 27 65 73 64 73 00 00 00 00 03 80 80 80
22 00 00 02 04 14 40 15 00 00 00 00 00 3A F1 00
00 2D E6 05 02 12 10 06 01 02

MP4Muxer.js: (B) 它应该是什么...

00 00 00 3365 73 64 73 00 00 00 00 03 80 80 80
22 00 00 02 04 80 80 80 14 40 15 00 00 00 00 00
3A F1 00 00 2D E6 05 80 80 80 02
12
0 10 06 02 8比较

FFMpeg ESDS for random AAC track新 (B) 版本

00 00 00 33 65 73 64 73 00 00 00 00 03 80 80 80
22 00 01 00 04 80 80 80 14 40 15 00 00 00 00 01
F4 74 00 01 F4 74 05 1 20 100 8 06 80 80 80 01 02


将版本 B) 的字节结构与 FFMpeg 的字节结构进行比较,我们现在看到完美对齐。有些值略有不同,因为它们不是由相同的音频数据制成的。

请注意,我们已将前四个字节(大小整数)从原来的(十进制 == 39 字节长度)更改为x33(十进制 == 51 字节长度)x27

于 2015-06-28T16:51:54.850 回答
2

0x80 字节不属于它之前的标签,而是属于它之后的长度值。ISO 规范的第 2 版更改了长度值的解释,因此它可以通过将其设为“VarInt32”类型来包装超过 255 个字节。每个字节中的高位表示后面有另一个长度字节,低 7 位编码该值。

您可以使用它来编码任意大值,但 ISO 规范将其限制为最多 4 个字节,或 0...2^(4*7)-1。

IE:

0x80,0x80,0x80,0x0E = 0x80,0x0E = 0x0E => 14
0x80,0x80,0x84,0x7f = 0x84,0x7f => 0x4 << 7 + 0x7f = 0x27f = 639

例如,Google 的 protobuf 使用相同的编码,命名为 Base128 Varint。

于 2020-04-04T14:49:15.560 回答
1

对于希望参考 ISO 14496-1 规范相关部分的人:

  • 第 8.6.5 节指定了ES_Descriptor类的格式,它继承自BaseDescriptor.
  • 第 8.2.2 节定义BaseDescriptor为可扩展类:
abstract aligned(8) expandable(2^28 - 1) class BaseDescriptor : bit(8) tag=0
{
    // empty. To be filled by classes extending this class.
}
  • 第 14.3.3 节描述了具有以下长度编码的可扩展类:
int sizeOfInstance = 0;
bit(1) nextByte;
bit(7) sizeOfInstance;
while (nextByte)
{
    bit(1) nextByte;
    bit(7) sizeByte;
    sizeOfInstance = sizeOfInstance << 7 | sizeByte;
}

从这个定义可以看出,a 的最大可扩展大小BaseDescriptor可以sizeOfInstance被编码为最多 4 个字节。当使用的字节数超过严格要求时,大小确实似乎以0x80字节为前缀。

于 2021-12-02T10:24:46.633 回答