MP4(二)-解复用器


MP4(二)-解复用器

MP4的一些基本的信息在上一篇博文已经介绍,转载的别人的博文,不过写的很好。这里指将几个遇到的问题,碰到新问题希望大家一起交流。
  1:MP4的box官方文档给了70多个,如果都解析了估计会写哭了,所以,解复用器中要得到几个box:
  moov,mdia,minf,stbl,stsd,stts,stco,stss,stsz,stsc,mdat,等等几个先关的box.


  2:chunk和sample的关系,一个chunk中有一个或多个sample,一个文件有多个chunk,在stco中标记了chunk在
文件中的绝对位置。不是相对于某一个box.stsz标记了每一个sample的大小,stsc则是chunk和sample的对应关系。
这里有个问题就是Stsc中有个 参数是first_chunk,这个是什么意思呢?
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……
就是这个意思。


  3:stsd这个box,很重要里面存放了音视频的信息,声道,采样率,样本,宽高,等等信息。通过这个box里面有个box,
名称:“avcC",这个box里面存放了H264的sps,pps等信息.


  4:如果音频是aac的则从mdat中取出来的数据既不是latm的也不是adts的,如果想转成adts的则需要加一个7字节的头,
每一帧都要加,这个头根据的填写根据,帧长度,声道,采样率有个下标:
//ADTS 头中相对有用的信息 采样率、声道数、帧长度
//adts头
//typedef struct
//{
// unsigned int syncword;  //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始
// unsigned int id;        //1 bslbf   MPEG 标示符, 设置为1
// unsigned int layer;     //2 uimsbf Indicates which layer is used. Set to ‘00’
// unsigned int protection_absent;  //1 bslbf  表示是否误码校验


// unsigned int profile;            //2 uimsbf  表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC
// unsigned int sf_index;           //4 uimsbf  表示使用的采样率下标
// unsigned int private_bit;        //1 bslbf
// unsigned int channel_configuration;  //3 uimsbf  表示声道数
// unsigned int original;               //1 bslbf
// unsigned int home;                   //1 bslbf
// 
// unsigned int copyright_identification_bit;   //1 bslbf
// unsigned int copyright_identification_start; //1 bslbf

// unsigned int aac_frame_length;               // 13 bslbf  一个ADTS帧的长度包括ADTS头和raw data block
// unsigned int adts_buffer_fullness;           //11 bslbf     0x7FF 说明是码率可变的码流
//
// 
// unsigned int no_raw_data_blocks_in_frame;    //2 uimsfb
//} ADTS_HEADER;

//•0: 96000 Hz
//•1: 88200 Hz
//•2: 64000 Hz
//•3: 48000 Hz
//•4: 44100 Hz
//•5: 32000 Hz
//•6: 24000 Hz
//•7: 22050 Hz
//•8: 16000 Hz
//•9: 12000 Hz
//•10: 11025 Hz
//•11: 8000 Hz
//•12: 7350 Hz
//•13: Reserved
//•14: Reserved
//•15: frequency is written explictly

//•0: Defined in AOT Specifc Config
//•1: 1 channel: front-center
//•2: 2 channels: front-left, front-right
//•3: 3 channels: front-center, front-left, front-right
//•4: 4 channels: front-center, front-left, front-right, back-center
//•5: 5 channels: front-center, front-left, front-right, back-left, back-right
//•6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
//•7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-

channel
//•8-15: Reserved


  5:如果视频是H264的,从mdat中取出来的数据是4个字节的长度加上帧数据,需要转换的是将四个字节的长度转换为
00 00 00 01 ,如果遇到一帧数据是I帧则需要将sps,pps填写到前面。关键帧信息在stssbox中存储,有些I帧前面是个SEI
帧,也就是说取出来的是两帧数据,则需要将这两帧分开,记住前缀 00 00 00 01 的问题。


  6:关于本程序是将文件中的box放到内存中做的处理,如果文件过大会出现分配内存失败的问题,所以应用到项目中时根据

需要分析所需要的box.


  7:这里暂时没做多个mdat_box的判断,一个文件中有可能有多个mdatbox,本程序未做判断,未找到类似的文件。这样会产生

一个问题就是文件定位数据帧的时候定位会有问题。


  8:本文参考官方文档:ISO_IEC_14496-12_2005(E)这个是文件中各个box的结构体信息
                       ISO_IEC_14496-14_2003-11-15这个文档是 ”avcC"box的结构体
  相关的文档信息下载地址:http://download.csdn.net/detail/zhuweigangzwg/5441775


  9:本文参考了一些网络中文章,写的都很好,分享给大家:
   http://www.cnblogs.com/haibindev/archive/2011/10/17/2214518.html
   http://wmnmtm.blog.163.com/blog/static/382457142011629523934/
   http://blog.csdn.net/wangxiaowanghui/article/details/8538574
   http://blog.csdn.net/lius1984/article/details/4464688
   http://www.rosoo.net/a/201109/15013.html
   http://blog.csdn.net/linzhiji/article/details/5630464
   http://www.cnblogs.com/skyseraph/archive/2012/04/01/2429384.html
 注:本程序的demo地址:http://download.csdn.net/detail/zhuweigangzwg/5441809
     交流请加QQ:379969650

 

 

改进:
1:demux.cpp,548行的eles代码替
else
 {
 printf("temporary_typestr : \"%s\"   ,  m_box->size : %d\n",temporary_typestr,m_box->size);
 if (!is_found_mdat_box)
 {
 m_in_mdat_box_place += m_box->size;
 }
 }

2:stsd_box.cpp, 189行更改为:
 stsdvide_pos -= 5;

 //stsdvide->depth =
 // stsdvide_buf[stsdvide_pos]  << 8 |
 // stsdvide_buf[stsdvide_pos +1];
 //stsdvide_pos +=2;
 //stsdvide->pre_defined_2 =
 // stsdvide_buf[stsdvide_pos]  << 8 |
 // stsdvide_buf[stsdvide_pos +1];
 //stsdvide_pos +=2; 

你可能感兴趣的:(MP4(二)-解复用器)