这部分代码个人觉得还布整洁,因为没机会整理,所以前段时间删除了。一位网友请求重新发表,于是我在整理一下发上来了

//filename mp4_boxes.cpp
#include 
<iostream>
#include 
<fstream>
#include 
<string>

#include 
<cstring>
#include 
<cstdlib>
#include 
<cerrno>

#include 
"mp4_boxes.h"

#ifndef RELEASE
#define RELEASE 1
#endif

#ifndef VARIABLES
#define VARIABLES                               \
    
int k = 0;                                  \
    unsigned 
char p[5];                         \
    
int inner_size = 0;
#endif

static struct mp4_moov_box moov;

/*final box
 
*/
int mp4_read_mvhd_box(FILE *f, int size)  //level 3
{
    printf(
"\t+%s\n""mvhd");
    VARIABLES;
    
int level_4_box_size    = 0;

    mp4_mvhd_box mvhd;
    memset(
&mvhd, 0sizeof(mvhd));
    
    mvhd.size               
= size;
    mvhd.type               
= ('m' | 'v'<<8 | 'h'<<16 | 'd'<<24);
    mvhd.version            
= read_uint8(f);                 //1
    fread(mvhd.flags, sizeof(mvhd.flags), 1, f);             //3
    mvhd.creation_time      = read_uint32_lit(f);            //4
    mvhd.modification_time  = read_uint32_lit(f);            //4
    mvhd.timescale          = read_uint32_lit(f);            //4
    mvhd.duration           = read_uint32_lit(f);            //4
    mvhd.rate               = read_uint32_lit(f);            //4
    mvhd.volume             = read_uint16_big(f);            //2
    fread(&mvhd.reserved1, sizeof(mvhd.reserved1), 1, f);    //2
    fread(&mvhd.reserved2, sizeof(mvhd.reserved2), 1, f);    //8
    fread(mvhd.matrix, sizeof(mvhd.matrix), 1, f);           //36
    fread(mvhd.pre_defined, sizeof(mvhd.pre_defined), 1, f); //24
    mvhd.next_track_id      = read_uint32_lit(f);            //4
    moov.mvhd               = mvhd;

    
    printf(
"\t\ttimescale: %u\n", moov.mvhd.timescale);
    printf(
"\t\tduration: %u\n", moov.mvhd.duration);
    printf(
"\t\trate: %u\n", moov.mvhd.rate );
    printf(
"\t\tvolume: 0x%x\n", moov.mvhd.volume);
    
    printf(
"\t\tmatrix:\n");
    
for(int i = 0; i < 3++i){
        printf(
"\t\t");
        
for(int j = 0; j < 3++j){
            printf(
" %8u ", moov.mvhd.matrix[i*3+j]);
        }
        printf(
"\n");
    }
    
    printf(
"\t\tnext track id: %u\n", moov.mvhd.next_track_id);
   
    printf(
"\n");
}


/*final box
 
*/
struct mp4_tkhd_box mp4_read_tkhd_box(FILE *f, int size)  //level 4
{
    printf(
"\t\t+%s\n""tkhd"); 
    
    VARIABLES;
    mp4_tkhd_box box;
        
    box.size              
= size;
    box.type              
= 0;
    box.version           
= read_uint8(f);
    fread(
&box.flags, sizeof(box.flags), 1, f);
    box.creation_time     
= read_uint32_lit(f);
    box.modification_time 
= read_uint32_lit(f);
    box.track_ID          
= read_uint32_lit(f);
    box.reserved1         
= read_uint32_lit(f);
    box.duration          
= read_uint32_lit(f);
    fread(
&box.reserved2, sizeof(box.reserved2), 1, f);
    box.layer             
= read_uint16_big(f);
    box.alternate_group   
= read_uint16_big(f);
    box.volume            
= read_uint16_big(f);
    box.reserved3         
= read_uint16_big(f);
    fread(
&box.matrix, sizeof(box.matrix), 1, f);
    box.width             
= read_uint32_lit(f);
    box.height            
= read_uint32_lit(f);

    
// printf("\t\t\tflags: 0x%4x\n", box.flags[2]
    
//        | box.flags[1] | box.flags[0]);
    
// printf("\t\t\tcreation time: %u\n", box.creation_time);
    
// printf("\t\t\tmodifaction time: %u\n",
    
//        box.modification_time);
    printf("\t\t\ttrack id: %u\n", box.track_ID);
    
// printf("\t\t\treserved1: 0x%x\n", box.reserved1);
    printf("\t\t\tduration: %d\n",box.duration);
    
// printf("\t\t\treserved2: 0x%x, 0x%x\n",
    
//        box.reserved2[0], box.reserved2[1]);
    printf("\t\t\tlayer: %d\n",box.layer);
    printf(
"\t\t\talternate group: %d\n", box.alternate_group);
    printf(
"\t\t\tvolume: 0x%x\n", box.volume);
    
// printf("\t\t\treserved3: 0x%x\n", box.reserved3);
        
    printf(
"\t\t\tmatrix:\n");
    
for(int i = 0; i < 3++i){
        printf(
"\t\t\t");
        
for(int j = 0; j < 3++j){
            printf(
" %8u ", box.matrix[i*3+j]);
        }
        printf(
"\n");
    }
    
//////////////////////////////////////////@a mark still don't know
    printf("\t\t\twidth: %u\n",box.width);
    printf(
"\t\t\theight: [%u].[%u]\n",
           box.height 
& 0xffff0000 >> 16,
           box.height 
& 0xffff);
  
    printf(
"\n");
    
    
return box;
}

/*container box
  (elst)
 
*/
struct mp4_edts_box mp4_read_edts_box(FILE *f, int size)
{
    printf(
"\t\t+%s\n""edts");
    
    
//return mp4_edts_box();
}

/*final box
 
*/
struct mp4_mdhd_box mp4_read_mdhd_box(FILE *f, int size)
{
    printf(
"\t\t\t+mdhd\n");
    
struct mp4_mdhd_box box;

    VARIABLES;
        
    box.size              
= size;
    box.type              
= 0;
    box.version           
= read_uint8(f);
    fread(
&box.flags, sizeof(box.flags), 1, f);
    box.creation_time     
= read_uint32_lit(f);
    box.modification_time 
= read_uint32_lit(f);
    box.timescale         
= read_uint32_lit(f);
    box.duration          
= read_uint32_lit(f);
    box.language          
= read_uint16_big(f);
    box.pre_defined       
= read_uint16_big(f);


    
// printf("\t\t\t\t\tflags: 0x%x\n", box.flags[2]
    
//        | box.flags[1] | box.flags[0]);
    
// printf("\t\t\t\t\tcreation time: %u\n", box.creation_time);
    
// printf("\t\t\t\t\tmodifaction time: %u\n",
    
//        box.modification_time);
    printf("\t\t\t\ttimescale: %u\n", box.timescale);
    printf(
"\t\t\t\tduration: %u\n", box.duration);
    printf(
"\t\t\t\tlanguage: %u\n", box.language);
    
// printf("\t\t\t\tpre-defined: %u\n", box.pre_defined);
    
//    printf("\n");

    
return box;
}

/*filnal box
 
*/
struct mp4_hdlr_box mp4_read_hdlr_box(FILE *f, int size)
{
    printf(
"\t\t\t%s\n""+hdlr");
    
struct mp4_hdlr_box box;
   
    VARIABLES;
    
    box.size            
= size;
    box.type            
= 'h'|'d'<<8|'l'<<16|'r'<<24;
    box.version         
= read_uint8(f);
    fread(
&box.flags, sizeof(box.flags), 1, f);
    box.pre_defined     
= read_uint32_lit(f);
    fread(
&box.handler_type, sizeof(box.handler_type), 1, f);
    box.handler_type[
4= 0;
    fread(
&box.reserved, sizeof(box.reserved), 1, f);
    fread(
&inner_size, 11, f);
    box.name            
= new char[inner_size + 1];
    
for(int i = 0; i < inner_size; ++i)
        fread(
&box.name[i], sizeof(unsigned char), 1, f);
    
    
// printf("\t\t\t\tflags: 0x%x\n",
    
//        box.flags[2] | box.flags[1] | box.flags[0]);
    
// printf("\t\t\t\tpre-defined: %d\n", box.pre_defined);
    printf("\t\t\t\thandler type: %s\n", box.handler_type);
    
// printf("\t\t\t\treserved: 0x%x, 0x%x, 0x%x\n",
    
//        box.reserved[0], box.reserved[1], box.reserved[2]);
    printf("\t\t\t\tname: %s\n", box.name);  //I have no idea what
                                             
//is this using for
    
// printf("\n");
    return box;
}

/*final box
 
*/
struct mp4_vmhd_box * mp4_read_vmhd_box(FILE *f, int size)
{
    printf(
"\t\t\t\t+%s\n""vmhd");

    VARIABLES;
    mp4_vmhd_box 
*box  = new mp4_vmhd_box;
    
    box
->size          = size;
    box
->type          = 0;
    box
->version       = read_uint8(f);
    fread(
&(box->flags), sizeof(box->flags), 1, f);
    box
->graphics_mode = read_uint32_lit(f);
    fread(
&(box->opcolor), sizeof(box->opcolor), 1, f);
        

    
// printf("\t\t\t\t\tflags: 0x%x\n", box.flags[2]
    
//        | box.flags[1] | box.flags[0]);
    printf("\t\t\t\t\tgraphics mode: %u\n", box->graphics_mode);
    printf(
"\t\t\t\t\topcolor: %u,%u,%u,%u\n",
           box
->opcolor[0],  box->opcolor[1],
           box
->opcolor[2],  box->opcolor[3]);
    
    
//printf("\n");
}

/*final box
 
*/
struct mp4_smhd_box *mp4_read_smhd_box(FILE *f, int size)
{
    printf(
"\t\t\t\t+%s\n""smhd");
    mp4_smhd_box box;
    
    box.size             
= size;
    box.type             
= 's'|'m'<<8|'h'<<16|'d'<<24;
    box.version          
= read_uint8(f);
    fread(
&box.flags, sizeof(box.flags), 1, f);
    box.balance          
= read_uint16_big(f);
    box.reserved         
= read_uint16_big(f);        

    
// printf("\t\t\t\t\tflags: 0x%x\n", box.flags[2]
    
//        | box.flags[1] | box.flags[0]);
    printf("\t\t\t\t\tbalance: %d,%d\n",
           box.balance 
& 0xff00 >> 8, box.balance & 0xff);
    
// printf("\t\t\t\t\treserved: 0x%x\n", box.reserved);
        
    
//  printf("\n");
    mp4_smhd_box *newbox = new mp4_smhd_box;
    
*newbox              = box;
    
return newbox;
}

struct mp4_stts_box mp4_read_stts_box(FILE *f, int size)  //level 8
{
    printf(
"\t\t\t\t\t+%s\n""stts");
    mp4_stts_box box;

    box.size                 
= size;
    box.version              
= read_uint8(f);
    fread(box.flags, 
sizeof(box.flags), 1, f);
    box.number_of_entries    
= read_uint32_lit(f);

    
// printf("\t\t\t\t\t\tflags: %u\n",
    
//        box.flags[0]|box.flags[1]|box.flags[2]);
    printf("\t\t\t\t\t\tnumber of entries: %u\n",box.number_of_entries);
     
    printf(
"\t\t\t\t\t\tentries:\n\t\t\t\t\t\t");
    box.time_to_sample_table 
= new uint32_t[box.number_of_entries];
    
for(int i = 0; i < box.number_of_entries; ++i){
        box.time_to_sample_table[i] 
= read_uint32_lit(f);
        
//  printf("%5u ", box.time_to_sample_table[i]);
        
// if(i%16 == 0) printf("\n");
    }
    
//delete [] box.time_to_sample_table;
    
    printf(
"\n");

    
return box;
}

/*final box*/
struct mp4_avcC_box *mp4_read_avcC_box(FILE *f)
{
    
struct mp4_avcC_box *ptr       = new mp4_avcC_box;
    
    ptr
->size                      = read_uint32_lit(f);
    printf(
"avcC_size:%u\n",ptr->size);
    
    ptr
->type                      = read_uint32_lit(f);
    
if( ptr->type                  ==  ('a'<<24|'v'<<16|'c'<<8|'C')){
        printf(
"type:avcC\n");
    }
    
    ptr
->configurationVersion      = read_uint8(f);
    printf(
"configurationVersion:%u\n", ptr->configurationVersion);
    ptr
->AVCProfileIndication      = read_uint8(f);
    printf(
"AVCProfileIndication: %x\n", ptr->AVCProfileIndication);
    ptr
->profile_compatibility     = read_uint8(f);
    ptr
->AVCLevelIndication        = read_uint8(f);
    ptr
->lengthSizeMinusOne        = 0x3 & read_uint8(f);  //2 bit
    printf("lengthSizeMinusOne:%u\n", ptr->lengthSizeMinusOne);
    ptr
->numOfSequenceParameterSet = 0x1F & read_uint8(f);  //5bit
    printf("numOfSequenceParameterSet:%x\n", ptr->numOfSequenceParameterSet);
    ptr
->sps                       = new mp4_avcC_box::SPS[ptr->numOfSequenceParameterSet];
    
    
forint i = 0; i < ptr->numOfSequenceParameterSet; ++i ){
        ptr
->sps[i].sequenceParameterSetLength = read_uint16_lit(f);
        printf(
"sequenceParameterSetLength: %u\n", ptr->sps[i].sequenceParameterSetLength);
        
        ptr
->sps[i].sequenceParameterSetNALUnit =
            
new uint8_t[ptr->sps[i].sequenceParameterSetLength];
        fread((ptr
->sps[i].sequenceParameterSetNALUnit),
              (ptr
->sps[i].sequenceParameterSetLength), 1, f);
        
        
for(int j = 0; j < ptr->sps[i].sequenceParameterSetLength; ++j){
            printf(
"%x", ptr->sps[i].sequenceParameterSetNALUnit[j]);
        }
        printf(
"============\n");
    }

    ptr
->numOfPictureParameterSets = read_uint8(f);
    printf(
"numOfPictureParameterSets:%u\n", ptr->numOfPictureParameterSets);
    ptr
->pps                       = new mp4_avcC_box::PPS[ptr->numOfPictureParameterSets];
    
forint i = 0; i < ptr->numOfPictureParameterSets; ++i){
        ptr
->pps[i].pictureParameterSetLength = read_uint16_lit(f);
        printf(
"%d\n", ptr->pps[i].pictureParameterSetLength);
        
        ptr
->pps[i].pictureParameterSetNALUnit
                                   
= new uint8_t[ptr->pps[i].pictureParameterSetLength];
        
        fread(ptr
->pps[i].pictureParameterSetNALUnit,
              ptr
->pps[i].pictureParameterSetLength, 1, f);
        
        
for(int j = 0; j < ptr->pps[i].pictureParameterSetLength; ++j){
            printf(
"%x", ptr->pps[i].pictureParameterSetNALUnit[j]);
        }
        printf(
"============\n");
    }
    
    
return ptr;
}

/*final box
  @a special contain a avcC box
 
*/
struct mp4_avc1_box* mp4_read_avc1_box(FILE *f, int size)  //level 9
{
    mp4_avc1_box 
*ptr = new mp4_avc1_box;
    
    ptr
->size                   = size;
    ptr
->type                   = (('a'<<24)|('v'<<16)|('c'<<8)|('1'));
    
    fread(ptr
->reserved, sizeof(ptr->reserved), 1, f);  //6
    ptr->data_reference_index   = read_uint16_lit(f);   //2
    ptr->pre_defined            = read_uint16_big(f);   //2
    ptr->reserved1              = read_uint16_big(f);   //2
    fread(ptr->pre_defined1, sizeof(ptr->pre_defined1), 1, f);  //3*4
    ptr->width                  = read_uint16_lit(f);   //2
    ptr->height                 = read_uint16_lit(f);   //2
    ptr->horiz_res              = read_uint32_lit(f);   //4
    ptr->vert_res               = read_uint32_lit(f);   //4
    ptr->reserved2              = read_uint32_lit(f);   //4
    ptr->frames_count           = read_uint16_lit(f);   //2
    fread(ptr->compressor_name, sizeof(ptr->compressor_name), 1, f);  //33
    ptr->bit_depth              = read_uint8(f);        //1
    ptr->pre_defined2           = read_uint16_big(f);   //2

    
//avcC --AVCDecoderConfigurationRecord
    printf("-------------------------------------\n");
    printf(
"data_reference_index:%x\n", ptr->data_reference_index);
    printf(
"width:%u\n", ptr->width);
    printf(
"height:%u\n", ptr->height);
    printf(
"frames_count:%x\n", ptr->frames_count);
    printf(
"bit_depth:%u\n", ptr->bit_depth);
    printf(
"pre_defined2: %x\n", ptr->pre_defined2);
    
    ptr
->avcC = mp4_read_avcC_box(f);
    
    printf(
"-------------------------------------\n");
    
return ptr;
}

/*final box
 
*/
struct mp4_mp4a_box * mp4_read_mp4a_box(FILE*f, int size)  //level 9
{
    printf(
"\t\t\t\t\t\t+mp4a\n");
    
return 0;
}

/*container box
  (mp4a,avc1)
 
*/
struct mp4_stsd_box mp4_read_stsd_box(FILE *f, int size)  //level 8
{
    printf(
"\t\t\t\t\t+%s\n""stsd");
    mp4_stsd_box box;

    box.size               
= size;
    box.version            
= read_uint8(f);
    fread(box.flags, 
sizeof(box.flags), 1, f);
    box.number_of_entries  
= read_uint32_lit(f);

    
// printf("\t\t\t\t\t\tflags: %u\n",
    
//        box.flags[0]|box.flags[1]|box.flags[2]);
    printf("\t\t\t\t\t\tnumber of entries: %u\n", box.number_of_entries);
    
    box.sample_description 
= new Sample_description[box.number_of_entries];
    
for(int i =0; i < box.number_of_entries; ++i){
        box.sample_description[i].size 
= read_uint32_lit(f);
        box.sample_description[i].type 
= read_uint32_lit(f);
        
        
if( box.sample_description[i].type == (('m'<<24)|('p'<<16)|('4'<<8)|('a'))){
            box.sample_description[i].mp4a
                
= mp4_read_mp4a_box(f, box.sample_description[i].size);
            box.sample_description[i].avc1 
= 0;
            
        }
else if(box.sample_description[i].type
                 
== (('a'<<24)|('v'<<16)|('c'<<8)|('1'))){
            box.sample_description[i].avc1
                
= mp4_read_avc1_box(f, box.sample_description[i].size);
            box.sample_description[i].mp4a 
= 0;
        } 
    }

    
return box;
}

/*final box
 
*/
struct mp4_stss_box mp4_read_stss_box(FILE *f, int size)  //level 8
{
    printf(
"\t\t\t\t\t+%s\n""stss");
    mp4_stss_box box;
    box.size              
= size;
    box.version           
= read_uint8(f);
    fread(box.flags, 
sizeof(box.flags), 1, f);
    box.number_of_entries 
= read_uint32_lit(f);
    
    
// printf("\t\t\t\t\t\t\tflags: %u\n",
    
//        box.flags[0]|box.flags[1]|box.flags[2]);
    printf("\t\t\t\t\t\tnumber of entries: %u\n",box.number_of_entries);

    printf(
"\t\t\t\t\t\tentries:\n");
    box.sync_sample_table 
= new uint32_t[box.number_of_entries];
    
for(int i =0; i < box.number_of_entries; ++i){
        box.sync_sample_table[i] 
= read_uint32_lit(f);
        printf(
"%6u ", box.sync_sample_table[i]);
        
if( (i+1)%12 == 0) printf("\n");
    }
    
// delete box.sync_sample_table;
    printf("\n");

    
return box;
}

/*final box
 
*/
struct mp4_stsc_box mp4_read_stsc_box(FILE *f, int size)  //level 8
{
    printf(
"\t\t\t\t\t+%s\n""stsc");

    mp4_stsc_box box;
    
    box.version    
= read_uint8(f);
    fread(
&box.flags, sizeof(box.flags), 1, f);
    box.map_amount 
= read_uint32_lit(f);
   
    printf(
"\t\t\t\t\t\tmap-amount: %u\n", box.map_amount);
    
    box.scmap      
= new mp4_list_t[box.map_amount];
    printf(
"\t\t\t\t\t\tfirst trunk:\tsamples-per-thunk:\tsample-description-ID\n");
    
for(int i = 0; i < box.map_amount; ++i){
        box.scmap[i].first_chunk_num 
= read_uint32_lit(f);
        box.scmap[i].sample_amount_in_cur_table 
= read_uint32_lit(f);
        box.scmap[i].sample_description_id 
= read_uint32_lit(f);
        
        printf(
"\t\t\t\t\t\t%13d", box.scmap[i].first_chunk_num);
        printf(
"\t%13d", box.scmap[i].sample_amount_in_cur_table);
        printf(
"\t%13d\n", box.scmap[i].sample_description_id);
    }
    
//delete box.scmap;
    return box;
}

/*final box
 
*/
struct mp4_stsz_box mp4_read_stsz_box(FILE *f, int size)  //level 8
{
    printf(
"\t\t\t\t\t+%s\n""stsz");
    mp4_stsz_box box;

    box.size                 
= size;
    box.version              
= read_uint8(f);
    fread(box.flags, 
sizeof(box.flags), 1, f);
    box.samples_size_intotal 
= read_uint32_lit(f);
    
    
if(box.samples_size_intotal == 0){
        box.table_size 
= read_uint32_lit(f);
        box.sample_size_table 
= new uint32_t[box.table_size];
        
// printf("\t\t\t\t\t\tflags: 0x%x\n",
        
//        box.flags[0]|box.flags[1]|box.flags[2]);
        printf("\t\t\t\t\t\tall samples amount: %u\n", box.samples_size_intotal);
        printf(
"\t\t\t\t\t\tsample table size: %u\n", box.table_size);
        
        printf(
"\t\t\t\t\t\tsmple_size_table:\n");
        
for(int i = 0; i < box.table_size; ++i){
            box.sample_size_table[i] 
= read_uint32_lit(f);
            
            printf(
"%8u ", box.sample_size_table[i]);
            
if((i+1% 10 == 0) printf("\n");
        }
        printf(
"\n");
    }
    
    
return box;
}

/*final box
 
*/
struct mp4_stco_box mp4_read_stco_box(FILE *f, int size)
{
    printf(
"\t\t\t\t\t+%s\n""stco");
    mp4_stco_box box;

    box.version                      
= read_uint8(f);
    fread(box.flags, 
sizeof(box.flags), 1, f);
    box.chunk_offset_amount          
= read_uint32_lit(f);

    printf(
"\t\t\t\t\t\tflags: 0x %x\n",
           box.flags[
0]|box.flags[1]|box.flags[2]);
    printf(
"\t\t\t\t\t\tchunk offest amount: %u\n",
           box.chunk_offset_amount);

    printf(
"\t\t\t\t\t\tchunk offset:\n");
    box.chunk_offset_from_file_begin 
= new uint32_t[box.chunk_offset_amount];
    
for(int i = 0 ; i < box.chunk_offset_amount; ++i){
        box.chunk_offset_from_file_begin[i] 
= read_uint32_lit(f);
        printf(
"%8x ", box.chunk_offset_from_file_begin[i]);
        
if((i+1% 10 == 0) printf("\n");
    }
//    delete [] box.chunk_offset_from_file_begin;

    
return box;
}

/*container box
  (stsd, stts, stsz|stz2, stsc, stco|co64, ctts, stss)
*/
struct mp4_stbl_box mp4_read_stbl_box(FILE *f, int size)
{
    printf(
"\t\t\t\t+stbl\n");
    
    mp4_stbl_box box;
    
    VARIABLES;
    
int box_size          = 0;
    
int cur_pos           = ftell(f) ;
    
do{
        fseek(f, cur_pos, SEEK_SET);
        
        box_size          
= read_uint32_lit(f);
        fread(p, 
41, f);
        p[
4]              = 0;
        
        std::
string name  = (char*)p;
        
if(name == "stsd") {
            box.stsd      
= mp4_read_stsd_box(f, box_size);
            
//根据不同的编码方案和存储数据的文件数目,
            
//每个media可以有一个到多个sample description。
            
//sample-to-chunk atom通过这个索引表,
            
//找到合适medai中每个sample的description。
            
        } 
else if(name == "stts"){
            box.stts      
= mp4_read_stts_box(f, box_size);
            
//Time-to-sample atoms存储了media sample的duration 信息,
            
//提供了时间对具体data sample的映射方法,通过这个atom,
            
//你可以找到任何时间的sample,类型是'stts'。
            
        } 
else if(name == "stss"){
            box.stss      
= mp4_read_stss_box(f, box_size);
            
//sync sample atom确定media中的关键帧。
        } else if(name == "stsc"){
            box.stsc      
= mp4_read_stsc_box(f, box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7922.html
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7923.html
            
        } 
else if(name == "stsz" || name == "stz2"){
            box.stsz      
= mp4_read_stsz_box(f, box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7924.html
            
        } 
else if(name == "stco" || name == "c064"){
            box.stco      
= mp4_read_stco_box(f, box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7925.html
            
        } 
else if(name == "ctts") {
            
//@a undefined
        } else {
            
//printf("\t\t====size: %u\n", box_size);
            printf("\t\t\t\t\t+%s===============mark undifined\n", p);
        }
        
        cur_pos    
+= box_size;
        inner_size 
+= box_size;
    } 
while(inner_size+8 != size);
    
    
//printf("\n");
    return box;
}

/*container box
  ()
 
*/
struct mp4_dinf_box mp4_read_dinf_box(FILE *f, int size)
{
    printf(
"\t\t\t\t+dinf\n");
    
struct mp4_dinf_box box;

    
return box;
}

/*container box
  (vmhd, smhd, hmhd, nmhd)
*/
struct mp4_minf_box mp4_read_minf_box(FILE *f, int size)
{
    
struct mp4_minf_box box;
    
    printf(
"\t\t\t+%s\n""minf");

    VARIABLES;
    
int level_5_box_size = 0;
    
int cur_pos          = ftell(f) ;
    
    
do{
        fseek(f, cur_pos, SEEK_SET);
        
        level_5_box_size 
= read_uint32_lit(f);
        fread(p, 
41, f);
        p[
4= 0;
        
        std::
string name = (char*)p;
        
if(name == "vmhd") {
            box.vmhd 
= mp4_read_vmhd_box(f, level_5_box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7913.html
            
        } 
else if(name == "dinf") {
            box.dinf 
= mp4_read_dinf_box(f, level_5_box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7915.html
            
        } 
else if(name == "stbl") {
            box.stbl 
= mp4_read_stbl_box(f, level_5_box_size);
            
//@a unfind
            
        }
else if(name == "smhd"){
            box.smhd 
= mp4_read_smhd_box(f, level_5_box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7914.html
            
        } 
else {
            printf(
"\t\t====size: %u\n", level_5_box_size);
            printf(
"\t\t====type: %s\n", p);
        }
        
        cur_pos    
+= level_5_box_size;
        inner_size 
+= level_5_box_size;
    } 
while(inner_size+8 != size);
    
    printf(
"\n");
    
return box;
}

/*container box
  (mdhd, hdlr, minf)
*/
struct mp4_mdia_box mp4_read_mdia_box(FILE *f, int size)
{
    printf(
"\t\t+%s\n""mdia");
    
    mp4_mdia_box box;
    box.size              
= size;
    box.type              
= 'm' | 'd'<<8 | 'i'<<16 | 'a'<<24;
    VARIABLES;
    
int box_size          = 0;
    
int cur_pos           = ftell(f) ;
    
do{
        fseek(f, cur_pos, SEEK_SET);
        
        box_size          
= read_uint32_lit(f);
        fread(p, 
41, f);
        p[
4]              = 0;
        
        std::
string name  = (char*)p;
        
if(name == "mdhd") {
            box.mdhd      
= mp4_read_mdhd_box(f, box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7908.html
            
        } 
else if(name == "hdlr") {
            box.hdlr      
= mp4_read_hdlr_box(f, box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7909.html
            
        }
else if(name == "minf"){
            box.minf      
= mp4_read_minf_box(f, box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7910.html
            
        } 
else {
            
//printf("\t\t====size: %u\n", box_size);
            printf("\t\t====type: %s\n", p);
        }
        
        cur_pos    
+= box_size;
        inner_size 
+= box_size;
    } 
while(inner_size+8 != size);
    printf(
"\n");
    
    
return box;
}

/*container box
 
*/
struct  mp4_udta_box mp4_read_udta_box(FILE *f, int size)
{
    printf(
"\t\t+%s\n""udta");

    
return mp4_udta_box();
}

/* container box
   (tkhd, mdia)
*/
int mp4_read_trak_box(FILE *f, int size)
{
    printf(
"\t+%s\n""trak");
    
    
struct mp4_trak_box *trak  = new struct mp4_trak_box;
    VARIABLES;
    
int box_size               = 0;
    
int cur_pos                = ftell(f) ;
    
do{
        fseek(f, cur_pos, SEEK_SET);

        box_size               
= read_uint32_lit(f);
        fread(p, 
41, f);
        p[
4]                   = 0;
        std::
string name       = (char*)p;
        
if(name == "tkhd") {
            trak
->tkhd         = mp4_read_tkhd_box(f, box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7903.html
            
        } 
else if(name == "edts") {
            trak
->edts         = mp4_read_edts_box(f, box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7904.html
            
        }
else if(name == "mdia"){
            trak
->mdia         = mp4_read_mdia_box(f, box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7907.html

        } 
else if(name == "udta"){
            trak
->udta         = mp4_read_udta_box(f, box_size);
            
//same as the level 3 box, @a special
            
        } 
else {
            
//printf("\t====size: %u\n", box_size);
            printf("\t\t+%s===========\n", p);
        }
        
        cur_pos    
+= box_size;
        inner_size 
+= box_size;
    } 
while(inner_size+8 != size);

    moov.trak.push_back(trak);
}

/*final box
 
*/
int mp4_read_iods_box(FILE *f, int size)  //level 3
{
    printf(
"\t+iods-------------------------undefined\n\n");
}

/*container box
  (mvhd, trak)
*/
int mp4_read_moov_box(FILE* f, int size)   //level 2
{
    printf(
"+%s\n",  "moov");
    
    moov.size             
= size;
    moov.type             
= 'm'|'o'<<8|'o'<<16|'v'<<24;
    VARIABLES;
    
int level_2_box_size  = 0;
    
    
int cur_pos           = ftell(f);
    
do{
        fseek(f, cur_pos, SEEK_SET);
        
        level_2_box_size  
= read_uint32_lit(f);
        
        fread(
&k, sizeof(k), 1, f);  //read byte
        indian_a.size     = k;
        memcpy(p, indian_a.
bytesizeof(indian_a.byte));
        p[
4]              = 0;
        
        std::
string name  = (char*)p;
        
if(name == "mvhd"){
            mp4_read_mvhd_box(f, level_2_box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7901.html
            
        } 
else if(name == "trak") {
            mp4_read_trak_box(f, level_2_box_size);
            
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7902.html
            
        } 
else if(name == "iods"){
            mp4_read_iods_box(f, level_2_box_size);
            
        } 
else if(name == "udta"){
            mp4_read_udta_box(f, level_2_box_size);
            
//@a mark parse it, unknow what it is    
        
        } 
else {
            printf(
"====%s\n\n", p);
        }
        
        cur_pos    
+= level_2_box_size;
        inner_size 
+= level_2_box_size;
    }
while( inner_size+8 != size);
}

/*final box
 
*/
int mp4_read_ftyp_box(FILE *f, int size)  //level 2
{
    printf(
"+ftyp\n");
    
    size 
-= 8;
    
char *ch = new char[size+1];
    
for(int i = 0; i < size; ++i) {
        fread(
&ch[i], sizeof(char), 1, f);
    }
    ch[size] 
= 0;
    
    printf(
"\tftyp: %s\n",  ch);
    delete [] ch;
}

/*@a special final box
 
*/
int mp4_read_mdat_box(FILE *f, int size)
{
    printf(
"\t+%s\n""mdat");
    printf(
"\t\tthis is the real media data\n");
}

/*container box
  (ftyp, free, mdat, moov)
*/
int mp4_read_root_box(FILE *f) //level 1
{
    
int k                 = 0;
    unsigned 
char p[5];
    
    
int level_1_box_size  = read_uint32_lit(f);
    
    fread(
&k, sizeof(k), 1, f);  //read byte
    indian_a.size         = k;
    memcpy(p, indian_a.
bytesizeof(indian_a.byte));
    p[
4]                  = 0;
    
    std::
string name      = (char*)p;
    
if(name == "moov"){
        mp4_read_moov_box(f, level_1_box_size);
        
//@a http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7900.html
        
    }
else if(name == "ftyp"){
        mp4_read_ftyp_box(f, level_1_box_size);
        
    } 
else if(level_1_box_size == 0){  //till the end of file
        return 1;
        
    }  
else if(name == "mdat"){
        mp4_read_mdat_box(f, level_1_box_size);

    } 
else if(name == "free"){
        printf(
"+free\n");
        
    } 
else {
        
//printf("==%u\n", level_1_box_size);
        printf("%s==mark undifined\n", p);
    }
    
    
return level_1_box_size;
}


void print_trak(const struct mp4_trak_box * trak)
{
    printf(
"trak\n");

    
    printf(
"\t+%s\n""tkhd");
    printf(
"\t\ttrack id: %u\n", trak->tkhd.track_ID);
    printf(
"\t\tduration: %d\n", trak->tkhd.duration);
    printf(
"\t\t\tlayer: %d\n",trak->tkhd.layer);
    printf(
"\t\t\talternate group: %d\n", trak->tkhd.alternate_group);
    printf(
"\t\t\tvolume: 0x%x\n", trak->tkhd.volume);
    printf(
"\t\t\tmatrix:\n");
    
for(int i = 0; i < 3++i){
        printf(
"\t\t\t");
        
for(int j = 0; j < 3++j){
            printf(
" %8u ", trak->tkhd.matrix[i*3+j]);
        }
        printf(
"\n");
    }
    printf(
"\t\t\twidth: %u\n",trak->tkhd.width);
    printf(
"\t\t\theight: [%u].[%u]\n",
           trak
->tkhd.height & 0xffff0000 >> 16,
           trak
->tkhd.height & 0xffff);


    
    printf(
"\t+%s\n""mdia");
    
    printf(
"\t\t\t\t\t\t+stsd\n");
    printf(
"\t\t\t\t\t\t\tnumber of entries: %u\n",
           trak
->mdia.minf.stbl.stsd.number_of_entries);
    
    
// printf("\t\t\t\t\t\t+stts: time to sample\n");
    
// printf("\t\t\t\t\t\t\tentries:\n\t\t\t\t\t\t\t");
    
// for(int i =0; i < trak->mdia.minf.stbl.stts.number_of_entries; ++i){
    
//     printf("%15u ", trak->mdia.minf.stbl.stts.time_to_sample_table[i]);
    
// }
    
// printf("\n");

    
// printf("\t\t\t\t\t+stss:关键帧\n");
    
// printf("\t\t\t\t\t\t\tentries:\n\t\t\t\t\t\t\t");
    
// for(int i =0; i < trak->mdia.minf.stbl.stss.number_of_entries; ++i){
    
//     printf("%15u ", trak->mdia.minf.stbl.stss.sync_sample_table[i]);
    
// }
    
// printf("\n");

    printf(
"\t\t\t\t\t\t+stsc:sample to chunk table\n");
    printf(
"\t\t\t\t\t\tfirst trunk:\tsamples-per-thunk:\tsample-description-ID\n");
    
for(int i = 0; i < trak->mdia.minf.stbl.stsc.map_amount; ++i){
        printf(
"\t\t\t\t\t\t%13d", trak->mdia.minf.stbl.stsc.scmap[i].first_chunk_num);
        printf(
"\t%13d", trak->mdia.minf.stbl.stsc.scmap[i].sample_amount_in_cur_table);
        printf(
"\t%13d\n", trak->mdia.minf.stbl.stsc.scmap[i].sample_description_id);
    }   printf(
"\n");

    printf(
"\t\t\t\t\t\t+%s\n""stsz");
    printf(
"\t\t\t\t\t\t\tsmple_size_table:\n\t\t\t\t\t\t");
    
for(int i = 0; i < trak->mdia.minf.stbl.stsz.table_size; ++i){
        printf(
"%8u ", trak->mdia.minf.stbl.stsz.sample_size_table[i]);
    }   printf(
"\n");

    printf(
"\t\t\t\t\t\t+stco\n");
    printf(
"\t\t\t\t\t\tchunk offset:\n\t\t\t\t\t");
    
for(int i = 0 ; i < trak->mdia.minf.stbl.stco.chunk_offset_amount; ++i){
        printf(
"%8u ",trak->mdia.minf.stbl.stco.chunk_offset_from_file_begin[i]);
    }
}

uint32_t get_sample_num_in_cur_chunk(
const struct mp4_stsc_box & box,
                                     
const uint32_t chunk_index)  //begin from 0
{
    
int sample_num_in_cur_chunk_ = 0;
    
    
for(int i = 0; i < box.map_amount; ++i) {
        
if(i+1 == box.map_amount){
            
//std::cout<<"chunk_index:"<<chunk_index<<std::endl;
                
            sample_num_in_cur_chunk_
                
= box.scmap[i].sample_amount_in_cur_table;
        }

        
if(chunk_index+1 >= box.scmap[i].first_chunk_num
           
&& chunk_index+1 < box.scmap[i+1].first_chunk_num){
            sample_num_in_cur_chunk_
                
=  box.scmap[i].sample_amount_in_cur_table;
            
                 
break;
        }
    }
    
    
//std::cout<<"sample_num_in_cur_chunk_:"<< sample_num_in_cur_chunk_;
    
    
return sample_num_in_cur_chunk_;
}

/*@a return index from 0*/
uint32_t get_sample_index(
const struct mp4_stsc_box &box,
                          
const uint32_t chunk_index)  //[1,end)
{
    
/*chunk   samples   id
      1         8        1
      2         7        1
      46        6        1
    
*/
    uint32_t me     
= chunk_index;
    uint32_t sindex 
= 0;
    
    
for(int i = 0; i < box.map_amount; ++i) {
        uint32_t chunk_amount 
= 0;
        uint32_t curr         
= box.scmap[i].first_chunk_num;
        
        
if(i+1 == box.map_amount){ //end() , we can't have next one to index
            chunk_amount = me - curr;  //do not add ONE
            sindex       += box.scmap[i].sample_amount_in_cur_table * chunk_amount;
            
break;
        }
        uint32_t next    
= box.scmap[i + 1].first_chunk_num;
        
if(me > curr){
            
if(me < next){
                chunk_amount 
= me - curr;  //do not add ONE
                sindex       += box.scmap[i].sample_amount_in_cur_table * chunk_amount;
                
break;
            }
else{
                chunk_amount 
= next - curr;  //do not add ONE
                sindex       += box.scmap[i].sample_amount_in_cur_table * chunk_amount;
            }
        } 
else if(me == curr){
            
break;
        }
    }
    
return sindex;
}

uint32_t get_sample_size(
const struct mp4_stsz_box &box,
                         
const uint32_t chunk_index)  //[0, end)
{
    
for(int i = 0; i < box.table_size; ++i) {
        
if(chunk_index == i)
            
return box.sample_size_table[i];
    }
}

void copy_chunk_data(FILE *fin, 
                     
const struct mp4_stbl_box &box,
                     
const uint32_t chunk_index,  //[0, end)
                     FILE *fout)
{
    fseek(fin, box.stco.chunk_offset_from_file_begin[chunk_index],
          SEEK_SET);
    
    uint32_t sample_num_in_cur_chunk_
        
= get_sample_num_in_cur_chunk(box.stsc, chunk_index);  //@a mark
    uint32_t sample_index_
        
= get_sample_index(box.stsc, chunk_index+1);

    printf(
"%x\tindex=%u\t",
           box.stco.chunk_offset_from_file_begin[chunk_index],
           sample_index_);
    
for(int i = 0; i < sample_num_in_cur_chunk_; ++i) {
        uint32_t sample_size_ 
= get_sample_size(box.stsz, sample_index_+i);
        std::cout
<<sample_size_<<std::endl;
        uint32_t NALU_size  
= 0;
        uint32_t NALU_total 
= 0;
        
        
while(NALU_total < sample_size_){
            NALU_size           
= read_uint32_lit(fin);
            NALU_total          
+= NALU_size+4;
            printf(
"\tNALU_size:%x\n", NALU_size);
            
            
char *ptr           = new char [NALU_size];
            fread(ptr, NALU_size, 
1, fin);
            
            
static uint32_t one = 1 << 24;
            fwrite(
&one, sizeof(one), 1, fout);
            fwrite(ptr, NALU_size, 
1, fout);
            
            delete [] ptr;
            NALU_size           
= 0;
        }
    }
}

void make_file(FILE *fin, const struct mp4_trak_box * trak, std::string name)
{
    
    
int chunk_offset_amount    = trak->mdia.minf.stbl.stco.chunk_offset_amount;
    
#if RELEASE
    
struct mp4_avc1_box * avc1 =
        trak
->mdia.minf.stbl.stsd.sample_description[0].avc1;
    
    name                       
+= "x";
    FILE 
*fout                 = fopen(name.c_str(), "w");
    
if(!fout){
        std::
string tmp        = "fopen_" + name ;
        perror(tmp.c_str());
    }
    
    
if(avc1 != 0){
        uint32_t one           
= 1 << 24;
        fwrite(
&one, sizeof(one), 1, fout);
        
        
struct mp4_avcC_box * avcC = avc1->avcC;
        fwrite(avcC
->sps[0].sequenceParameterSetNALUnit,
               avcC
->sps[0].sequenceParameterSetLength, 1, fout);
        fwrite(
&one, sizeof(one), 1, fout);
        fwrite(avcC
->pps[0].pictureParameterSetNALUnit,
               avcC
->pps[0].pictureParameterSetLength, 1, fout);
    }
    
for(int chunk_index = 0 ; chunk_index < chunk_offset_amount;
        
++chunk_index) {
        copy_chunk_data(fin, trak
->mdia.minf.stbl, chunk_index, fout);
    }
    
    fclose(fout);
#else
    
    system(std::
string("rm -rf " + name).c_str());
    system(std::
string("mkdir "  + name).c_str());
    
    
for(int chunk_index = 0 ; chunk_index < chunk_offset_amount;
        
++chunk_index) {
        
char char_num[10];
        sprintf(char_num, 
"%u", chunk_index);
        
        FILE 
*fout =
            fopen(std::
string(name + "/" + name + char_num).c_str(), "w");
        
        
if(fout == (FILE*)0){
            printf(
"error\n");
            std::exit(
-1);
        }
        
        copy_chunk_data(fin, trak
->mdia.minf.stbl, chunk_index, fout);
        fclose(fout);
    }
#endif
}

int main(){
    std::ios_base::sync_with_stdio(
true);

    std::
string luo   = "luohunshidai01_001.mp4";
    std::
string _600  = "6004501011.mp4";
    
//    FILE *fin       = fopen(luo.c_str(), "r");
    FILE *fin         = fopen(_600.c_str(), "r");
    
//FILE *f_video   = fopen("video", "w+");
    
//FILE *f_audio   = fopen("audio", "w+");
    
    
if(fin == (FILE*)0){
        printf(
"failed to open\n");
        
return 0;
    }
    
    
//level 0
    int cur_pos       = ftell(fin);
    
for(; !feof(fin); ) {
        fseek(fin, cur_pos, SEEK_SET);
        printf(
"----------------------------------------level 0\n");
        cur_pos 
+= mp4_read_root_box(fin);
    }

    
//print_trak(moov.trak[0]);
    
//print_trak(moov.trak[1]);

    make_file(fin, moov.trak[
0], ("video"));
//    make_file(fin, moov.trak[1], ("audio"));

    
return 0;
}

















//filename mp4_boxes.h
#ifndef MP4_BOXES_H
#define
 MP4_BOXES_H

#include 
<vector>
#include 
<inttypes.h>


static union ____indian_swap{
    unsigned 
char byte[4];
    unsigned 
int size;
}indian_a , indian_b;

unsigned read_uint16_big(FILE 
*f)
{
    unsigned 
short k = 0;
    fread(
&k, sizeof(k), 1, f);
    
return k;
}

uint16_t read_uint16_lit(FILE 
*f)
{
    uint16_t k;
    fread(
&k, sizeof(k), 1, f);
    
return ((k&0xff00>> 8)|((k&0xff<< 8);
}

unsigned 
char read_uint8(FILE *f)
{
    unsigned 
char x;
    fread(
&x, sizeof(x), 1, f);
    
return x;
}

int read_uint32_lit(FILE *f){
    
int k = 0;
    fread(
&k, sizeof(k), 1, f);
    indian_a.size 
= k;
    
for(int i = 0, j = 3; i < 4; i++, j--)
        indian_b.
byte[i] = indian_a.byte[j];
    
    
return indian_b.size;
}

#ifndef MP4_BASE_BOX
#define MP4_BASE_BOX                            \
    uint32_t type;                              \
    uint32_t  size;
#endif

#ifndef MP4_FULL_BOX
#define MP4_FULL_BOX                            \
    MP4_BASE_BOX;                               \
    uint8_t version;                            \
    uint8_t flags[
3]
#endif

#ifndef MP4_SAMPLE_ENTRY_FIELDS
#define MP4_SAMPLE_ENTRY_FIELDS                    \
    MP4_BASE_BOX;                                \
    
char reserved[6];                            \
    uint16_t data_reference_index;
#endif

#ifndef VISUAL_SAMPLE_ENTRY_FIELDS
#define VISUAL_SAMPLE_ENTRY_FIELDS                \
    MP4_SAMPLE_ENTRY_FIELDS;                    \
    uint16_t      pre_defined;                  \
    uint16_t      reserved1;                    \
    uint32_t      pre_defined1[
3];              \
    uint16_t      width;                        \
    uint16_t      height;                       \
    uint32_t      horiz_res;                    \
    uint32_t      vert_res;                     \
    uint32_t      reserved2;                    \
    
/**/uint16_t  frames_count;                 \
    
/*以下是AVCDecoderConfigurationRecord*/     \
    
/**/char      compressor_name[33];          \
    
/**/uint16_t  bit_depth;                    \
    
/**/int16_t   pre_defined2
#endif

struct mp4_box{
    MP4_BASE_BOX;
};

struct mp4_avcC_box{
    uint32_t      size;
    uint32_t      type;
    uint8_t       configurationVersion;      
//=1
    uint8_t       AVCProfileIndication;
    uint8_t       profile_compatibility;
    uint8_t       AVCLevelIndication;
    
    uint8_t       lengthSizeMinusOne;        
// & 0x3,  ==2 bit
    uint8_t       numOfSequenceParameterSet; // & 0x1F  ==5bit
    struct SPS{
        uint16_t  sequenceParameterSetLength;
        uint8_t   
*sequenceParameterSetNALUnit;
    }             
*sps;

    uint8_t       numOfPictureParameterSets;
    
struct PPS{
        uint16_t  pictureParameterSetLength;
        uint8_t   
*pictureParameterSetNALUnit;
    }             
*pps; 
};


struct mp4_avc1_box {
    VISUAL_SAMPLE_ENTRY_FIELDS;
    
struct mp4_avcC_box *avcC;
    
struct mp4_btrt_box *btrt;
    
/*ext descriptors */
    
struct mp4_m4ds_box *m4ds;
};

struct mp4_tkhd_box {
    MP4_FULL_BOX;
    uint32_t creation_time;
    uint32_t modification_time;
    uint32_t track_ID;
    uint32_t reserved1;
    uint32_t duration;

    uint32_t reserved2[
2];
    uint16_t layer;
    uint16_t alternate_group;

    uint16_t volume;
    uint16_t reserved3;
    uint32_t matrix[
9];
    uint32_t width;
    uint32_t height;
};

struct editList{
    uint32_t trak_duration;
    uint32_t duration;
    uint32_t rate;
};

struct mp4_elst_box{
    MP4_FULL_BOX;
    uint32_t amount;
    editList 
*edit_list;
};

struct mp4_mdhd_box {
    MP4_FULL_BOX;
    uint32_t creation_time;
    uint32_t modification_time;
    uint32_t timescale;
    uint32_t duration;
    uint16_t language;
    uint16_t pre_defined;
};

struct mp4_vmhd_box{
    MP4_FULL_BOX;
    uint32_t graphics_mode;
    uint8_t opcolor[
4];  //==============take care
};

struct mp4_dref_box{
    MP4_FULL_BOX;
    uint32_t entry_count;
    
//there are many urls
    
//======================================
};

struct mp4_list_t{
    uint32_t first_chunk_num;
    uint32_t sample_amount_in_cur_table;
    uint32_t sample_description_id;
};

struct mp4_stsc_box{  //Sample-to-Chunk Atoms
    MP4_FULL_BOX;
    uint32_t map_amount;
    mp4_list_t 
*scmap; //sample-to-trunk表的结构
};

struct mp4_stsz_box{  //sample size
    MP4_FULL_BOX;
    uint32_t samples_size_intotal;
    uint32_t table_size;  
// 全部sample的数目。如果所有的sample有相同的长度,这个字段就是这个值。
                                
// 否则,这个字段的值就是0。那些长度存在sample size表中
    uint32_t *sample_size_table;  //多个sample的大小相加就是整个电影的长度
};

struct mp4_stco_box{  //Chunk Offset
    MP4_FULL_BOX;
    uint32_t chunk_offset_amount;
    uint32_t 
*chunk_offset_from_file_begin;
};

struct mp4_stss_box{  //Sync Sample 
    MP4_FULL_BOX;
    uint32_t number_of_entries;
    uint32_t 
*sync_sample_table;
};

struct mp4_stts_box{  //Time-to-Sample
    MP4_FULL_BOX;
    uint32_t number_of_entries;
    uint32_t 
*time_to_sample_table;
};

#ifndef MP4_SAMPLE_ENTRY_FIELDS
#define MP4_SAMPLE_ENTRY_FIELDS                    \
    MP4_BASE_BOX;                                \
    
char     reserved[6];                       \
    uint16_t data_reference_index;
#endif

struct mp4_mp4a_box{
};

struct Sample_description{
    uint32_t            size;
    uint32_t            type;
    
struct mp4_avc1_box *avc1;
    
struct mp4_mp4a_box *mp4a;
    
//利用这个索引可以检索与当前sample description关联的数据。
    
//数据引用存储在data reference atoms。
};

struct mp4_stsd_box{
    MP4_FULL_BOX;                           
//12 bytes
    uint32_t            number_of_entries;  //4 bytes
    Sample_description *sample_description;
};

struct mp4_smhd_box{  //sound media header box
    MP4_FULL_BOX;
    uint16_t            balance;
    uint16_t            reserved;
};

struct mp4_hdlr_box {
    MP4_FULL_BOX;
    uint32_t       pre_defined;
    uint8_t        handler_type[
5];
    uint32_t       reserved[
3];
    
char           *name;  //end with '\0'
};

/* 14496-12 8.2, media data container */
struct mp4_mdat_box {
    MP4_BASE_BOX;
    uint64_t data_size;
    
char     *data;
};

struct mp4_mvhd_box{
    MP4_FULL_BOX;                
//12
    uint32_t creation_time;      //4
    uint32_t modification_time;  //4
    uint32_t timescale;          //4
    uint32_t duration;           //4
    uint32_t rate;               //4
    uint16_t volume;             //2
    uint16_t reserved1;          //2
    uint32_t reserved2[2];       //8
    uint32_t matrix[9];          //36
    uint32_t pre_defined[6];     //24
    uint32_t next_track_id;      //4
};

struct mp4_iods_box{
};

struct mp4_udta_box{
};

struct mp4_dinf_box{
};

struct mp4_stbl_box{
    
struct mp4_stsd_box stsd;
    
struct mp4_stts_box stts;
    
struct mp4_stss_box stss;
    
struct mp4_stsc_box stsc;
    
struct mp4_stsz_box stsz;
    
struct mp4_stco_box stco;
};

struct mp4_minf_box{
    MP4_BASE_BOX;
    
struct mp4_vmhd_box *vmhd;
    
struct mp4_smhd_box *smhd;
    
struct mp4_hdlr_box hdlr;
    
struct mp4_dinf_box dinf;
    
struct mp4_stbl_box stbl;
};

struct mp4_mdia_box{
    MP4_BASE_BOX;
    
struct mp4_mdhd_box mdhd;
    
struct mp4_hdlr_box hdlr;
    
struct mp4_minf_box minf;
};

struct mp4_edts_box{
};

struct mp4_trak_box{
    
struct mp4_tkhd_box tkhd;
    
struct mp4_mdia_box mdia;
    
struct mp4_edts_box edts;
    
struct mp4_udta_box udta;
};

struct mp4_moov_box{
    MP4_BASE_BOX;
    
struct mp4_mvhd_box mvhd;
    
struct mp4_iods_box iods;
    std::vector
<struct mp4_trak_box *>
                        trak;
    
struct mp4_udta_box udta;
};

#endif  //MP4_BOXES_H