参考资料:

1.MP4文件格式的解析,以及MP4文件的切割算法

2.mp4文件解析(纯c解析代码)

3.MP4文件格式详解——元数据moov(一)mvhd box

4.音视频解封装:MP4核心Box详解及H264&AAC打包方案

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PRINTF_DEBUG

#define BOX_TYPE_FTYPE "ftyp"
#define BOX_TYPE_MOOV "moov"
#define BOX_TYPE_MVHD "mvhd"
#define BOX_TYPE_TRAK "trak"
#define BOX_TYPE_TKHD "tkhd"
#define BOX_TYPE_EDTS "edts"
#define BOX_TYPE_MDIA "mdia"
#define BOX_TYPE_MDHD "mdhd"
#define BOX_TYPE_HDLR "hdlr"
#define BOX_TYPE_MINF "minf"
#define BOX_TYPE_VMHD "vmhd"
#define BOX_TYPE_DINF "dinf"
#define BOX_TYPE_DREF "dref"
#define BOX_TYPE_STBL "stbl"
#define BOX_TYPE_STSD "stsd"
#define BOX_TYPE_STTS "stts"
#define BOX_TYPE_STSS "stss"
#define BOX_TYPE_STSC "stsc"
#define BOX_TYPE_STSZ "stsz"
#define BOX_TYPE_STCO "stco"
#define BOX_TYPE_UDTA "udta"

#define MAX_BOX_SIZE_LEN 4
#define MAX_BOX_TYPE_LEN 4
#define MAX_HANDLER_TYPE_LEN 4
#define MAX_FTYP_BRABDS_LEN 4
#define MAX_FTYP_BRABDS_NUM 4
#define MAX_STTS_ENTRY_NUM 8
#define MAX_STSS_ENTRY_NUM 8
#define MAX_STSC_ENTRY_NUM 100
#define MAX_STSZ_ENTRY_NUM 100 /* now parse 100 frame */
#define MAX_STCO_ENTRY_NUM 100
#define MAX_MVHD_RESERVED_LEN 10
#define MAX_PRE_DEFINE_LEN 24
#define MAX_MATRIX_LEN 36
#define MAX_HDLR_NAME_LEN 100


typedef struct t_box_header
{
    int boxSize;

    unsigned char boxType[MAX_BOX_TYPE_LEN+1];

    long largeBoxSize; /* if boxSize=1 use, if boxSize=0, end of file */
} T_BOX_HEADER;

/********************************************************************************************
**                            File Type Box (ftyp): file type, 表明文件类型
**
--------------------------------------------------------------------------------------------
**        字段名称              |    长度(bytes)   |        有关描述
--------------------------------------------------------------------------------------------
**        boxsize               |    4            |        box的长度
**        boxtype               |    4            |        box的类型
**        major_brand           |    4            |
**        minor_version         |    4            |        版本号
**        compatible_brands     |    4 * N        |        本文件遵从的多种协议(ismo, iso2, mp41)
********************************************************************************************/
typedef struct t_box4ftyp_brand
{
    unsigned char brands[MAX_FTYP_BRABDS_LEN+1];
} T_BOX4FTYP_BRAN;

typedef struct t_box4ftyp
{
    unsigned char major_brand[MAX_FTYP_BRABDS_LEN+1];

    int minor_version;

    T_BOX4FTYP_BRAN compatible_brands[MAX_FTYP_BRABDS_NUM];
} T_BOX4FTYP;

/************************************************************************************************************
**                                            mvhd: movie header, 文件的总体信息: 时长, 创建时间等
**
--------------------------------------------------------------------------------------------
**        字段名称              |    长度(bytes)   |        有关描述
--------------------------------------------------------------------------------------------
**        boxsize               |    4            |        box的长度
**        boxtype               |    4            |        box的类型
**        version               |    1            |        box版本,0或1,一般为0(以下字节数均按version = 0)
**        flags                 |    3            |
**        creation time         |    4            |        创建时间(相对于UTC时间1904 - 01 - 01零点的秒数)
**        modification time     |    4            |        修改时间
**        time scale            |    4            |        文件媒体在1秒时间内的刻度值,可以理解为1秒长度的时间单元数
**        duration              |    4            |        该track的时间长度,用duration和time scale值可以计算track时长
**        rate                  |    4            |        推荐播放速率,高16位和低16位分别为小数点整数部分和小数部分,即[16.16] 格式.该值为1.0 (0x00010000)
**        volume                |    2            |        与rate类似,[8.8] 格式,1.0(0x0100)表示最大音量
**        reserved              |    10           |        保留位
**        matrix                |    36           |        视频变换矩阵
**        pre-defined           |    24           |
**        next track id         |    4            |        下一个track使用的id号
**
if (version==1)
{
    unsigned int(64) creation_time;
    unsigned int(64) modification_time;
    unsigned int(32) timescale;
    unsigned int(64) duration;
}
else
{
    unsigned int(32) creation_time;
    unsigned int(32) modification_time;
    unsigned int(32) timescale;
    unsigned int(32) duration;
}
************************************************************************************************************/
typedef struct t_box4mvhd
{
    int creation_time;
    int modification_time;
    int timescale;
    int duration;
    float rate;
    float volume;
    int next_track_id;
} T_BOX4MVHD;

/************************************************************************************************************
**                                        tkhd: track header, track的总体信息, 如时长, 宽高等
**
-------------------------------------------------------------------------------------------------------------
**        字段名称               |    长度(bytes)   |        有关描述
-------------------------------------------------------------------------------------------------------------
**        boxsize                |    4            |        box的长度
**        boxtype                |    4            |        box的类型
**        version                |    1            |        box版本,0或1,一般为0。(以下字节数均按version = 0)
**        flags                  |    3            |        按位或操作结果值,预定义如下;
                                                         0x000001 track_enabled,否则该track不被播放;
                                                         0x000002 track_in_movie,表示该track在播放中被引用;
                                                         0x000004 track_in_preview,表示该track在预览时被引用。
                                                         一般该值为7,如果一个媒体所有track均未设置track_in_movie和track_in_preview,将被理解为所有track均设置了这两项;
                                                         对于hint track,该值为0;
**        creation_time          |    4            |        创建时间(相对于UTC时间1904 - 01 - 01零点的秒数)
**        modification_time      |    4            |        修改时间
**        track_id               |    4            |        id号 不能重复且不能为0
**        reserved               |    4            |        保留位
**        duration               |    4            |        track的时间长度
**        reserved               |    8            |        保留位
**        layer                  |    2            |        视频层,默认为0,值小的在上层
**        alternate_group        |    2            |        track分组信息,默认为0表示该track未与其他track有群组关系
**        volume                 |    2            |        [8.8] 格式,如果为音频track,1.0(0x0100)表示最大音量;否则为0
**        reserved               |    2            |        保留位
**        matrix                 |    36           |        视频变换矩阵
**        width                  |    4            |        宽
**        height                 |    4            |        高,均为[16.16] 格式值 与sample描述中的实际画面大小比值,用于播放时的展示宽高
if (version==1)
{
    unsigned int(64) creation_time;
    unsigned int(64) modification_time;
    unsigned int(32) track_ID;
    const unsigned int(32) reserved = 0;
    unsigned int(64) duration;
}
else
{
    unsigned int(32) creation_time;
    unsigned int(32) modification_time;
    unsigned int(32) track_ID;
    const unsigned int(32) reserved = 0;
    unsigned int(32) duration;
}
************************************************************************************************************/
typedef struct t_box4tkhd
{
    int flags;
    int creation_time;
    int modification_time;
    int track_id;
    int duration;
    int layer;
    int alternate_group;
    float volume;
    float width;
    float height;
} T_BOX4TKHD;

/************************************************************************************************************
**                                        mdhd: 包含了了该track的总体信息, mdhd和tkhd 内容大致都是一样的.
**
-------------------------------------------------------------------------------------------------------------
**        字段名称              |      长度(bytes)   |        有关描述
-------------------------------------------------------------------------------------------------------------
**        boxsize               |    4                |        box的长度
**        boxtype               |    4                |        box的类型
**        version               |    1         |        box版本0或1 一般为0 (以下字节数均按version=0)
**        flags                 |    3                |
**        creation_time         |    4                |        创建时间(相对于UTC时间1904 - 01 - 01零点的秒数)
**        modification_time     |    4                |        修改时间
**        time_scale            |    4                |
**        duration              |    4               |        track的时间长度
**        language              |    2               |        媒体语言码,最高位为0 后面15位为3个字符[见ISO 639-2/T标准中定义]
**        pre-defined           |    2                |        保留位

** tkhd通常是对指定的track设定相关属性和内容, 而mdhd是针对于独立的media来设置的, 一般情况下二者相同.
************************************************************************************************************/
typedef struct t_box4mdhd
{
    int creation_time;
    int modification_time;
    int timescale;
    int duration;
    short language;
} T_BOX4MDHD;

/************************************************************************************************************
**                                        hdlr: Handler Reference Box, 媒体的播放过程信息, 该box也可以被包含在meta box(meta)中
**
-------------------------------------------------------------------------------------------------------------
**        字段名称               |    长度(bytes)    |        有关描述
-------------------------------------------------------------------------------------------------------------
**        boxsize                |    4             |        box的长度
**        boxtype                |    4             |        box的类型
**        version                |    1             |        box版本0或1 一般为0 (以下字节数均按version=0)
**        flags                  |    3             |
**        pre-defined            |    4             |
**        handler type           |    4             |        在media box中,该值为4个字符
                                                          "vide"— video track
                                                          "soun"— audio track
                                                          "hint"— hint track
**        reserved               |    12            |
**        name                   |    不定           |        track type name,以‘\0’结尾的字符串
************************************************************************************************************/
typedef struct t_box4hdlr
{
    unsigned char handler_type[MAX_HANDLER_TYPE_LEN+1];
    unsigned char name[MAX_HDLR_NAME_LEN+1];
} T_BOX4HDLR;

/************************************************************************************************************
**                                        vmhd: Video Media Header Box
**
-------------------------------------------------------------------------------------------------------------
**        字段名称            |    长度(bytes)    |        有关描述
-------------------------------------------------------------------------------------------------------------
**        boxsize                |    4            |        box的长度
**        boxtype                |    4            |        box的类型
**        version                |    1            |        box版本0或1 一般为0 (以下字节数均按version=0)
**        flags                     |    3            |
**        graphics_mode          |    4            |        视频合成模式,为0时拷贝原始图像,否则与opcolor进行合成
**        opcolor                |    2 ×3         |        {red,green,blue}

"vide"—vmhd 视频
"soun"— smhd 音频
"hint"—hmhd 忽略
************************************************************************************************************/
typedef struct t_box4vmhd
{
    int graphics_mode;
} T_BOX4VMHD;

/************************************************************************************************************
**                                        dref: data reference box
**
-------------------------------------------------------------------------------------------------------------
**        字段名称               |    长度(bytes)    |        有关描述
-------------------------------------------------------------------------------------------------------------
**        boxsize                |    4             |        box的长度
**        boxtype                |    4             |        box的类型
**        version                |    1             |        box版本0或1 一般为0 (以下字节数均按version=0)
**        flags                  |    3             |
**        entry count            |    4             |         "url"或"urn"表的元素个数
**        "url"或"urn"列表       |    不定          |

** "dref"下会包含若干个"url"或"urn", 这些box组成一个表, 用来定位track数据. 简单的说, track可以被分成若干段,
   每一段都可以根据"url"或"urn"指向的地址来获取数据, sample描述中会用这些片段的序号将这些片段组成一个完整的track.
   一般情况下, 当数据被完全包含在文件中时, "url"或"urn"中的定位字符串是空的.
************************************************************************************************************/
typedef struct t_box4dref
{
    int entry_count;
} T_BOX4DREF;

/************************************************************************************************************
**                                        stsd: Sample Description Box
**
-------------------------------------------------------------------------------------------------------------
**        字段名称               |    长度(bytes)    |        有关描述
-------------------------------------------------------------------------------------------------------------
**        boxsize                |    4             |        box的长度
**        boxtype                |    4             |        box的类型
**        version                |    1             |        box版本0或1 一般为0 (以下字节数均按version=0)
**        entry count            |    4             |         "url"或"urn"表的元素个数

** box header和version字段后会有一个entry count字段, 根据entry的个数, 每个entry会有type信息, 如"vide", "sund"等,
   根据type不同sample description会提供不同的信息, 例如对于video track, 会有"VisualSampleEntry"类型信息,
   对于audio track会有"AudioSampleEntry"类型信息. 视频的编码类型, 宽高, 长度, 音频的声道, 采样等信息都会出现在这个box中
************************************************************************************************************/
typedef struct t_box4stsd
{
    int entry_count;

    //TODO
} T_BOX4STSD;

/************************************************************************************************************
**                                        stts: Time To Sample Box
**
-------------------------------------------------------------------------------------------------------------
**        字段名称               |    长度(bytes)    |        有关描述
-------------------------------------------------------------------------------------------------------------
**        boxsize                |    4             |        box的长度
**        boxtype                |    4             |        box的类型
**        version                |    1             |        box版本,0或1,一般为0(以下字节数均按version = 0)
**        flags                  |    3             |
**        entry count            |    4             |         sample_count和sample_delta的个数
**        sample_count           |    4             |
**        sample_delta           |    4             |

** "stts”"存储了sample的duration, 描述了sample时序的映射方法, 我们通过它可以找到任何时间的sample. "stts"可以
   包含一个压缩的表来映射时间和sample序号, 用其他的表来提供每个sample的长度和指针. 表中每个条目提供了在同一个
   时间偏移量里面连续的sample序号, 以及samples的偏移量. 递增这些偏移量, 就可以建立一个完整的time to sample表.

   例: 说明该视频包含87帧数据(sample_count), 每帧包含512个采样(sample_delta). 总共512*87=44544个采样,
       和我们前面mdhd box的Duration完全一致。
       Duration/TimeScale = 44544/12288 = 3.625s, 正是我们的视频播放长度.
       12288/512 = 24 p/s (帧率)
************************************************************************************************************/
typedef struct t_box4stts_entry
{
    int sample_count;
    int sample_delta;
} T_BOX4STTS_ENTRY;

typedef struct t_box4stts
{
    int entry_count;

    T_BOX4STTS_ENTRY entrys[MAX_STTS_ENTRY_NUM];
} T_BOX4STTS;

/************************************************************************************************************
**                                        stss: Sync Sample Box
**
-------------------------------------------------------------------------------------------------------------
**        字段名称               |    长度(bytes)    |        有关描述
-------------------------------------------------------------------------------------------------------------
**        boxsize                |    4             |        box的长度
**        boxtype                |    4             |        box的类型
**        version                |    1             |        box版本,0或1,一般为0(以下字节数均按version = 0)
**        flags                  |    3             |
**        entry count            |    4             |         sample_num的个数
**        sample_num                |    4             |

** "stss"确定media中的关键帧. 对于压缩媒体数据, 关键帧是一系列压缩序列的开始帧, 其解压缩时不依赖以前的帧,
   而后续帧的解压缩将依赖于这个关键帧. "stss"可以非常紧凑的标记媒体内的随机存取点, 它包含一个sample序号表,
   表内的每一项严格按照sample的序号排列, 说明了媒体中的哪一个sample是关键帧. 如果此表不存在, 说明每一个sample
   都是一个关键帧, 是一个随机存取点.
************************************************************************************************************/
typedef struct t_box4stss_entry
{
    int sample_num;
} T_BOX4STSS_ENTRY;

typedef struct t_box4stss
{
    int entry_count;

    T_BOX4STSS_ENTRY entrys[MAX_STSS_ENTRY_NUM];
} T_BOX4STSS;

/************************************************************************************************************
**                                        stsc: Sample To Chunk Box
**
-------------------------------------------------------------------------------------------------------------
**        字段名称               |    长度(bytes)    |        有关描述
-------------------------------------------------------------------------------------------------------------
**        boxsize                |    4             |        box的长度
**        boxtype                |    4             |        box的类型
**        version                |    1             |        box版本,0或1,一般为0(以下字节数均按version = 0)
**        flags                  |    3             |
**        entry count            |    4             |         entry的个数
**        first_chunk            |    4             |
**        samples_per_chunk      |    4             |
**        sample_des_index       |    4             |

** 用chunk组织sample可以方便优化数据获取, 一个thunk包含一个或多个sample. "stsc"中用一个表描述了sample与chunk的映射关系,
   查看这张表就可以找到包含指定sample的thunk, 从而找到这个sample.
************************************************************************************************************/
typedef struct t_box4stsc_entry
{
    int first_chunk;
    int samples_per_chunk;
    int sample_description_index;
} T_BOX4STSC_ENTRY;

typedef struct t_box4stsc
{
    int entry_count;

    T_BOX4STSC_ENTRY entrys[MAX_STSC_ENTRY_NUM];
} T_BOX4STSC;

/************************************************************************************************************
**                                        stsz: Sample To Chunk Box
**
-------------------------------------------------------------------------------------------------------------
**        字段名称               |    长度(bytes)    |        有关描述
-------------------------------------------------------------------------------------------------------------
**        boxsize                |    4             |        box的长度
**        boxtype                |    4             |        box的类型
**        version                |    1             |        box版本,0或1,一般为0(以下字节数均按version = 0)
**        flags                  |    3             |
**        sample_size            |    4             |
**        sample_count           |    4             |         entry的个数
**        entry_size             |    4             |

**  "stsz"定义了每个sample的大小, 包含了媒体中全部sample的数目和一张给出每个sample大小的表. 这个box相对来说体积是比较大的.
************************************************************************************************************/
typedef struct t_box4stsz_entry
{
    int entry_size;
} T_BOX4STSZ_ENTRY;

typedef struct t_box4stsz
{
    int sample_size;
    int sample_count;

    T_BOX4STSZ_ENTRY entrys[MAX_STSZ_ENTRY_NUM];
} T_BOX4STSZ;

/************************************************************************************************************
**                                        stco: Chunk Offset Box
**
-------------------------------------------------------------------------------------------------------------
**        字段名称               |    长度(bytes)    |        有关描述
-------------------------------------------------------------------------------------------------------------
**        boxsize                |    4             |        box的长度
**        boxtype                |    4             |        box的类型
**        version                |    1             |        box版本,0或1,一般为0(以下字节数均按version = 0)
**        flags                  |    3             |
**        entry_count            |    4             |
**        chunk_offset           |    4             |

**  "stco"定义了每个thunk在媒体流中的位置, sample的偏移可以根据其他box推算出来. 位置有两种可能, 32位的和64位的,
    后者对非常大的电影很有用. 在一个表中只会有一种可能, 这个位置是在整个文件中的, 而不是在任何box中的.
    这样做就可以直接在文件中找到媒体数据, 而不用解释box. 需要注意的是一旦前面的box有了任何改变, 这张表都要重新建立, 因为位置信息已经改变了.
************************************************************************************************************/
typedef struct t_box4stco_entry
{
    int chunk_offset;
} T_BOX4STCO_ENTRY;

typedef struct t_box4stco
{
    int entry_count;

    T_BOX4STCO_ENTRY entrys[MAX_STCO_ENTRY_NUM];
} T_BOX4STCO;

typedef struct t_box
{
    T_BOX_HEADER boxHeader;

    unsigned char *boxData;
} T_BOX;

static void DealBox4ftyp(const T_BOX *box)
{
    int i = 0;
    int j = 0;
    int brandsNum = 0;

    T_BOX4FTYP box4ftyp = {0};

    memset(&box4ftyp, 0x0, sizeof(T_BOX4FTYP));

    memcpy(box4ftyp.major_brand, box->boxData, 4);
    box4ftyp.major_brand[MAX_FTYP_BRABDS_LEN] = '\0';

    box4ftyp.minor_version =  box->boxData[4] << 24 | box->boxData[5] << 16 | box->boxData[6] << 8 | box->boxData[7];

    brandsNum = (box->boxHeader.boxSize - MAX_BOX_SIZE_LEN - MAX_BOX_TYPE_LEN - MAX_FTYP_BRABDS_LEN - 4) / 4;

    /* 1. if not have '\0', 每个brands的内存是连续的, 导致打印时后面的每4个数据都会加到前面;
       2. unsigned char brands[MAX_FTYP_BRABDS_LEN+1]; 可解决, 此时也不必加'\0', 但需初始化;
       3. 因此字符串最好定义+1并赋'\0';
       4. 复现: unsigned char brands[MAX_FTYP_BRABDS_LEN]
    */
    for (i=0; i<brandsNum; i++)
    {
        memcpy(box4ftyp.compatible_brands[i].brands, box->boxData+MAX_FTYP_BRABDS_LEN+4+4*i, 4);

        box4ftyp.compatible_brands[i].brands[MAX_FTYP_BRABDS_LEN] = '\0';
    }

#ifdef PRINTF_DEBUG
    printf("\tmajor_brand: %s, minor_version: %d, compatible_brands: ", box4ftyp.major_brand, box4ftyp.minor_version);

    for (i=0; i<brandsNum; i++)
    {
        if (i==brandsNum-1)
        {
            printf("%s", box4ftyp.compatible_brands[i].brands);
        }
        else
        {
            printf("%s,", box4ftyp.compatible_brands[i].brands);
        }
    }

    printf("\n");
#endif
}

static void DealBox4mvhd(const unsigned char *mvhdData)
{
    unsigned char *data = NULL;

    T_BOX4MVHD box4mvhd = {0};

    memset(&box4mvhd, 0x0, sizeof(T_BOX4MVHD));

    data = (unsigned char *)mvhdData;

    data += 4;
    box4mvhd.creation_time = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;
    box4mvhd.modification_time = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;
    box4mvhd.timescale = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;
    box4mvhd.duration = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;
    //box4mvhd.rate = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
    box4mvhd.rate = (data[0] << 8 | data[1]) + (data[2] << 8 | data[3]);

    data += 4;
    //box4mvhd.volume = data[0] << 8 | data[1];
    box4mvhd.volume = data[0] + data[1];

    data += 2;
    data += (MAX_MVHD_RESERVED_LEN + MAX_PRE_DEFINE_LEN + MAX_MATRIX_LEN);
    box4mvhd.next_track_id = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

#ifdef PRINTF_DEBUG
    printf("\t\tcreation_time: %d, modification_time: %d, timescale: %d, duration: %d, rate: %f, volume: %f, next_track_id: %d\n",
            box4mvhd.creation_time, box4mvhd.modification_time, box4mvhd.timescale, box4mvhd.duration, box4mvhd.rate, box4mvhd.volume, box4mvhd.next_track_id);
#endif
}

static void DealBox4tkhd(const unsigned char *tkhdData)
{
    unsigned char *data = NULL;

    T_BOX4TKHD box4tkhd = {0};

    memset(&box4tkhd, 0x0, sizeof(box4tkhd));

    data = (unsigned char *)tkhdData;

    box4tkhd.flags = data[1] << 16 | data[2] << 8 | data[3];

    data += 4;
    box4tkhd.creation_time = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;
    box4tkhd.modification_time = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;
    box4tkhd.track_id = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;

    data += 4; /* 4 reserved */
    box4tkhd.duration = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;

    data += 8; /* 8 reserved */
    box4tkhd.layer = data[0] << 8 | data[1];

    data += 2;
    box4tkhd.alternate_group = data[0] << 8 | data[1];

    data += 2;
    box4tkhd.volume = data[0] + data[1];

    data += 2;

    data += 2;

    data += 36;
    box4tkhd.width = (data[0] << 8 | data[1]) + (data[2] << 8 | data[3]);

    data += 4;
    box4tkhd.height = (data[0] << 8 | data[1]) + (data[2] << 8 | data[3]);

#ifdef PRINTF_DEBUG
    printf("\t\t\tflags: %d, creation_time: %d, modification_time: %d, track_id: %d, duration: %d, layer: %d, alternate_group: %d, volume: %f, width: %f, height: %f\n",
            box4tkhd.flags, box4tkhd.creation_time, box4tkhd.modification_time, box4tkhd.track_id, box4tkhd.duration, box4tkhd.layer, box4tkhd.alternate_group, box4tkhd.volume, box4tkhd.width, box4tkhd.height);
#endif
}

static void DealBox4dref(const T_BOX *box)
{
    // TODO
}

static void DealBox4dinf(const T_BOX *box)
{    int boxSize = 0;
    int dinfDataSize = 0;

    unsigned char *dinfData = NULL;
    unsigned char *data = NULL;

    char boxType[MAX_BOX_TYPE_LEN+1] = {0};

    T_BOX drefBox = {0};

    dinfData = box->boxData;
    dinfDataSize = box->boxHeader.boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN;

    while (dinfDataSize > 0)
    {
        boxSize = dinfData[0] << 24 | dinfData[1] << 16 | dinfData[2] << 8 | dinfData[3];

        memcpy(boxType, dinfData+MAX_BOX_SIZE_LEN, 4);

#ifdef PRINTF_DEBUG
    printf("\t\t\t\t\t****BOX: Layer6****\n");
    printf("\t\t\t\t\t\tsize: %d\n", boxSize);
    printf("\t\t\t\t\t\ttype: %s\n", boxType);
#endif
        if (0 == strcmp(boxType, BOX_TYPE_DREF))
        {
            memset(&drefBox, 0x0, sizeof(T_BOX));

            drefBox.boxHeader.boxSize = boxSize;

            memcpy(drefBox.boxHeader.boxType, boxType, strlen(boxType));

            drefBox.boxData = (unsigned char*)malloc(boxSize);
            if (drefBox.boxData)
            {
                memcpy(drefBox.boxData, dinfData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4dref((const T_BOX*)&drefBox);

                free(drefBox.boxData);
                drefBox.boxData = NULL;
            }
        }

        dinfData += boxSize;
        dinfDataSize -= boxSize;
    }
}

static void DealBox4stts(const unsigned char *sttsData)
{
    int i = 0;

    unsigned char *data = NULL;

    T_BOX4STTS box4stts = {0};

    memset(&box4stts, 0x0, sizeof(box4stts));

    data = (unsigned char *)sttsData;

    data += 4;

    box4stts.entry_count = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;

    for (i=0; i<box4stts.entry_count; i++)
    {
        if (i == MAX_STTS_ENTRY_NUM)
        {
            break;
        }

        box4stts.entrys[i].sample_count = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

        data += 4;

        box4stts.entrys[i].sample_delta = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

        data += 4;
    }

#ifdef PRINTF_DEBUG
    printf("\t\t\tentry_count: %d, [sample_count, sample_delta]: ", box4stts.entry_count);

    if (box4stts.entry_count>MAX_STTS_ENTRY_NUM)
    {
        box4stts.entry_count = MAX_STTS_ENTRY_NUM;
    }

    for (i=0; i<box4stts.entry_count; i++)
    {
        if (i>0)
        {
            printf(", ");
        }

        printf("[%d, %d]", box4stts.entrys[i].sample_count, box4stts.entrys[i].sample_delta);
    }

    if (box4stts.entry_count==MAX_STTS_ENTRY_NUM)
    {
        printf("...(just show %d now)", MAX_STTS_ENTRY_NUM);
    }

    printf("\n");
#endif
}

static void DealBox4stss(const unsigned char *stssData)
{
    int i = 0;

    unsigned char *data = NULL;

    T_BOX4STSS box4stss = {0};

    memset(&box4stss, 0x0, sizeof(box4stss));

    data = (unsigned char *)stssData;

    data += 4;

    box4stss.entry_count = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;

    for (i=0; i<box4stss.entry_count; i++)
    {
        if (i == MAX_STSS_ENTRY_NUM)
        {
            break;
        }

        box4stss.entrys[i].sample_num = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

        data += 4;
    }

#ifdef PRINTF_DEBUG
    printf("\t\t\tentry_count: %d, sample_num: ", box4stss.entry_count);

    if (box4stss.entry_count>MAX_STSS_ENTRY_NUM)
    {
        box4stss.entry_count = MAX_STSS_ENTRY_NUM;
    }

    for (i=0; i<box4stss.entry_count; i++)
    {
        if (i>0)
        {
            printf(", ");
        }

        printf("%d", box4stss.entrys[i].sample_num);
    }

    if (box4stss.entry_count==MAX_STSS_ENTRY_NUM)
    {
        printf("...(just show %d now)", MAX_STSS_ENTRY_NUM);
    }

    printf("\n");
#endif
}

static void DealBox4stsc(const unsigned char *stscData)
{
    int i = 0;

    unsigned char *data = NULL;

    T_BOX4STSC box4stsc = {0};

    memset(&box4stsc, 0x0, sizeof(box4stsc));

    data = (unsigned char *)stscData;

    data += 4;

    box4stsc.entry_count = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;

    for (i=0; i<box4stsc.entry_count; i++)
    {
        if (i == MAX_STSC_ENTRY_NUM)
        {
            break;
        }

        box4stsc.entrys[i].first_chunk = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

        data += 4;

        box4stsc.entrys[i].samples_per_chunk = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

        data += 4;

        box4stsc.entrys[i].sample_description_index = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

        data += 4;
    }

#ifdef PRINTF_DEBUG
    printf("\t\t\tentry_count: %d, [first_chunk, samples_per_chunk, sample_description_index]: ", box4stsc.entry_count);

    if (box4stsc.entry_count>MAX_STSC_ENTRY_NUM)
    {
        box4stsc.entry_count = MAX_STSC_ENTRY_NUM;
    }

    for (i=0; i<box4stsc.entry_count; i++)
    {
        if (i>0)
        {
            printf(", ");
        }

        printf("[%d, %d, %d]", box4stsc.entrys[i].first_chunk, box4stsc.entrys[i].samples_per_chunk, box4stsc.entrys[i].sample_description_index);
    }

    if (box4stsc.entry_count==MAX_STSC_ENTRY_NUM)
    {
        printf("...(just show %d now)", MAX_STSC_ENTRY_NUM);
    }

    printf("\n");
#endif
}

static void DealBox4stsz(const unsigned char *stszData)
{
    int i = 0;

    unsigned char *data = NULL;

    T_BOX4STSZ box4stsz = {0};

    memset(&box4stsz, 0x0, sizeof(box4stsz));

    data = (unsigned char *)stszData;

    data += 4;

    box4stsz.sample_size = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;

    box4stsz.sample_count = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;

    for (i=0; i<box4stsz.sample_count; i++)
    {
        if (i == MAX_STSZ_ENTRY_NUM)
        {
            break;
        }

        box4stsz.entrys[i].entry_size = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

        data += 4;
    }

#ifdef PRINTF_DEBUG
    printf("\t\t\tsample_size: %d, sample_count: %d, [entry_size]: ", box4stsz.sample_size, box4stsz.sample_count);

    if (box4stsz.sample_count>MAX_STSZ_ENTRY_NUM)
    {
        box4stsz.sample_count = MAX_STSZ_ENTRY_NUM;
    }

    for (i=0; i<box4stsz.sample_count; i++)
    {
        if (i>0)
        {
            printf(", ");
        }

        printf("[%d]", box4stsz.entrys[i].entry_size);
    }

    if (box4stsz.sample_count==MAX_STSZ_ENTRY_NUM)
    {
        printf("...(just show %d now)", MAX_STSZ_ENTRY_NUM);
    }

    printf("\n");
#endif
}

static void DealBox4stco(const unsigned char *stcoData)
{
    int i = 0;

    unsigned char *data = NULL;

    T_BOX4STCO box4stco = {0};

    memset(&box4stco, 0x0, sizeof(box4stco));

    data = (unsigned char *)stcoData;

    data += 4;

    box4stco.entry_count = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;

    for (i=0; i<box4stco.entry_count; i++)
    {
        if (i == MAX_STCO_ENTRY_NUM)
        {
            break;
        }

        box4stco.entrys[i].chunk_offset = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

        data += 4;
    }

#ifdef PRINTF_DEBUG
    printf("\t\t\entry_count: %d, [chunk_offset]: ", box4stco.entry_count);

    if (box4stco.entry_count>MAX_STCO_ENTRY_NUM)
    {
        box4stco.entry_count = MAX_STCO_ENTRY_NUM;
    }

    for (i=0; i<box4stco.entry_count; i++)
    {
        if (i>0)
        {
            printf(", ");
        }

        printf("[%d]", box4stco.entrys[i].chunk_offset);
    }

    if (box4stco.entry_count==MAX_STCO_ENTRY_NUM)
    {
        printf("...(just show %d now)", MAX_STCO_ENTRY_NUM);
    }

    printf("\n");
#endif
}

static void DealBox4stbl(const T_BOX *box)
{
    int boxSize = 0;
    int stblDataSize = 0;

    unsigned char *stblData = NULL;
    unsigned char *data = NULL;

    char boxType[MAX_BOX_TYPE_LEN+1] = {0};

    stblData = box->boxData;
    stblDataSize = box->boxHeader.boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN;

    while (stblDataSize > 0)
    {
        boxSize = stblData[0] << 24 | stblData[1] << 16 | stblData[2] << 8 | stblData[3];

        memcpy(boxType, stblData+MAX_BOX_SIZE_LEN, 4);

#ifdef PRINTF_DEBUG
    printf("\t\t\t\t\t****BOX: Layer6****\n");
    printf("\t\t\t\t\t\tsize: %d\n", boxSize);
    printf("\t\t\t\t\t\ttype: %s\n", boxType);
#endif

        if (0 == strcmp(boxType, BOX_TYPE_STTS))
        {
            data = (unsigned char*)malloc(boxSize);
            if (data)
            {
                memcpy(data, stblData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4stts(data);

                free(data);
                data = NULL;
            }
        }
        else if (0 == strcmp(boxType, BOX_TYPE_STSS))
        {
            data = (unsigned char*)malloc(boxSize);
            if (data)
            {
                memcpy(data, stblData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4stss(data);

                free(data);
                data = NULL;
            }
        }
        else if (0 == strcmp(boxType, BOX_TYPE_STSC))
        {
            data = (unsigned char*)malloc(boxSize);
            if (data)
            {
                memcpy(data, stblData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4stsc(data);

                free(data);
                data = NULL;
            }
        }
        else if (0 == strcmp(boxType, BOX_TYPE_STSZ))
        {
            data = (unsigned char*)malloc(boxSize);
            if (data)
            {
                memcpy(data, stblData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4stsz(data);

                free(data);
                data = NULL;
            }
        }
        else if (0 == strcmp(boxType, BOX_TYPE_STCO))
        {
            data = (unsigned char*)malloc(boxSize);
            if (data)
            {
                memcpy(data, stblData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4stco(data);

                free(data);
                data = NULL;
            }
        }

        stblData += boxSize;
        stblDataSize -= boxSize;
    }
}

static void DealBox4mdhd(const unsigned char *mdhdData)
{
    unsigned char *data = NULL;

    T_BOX4MDHD box4mdhd = {0};

    memset(&box4mdhd, 0x0, sizeof(box4mdhd));

    data = (unsigned char *)mdhdData;

    data += 4;
    box4mdhd.creation_time = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;
    box4mdhd.modification_time = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;
    box4mdhd.timescale = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;
    box4mdhd.duration = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

    data += 4;
    box4mdhd.language = data[0] << 8 | data[1];

#ifdef PRINTF_DEBUG
    //printf("\t\t\tcreation_time: %d, modification_time: %d, timescale: %d, duration: %d, language: %c%c%c\n",
            //box4mdhd.creation_time, box4mdhd.modification_time, box4mdhd.timescale, box4mdhd.duration, (box4mdhd.language>>10&0x1f), (box4mdhd.language>>5&0x1f), (box4mdhd.language&0x1f));

    printf("\t\t\t\tcreation_time: %d, modification_time: %d, timescale: %d, duration: %d, language:%d\n",
            box4mdhd.creation_time, box4mdhd.modification_time, box4mdhd.timescale, box4mdhd.duration, box4mdhd.language);
#endif
}

static void DealBox4hdlr(const unsigned char *hdlrData)
{
    int i = 0;

    unsigned char *data = NULL;

    T_BOX4HDLR box4hdlr = {0};

    memset(&box4hdlr, 0x0, sizeof(box4hdlr));

    data = (unsigned char *)hdlrData;

    data += 4;
    data += 4;

    memcpy(box4hdlr.handler_type, data, 4);

    box4hdlr.handler_type[MAX_HANDLER_TYPE_LEN] = '\0';

    data += 4;

    data += 12;

    while ('\0' != data[i])
    {
        i++;
    }

    memcpy(box4hdlr.name, data, i);

    box4hdlr.name[MAX_HDLR_NAME_LEN] = '\0';

#ifdef PRINTF_DEBUG
    printf("\t\t\t\thandler_type: %s, name: %s\n", box4hdlr.handler_type, box4hdlr.name);
#endif
}

static void DealBox4vmdhd(const unsigned char *vmdhdData)
{
    // TODO
}

static void DealBox4minf(const T_BOX *box)
{    int boxSize = 0;
    int minfDataSize = 0;

    unsigned char *minfData = NULL;
    unsigned char *data = NULL;

    char boxType[MAX_BOX_TYPE_LEN+1] = {0};

    T_BOX dinfBox = {0};
    T_BOX stblBox = {0};

    minfData = box->boxData;
    minfDataSize = box->boxHeader.boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN;

    while (minfDataSize > 0)
    {
        boxSize = minfData[0] << 24 | minfData[1] << 16 | minfData[2] << 8 | minfData[3];

        memcpy(boxType, minfData+MAX_BOX_SIZE_LEN, 4);

#ifdef PRINTF_DEBUG
    printf("\t\t\t\t********BOX: Layer5********\n");
    printf("\t\t\t\t\tsize: %d\n", boxSize);
    printf("\t\t\t\t\ttype: %s\n", boxType);
#endif
        if (0 == strcmp(boxType, BOX_TYPE_VMHD))
        {
            data = (unsigned char*)malloc(boxSize);
            if (data)
            {
                memcpy(data, minfData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4vmdhd(data);

                free(data);
                data = NULL;
            }
        }
        else if (0 == strcmp(boxType, BOX_TYPE_DINF))
        {
            memset(&dinfBox, 0x0, sizeof(T_BOX));

            dinfBox.boxHeader.boxSize = boxSize;

            memcpy(dinfBox.boxHeader.boxType, boxType, strlen(boxType));

            dinfBox.boxData = (unsigned char*)malloc(boxSize);
            if (dinfBox.boxData)
            {
                memcpy(dinfBox.boxData, minfData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4dinf((const T_BOX*)&dinfBox);

                free(dinfBox.boxData);
                dinfBox.boxData = NULL;
            }
        }
        else if (0 == strcmp(boxType, BOX_TYPE_STBL))
        {
            memset(&stblBox, 0x0, sizeof(T_BOX));

            stblBox.boxHeader.boxSize = boxSize;

            memcpy(stblBox.boxHeader.boxType, boxType, strlen(boxType));

            stblBox.boxData = (unsigned char*)malloc(boxSize);
            if (stblBox.boxData)
            {
                memcpy(stblBox.boxData, minfData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4stbl((const T_BOX*)&stblBox);

                free(stblBox.boxData);
                stblBox.boxData = NULL;
            }
        }

        minfData += boxSize;
        minfDataSize -= boxSize;
    }
}

static void DealBox4mdia(const T_BOX *box)
{    int boxSize = 0;
    int mdiaDataSize = 0;

    unsigned char *mdiaData = NULL;
    unsigned char *data = NULL;

    char boxType[MAX_BOX_TYPE_LEN+1] = {0};

    T_BOX minfBox = {0};

    mdiaData = box->boxData;
    mdiaDataSize = box->boxHeader.boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN;

    while (mdiaDataSize > 0)
    {
        boxSize = mdiaData[0] << 24 | mdiaData[1] << 16 | mdiaData[2] << 8 | mdiaData[3];

        memcpy(boxType, mdiaData+MAX_BOX_SIZE_LEN, 4);

#ifdef PRINTF_DEBUG
    printf("\t\t\t************BOX: Layer4************\n");
    printf("\t\t\t\tsize: %d\n", boxSize);
    printf("\t\t\t\ttype: %s\n", boxType);
#endif
        if (0 == strcmp(boxType, BOX_TYPE_MDHD))
        {
            data = (unsigned char*)malloc(boxSize);
            if (data)
            {
                memcpy(data, mdiaData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4mdhd(data);

                free(data);
                data = NULL;
            }
        }
        else if (0 == strcmp(boxType, BOX_TYPE_HDLR))
        {
            data = (unsigned char*)malloc(boxSize);
            if (data)
            {
                memcpy(data, mdiaData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4hdlr(data);

                free(data);
                data = NULL;
            }
        }
        else if (0 == strcmp(boxType, BOX_TYPE_MINF))
        {
            memset(&minfBox, 0x0, sizeof(T_BOX));

            minfBox.boxHeader.boxSize = boxSize;

            memcpy(minfBox.boxHeader.boxType, boxType, strlen(boxType));

            minfBox.boxData = (unsigned char*)malloc(boxSize);
            if (minfBox.boxData)
            {
                memcpy(minfBox.boxData, mdiaData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4minf((const T_BOX*)&minfBox);

                free(minfBox.boxData);
                minfBox.boxData = NULL;
            }
        }

        mdiaData += boxSize;
        mdiaDataSize -= boxSize;
    }
}

static void DealBox4trak(const T_BOX *box)
{
    int boxSize = 0;
    int trakDataSize = 0;

    unsigned char *trakData = NULL;
    unsigned char *data = NULL;

    char boxType[MAX_BOX_TYPE_LEN+1] = {0};

    T_BOX mdiaBox = {0};

    trakData = box->boxData;
    trakDataSize = box->boxHeader.boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN;

    while (trakDataSize > 0)
    {
        boxSize = trakData[0] << 24 | trakData[1] << 16 | trakData[2] << 8 | trakData[3];

        memcpy(boxType, trakData+MAX_BOX_SIZE_LEN, 4);

#ifdef PRINTF_DEBUG
    printf("\t\t****************BOX: Layer3****************\n");
    printf("\t\t\tsize: %d\n", boxSize);
    printf("\t\t\ttype: %s\n", boxType);
#endif

        if (0 == strcmp(boxType, BOX_TYPE_TKHD))
        {
            data = (unsigned char*)malloc(boxSize);
            if (data)
            {
                memcpy(data, trakData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4tkhd(data);

                free(data);
                data = NULL;
            }
        }
        else if (0 == strcmp(boxType, BOX_TYPE_MDIA))
        {
            memset(&mdiaBox, 0x0, sizeof(T_BOX));

            mdiaBox.boxHeader.boxSize = boxSize;

            memcpy(mdiaBox.boxHeader.boxType, boxType, strlen(boxType));

            mdiaBox.boxData = (unsigned char*)malloc(boxSize);
            if (mdiaBox.boxData)
            {
                memcpy(mdiaBox.boxData, trakData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4mdia((const T_BOX*)&mdiaBox);

                free(mdiaBox.boxData);
                mdiaBox.boxData = NULL;
            }
        }

        trakData += boxSize;
        trakDataSize -= boxSize;
    }
}

static void DealBox4moov(const T_BOX *box)
{
    int boxSize = 0;
    int moovDataSize = 0;

    unsigned char *moovData = NULL;
    unsigned char *data = NULL;

    char boxType[MAX_BOX_TYPE_LEN+1] = {0};

    T_BOX trakBox = {0};

    moovData = box->boxData;
    moovDataSize = box->boxHeader.boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN;

    while (moovDataSize > 0)
    {
        boxSize = moovData[0] << 24 | moovData[1] << 16 | moovData[2] << 8 | moovData[3];

        memcpy(boxType, moovData+MAX_BOX_SIZE_LEN, 4);

        boxType[MAX_BOX_TYPE_LEN] = '\0';

#ifdef PRINTF_DEBUG
    printf("\t********************BOX: Layer2********************\n");
    printf("\t\tsize: %d\n", boxSize);
    printf("\t\ttype: %s\n", boxType);
#endif

        if (0 == strcmp(boxType, BOX_TYPE_MVHD))
        {
            data = (unsigned char*)malloc(boxSize);
            if (data)
            {
                memcpy(data, moovData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4mvhd(data);

                free(data);
                data = NULL;
            }
        }
        else if (0 == strcmp(boxType, BOX_TYPE_TRAK))
        {
            memset(&trakBox, 0x0, sizeof(T_BOX));

            trakBox.boxHeader.boxSize = boxSize;

            memcpy(trakBox.boxHeader.boxType, boxType, strlen(boxType));

            trakBox.boxData = (unsigned char*)malloc(boxSize);
            if (trakBox.boxData)
            {
                memcpy(trakBox.boxData, moovData+MAX_BOX_SIZE_LEN+MAX_BOX_TYPE_LEN, boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);

                DealBox4trak((const T_BOX*)&trakBox);

                free(trakBox.boxData);
                trakBox.boxData = NULL;
            }
        }

        moovData += boxSize;
        moovDataSize -= boxSize;
    }
}

static void DealBox(const T_BOX *box)
{
#ifdef PRINTF_DEBUG
    printf("****************************BOX: Layer1****************************\n");
    printf("\tsize: %d\n", box->boxHeader.boxSize);
    printf("\ttype: %s\n", box->boxHeader.boxType);
#endif

    if (0 == strcmp(box->boxHeader.boxType, BOX_TYPE_FTYPE))
    {
        DealBox4ftyp(box);
    }
    else if (0 == strcmp(box->boxHeader.boxType, BOX_TYPE_MOOV))
    {
        DealBox4moov(box);
    }
}

int main(int argc, char *argv[])
{
    unsigned char boxSize[MAX_BOX_SIZE_LEN] = {0};

    FILE *fp = NULL;

    T_BOX box = {0};

    if (2 != argc)
    {
        printf("Usage: mp4parse **.mp4\n");

        return -1;
    }

    fp = fopen(argv[1], "rb");
    if (!fp)
    {
        printf("open file[%s] error!\n", argv[1]);

        return -1;
    }


    while (1)
    {
        memset(&box, 0x0, sizeof(T_BOX));

        if (fread(boxSize, 1, 4, fp) <= 0)
        {
            break;
        }

        box.boxHeader.boxSize = boxSize[0] << 24 | boxSize[1] << 16 | boxSize[2] << 8 | boxSize[3];

        fread(box.boxHeader.boxType, 1, 4, fp);

        box.boxHeader.boxType[MAX_BOX_TYPE_LEN] = '\0';

        box.boxData = (unsigned char*)malloc(box.boxHeader.boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN);
        if (!box.boxData)
        {
            printf("malloc data error!\n");

            break;
        }

        fread(box.boxData, 1, box.boxHeader.boxSize-MAX_BOX_SIZE_LEN-MAX_BOX_TYPE_LEN, fp);

        printf("\n=====================================\n");

        /* deal box data */
        DealBox(&box);

        /* free box */
        free(box.boxData);

        box.boxData = NULL;
    }

    fclose(fp);

    printf("\n");

    return 0;
}