MP4格式
文章目录mp4简介核心概念MP4结构Box HeaderBox bodyftypmoovmdatTrack / chunk /samplemp4简介MP4也称 MPEG-4 Part 14是一种标准的数字多媒体容器格式扩展名通常为 .mp4。但第三方也常用其他扩展名来区分内容类型如 .m4a 表示音频文件。.mp4通常用于包含视频和音频的 MPEG-4 容器文件也可以只包含视频或只包含音频但最常见是音视频都有。.m4a通常用于只包含音频的 MPEG-4 容器文件.m4v有时用于视频文件尤其是 Apple/iTunes 生态里。.m4b常用于有声书、播客支持章节和书签。MP4 是一个“容器”里面可以放很多种数据比如视频、音频、字幕、章节、封面、元数据等。这些数据通常不是混在一起乱放而是按不同的“轨道”或“数据流”分别保存。比如一个 MP4 文件里可能有一个视频轨道保存画面比如 H.264 视频一个音频轨道保存声音比如 AAC 音频一个字幕轨道保存字幕一个元数据轨道保存标题、封面、时长等信息编解码器或数据流格式”指的是这些轨道里的数据具体用什么格式保存。比如视频可以用 H.264音频可以用 AAC核心概念要理解 MP4 文件格式先要理解几个核心概念Box、Track、Sample 和 Chunk。它们决定了 MP4 文件如何组织、索引和读取音视频数据。Box是 MP4 文件的基本结构单位可以理解为一个“数据盒子”。每个 Box 通常由头部和数据两部分组成头部说明这个 Box 的类型和大小数据部分存放具体内容。Box 里可以存放媒体数据、元数据也可以继续包含其他 Box。能包含其他 Box 的 Box 通常称为 Container Box。Track是一组 Sample 的集合表示一条独立的媒体轨道。比如视频轨道是一组视频 Sample音频轨道是一组音频 Sample字幕轨道是一组字幕 Sample。一个 MP4 文件通常可以包含多个 Track例如一个视频 Track、一个音频 Track 和一个字幕 Track。简单来说Track 就是电影中可以独立操作的媒体单位。Chunk是 Track 中若干个连续 Sample 在文件中的存储单元。一个 Chunk 里包含一组连续存放的 Sample并且每个 Chunk 在文件中都有自己的偏移位置。播放器可以根据这些偏移信息快速找到并读取对应的数据。Sample是媒体数据的基本单位。对于视频来说一个 Sample 通常可以理解为一帧画面对于音频来说一个 Sample 通常是一小段连续的音频数据。也就是说真正的音视频内容最终是由一个个 Sample 组成的。简单关系可以理解为Track └─ 描述一组 Sample 的时间、大小、位置等信息 Chunk └─ 文件中连续存放的一组 Sample Sample └─ 最小媒体数据单位比如一帧视频或一段音频 MP4 文件 ├─ Box组织文件结构和信息 ├─ Track一条媒体轨道如视频轨、音频轨 │ ├─ Chunk一组连续存储的 Sample │ │ ├─ Sample一帧视频或一小段音频MP4 用 Box 管理整体结构用 Track 区分不同媒体类型用 Chunk 提高存储和读取效率用 Sample 表示最基本的媒体数据单位。MP4这种封装格式才容易实现灵活、高效、开放的特性MP4结构MP4格式是一个box的格式box容器套box子容器box子容器再套box子容器。[container box]-------------------------------------------------|header|body|-------------------------------------------------|box1|box2|...|boxN|[box header 基础字段]---------------------------------------------------|size|type|largesize*|version|flags||4B|4B|8B(size1时有)|1B|3B|---------------------------------------------------*Full box:在基础 header 后再带 versionflags每个 Box 一般由两部分组成Box ├─ Box Header 说明这个盒子是什么、有多大 └─ Box Body 这个盒子真正存放的内容Box HeaderBox Header 就是每个 MP4 Box 开头的一小段信息用来告诉解析器这个 Box 是什么类型有多大该怎么往后读最基本的 Box Header 只有两个字段--------------------------------|size(4bytes)|type(4bytes)|--------------------------------含义size这个 Box 的总大小包含 header bodytype这个 Box 的类型比如 ftyp、moov、mdat (后面会说)还有一些特殊情况------------------------------------------------|size(4bytes)|type(4bytes)|largesize(8B)|------------------------------------------------如果 size 1说明真实大小太大用后面的 largesize 表示如果 size 0说明这个 Box 一直延伸到文件末尾如果 type ‘uuid’后面还会有 usertype 字段长度 16 字节除了上面这些基础字段外MP4 中还有一类更特殊的 Box叫做 Full Box。Box只有基础头部主要描述大小和类型。Full Box在基础头部后多了 version flags用于表示版本和附加标志。Full Box ├─ size ├─ type ├─ version 版本号 ├─ flags 标识 └─ body-----------------------------------------------------|size(4bytes)|type(4bytes)|version(1bytes)|flags(3bytes)|-----------------------------------------------------其中version表示该 Box 使用的结构版本不同版本下字段长度或含义可能不同flags表示一些控制标志用来描述该 Box 的额外属性或行为某个 box 是普通 Box 还是 Full Box取决于它的 box type。ftyp-普通 Box moov-普通 Box/container box mdat-普通 Box mvhd-Full Box tkhd-Full Box mdhd-Full Box hdlr-Full Box stsd-Full Box stts-Full Box stsc-Full Box stsz-Full Box stco-Full BoxBox bodyBox Body 就是 Box Header 后面的内容区也叫 payload。它里面具体放什么取决于这个 box type。MP4 文件本身不是一个 Box它只是一个按顺序存放多个 top-level box 的字节流。因此 ftyp、moov、mdat 是直接位于文件层的顶层 Box而不是某个“MP4 Box Body”里的子 Box。MP4 里常见的几个顶层 Box就是 直接位于 MP4 文件最外层的 Box不嵌套在别的 Box 里面。 cpp MP4 文件 -------------------------------------------------- | ftyp | moov | mdat | -------------------------------------------------- | | | | | -- 正文内容真实音视频数据 | --------- 目录说明时长、轨道、索引、编码等 ---------------- 文件身份证类型与兼容性 再看一个稍微展开的图 [ftyp] File Type Box - major_brand / compatible_brands - 告诉播放器我是什么格式、你能不能兼容我 [moov] Movie Box - mvhd整体时长/时间基 - trak视频轨、音频轨、字幕轨等 - stblsample/chunk/offset 等索引表 - 告诉播放器媒体怎么组织、去哪里找数据 [mdat] Media Data Box - 真正的媒体码流数据H.264/H.265/AAC... - 告诉播放器内容本体在这里ftyp我是谁moov怎么读mdat读什么整体结构MP4 文件File Level不是 box ┌──────────────────────────────────────────────────────────────────────────────────────────────┐ │ MP4 FILE │ │ │ │ Top-level Box #1│ │ ┌────────────────────────────────────────────────────────────────────────────────────────┐ │ │ │ ftyp box │ │ │ │ ┌───────────────────────────────┬──────────────────────────────────────────────────┐ │ │ │ │ │ Box Header │ Box Body │ │ │ │ │ │-size │-major_brand │ │ │ │ │ │-typeftyp│-minor_version │ │ │ │ │ │-[largesizeifsize1]│-compatible_brands[]│ │ │ │ │ └───────────────────────────────┴──────────────────────────────────────────────────┘ │ │ │ └────────────────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ Top-level Box #2│ │ ┌────────────────────────────────────────────────────────────────────────────────────────┐ │ │ │ moovbox(container box)│ │ │ │ ┌───────────────────────────────┬──────────────────────────────────────────────────┐ │ │ │ │ │ Box Header │ Box Body子 box 集合 │ │ │ │ │ │-size │ │ │ │ │ │ │-typemoov│ ┌────────────────────────────────────────────┐ │ │ │ │ │ │-[largesizeifsize1]│ │ mvhd box通常 Full Box │ │ │ │ │ │ │ │ │-header:size,type,version,flags │ │ │ │ │ │ │ │ │-body:timescale,duration,...│ │ │ │ │ │ │ │ └────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ │ │ │ │ │ trakbox(video)│ │ │ │ │ │ │ │ │ ├─ tkhd │ │ │ │ │ │ │ │ │ └─mdia(container)│ │ │ │ │ │ │ │ │ ├─ mdhd │ │ │ │ │ │ │ │ │ ├─ hdlr │ │ │ │ │ │ │ │ │ └─minf(container)│ │ │ │ │ │ │ │ │ └─stbl(container)│ │ │ │ │ │ │ │ │ ├─ stsd │ │ │ │ │ │ │ │ │ ├─ stts │ │ │ │ │ │ │ │ │ ├─ stsc │ │ │ │ │ │ │ │ │ ├─ stsz │ │ │ │ │ │ │ │ │ └─ stco/co64 │ │ │ │ │ │ │ │ └────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ │ │ │ │ │ trakbox(audio)结构类似 │ │ │ │ │ │ │ │ └────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ │ │ │ │ │[udta/meta 等可选 box]│ │ │ │ │ │ │ │ └────────────────────────────────────────────┘ │ │ │ │ │ └───────────────────────────────┴──────────────────────────────────────────────────┘ │ │ │ └────────────────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ Top-level Box #3│ │ ┌────────────────────────────────────────────────────────────────────────────────────────┐ │ │ │ mdat box │ │ │ │ ┌───────────────────────────────┬──────────────────────────────────────────────────┐ │ │ │ │ │ Box Header │ Box Body │ │ │ │ │ │-size │-mediabytes(video/audio bitstream)│ │ │ │ │ │-typemdat│ │ │ │ │ │ │-[largesizeifsize1]│ │ │ │ │ │ └───────────────────────────────┴──────────────────────────────────────────────────┘ │ │ │ └────────────────────────────────────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────────────────────────┘Box Body 可以继续嵌套 Box但并不是所有 Box 都这样。只有 container box 的 body 才主要用于存放子 Box例如 moov、trak、mdia、minf、stbl 等。一个可正常播放的 MP4 文件通常只依赖少数关键 Box。最核心的就是顶层 Boxftypftyp 一般出现在文件的开头用来指示该 mp4 文件使用的标准规范告诉播放器该文件属于哪种 MP4 格式。moovmoov是一个container box一个文件只有一个其包含的所有box用于描述媒体信息metadata。moov的位置可以紧随着 ftyp 出现也可以出现在文件末尾。由于是一个 container box所以除了 box header其 box body 就是其它的 box。子Boxmvhd(moov header)用于简单描述一些所有媒体共享的信息。trak即 track轨道用于描述音频流或视频流信息可以有多个轨道如上出现了 2 次分别表示一路音频和一路视频流。udta(user data)用户自定义可忽略。mdatmdat可以理解为 MP4 文件里真正存放“内容”的地方。前面说的moov更像目录和说明书告诉播放器视频有几轨、时长是多少、每一帧在哪里、每一帧多大、用什么编码。而mdat里面放的就是实际的音视频数据也就是编码之后的二进制数据。比如视频可能是 H.264/H.265 编码后的数据音频可能是 AAC 编码后的数据。需要注意的是mdat本身也是一个普通 box所以它也有box header说明这是一个mdatbox以及它的大小box body真正的媒体数据内容mdat是 MP4 里真正存放编码后音视频数据的 box但它自己不负责解释这些数据播放器要靠moov里的索引信息找到并解析mdat中的 sample。在 mdat 的 body 中媒体数据通常是按一个个 sample 存放的对视频来说一个 sample 通常可以理解为一帧视频数据。对音频来说一个 sample 通常可以理解为一小段音频帧数据。Track / chunk /sampleMP4 ├─ moov │ └─trak(Track轨道说明)│ └─stbl(Sample Table样本索引表)│ ├─ stts sample 时间信息 │ ├─ stsz sample 大小信息 │ ├─ stsc sample 属于哪个 chunk │ └─ stco chunk 在 mdat 中的偏移位置 │ └─ mdat ├─ chunk1│ ├─ sample1│ ├─ sample2│ └─ sample3│ ├─ chunk2│ ├─ sample4│ ├─ sample5│ └─ sample6│ └─ chunk3├─ sample7├─ sample8└─ sample9Track 描述 SampleChunk 存放一组连续 SampleSample 是媒体数据单位Track 是逻辑轨道和索引信息Chunk 是文件里的连续数据块Sample 才是真正的媒体数据单位。Track/trak 不是直接装 sample 数据 它负责记录 sample 的说明和索引 │ ▼ mdat 里才是真正的数据 chunk1-sample1,sample2,sample3chunk2-sample4,sample5,sample6Track 在 moov/trak 里描述一条媒体轨道真实的 sample 数据在 mdat 里chunk 是多个连续 sample 在文件中的存放分组。

相关新闻