3

我编写了一个 MP4 解析器,它可以很好地读取 MP4 中的原子,并将它们缝合在一起 - 结果是 Quicktime 可以打开的技术上有效的 MP4 文件等,但它不能播放任何音频,因为我相信定时/采样信息全部关闭。我可能应该提到我只对音频感兴趣。

我正在做的是尝试从现有的 MP4 中获取 moov 原子/等,然后只获取文件中 mdat 原子的一个子集来创建一个新的、更小的 MP4。在这样做的过程中,我改变了duration原子中的mvhd,以及mdia标题中的持续时间。这个文件中没有tkhd原子可以编辑,所以我相信我不需要改变那里的持续时间 - 我错过了什么?

在创建新的 MP4 时,我mdat用一个宽框正确地分割了块,并将“mdat”标题/大小保持在正确的位置——我确保使用新内容更新大小。

现在完全有 110% 的可能我遗漏了一些关于格式的重要内容,但如果可能的话,我很想得到最后一块。有人有任何意见/想法吗?

代码可以在以下链接中找到:

https://gist.github.com/ryanmcgrath/958c602cff133bd7fa0b

4

1 回答 1

35

我将在这里暗中刺伤,并说您没有stbl正确更新偏移量。至少我没有(乍一看)看到你的蟒蛇在任何地方这样做。

STSC

让我们从数据的位置开始。数据包以块的形式写入文件,标题告诉解码器这些块的每个“块”存在于何处。该stsc表说明了每个块存在多少个项目。first chunk表示新块从哪里开始。这有点令人困惑,但看看我的例子。这就是说每个块有 100 个样本,直到第 8 个块。第 8 块有 98 个样本。

在此处输入图像描述

STCO

也就是说,您还必须跟踪这些块的偏移量在哪里。这就是stco桌子的工作。因此,文件中的块偏移量 1 或块偏移量 2 等在哪里。

在此处输入图像描述

如果您修改其中的任何数据,mdat则必须维护这些表。您不能只是mdat将数据切掉,然后期望解码器知道该做什么。

好像这还不够,现在您还必须维护样本时间表 ( stts) 样本大小表 ( stsz),如果这是视频,则还必须维护同步样本表 ( stss)。

STTS

stts表示样本应该以时间尺度为单位播放多长时间。如果您正在制作音频,则时间刻度可能是 44100 或 48000 (kHz)。

在此处输入图像描述

如果您删除了一些数据,那么现在一切都可能不同步。如果这里的所有值都具有完全相同的持续时间,但你会没事的。

STSZ

stsz表示每个样本的大小(以字节为单位)。这对于解码器能够从一个块开始,然后按其大小遍历每个样本很重要。

在此处输入图像描述

同样,如果所有样本大小都完全相同,那么您就可以了。音频往往几乎相同,但视频内容差异很大(关键帧之类的)

STSS

最后但并非最不重要的一点是,我们有stss一张表格,其中说明了哪些帧是关键帧。我只有 AAC 的经验,但每个音频帧都被认为是一个关键帧。在这种情况下,您可以拥有一个描述所有数据包的条目。

在此处输入图像描述


关于您最初的问题,每个玩家的时间显示并不总是以相同的方式得到尊重。最准确的方法是将标头中所有帧的持续时间相加,并将其用作总时间。其他播放器使用曲目标题中的元数据。我发现最好保持所有值相同,然后玩家就会开心。

如果您正在做所有这些并且我在脚本中错过了它,那么您可以发布一个示例 mp4 和一个独立的应用程序,我可以尝试帮助您。

于 2013-08-31T21:06:32.827 回答