MP4封装解析

前言

MP4封装格式比较常见,但是有些会有问题,下面解析一下具体信息

正文

工具

比较好的是mp4在线工具

MP4主要结构
MP4主要结构类似于树状图。每个节点开头都有8位,前四位记录大小,后四位标记节点类型。根节点一般包含四个字节点(ftyp,free,mdat,moov)。

  • ftyp(File Type Box)一般在文件的开始位置,描述的文件的版本、兼容协议等。
  • mdat 多媒体的存储位置
  • free预留位置,没用
  • moov 关键信息,记录多媒体轨道和索引信息

moov关键的是track。track节点中包含了tkhd,记录track信息。供播放器显示多媒体信息。media记录关键索引信息,解码器搜寻sample位置。
meida中的mdhd记录识别的总时长,以及时间粒度。供后边分析pts和cts等操作。minf节点中的stbl才是真的记录采样点的位置信息。以及计算方法。
这里有个比较重要的概念。chunk。他是一些编码后的数据,成为一簇。方便管理以及避免错误的干扰
下面解析一个750s的视频,有130个chunk。45008帧数据,

stsd

描述,不重要,

stts

描述数据帧的时间间隔。因为间隔大部分一样,所以是统计信息,

相同时间间隔个数 时间间隔(单位是moov-trak-media-mdhd-timescale的信息)

比如一个典型的数据是:

entry_count 1
samples {“sample_count”:45008,“sample_delta”:1001}

显示当前轨道,所有帧时长是一样的。都是16.683毫秒,帧率是59.94005994005994

而timescale是1/60000.所以总时长是 45008 * 1001 /timescale(60000) = 750.8834 秒。时长应该是 750秒。130个chunk。

stss

entry_count 130
sync_samples.0 1
sync_samples.1 207
sync_samples.2 397
sync_samples.3 713
sync_samples.4 939
sync_samples.5 1139
sync_samples.6 1437

用来记录关键帧。方便快速seek

ctts用来记录视频帧和显示时间的间隔。主要是解决视频向后参考关键帧。音频一般情况下只有一条,

entry_count 2
samples.0 {“sample_count”:1,“composition_offset”:1001}
samples.1 {“sample_count”:32339,“composition_offset”:0}

视频比较复杂:
如下

entry_count 36456
samples.0 {“sample_count”:1,“composition_offset”:1001}
samples.1 {“sample_count”:1,“composition_offset”:3003}
samples.2 {“sample_count”:2,“composition_offset”:0}
samples.3 {“sample_count”:3,“composition_offset”:1001}
samples.4 {“sample_count”:1,“composition_offset”:2002}
samples.5 {“sample_count”:1,“composition_offset”:0}
samples.6 {“sample_count”:1,“composition_offset”:1001}
samples.7 {“sample_count”:1,“composition_offset”:2002}
samples.8 {“sample_count”:1,“composition_offset”:0}
samples.9 {“sample_count”:4,“composition_offset”:1001}
samples.10 {“sample_count”:1,“composition_offset”:2002}

这个sample顺序cts是根据stts来计算的,根据之前分析,则sample则根据顺序排列

index cts dts

1 0 1001
2 1001 4004
3 2002 2002
4 3003 3003
5 4004 5005
6 5005 6006
7 6006 7007
8 7007 9009
9 8008 8008
10 9009 10010
11 10010 12012
13 11011 11011
14 12012 13013

比较明显,第二帧数据,应该在第四个时刻显示,但是第三,和第四帧解码需要第二帧,所以先解码第二帧,根据pts修正显示时刻。

stsc

sample-chunk映射表。

entry_count 61
chunks.0 {“first_chunk”:1,“samples_per_chunk”:206,“sample_description_index”:1}
chunks.1 {“first_chunk”:2,“samples_per_chunk”:190,“sample_description_index”:1}
chunks.2 {“first_chunk”:3,“samples_per_chunk”:316,“sample_description_index”:1}
chunks.59 {“first_chunk”:62,“samples_per_chunk”:420,“sample_description_index”:1}
chunks.60 {“first_chunk”:130,“samples_per_chunk”:458,“sample_description_index”:1}

这是记录chunk 一共130个。每个chunk可能有不同的sample。比如第一个有206 62到 130 的chunk每个里面有458个。

stsz

每个sample的字节大小

sample_count 45008
sample_size.0 513
sample_size.1 270
sample_size.2 85
sample_size.3 89
sample_size.4 1258
sample_size.5 1581

stco

每个chunk在文件中的偏移

entry_count 130
chunk_offset.0 48
chunk_offset.1 1011504
chunk_offset.2 3302476
chunk_offset.129 213665857

这些用来记录关键的chunk的位置,具体每个sample参考sample具体的位置

后记

MP4的解析基本完成。原理还是比较 简单,以后如果写完解码器,自己就手写一个解封装模块,实现必要的功能

你可能感兴趣的:(音视频)