MP4文件stsd box的解析

1 篇文章 0 订阅
1 篇文章 0 订阅
简单记录一次MP4文件stsd box的解析过程,被解析的MP4文件stsd box信息如下:
00 00 00 B5 73 74 73 64 00 00 00 00 00 00 00 01 00 00 00 A5 61 76 63 31 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 80 01 68 00 48 00 00 00 48 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 FF FF 00 00 00 3F 61 76 63 43 01 64 00 1E FF E1 00 28 27 64 00 1E AC 13 16 C0 A0 2F F9 7F F0 13 F0 14 01 00 00 27 10 00 07 A1 20 E0 60 00 BB 80 00 2E E0 BD EF 83 E1 10 8D C0 01 00 04 28 EE 1F 2C 

首先熟悉stsd box的标准规范,参考ISO/IEC 14496-12:

stsd box(The sample description table gives detailed information about the coding type used, and any initialization information needed for that coding. 即定义了视频/音频解码相关的参数,如h264的sps,pps)。stsd box的数据结构用类SampleDescriptionBox去描述。SampleDescriptionBox定义在ISO/IEC 14496-12中,如下:


aligned(8) class SampleDescriptionBox (unsigned int(32) handler_type) extends FullBox('stsd', 0, 0){
    int i ;//不算成员哦
    unsigned int(32) entry_count;//一般为1,一个trak只有一套解码参数
    for (i = 1 ; i u entry_count ; i++){
        switch (handler_type){
        case ‘soun’: // for audio tracks
            AudioSampleEntry();
            break;
        case ‘vide’: // for video tracks
            VisualSampleEntry();
            break;
        case ‘hint’: // Hint track
            HintSampleEntry();
            break;
        }
    }
}
SampleDescriptionBox继承了FullBox,FullBox又继承了Box,这里把FullBox和Box也贴出来:

//最顶层box,所有box都直接或间接继承Box
aligned(8) class Box (unsigned int(32) boxtype, optional unsigned int(8)[16] extended_type) {
    unsigned int(32) size;
    unsigned int(32) type = boxtype;
    if (size==1) {
        unsigned int(64) largesize;
    } else if (size==0) {
        // box extends to end of file
    }
    if (boxtype==‘uuid’) {
        unsigned int(8)[16] usertype = extended_type;
    }
}



//大部分box都会继承FullBox,也有直接继承Box的。
aligned(8) class FullBox(unsigned int(32) boxtype, unsigned int(8) v, bit(24) f) extends Box(boxtype) {
    unsigned int(8) version = v;
    bit(24) flags = f;
}


可知SampleDescriptionBox根据handler_type不同持有entry_count个AudioSampleEntry或VisualSampleEntry或HintSampleEntry对象。以视频为例,SampleDescriptionBox持有一个VisualSampleEntry,VisualSampleEntry定义如下:
//基类VisualSampleEntry
class VisualSampleEntry(codingname) extends SampleEntry (codingname){
    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;
}


//VisualSampleEntry又继承了SampleEntry:

//抽象接口SampleEntry
aligned(8) abstract class SampleEntry (unsigned int(32) format) extends Box(format){
    const unsigned int(8)[6] reserved = 0;
    unsigned int(16) data_reference_index;
}

VisualSampleEntry类没有默认构造,需要传入参数codingname,codingname由具体的VisualSampleEntry子类传入。VisualSampleEntry只是各种编码格式(h264,h265)视频XXXSampleEntry基类,ISO/IEC 14496-12只定义了VisualSampleEntry这个基类,具体是哪种编码格式则在其他文档里定义。如h264使用AVCSampleEntry,AVCSampleEntry继承了VisualSampleEntry,构造时codingname为“avc1”。AVCSampleEntry是在ISO/IEC 14496-15中定义,如下:


//具体的AVCSampleEntry子类,继承了VisualSampleEntry,复合AVCConfigurationBox等
class AVCSampleEntry() extends VisualSampleEntry (‘avc1’){
    AVCConfigurationBox config;
    MPEG4BitRateBox (); // optional,可选
    MPEG4ExtensionDescriptorsBox (); // optional
}
其中AVCSampleEntry成员也在ISO/IEC 14496-15中定义,持有一个AVCDecoderConfigurationRecord,如下
class AVCConfigurationBox extends Box(‘avcC’) {
    AVCDecoderConfigurationRecord() AVCConfig;
}
同样AVCDecoderConfigurationRecord也在ISO/IEC 14496-15中定义,如下
aligned(8) class AVCDecoderConfigurationRecord {
    unsigned int(8) configurationVersion = 1;
    unsigned int(8) AVCProfileIndication;
    unsigned int(8) profile_compatibility;
    unsigned int(8) AVCLevelIndication;
    bit(6) reserved = ‘111111’b;
    unsigned int(2) lengthSizeMinusOne;
    bit(3) reserved = ‘111’b;
    unsigned int(5) numOfSequenceParameterSets;//SPS数据个数
    for (i=0; i< numOfSequenceParameterSets; i++) {
        unsigned int(16) sequenceParameterSetLength ;//一个SPS数据内容长度
        bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit; //一个SPS数据内容
    }
    unsigned int(8) numOfPictureParameterSets; //PPS数据个数
    for (i=0; i< numOfPictureParameterSets; i++) {
        unsigned int(16) pictureParameterSetLength; //一个PPS数据内容长度
        bit(8*pictureParameterSetLength) pictureParameterSetNALUnit; //一个PPS数据内容
    }
    if( profile_idc == 100 || profile_idc == 110 ||
        profile_idc == 122 || profile_idc == 144 )
    {
        bit(6) reserved = ‘111111’b;
        unsigned int(2) chroma_format;
        bit(5) reserved = ‘11111’b;
        unsigned int(3) bit_depth_luma_minus8;
        bit(5) reserved = ‘11111’b;
        unsigned int(3) bit_depth_chroma_minus8;
        unsigned int(8) numOfSequenceParameterSetExt;
        for (i=0; i< numOfSequenceParameterSetExt; i++) {
            unsigned int(16) sequenceParameterSetExtLength;
            bit(8*sequenceParameterSetExtLength) sequenceParameterSetExtNALUnit;
        }
    }
}
参考以上各类的说明,结合ISO/IEC 14496-12和ISO/IEC 14496-15文档的具体描述,相应各字节的解析结果如下:
00 00 00 B5 73 74 73 64 :box size(181字节)+boxtype("stsd")
00 00 00 00 :fullbox,verison+flag
00 00 00 01 : entry_count=1,持有一个VisualSampleEntry,如下 
00 00 00 A5 61 76 63 31 ::size(165字节)+boxtype("avc1")
00 00 00 00 00 00  :const unsigned int(8)[6] reserved = 0;
00 01  :unsigned int(16) data_reference_index;
00 00 :unsigned int(16) pre_defined = 0;
00 00 :const unsigned int(16) reserved = 0;
00 00 00 00 00 00 00 00 00 00 00 00 :unsigned int(32)[3] pre_defined = 0;
02 80 :视频宽640,unsigned int(16) width;
01 68 :视频高360,unsigned int(16) height;
00 48 00 00 :template unsigned int(32) horizresolution = 0x00480000; // 72 dpi
00 48 00 00 :template unsigned int(32) vertresolution = 0x00480000; // 72 dpi
00 00 00 00 :const unsigned int(32) reserved = 0;
00 01 :template unsigned int(16) frame_count = 1;//视频必须为1
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 :string[32] compressorname;
00 18 :template unsigned int(16) depth = 0x0018;
FF FF :int(16) pre_defined = -1;
00 00 00 3F 61 76 63 43 : box size(63字节)+boxtype("avcC")
01 :unsigned int(8) configurationVersion = 1;
64 : Profile为100,unsigned int(8) AVCProfileIndication;
00 : unsigned int(8) profile_compatibility;
1E : unsigned int(8) AVCLevelIndication
FF : bit(6) reserved = ‘111111’b; unsigned int(2) lengthSizeMinusOne;//读出的每个packet的前几字节代表数据大小,3+1字节
E1 : sps个数为1 =1,bit(3) reserved = ‘111’b ;unsigned int(5) numOfSequenceParameterSets;
00 28 :sps长度为40字节 。unsigned int(16) sequenceParameterSetLength ;
27 64 00 1E AC 13 16 C0 A0 2F F9 7F F0 13 F0 14 01 00 00 27 10 00 07 A1 20 E0 60 00 BB 80 00 2E E0 BD EF 83 E1 10 8D C0
:40字节的sps数据。bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;


01 :pps个数为1. unsigned int(8) numOfPictureParameterSets;
00 04 :pps数据长度4。unsigned int(16) pictureParameterSetLength;
28 EE 1F 2C :4字节的pps数据。bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
//avcCbox数据结束。
以上没按标准来,按AVCDecoderConfigurationRecord规定,profile_idc == 100时理应还有部分数据,但size已经到头了



  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值