MP4(三)-复用器,数据的存储

来源:互联网 发布:mac怎么删除文件夹 编辑:程序博客网 时间:2024/06/06 01:40
MP4(三)-复用器

1:MP4的box有很多,见过的70多个吧,这里一共写了必须的10多个,剩下的可以扩展,有:fpyt,free,mdat,moov,mvhd,trak,
  tkhd,mdia,mdhd,hdlr,minf,vmhd,smhd,dinf,stbl,stsd,stts,stsc,stsz,stco,stss,ctts(可选),avc1,accC,mp4a,esds。

 

2:time scale 和 duration的关系
   time scale 是单位 以秒为单位 duration 是时常,可以以毫秒为单位也可以不是,只要算出来那个值就行了:例如:
   time scale = 600, duration = 42000 算出来 duration/timescale = 70.00 , time scale = 1000 , duration = 70000,算出来 duration/timescale = 70.00 相同的值,道理就是这样。本程序需要三个这样的值,一个是文件总的时常,二是音频的时常,三个是视频的时常,存储在不同的box中,这些数值,具体看官方文档。

 

3:本程序有一个简便的方法,MP4中引用了很多chunk和sampel的关系如下图:

但问程序为了简便,将chunk和sample 一一对应,也就是说一个chunk中只有一个sample,这里要注意。


4:stts:TimeToSampleBox
   结构如下:


   如果多个sample有相同的duration,可以只用一项描述所有这些samples,数量字段说明sample的个数。例如,如果一个视     频媒体的帧率保持不变,整个表可以只有一项,数量就是全部的帧数。
   例1: 视频
   entry_count:1
   sample_count:37   //上面已经有duration时间了,duration指整个mdat中video的时长,这里37却为chunks数目
   sample_delta:1001 //1001 * 37=37037 sample_delta*sample_count=duration

   例2: 音频
   sentry_count:1
   sample_count:67   //音频分了67个chunks
   sample_delta:1024 //同上

 

5:stsz:SampleSizeBox
   结构如下:


   就是表示每一个sample的大小,视频的时候,这里一定要注意 这个长度是 4个字节的长度前缀加上数据的长度,要不然播放不出来。

 

6: stsd:SampleDescriptionBox
   结构如下:


   这个box中包含的音频的采样率,声道,样本,视频的sps,pps等信息,这些信息的结构可以看官方文档
   如图:


视频:AVC sequence header就是AVCDecoderConfigurationRecord结构,该结构在标准文档“ISO-14496-15 AVC file format”中有详细说明。
视频和flv的相同。avcc结构。
音频:有两种:
1):
AAC sequence header存放的是AudioSpecificConfig结构,该结构则在“ISO-14496-3 Audio”中描述。AudioSpecificConfig结构的描述非常复杂,这里我做一下简化,事先设定要将要编码的音频格式,其中,选择"AAC-LC"为音频编码,音频采样率为44100,于是AudioSpecificConfig简化为下表:

这种的和flv的相同里面存放了采样率,声道等信息。
2):mp4a(box)->esds(box)
这种的信息请看条目11。

这里还有一点要注意:MP4中所有的项都是box,stsd下面有几种box,视频:stsd->
avc1(box)->avcC(box),
音频:stsd->mp4a(box)->esds(box),是box就有box头,一定要注意。

 

7:stss:SyncSampleBox
   结构如下:


stss: syn Sample box
   例1: 视频
   entry_count:1
   sample_number:1
   但音频里没有这个box,
   这个Box非常重要, 决定了整个mp4文件是否可以拖拉, 如果这个box只有一个entry,则拖拉时将cpu达到100%, 如果这个box不存在, 可以拖拉, 也不会达到   100%, 但是会略等一会, 通常做法可以搞100条.
“stss”确定media中的关键帧。对于压缩媒体数据,关键帧是一系列压缩序列的开始帧,其解压缩时不依赖以前的帧,而后续帧的解压缩将依赖于这个关键帧。“stss”可以非常紧凑的标记媒体内的随机存取点,它包含一个sample序号表,表内的每一项严格按照sample的序号排列,说明了媒体中的哪一个sample是关键帧。如果此表不存在,说明每一个sample都是一个关键帧,是一个随机存取点。
这里没有chunk的概念,entry_count:一共有多少个关键帧,sample_number:关键帧sample的标号。

8:stco:ChunkOffsetBox
   结构如下:

 “stco”定义了每个chunk在媒体流中的位置。位置有两种可能,32位的和64位的,后者对非常大的电影很有用。在一个表中只会有一种可能,这个位置是在整个文件中的,而不是在任何box中的,这样做就可以直接在文件中找到媒体数据,而不用解释box。需要注意的是一旦前面的box有了任何改变,这张表都要重新建立,因为位置信息已经改变了。


9: stsc:SampleToChunkBox
   结构如下:



First chunk Samples per chunk Sample description ID
1           4                        1
4           3                        1
5           4                        1
8           3                        1
可以看出chunk1、chunk2、chunk3都有4个sample,chunk4有3个sample,chunk5、chunk6、chunk7有4个sample……
就是这个意思。

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


10:
avc1(box)->avcC(box)

acc1 box size //32
avc1 boxheader: //32
const unsigned int(8)[6] reserved = 0;
unsigned int(16) data_reference_index;
unsigned int(16) pre_defined = 0;
const unsigned int(16) reserved = 0;
unsigned int(32)[3] pre_defined = 0;
unsigned int(16) width;
unsigned int(16) height;
template unsigned int(32) horizresolution = 0x00480000; // 72 dpi
template unsigned int(32) vertresolution = 0x00480000; // 72 dpi
const unsigned int(32) reserved = 0;
template unsigned int(16) frame_count = 1;
string[32] compressorname;
template unsigned int(16) depth = 0x0018;
int(16) pre_defined = -1;

accC box size //32
avcC boxheader: //32
unsigned char configurationVersion;  //8;= 0x01
unsigned char AVCProfileIndication;  //sps即sps的第2字节,所谓的AVCProfileIndication
unsigned char profile_compatibility; //sps即sps的第3字节,所谓的profile_compatibility
unsigned char AVCLevelIndication;    //sps即sps的第4字节,所谓的AVCLevelIndication
unsigned char reserved_1;            //‘111111’b;
unsigned char lengthSizeMinusOne;    //NALUnitLength 的长度 -1 一般为0x03
unsigned char reserved_2;            //‘111’b;
unsigned char numOfSequenceParameterSets;  //一般都是一个
unsigned int sequenceParameterSetLength;   //sps长度
unsigned char * sequenceParameterSetNALUnit; //sps数据
unsigned char numOfPictureParameterSets;   //一般都是一个
unsigned int  pictureParameterSetLength;   //pps长度
unsigned char * pictureParameterSetNALUnit;//pps数据
这样结构就完成了。最简便的方式。

 

11: mp4a(box)->AudioSpecificConfig(这里用的是esds的名称)

mp4a box size //32
mp4a boxheader: //32
const unsigned int(8)[6] reserved = 0;
unsigned int(16) data_reference_index;
const unsigned int(32)[2] reserved = 0;
template unsigned int(16) channelcount = 2;
template unsigned int(16) samplesize = 16;
unsigned int(16) pre_defined = 0;
const unsigned int(16) reserved = 0 ;
template unsigned int(32) samplerate = {timescale of media}<<16;

esdsbox size //32
esds boxheader: //32
version,flag //32
unsigned char audioObjectType;              //5;编解码类型:AAC-LC = 0x02
unsigned char samplingFrequencyIndex;       //4;采样率 44100 = 0x04
unsigned char channelConfiguration;         //4;声道 = 2
unsigned char framelengthFlag;              //1;标志位,位于表明IMDCT窗口长度 = 0
unsigned char dependsOnCoreCoder;           //1;标志位,表明是否依赖于corecoder = 0
unsigned char extensionFlag;                //1;选择了AAC-LC = 0
按照这个结构写填写vlc也能正常播放,估计是vlc 比较强大。

 

12:mp4a(box)->esds(box)

mp4a box size //32
mp4a boxheader: //32
const unsigned int(8)[6] reserved = 0;
unsigned int(16) data_reference_index;
const unsigned int(32)[2] reserved = 0;
template unsigned int(16) channelcount = 2;
template unsigned int(16) samplesize = 16;
unsigned int(16) pre_defined = 0;
const unsigned int(16) reserved = 0 ;
template unsigned int(32) samplerate = {timescale of media}<<16;

esdsbox size //32
esds boxheader: //32
version,flag //32
unsigned char tag; //8
unsigned char Length_Field; //8   Length Field:25
unsigned int  ES_ID;  //bit(16)   ES_ID: 是0
unsigned char streamDependenceFlag; //bit(1)  steamDependenceFlag,如果为1,则有16bits的
unsigned char URL_Flag;    //bit(1)  :URL_Flag,如果为1,后边则有8bits URLlength, 和相应的URLstring(URLlength)
unsigned char OCRstreamFlag; //bit(1) 如果为1,有16bits OCR_ES_id;
unsigned char streamPriority; //bit(5)
unsigned char DecoderConfigDescriptor_tag; //8  = 0x04
unsigned char Length_Field_1;      //8 = 0x11
unsigned char objectTypeIndication; //8 = 0x40  14496-1 Table8, 0x40是Audio ISO/IEC 14496-3
unsigned char streamType ; //6   5是Audio Stream, 14496-1 Table9
unsigned char upStream;    //1
unsigned char reserved;    //1
unsigned int  bufferSizeDB;//24         //这里是调节比特率的   
unsigned int  maxBitrate;  //32 
unsigned int  avgBitrate; //32
unsigned char DecSpecificInfotag; //8 = 0x05
unsigned char Length_Field_2; //8  = 0x02
unsigned char audioObjectType_2_GASpecificConfig; //5         //编解码类型:AAC-LC = 0x02
unsigned char samplingFrequencyIndex; //4                     //采样率 44100 = 0x04      
unsigned char channelConfiguration; //4                       //声道 = 2
unsigned char cpConfig; //2                                  
unsigned char directMapping;// 1
unsigned char SLConfigDescrTag;//8  = 0x06
unsigned char Length_Field_3;//8    = 0x01
unsigned char predefined;//8  predefined 0x02 Reserved for use in MP4 files
这个box的信息是从:http://blog.csdn.net/coreavs163/article/details/8603026 这位网友的分享中看到的,一直没找到官方文档的信息,
不过有这些已经够了,将采样率,声道都填入到了这个box里面。
如果用上面的AudioSpecificConfig,文件夹中的小图标是不能显示mp4的图像的。

 

13:ctts:CompositionOffsetBox(可选)
这个box具体是怎么应用的不太清楚,网上也没找到相关的解析,应该是个可选的box,不过我看一般的MP4文件都有这个box,期待高手给解析吧,如果哪位高手知道这个box是怎么填写的,请联系我。

 

注:本demo地址:http://download.csdn.net/detail/zhuweigangzwg/5580637
    交流请加QQ:379969650

0 0
原创粉丝点击