找回密码
 注册
搜索
查看: 1665|回复: 3

mp4 文件解析

[复制链接]
发表于 2008-1-11 16:21:11 | 显示全部楼层 |阅读模式
??前段时间做完mp4文件的分析,写出来大家分享,由于能力有限,错误之处还请指正。本文只对mp4的必要Box进行了分析。

??*.mp4和*.avi一样,并不是一种具体的编码方式,而是一种容器。*.mp4格式遵循ISO-14496-12标准,很多文件类型都是从它派生出来的,例如*.3gp,*.mp4文件等。ISO-14496-12定义数据排列方式为大端。

??ISO-14496-12定义的基本类型结构是Box和FullBox,它的语法结构如下:

??Box:

??{

??/*整个Box的长度,单位byte*/

??unsignedint(32)size;

??/*Box的类型,4个ASCII码组成*/

??unsignedint(32)type;

??if(size==1){

??unsignedint(64)largesize;

??}elseif(size==0){

??//boxextendstoendoffile

??}

??/*box的数据,可以包含其它的box或者FullBox*/

??unsignedint(8)[]data;

??}

??FullBox:

??{

??/*整个FullBox的长度,单位byte*/

??unsignedint(32)size;

??/*FullBox的类型,4个ASCII码组成*/

??unsignedint(32)type;

??if(size==1){

??unsignedint(64)largesize;

??}elseif(size==0){

??//boxextendstoendoffile

??}

??/*一般没什么用,根据具体的FullBox类型确定其意义*/

??unsignedint(8)version;

??/*一般没什么用,根据具体的FullBox类型确定其意义*/

??bit(24)flags;

??/*FullBox的数据,可以包含其它的box或者FullBox*/

??unsignedint(8)[]data;

??}
 楼主| 发表于 2008-1-11 16:26:43 | 显示全部楼层

mp4文件分析续

??一个遵循ISO-14496-12标准的文件就是有各种Box以及FullBox构成,Box(FullBox)之间可以互相包含。各个Box以及FullBox的包含关系入下表:(这里只列出了部分,其它类型的Box或者FullBox,笔者在分析*.mp4文件的时候并没有用到)

??ftyp

??…

??moov

??          mvhd

??          trak

??                     tkhd

??                     tref

??                     edts

??                              elst

??                     mdia

??                              mdhd

??                              hdlr

??                              minf

??                                        vmhd

??                                        smhd

??                                        hmhd

??                                        nmhd

??                                        dinf

??                                                  dref

??                                         stbl

??                                                  stsd

??                                                  stts

??                                                  ctts

??                                                  stsc

??                                                  stsz

??                                                  stz2

??                                                  stco

??                                                  co64

??                                                  stss

??                                                   …

??            …

??…

??mdat

??…

??说明:

??文件打开读取的第一个Box必定是ftypBox,根据ftypBox的内容可以判断文件的类型(mp4or3gp,…)。

??moovBox记录着文件所有重要的信息,文件中所有的流都在这个Box中定义。每个流用一个trakBox描述(流的ID,流的类型(音频or视频or字幕or…),流的基本参数,…)。

??mdatBox存储所有流的数据。所有的数据都是原始数据并没有进行封装。也就是说,流数据前面没有像avi一样的‘00dc’‘01wb’这样的引导标志。流的读取应根据各自流的trakBox中的信息进行读取。在trakBox中非常详细的定义了,从哪个字节开始,长度为多少字节,这段数据是什么类型的,它的起始时间戳是多少,它的持续时间是多少等信息。

??除了ftypBox必定位于文件起始位置外,其它的Box没有固定的排列顺序(可以是mdatBox在前,也可以是moovBox在前)。一个Box内部的子Box也没有固定的排列顺序。

??表中的…表示可能存在其它的Box,分析文件的时候,可以根据Box的长度直接跳过。
下面对各个Box进行详细描述。
点评回复

使用道具 举报

 楼主| 发表于 2008-1-11 16:29:32 | 显示全部楼层
ftyp Box定义:
{
/* ftyp Box 大小,单位byte */
unsigned int(32) size;

/* Box类型:‘ftyp’*/
unsigned int(32) type = ‘ftyp’;
if (size==1){
unsigned int(64) largesize;
}else if (size==0) {
// box extends to end of file
}

/* 分支类型 */
unsigned int(32) major_brand;
/* 分支版本号 */
unsigned int(32) minor_version;
unsigned int(32) compatible_brands[];
}
说明:
整个文件只有一个ftyp Box;file type box
读取分支类型可以确定此文家是mp4文件还是3gp文件还是其它类型的文件;

moov Box定义:
{
/* moov Box的长度,单位byte */
unsigned int(32) size;
/* Box类型:‘moov’*/
unsigned int(32) type = ‘moov’;
if (size==1){
unsigned int(64) largesize;
}else if (size==0) {
// box extends to end of file
}
unsigned int(8)[] data;
}

说明:
整个文件只有一个moov Box;movie box
moov Box的data部分包含着表中所述的子Box;

mdat Box定义:
{
/* mdat Box的长度,单位byte */
unsigned int(32) size;
/* Box类型:‘mdat’*/
unsigned int(32) type =‘mdat’;
if (size==1){
unsigned int(64) largesize;
}else if (size==0) {
// box extends to end of file
}
/* 多媒体数据 */
unsigned int(8)[] data;
}

mvhd Box定义:
{
/* mvhd Box的长度,单位byte */
unsigned int(32) size;
/* Box类型:‘mvhd’ */
unsigned int(32) type = ‘mvhd’;
if (size==1){
unsigned int(64) largesize;
}else if (size==0) {
// box extends to end of file
}
    unsigned int(8) version;
bit(24) flags = 0;
if (version==1) {
/* 创建时间单位s,从1904年1月1日0:0:0开始 */
unsigned int(64) creation_time;
/* 最近访问时间,同上 */
unsigned int(64) modification_time;
/* 时间单位(1秒 = timescale,类似播放器中90k)*/
unsigned int(32) timescale;
/* 文件播放时间(与播放时间最长流相同),单位是时间单位;
文件播放时间换算成秒就是:(duration / 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;
template int(16) volume = 0x0100;
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;
}
说明:
只有一个mvhd Box;movie header box
template int(32) rate = 0x00010000;32位定点数: 16位整数,16位小数(1.0)
template int(16) volume = 0x0100; 16位定点数::8位整数,8位小数(1.0)

trak Box定义:
{
/* trak Box的长度,单位byte */
unsigned int(32) size;
/* Box类型:‘trak’*/
unsigned int(32) type = ‘trak’;
if (size==1){
unsigned int(64) largesize;
}else if (size==0) {
// box extends to end of file
}
unsigned int(8)[] data; /* 流具体定义 */
}

tkhd Box定义:
{
/* tkhd Box的长度,单位byte */
unsigned int(32) size;
/* Box类型:‘tkhd’ */
unsigned int(32) type = ‘tkhd’;
if (size==1){
unsigned int(64) largesize;
}else if (size==0) {
// box extends to end of file
}
    unsigned int(8) version;
bit(24) flags;
if (version==1) {
    /* 与mvhd定义相同 */
unsigned int(64) creation_time;
unsigned int(64) modification_time;
/* 流ID */
unsigned int(32) track_ID;
const unsigned int(32) reserved = 0;
/* 流播放时间,单位是时间单位,时间单位使用mvhd描述的时间单位 */
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;
const unsigned int(16) reserved = 0;
template int(32)[9] matrix=
{ 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 };
unsigned int(32) width;
unsigned int(32) height;
}
说明:
Track Header Box:每个Track Box一个Track Header Box;
Width和height是16.16的定点数
在这个Box中主要的信息就是:流ID(track_ID);

mdia Box定义:
{
/* mdia Box的长度,单位byte */
unsigned int(32) size;
/* Box类型:‘mdia’*/
unsigned int(32) type =‘mdia’;
if (size==1){
unsigned int(64) largesize;
}else if (size==0) {
// box extends to end of file
}
/* 子Box */
unsigned int(8)[] data;
}

mdhd Box定义:
{
/* mdhd Box的长度,单位byte */
unsigned int(32) size;
/* Box类型:‘mdhd’ */
unsigned int(32) type = ‘mdhd’;
if (size==1){
unsigned int(64) largesize;
}else if (size==0) {
// box extends to end of file
}
    unsigned int(8) version;
bit(24) flags = 0;
if (version==1) {
unsigned int(64) creation_time;
unsigned int(64) modification_time;
/* 与mvhd含义相同 */
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;
}
bit(1) pad = 0;
unsigned int(5)[3] language; // ISO-639-2/T language code
unsigned int(16) pre_defined = 0;
}
说明:
Media Header Box:每个Media Box一个Media Header Box;
在这个Box中主要的信息就是:流的时间单位(timescale)以及流的长度(duration)

hdlr Box定义:
{
/* hdlr Box的长度,单位byte */
unsigned int(32) size;
/* Box类型:‘hdlr’ */
unsigned int(32) type = ‘hdlr’;
if (size==1){
unsigned int(64) largesize;
}else if (size==0) {
// box extends to end of file
}
    unsigned int(8) version = 0;
bit(24) flags = 0;
unsigned int(32) pre_defined = 0;
unsigned int(32) handler_type;
const unsigned int(32)[3] reserved = 0;
string name;
}
说明:
Handler Box,每个mdia Box一个hdlr Box;
handler_type:‘vide’说明是视频流
              ‘soun’说明是音频流
               …     其它用处流
一个Trak Box可以根据hdlr Box里面的handler_type确定其流类型,也可以根据minf Box的子Box media info header Box确定其流类型。

minf Box定义:
{
/* minf Box的长度,单位byte */
unsigned int(32) size;
/* Box类型:‘minf’*/
unsigned int(32) type =‘minf’;
if (size==1){
unsigned int(64) largesize;
}else if (size==0) {
// box extends to end of file
}
/* 子Box */
unsigned int(8)[] data;
}

vmhd/smhd/nmhd Box:media info header Box
如果hdlr Box中指定的流类型为video流,那么此处media info header Box的类型应该为vmhd Box;同理,如果hdlr Box中指定的流类型为audio流,那么此处media info header Box的类型为smhd Box;
点评回复

使用道具 举报

发表于 2014-4-21 13:26:45 | 显示全部楼层
怎样编码读取MP4 文件呢?
点评回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

Archiver|手机版|小黑屋|52RD我爱研发网 ( 沪ICP备2022007804号-2 )

GMT+8, 2024-11-23 01:31 , Processed in 1.064867 second(s), 17 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表