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

//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,  0 sizeof (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,  1 1 , 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];
    
    
for int  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];
    
for int  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, 
4 1 , 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, 
4 1 , 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, 
4 1 , 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, 
4 1 , 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.
byte sizeof (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.
byte sizeof (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