MP4标准详解

前言

视频文件的本质:用二进制记录编码后的视频帧并能被播放器还原解码播放

视频文件的关键:高效率记录信息、兼容性

MP4简介

首先,介绍下封装格式。多媒体封装格式(也叫容器格式),是指按照一定的规则,将视频数据、音频数据等,放到一个文件中。常见的 MKV、AVI 以及本文介绍的 MP4 等,都是封装格式。

MP4是最常见的封装格式之一,因为其跨平台的特性而得到广泛应用。MP4文件的后缀为.mp4,基本上主流的播放器、浏览器都支持MP4格式。

MP4文件的格式主要由 MPEG-4 Part 12、MPEG-4 Part 14 两部分进行定义。其中,MPEG-4 Part 12 定义了ISO基础媒体文件格式,用来存储基于时间的媒体内容。MPEG-4 Part 14 实际定义了MP4文件格式,在MPEG-4 Part 12的基础上进行扩展。

MP4封装格式是基于QuickTime容器格式(苹果早期框架)定义,媒体描述与媒体数据分开,并且媒体数据的组织也很自由,不一定要按照时间顺序排列,甚至媒体数据可以直接引用其他文件(通过URL访问)。同时,MP4也支持流媒体(边下边播)。

由于MP4非常开放,标准定义不是很死板,但是兼容性可能会出现一些问题,比如有的播放器没法播放一部分MP4.
视频的播放时按时间顺序的,但MP4中媒体数据的组织不一定按时间顺序排列。于是就能了解到,在解码播放MP4的时候,肯定时有一个缓冲的,不是解一帧播放一帧,当前解码的帧不一定是上一帧的后面一帧。这就是播放器耗内存的原因,边下边播的缓冲随机分布也是这个原因。

目前被广泛应用于封装h.264视频和ACC音频,是高清视频/HDV的代表。

标准下载:https://standards.iso.org/ittf/PubliclyAvailableStandards/index.html

几个概念

名词含义
track一些sample的集合,对于媒体数据来说,track表示一个视频或者音频的序列
hint track这个特殊的track并不包含媒体数据,而是包含了一些将其他数据track打包成流媒体的指示信息
sample对于非hint track来说,video sample即为一帧视频,或一组连续视频帧,audio sample即为一段连续的压缩音频,它们统称sample。对于hint track,sample定义一个或多个流媒体包的格式
sample table指sample时序和物理布局的表
chunk一个track的几个sample组成的单元

本文不讨论hint的内容,主要关注包含媒体数据的本地MP4文件
下图是一个典型的MP4文件的结构树
在这里插入图片描述

MP4格式概览

box是MP4中的最小单位,打包和解包也是以box为单位进行解析的
不同种类的box存储不同的信息,且box之间是树状结构
box采用网络字节序,即大端字节序

简单的说,就是一个32位的4字节整数存储方式为高位字节在内存的低端。
在这里插入图片描述

BOX简介

Box由header和body组成,其中header统一指明box的大小和类型,body根据类型有不同的意义和格式。

标准的box开头的4个字节(32位)为box size,该大小包括box header和box body整个box的大小,这样我们就可以在文件中定位各个box。

  • 如果size为1,则表示这个box的大小为large size,真正的size值要在largesize域上得到。
    (实际上只有“mdat”类型的box才有可能用到large size。)
  • 如果size为0,表示该box为文件的最后一个box,文件结尾即为该box结尾。
    (同样只存在于“mdat”类型的box中。)

size后面紧跟的32位为box type,一般是4个字符,如“ftyp”、“moov”等,这些box type都是已经预定义好的,分别表示固定的意义。如果是“uuid”,表示该box为用户扩展类型。如果box type是未定义的,应该将其忽略。

BOX结构详解

1个box由两部分组成:box header、box body。

  • box header:box的元数据,比如box type、box size。
  • box body:box的数据部分,实际存储的内容跟box类型有关,比如mdat中body部分存储的媒体数据。

box header中,只有type、size是必选字段。当size==0时,存在largesize字段。

  • 在部分box中,还存在version、flags字段,这样的box叫做Full Box
  • 当box body中嵌套其他box时,这样的box叫做container box

在这里插入图片描述

Box Header

字段定义如下:

  • type:box类型,包括 “预定义类型”、“自定义扩展类型”,占4个字节;
    • 预定义类型:比如ftyp、moov、mdat等预定义好的类型;
    • 自定义扩展类型:如果type==uuid,则表示是自定义扩展类型。size(或largesize)随后的16字节,为自定义类型的值(extended_type)
  • size:包含box header在内的整个box的大小,单位是字节。当size为0或1时,需要特殊处理:
    • size等于0:box的大小由后续的largesize确定(一般只有装载媒体数据的mdat box会用到largesize);
    • size等于1:当前box为文件的最后一个box,通常包含在mdat box中;
  • largesize:box的大小,占8个字节;
  • extended_type:自定义扩展类型,占16个字节;

Box Body

box数据体,不同box包含的内容不同,需要参考具体box的定义。

  • 有的 box body 很简单,比如 ftyp。
  • 有的 box 比较复杂,可能嵌套了其他box,比如moov。

Box vs FullBox

在Box的基础上,扩展出了FullBox类型。相比Box,FullBox 多了 version、flags 字段。

  • version:当前box的版本,为扩展做准备,占1个字节;
  • flags:标志位,占24位,含义由具体的box自己定义;

FullBox主要在moov中的box用到,比如 moov.mvhd,后面会介绍到

常用BOX详解

首先科普isom

isom(ISO Base Media file)是在 MPEG-4 Part 12 中定义的一种基础文件格式,MP4、3gp、QT 等常见的封装格式,都是基于这种基础文件格式衍生的。

MP4 文件可能遵循的规范有mp41、mp42,而mp41、mp42又是基于isom衍生出来的。

3gp(3GPP):一种容器格式,主要用于3G手机上; QT:QuickTime的缩写,.qt 文件代表苹果QuickTime媒体文件;

在这里插入图片描述

关于AVC/AVC1
在讨论 MP4 规范时,提到AVC,有的时候指的是“AVC文件格式”,有的时候指的是"AVC压缩标准(H.264)",这里简单做下区分。

  • AVC文件格式:基于 ISO基础文件格式 衍生的,使用的是AVC压缩标准,可以认为是MP4的扩展格式,对应的brand 通常是 avc1,在MPEG-4 PART 15 中定义。
  • AVC压缩标准(H.264):在MPEG-4 Part 10中定义。
  • ISO基础文件格式(Base Media File Format) 在 MPEG-4 Part 12 中定义。

File Type Box(ftyp)

该Box有且只有1个,并且只能被包含在文件层,而不能被其他Box包含。该Box应该被放在文件的最开始,指示该MP4文件应用的相关信息

“ftyp” body依次包括1个32位的major brand(4个字符),1个32位的minor version(整数)和1个以32位(4个字符)为单位元素的数组Compatible Brands。

aligned(8) class FileTypeBox extends Box(‘ftyp’) {  
  unsigned int(32) major_brand;  
  unsigned int(32) minor_version;  
  unsigned int(32) compatible_brands[]; // to end of the box  
} 

下面是是 brand 的描述,其实就是具体封装格式对应的代码,用4个字节的编码来表示,比如 mp41。

A brand is a four-letter code representing a format or subformat. Each file has a major brand (or primary brand), and also a compatibility list of brands.

ftyp 的几个字段的含义:

  • major_brand:比如常见的 isom、mp41、mp42、avc1、qt等。它表示“最好”基于哪种格式来解析当前的文件。
    举例,major_brand 是 A,compatible_brands 是 A1,当解码器同时支持 A、A1 规范时,最好使用A规范来解码当前媒体文件,如果不支持A规范,但支持A1规范,那么,可以使用A1规范来解码;
  • minor_version:提供 major_brand 的说明信息,比如版本号,不得用来判断媒体文件是否符合某个标准/规范;
  • compatible_brands:文件兼容的brand列表。比如 mp41 的兼容 brand 为 isom。通过兼容列表里的 brand 规范,可以将文件 部分(或全部)解码出来;

在实际使用中,不能把 isom 做为 major_brand,而是需要使用具体的brand(比如mp41),因此,对于 isom,没有定义具体的文件扩展名、mime type。

下面列出常见的brand,以及对应的文件扩展名、mime type。更多的brand参考

BrandExtensionMime Type
MP4mp41、mp42.mp4video/mp4,audio/mp4,application/mp4
3GPPvarious,e.g,3gp4,3gp5.3gpvideo/3gpp,audio/3gpp
3GPP23g2a.3g2video/3gpp2,audio/3gpp2
Motion JPEG 2000mjp2.mjp2video/mh2
uickTime“qt”.movvideo/quicktime

moov(Movie Box)

Movie Box,存储 mp4 的 metadata,一般位于mp4文件的开头。
该box包含了文件媒体的metadata信息,“moov”是一个container box,具体内容信息由子box诠释。同File Type Box一样,该box有且只有一个,且只被包含在文件层。一般情况下,“moov”会紧随“ftyp”出现。

moov定义了一个MP4文件中的数据信息,类型是moov,是一个容器Atom,其至少必须包含一下三种Atom中的一种:mvhd标签、cmov标签、rmra标签。

  • mvhd标签:Movie Header Atom,存放未压缩过的影片信息的头容器。
  • cmov标签:Compressed Movie Atom,压缩过的电影信息容器,此容器不常用。
  • rmra标签:Reference Movie Atom,参考电影信息容器,此容器不常用。

一般情况下,“moov”中会包含1个“mvhd”和若干个“trak”。

  • mvhd:Movie Header Box,mp4文件的整体信息,比如创建时间、文件时长等;
    header box
  • trak:Track Box,一个mp4可以包含一个或多个轨道(比如视频轨道、音频轨道),轨道相关的信息就在trak里
    trak是container box,至少包含两个box,tkhd、mdia;

mvhd(Movie Header Box)

MP4文件的整体信息,跟具体的视频流、音频流无关,比如创建时间、文件时长等。
定义如下

aligned(8) class MovieHeaderBox extends FullBox(‘mvhd’, version, 0) { if (version==1) {
      unsigned int(64)  creation_time;
      unsigned int(64)  modification_time;
      unsigned int(32)  timescale;
      unsigned int(64)  duration;
   } else { // version==0
      unsigned int(32)  creation_time;
      unsigned int(32)  modification_time;
      unsigned int(32)  timescale;
      unsigned int(32)  duration;
}
template int(32) rate = 0x00010000; // typically 1.0
template int(16) volume = 0x0100; // typically, full volume const bit(16) reserved = 0;
const unsigned int(32)[2] reserved = 0;
template int(32)[9] matrix =
{ 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 };
      // Unity matrix
   bit(32)[6]  pre_defined = 0;
   unsigned int(32)  next_track_ID;
}

字段含义如下

  • creation_time:文件创建时间;
  • modification_time:文件修改时间;
  • timescale:一秒包含的时间单位(整数)。举个例子,如果timescale等于1000,那么,一秒包含1000个时间单位(后面track等的时间,都要用这个来换算,比如track的duration为10,000,那么,track的实际时长为10,000/1000=10s);
  • duration:影片时长(整数),根据文件中的track的信息推导出来,等于时间最长的track的duration;
  • rate:推荐的播放速率,32位整数,高16位、低16位分别代表整数部分、小数部分([16.16]),举例 0x0001 0000 代表1.0,正常播放速度;
  • volume:播放音量,16位整数,高8位、低8位分别代表整数部分、小数部分([8.8]),举例 0x01 00 表示 1.0,即最大音量;
  • matrix:视频的转换矩阵,一般可以忽略不计;
  • next_track_ID:32位整数,非0,一般可以忽略不计。当要添加一个新的track到这个影片时,可以使用的track id,必须比当前已经使用的track id要大。也就是说,添加新的track时,需要遍历所有track,确认可用的track id;

内存排列如下

字段字节数意义
box size4box大小
box type4box 类型
version1box版本,0或1,一般为0(以下字节数均按version=0)
flags3
creation time4创建时间(相对于UTC时间1904-01-01零点时间的秒数)
modification time4修改时间
time scale4文件媒体在1秒时间内的刻度值,可以理解为1秒长度的时间单元数
duration4track的时间长度
rate4推荐播放速率,高16位和低16位分别为小数点整数部分和小数部分,即[16.16] 格式,该值为1.0(0x00010000)表示正常前向播放
volume2与rate类似,[8.8] 格式,1.0(0x0100)表示最大音量
reserved10保留
matrix36视频变换矩阵
pre-defined24
next track id4下一个track使用的id号

Track Box(trak)

“trak”也是一个container box,其子box包含了该track的媒体数据引用和描述(hint track除外)。一个MP4文件中的媒体可以包含多个track,且至少有一个track,这些track之间彼此独立,有自己的时间和空间信息。“trak”必须包含一个“tkhd”和一个“mdia”,此外还有很多可选的box(略)。
其中“tkhd”为track header box,“mdia”为media box,该box是一个包含一些track媒体数据信息box的container box。

Track Box(tkhd)

定义如下

aligned(8) class TrackHeaderBox 
  extends FullBox(‘tkhd’, version, flags){ 
	if (version==1) {
	      unsigned int(64)  creation_time;
	      unsigned int(64)  modification_time;
	      unsigned int(32)  track_ID;
	      const unsigned int(32)  reserved = 0;
	      unsigned int(64)  duration;
	   } else { // version==0
	      unsigned int(32)  creation_time;
	      unsigned int(32)  modification_time;
	      unsigned int(32)  track_ID;
	      const unsigned int(32)  reserved = 0;
	      unsigned int(32)  duration;
	}
	const unsigned int(32)[2] reserved = 0;
	template int(16) layer = 0;
	template int(16) alternate_group = 0;
	template int(16) volume = {if track_is_audio 0x0100 else 0}; const unsigned int(16) reserved = 0;
	template int(32)[9] matrix= { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 }; // unity matrix
	unsigned int(32) width;
	unsigned int(32) height;
}

字段含义如下

  • version:tkhd box的版本;
  • flags:按位或操作获得,默认值是7(0x000001 | 0x000002 | 0x000004),表示这个track是启用的、用于播放的 且 用于预览的。
  • Track_enabled:值为0x000001,表示这个track是启用的,当值为0x000000,表示这个track没有启用;
  • Track_in_movie:值为0x000002,表示当前track在播放时会用到;
  • Track_in_preview:值为0x000004,表示当前track用于预览模式;
  • creation_time:当前track的创建时间;
  • modification_time:当前track的最近修改时间;
  • track_ID:当前track的唯一标识,不能为0,不能重复;
  • duration:当前track的完整时长(需要除以timescale得到具体秒数);
  • layer:视频轨道的叠加顺序,数字越小越靠近观看者,比如1比2靠上,0比1靠上;
  • alternate_group:当前track的分组ID,alternate_group值相同的track在同一个分组里面。同个分组里的track,同一时间只能有一个track处于播放状态。当alternate_group为0时,表示当前track没有跟其他track处于同个分组。一个分组里面,也可以只有一个track;
  • volume:audio track的音量,介于0.0~1.0之间;
  • matrix:视频的变换矩阵;
  • width、height:视频的宽高;

内存排列如下

字段字节数意义
box size4box大小
box type4box 类型
version1box版本,0或1,一般为0(以下字节数均按version=0)
flags3按位或操作结果值,预定义如下:0x000001 track_enabled,否则该track不被播放;0x000002 track_in_movie,表示该track在播放中被引用;0x000004 track_in_preview,表示该track在预览时被引用。一般该值为7,如果一个媒体所有track均未设置track_in_movie和track_in_preview,将被理解为所有track均设置了这两项;对于hint track,该值为0
creation time4创建时间(相对于UTC时间1904-01-01零点时间的秒数)
modification time4修改时间
track id4保留位
reserved4track的时间长度
duration4track的时间长度
reserved8保留位
layer2track分组信息,默认为0表示该track未与其他track有群组关系
alternate group2视频变换矩阵
volume2[8.8] 格式,如果为音频track,1.0(0x0100)表示最大音量;否则为0
reserved2保留位
matrix36视频变换矩阵
width4
height4高,均为 [16.16] 格式值,与sample描述中的实际画面大小比值,用于播放时的展示宽高

Media Box(mdia)

总体来说,“mdia”定义了track媒体类型以及sample数据,描述sample信息。一般“mdia”包含一个“mdhd”,一个“hdlr”和一个“minf”,其中“mdhd”为media header box,“hdlr”为handler reference box,“minf”为media information box。下面依次看一下这几个box的结构。
在这里插入图片描述

Media Header Box(mdhd)

字段字节数意义
box size4box大小
box type4box 类型
version1box版本,0或1,一般为0(以下字节数均按version=0)
flags3
creation time4创建时间(相对于UTC时间1904-01-01零点时间的秒数)
modification time4修改时间
time scale4文件媒体在1秒时间内的刻度值,可以理解为1秒长度的时间单元数
duration4track的时间长度
language2媒体语言码。最高位为0,后面15位为3个字符(见ISO 639-2/T标准中定义)
pre-defined2

hdlr(Handler Reference Box)

“hdlr”解释了媒体的播放过程信息,该box也可以被包含在meta box(meta)中
声明当前track的类型,以及对应的处理器(handler)。

handler_type的取值包括:

  • vide(0x76 69 64 65),video track;
  • soun(0x73 6f 75 6e),audio track;
  • hint(0x68 69 6e 74),hint track;

name为utf8字符串,对handler进行描述,比如 L-SMASH Video Handler(参考 这里)。

字段字节数意义
box size4box大小
box type4box 类型
version1box版本,0或1,一般为0(以下字节数均按version=0)
flags3
pre-defined4
handler type4media box中,该值为4个字符videsounhint
reserved12
name不定track type name,以"\0"结尾的字符串

Media Information Box(minf)

“minf”存储了解释track媒体数据的handler-specific信息,media handler用这些信息将媒体时间映射到媒体数据并进行处理。“minf”中的信息格式和内容与媒体类型以及解释媒体数据的media handler密切相关,其他media handler不知道如何解释这些信息。“minf”是一个container box,其实际内容由子box说明。

一般情况下,“minf”包含一个header box,一个“dinf”和一个“stbl”,其中,header box根据track type(即media handler type)分为“vmhd”、“smhd”、“hmhd”和“nmhd”,“dinf”为data information box,“stbl”为sample table box。下面分别介绍。

Video Media Header Box(vmhd)

字段字节数意义
box size4box大小
box type4box 类型
version1box版本,0或1,一般为0(以下字节数均按version=0)
flags3
graphics mode4视频合成模式,为0时拷贝原始图像,否则与opcolor进行合成
opcolor2x3{red,green,blue}

Sound Media Header Box(smhd)

字段字节数意义
box size4box大小
box type4box 类型
version1box版本,0或1,一般为0(以下字节数均按version=0)
flags3
balance2立体声平衡,[8.8] 格式值,一般为0,-1.0表示全部左声道,1.0表示全部右声道
reserved2

Hint Media Header Box(hmhd)

Null Media Header Box(nmhd)

非视音频媒体使用该box,略。

Data Information Box(dinf)

“dinf”解释如何定位媒体信息,是一个container box。“dinf”一般包含一个“dref”,即data reference box;“dref”下会包含若干个“url”或“urn”,这些box组成一个表,用来定位track数据。简单的说,track可以被分成若干段,每一段都可以根据“url”或“urn”指向的地址来获取数据,sample描述中会用这些片段的序号将这些片段组成一个完整的track。一般情况下,当数据被完全包含在文件中时,“url”或“urn”中的定位字符串是空的。

字段字节数意义
box size4box大小
box type4box 类型
version1box版本,0或1,一般为0(以下字节数均按version=0)
flags3
entry count4“url”或“urn”表的元素个数
“url”或“urn”列表不定

“url”或“urn”都是box,“url”的内容为字符串(location string),“urn”的内容为一对字符串(name string and location string)。当“url”或“urn”的box flag为1时,字符串均为空。

Sample Table Box(stbl)

MP4文件的媒体数据部分在mdat box里,而stbl则包含了这些媒体数据的索引以及时间信息,了解stbl对解码、渲染MP4文件很关键。

在MP4文件中,媒体数据被分成多个chunk,每个chunk可包含多个sample,而sample则由帧组成(通常1个sample对应1个帧)

ample是媒体数据存储的单位,存储在media的chunk中,chunk和sample的长度均可互不相同
在这里插入图片描述

“stbl”包含了关于track中sample所有时间和位置的信息,以及sample的编解码等信息。利用这个表,可以解释sample的时序、类型、大小以及在各自存储容器中的位置。“stbl”是一个container box,其子box包括:

  • sample description box(stsd)
    给出视频、音频的编码、宽高、音量等信息,以及每个sample中包含多少个frame
  • time to sample box(stts)
    每个sample的时长
  • sample size box(stsz或stz2)
    每个sample的size(单位是字节)
  • sample to chunk box(stsc)
    每个thunk中包含几个sample
  • chunk offset box(stco或co64)
    thunk在文件中的偏移
  • composition time to sample box(ctts)
    帧解码到渲染的时间差值,通常用在B帧的场景
  • sync sample box(stss)
    哪些sample是关键帧
  • 等等

“stsd”必不可少,且至少包含一个条目,该box包含了data reference box进行sample数据检索的信息。没有“stsd”就无法计算media sample的存储位置。“stsd”包含了编码的信息,其存储的信息随媒体类型不同而不同。

Sample Description Box(stsd)

box header和version字段后会有一个entry count字段,根据entry的个数,每个entry会有type信息,如“vide”、“sund”等,根据type不同sample description会提供不同的信息,例如对于video track,会有“VisualSampleEntry”类型信息,对于audio track会有“AudioSampleEntry”类型信息。

视频的编码类型、宽高、长度,音频的声道、采样等信息都会出现在这个box中

在SampleDescriptionBox 中,handler_type 参数 为 track 的类型(soun、vide、hint),entry_count 变量代表当前box中 smaple description 的条目数。

针对不同的handler_type,SampleDescriptionBox 后续应用不同的 SampleEntry 类型,比如video track为VisualSampleEntry。

VisualSampleEntry包含如下字段:

  • data_reference_index:当MP4文件的数据部分,可以被分割成多个片段,每一段对应一个索引,并分别通过URL地址来获取,此时,data_reference_index 指向对应的片段(比较少用到);
  • width、height:视频的宽高,单位是像素;
  • horizresolution、vertresolution:水平、垂直方向的分辨率(像素/英寸),16.16定点数,默认是0x00480000(72dpi);
  • frame_count:一个sample中包含多少个frame,对video track来说,默认是1;
  • compressorname:仅供参考的名字,通常用于展示,占32个字节,比如 AVC Coding。第一个字节,表示这个名字实际要占用N个字节的长度。第2到第N+1个字节,存储这个名字。第N+2到32个字节为填充字节。compressorname 可以设置为0;
  • depth:位图的深度信息,比如 0x0018(24),表示不带alpha通道的图片;

Chunk Offset Box(stco)

chunk在文件中的偏移量。针对小文件、大文件,有两种不同的box类型,分别是stco、co64,它们的结构是一样的,只是字段长度不同。

chunk_offset 指的是在文件本身中的 offset,而不是某个box内部的偏移。

在一个表中只会有一种可能,这个位置是在整个文件中的,而不是在任何box中的,这样做就可以直接在文件中找到媒体数据,而不用解释box。需要注意的是一旦前面的box有了任何改变,这张表都要重新建立,因为位置信息已经改变了。

在构建mp4文件的时候,需要特别注意 moov 所处的位置,它对于chunk_offset 的值是有影响的。有一些MP4文件的 moov 在文件末尾,为了优化首帧速度,需要将 moov 移到文件前面,此时,需要对 chunk_offset 进行改写

在这里插入图片描述

Sample To Chunk Box(stsc)

用chunk组织sample可以方便优化数据获取,一个thunk包含一个或多个sample。“stsc”中用一个表描述了sample与chunk的映射关系,查看这张表就可以找到包含指定sample的thunk,从而找到这个sample。

sample 以 chunk 为单位分成多个组。chunk的size可以是不同的,chunk里面的sample的size也可以是不同的。

  • entry_count:有多少个表项(每个表项,包含first_chunk、samples_per_chunk、sample_description_index信息);
  • first_chunk:当前表项中,对应的第一个chunk的序号;
  • samples_per_chunk:每个chunk包含的sample数;
  • sample_description_index:指向 stsd 中 sample description 的索引值(参考stsd小节);

这么表述有点抽象,这里给出例子
在这里插入图片描述
在这里插入图片描述

Sample Size Box(stsz)

“stsz” 定义了每个sample的大小,包含了媒体中全部sample的数目和一张给出每个sample大小的表。这个box相对来说体积是比较大的。

sample_size 字段,可以知道当前track包含了多少个sample(或帧)。

有两种不同的box类型,stsz、stz2。

stsz:

  • sample_size:默认的sample大小(单位是byte),通常为0。如果sample_size不为0,那么,所有的sample都是同样的大小。如果sample_size为0,那么,sample的大小可能不一样。
  • sample_count:当前track里面的sample数目。如果 sample_size==0,那么,sample_count 等于下面entry的条目;
  • entry_size:单个sample的大小(如果sample_size==0的话);

stz2:

  • field_size:entry表中,每个entry_size占据的位数(bit),可选的值为4、8、16。4比较特殊,当field_size等于4时,一个字节上包含两个entry,高4位为entry[i],低4位为entry[i+1];
  • sample_count:等于下面entry的条目;
  • entry_size:sample的大小。

在这里插入图片描述

Time To Sample Box(stts)

“stts”存储了sample的duration,描述了sample时序的映射方法,我们通过它可以找到任何时间的sample。

stts包含了DTS到sample number的映射表,主要用来推导每个帧的时长。

  • entry_count:stts 中包含的entry条目数;
  • sample_count:单个entry中,具有相同时长(duration 或 sample_delta)的连续sample的个数。
  • sample_delta:sample的时长(以timescale为计量)

举例
在这里插入图片描述
还是看例子,如下图,entry_count为3,前250个sample的时长为1000,第251个sample时长为999,第252~283个sample的时长为1000。

假设timescale为1000,则实际时长需要除以1000。

Sync Sample Box(stss)

mp4文件中,关键帧所在的sample序号。如果没有stss的话,所有的sample中都是关键帧。

  • entry_count:entry的条目数,可以认为是关键帧的数目;
  • sample_number:关键帧对应的sample的序号;(从1开始计算)

举例
在这里插入图片描述

Composition Time to Sample Box(ctts)

从解码(dts)到渲染(pts)之间的差值。

对于只有I帧、P帧的视频来说,解码顺序、渲染顺序是一致的,此时,ctts没必要存在。

对于存在B帧的视频来说,ctts就需要存在了。当PTS、DTS不相等时,就需要ctts了,公式为 CT(n) = DT(n) + CTTS(n) 。

在这里插入图片描述

Free Space Box(free或skip)

“free”中的内容是无关紧要的,可以被忽略。该box被删除后,不会对播放产生任何影响。

Meida Data Box(mdat)

该box包含于文件层,可以有多个,也可以没有(当媒体数据全部为外部文件引用时),用来存储媒体数据。数据直接跟在box type字段后面,具体数据结构的意义需要参考metadata(主要在sample table中描述)。

在MP4格式文件中,H264 slice并不是以00 00 00 01来作分割,而是存储在mdat box中

举例
在这里插入图片描述
接下来的65就是NALU header,可以由65&0x1F来求的后五个bit,从而得知此slice为I frame

拓展

fMP4(Fragmented mp4)
fMP4 跟普通 mp4 基本文件结构是一样的。普通mp4用于点播场景,fmp4通常用于直播场景。

mvex(Movie Extends Box)
当存在mvex时,表示当前文件是fmp4

总结

在这里插入图片描述
下一篇会结合具体MP4文件进行分析

参考
https://www.cnblogs.com/ranson7zop/p/7889272.html
https://www.cnblogs.com/chyingp/p/mp4-file-format.html
https://www.cnblogs.com/skyseraph/archive/2012/04/01/2429384.html

  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Spark!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值