手写解复用(四):ASF(WMA、WMV)解析

1、本文的基本作用:引导理解封装格式,但更重要的是要自己去阅读协议,上手实践;
2、本文的最大价值:久之,皆已遗忘;顾之,皆已忆起。

一、基本知识

1、结构概览

ASF是由一个个ASF object组成的,通过Object GUID区分Object的类型,通过Object Size描述一个Object的长度。

ASF object的结构:

2、总体结构

主要由3大部分组成: Header Object,Data Object,Index Object(s)Header Object在最前面,然后是Data Object。Header Object里面嵌套了很多子Object,Data Object里面是音视频数据。

3、ASF Header Object

描述了文件的信息、解码器的信息等。其中Number of Header Objects描述了子Obect的个数,这样就能找到并解析子Object了。

实例:

3.1、File Properties Object

主要描述了文件的大小、时长、数据包的个数等。

实例:

3.2、Stream Properties Object

主要描述了文件中有几路流以及流的基本信息。

实例:

3.3、Codec List Object

主要描述了解码器的信息。

实例:

4、ASF Data Object

4.1、Data Object

主要记录了Data Packet的个数。

实例:

4.2、Data Packet

4.2.1、Payload Parsing Information

4.2.2、Payload data

实际的媒体数据按照Payload Parsing Information的描述组织起来。一个packet可以包含一个或者多个payload数据,依赖于Payload Parsing Information中的Multiple Payloads Present标记。如果Multiple Payloads Present设置为1,这个packet就由多个payload组成。有四种payload:

  • Single Payload
  • Single Payload,Compressed Payload Data
  • Multiple Payload
  • Multiple Payload,Compressed Payload Data
4.2.2.1、Single Payload

Packet中只有一个Packet。

4.2.2.2、Single Payload,Compressed Payload Data

这种也是Single Payload类型,只是它的payload是压缩的。

4.2.2.3、Multiple Payload

Packet中有多个payload。描述了Payloads的个数。

Payloads格式:

记录了每个Playload的长度以及数据。

4.2.2.4、Multiple Payload,Compressed Payload Data

Packet中有多个payload。描述了Payloads的个数。

Compressed Payloads格式:

记录了每个Playload的长度等。

5、ASF Simple Index Object

主要用于Seek操作,描述了关键帧的信息。

Index Entries:

主要描述了关键的Packet Number.

实例:

二、重点代码

1、寻找Object

int main(int argc, char *argv[]) {
    while (1) {
        baseObject.baseObjHeader.object_size = asf_rl64(baseObjectHeaderdata + MAX_GUID_LEN);
        fread(baseObject.object_playload, 1, baseObject.baseObjHeader.object_size - ASF_BASE_OBJECT_HEADER_LEN, fp);
        asf_DealObject(&baseObject, ASF_TOP_OBJECT);
    }
}

2、解析Header Object

static void asf_DealHeader(T_ASF_BASE_OBJECT *baseObject) {
    for (i=0; i<asfHeader.object_nums; i++) {
        subBaseObject[i]->baseObjHeader.object_size = asf_rl64(subData);
        subData += (subBaseObject[i]->baseObjHeader.object_size - ASF_BASE_OBJECT_HEADER_LEN);
        asf_DealObject(subBaseObject[i], ASF_HEADER_OBJECT);
    }
}

2.1、解析File Properties Object

static void asf_Header_DealFileProperties(T_ASF_BASE_OBJECT *baseObject) {
    asfFileProperties.fielSize = asf_rl64(data);

    data += 8;

    asfFileProperties.creationDate = asf_rl64(data);

    data += 8;

    asfFileProperties.dataPacketsCount = asf_rl64(data);

    data += 8;

    asfFileProperties.playDuration = asf_rl64(data);
}

2.2、解析Stream Properties Object

static void asf_Header_DealStreamProperties(T_ASF_BASE_OBJECT *baseObject) {
    asfStreamProperties.timeOffset = asf_rl64(data);

    data += 8;

    asfStreamProperties.typeSpecDataLen = asf_rl32(data);

    data += 4;

    asfStreamProperties.errorCorrectionDataLen = asf_rl32(data);

    data += 4;

    asfStreamProperties.flags = asf_rl16(data);
}

2.3、解析Codec List Object

static void asf_Header_DealCodecList(T_ASF_BASE_OBJECT *baseObject) {
        for (i=0; i<asfCodecList.codecEntryCount; i++) {
        asfCodecList.codecEntries[i] = (T_ASF_CODECLIST_ENTRY *)malloc(sizeof(T_ASF_CODECLIST_ENTRY));
        if (!asfCodecList.codecEntries[i]) {
            printf("malloc codec list entry error!\n");

            return;
        }

        memset(asfCodecList.codecEntries[i], 0x0, sizeof(T_ASF_CODECLIST_ENTRY));

        asfCodecList.codecEntries[i]->type = asf_rl16(entriesData);

        entriesData += 2;
    }
}

3、解析Data Object

static void asf_DealData(T_ASF_BASE_OBJECT *baseObject) {
    asfData.totalDataPackets = asf_rl64(data);

    data += 8;

    asfData.reserved = asf_rl16(data);
}

3.1、解析Single Payload

static void asf_DealData(T_ASF_BASE_OBJECT *baseObject) {
    asfData.packets[i]->playload.singlePlayload.streamNum = tmpStreamNum;
    asfData.packets[i]->playload.singlePlayload.streamNum7Bits =             tmpStreamNum7Bits;
    asfData.packets[i]->playload.singlePlayload.keyFrame1Bit = tmpKeyFrame1Bit;
}

3.2、解析Single Payload,Compressed Payload Data

static void asf_DealData(T_ASF_BASE_OBJECT *baseObject) {
    // Single payload, compressed payload data
    if (1 == tmpRepDataLen) {
        // used for print
        asfData.packets[i]->isSingleCompressedPlayload = 1;

        asfData.packets[i]->playload.singleCompressedPlayload.streamNum = tmpStreamNum;
    }
}

3.3、解析处理Multiple Payload

static void asf_DealData(T_ASF_BASE_OBJECT *baseObject) {
    oneplayload->streamNum = tmpStreamNum;
    oneplayload->streamNum7Bits = tmpStreamNum7Bits;
    oneplayload->keyFrame1Bit = tmpKeyFrame1Bit;

    asfData.packets[i]->playload.multipePlayloads.playloads[asfData.packets[i]->playload.multipePlayloads.oneplayloadNums] = oneplayload
}

3.4、解析处理Multiple Payload,Compressed Payload Data

static void asf_DealData(T_ASF_BASE_OBJECT *baseObject) {
    // Multiple payloads, compressed payload data
    if (1 == tmpRepDataLen) {
        compressedplayload->streamNum = tmpStreamNum;
        compressedplayload->streamNum7Bits = tmpStreamNum7Bits;
        compressedplayload->keyFrame1Bit = tmpKeyFrame1Bit;
    }
}

4、解析Simple Index Object

static void asf_DealSimpleIndex(T_ASF_BASE_OBJECT *baseObject) {
    for (i=0; i<asfSimpleIndex.indexEntriesCount; i++) {
        asfSimpleIndex.simpleIndexEntries[i] = (T_ASF_SIMPLE_INDEX_ENTRY *)malloc(sizeof(T_ASF_SIMPLE_INDEX_ENTRY));
        if (!asfSimpleIndex.simpleIndexEntries[i] ) {
            printf("malloc simple index entry error!\n");

            return;
        }

        memset(asfSimpleIndex.simpleIndexEntries[i], 0x0, sizeof(T_ASF_SIMPLE_INDEX_ENTRY));

        asfSimpleIndex.simpleIndexEntries[i]->packetNum = asf_rl32(entryData);

        entryData += 4;
        
        asfSimpleIndex.simpleIndexEntries[i]->packetCount = asf_rl16(entryData);

        entryData += 2;
    }
}

三、完整源码

纯C代码,gcc编译就能直接运行。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <arpa/inet.h>

#define PRINTF_DEBUG
#define PRINTF_DEBUG_DETAIL

// noting means, todo
#define PRINTF_FROM_SPECIFICATION 0
#define PRINTF_FROM_ASFVIEW 1

// 16 + 8
#define ASF_BASE_OBJECT_HEADER_LEN 24

#define SHOW_SIMPLE_INDEX_ENTRY_COUNT 30

#define SHOW_PACKET_COUNT 30

/************************************************************************************************************
**                                        basic data types
**
-------------------------------------------------------------------------------------------------------------
**        Type                |    Size (bits)   |        Signed
-------------------------------------------------------------------------------------------------------------
**        BYTE                 |    8             |        no
**        WCHAR                |    16            |        no
**        WORD                 |    16            |        no
**        DWORD                |    32            |        no
**        QWORD                |    64            |        no
**        GUID                 |    128           |        no
************************************************************************************************************/
#define MAX_GUID_LEN 16
#define MAX_NAME_LEN 255

typedef unsigned char BYTE;
typedef unsigned short WCHAR;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef unsigned long long QWORD;

typedef unsigned char GUID[MAX_GUID_LEN];

// FOURCC
#ifdef BIGENDIAN
#define ASF_FOURCC( a, b, c, d ) \
        ( ((BYTE)d) | ( ((BYTE)c) << 8 ) \
           | ( ((BYTE)b) << 16 ) | ( ((BYTE)a) << 24 ) )
#else
#define ASF_FOURCC( a, b, c, d ) \
        ( ((BYTE)a) | ( ((BYTE)b) << 8 ) \
           | ( ((BYTE)c) << 16 ) | ( ((BYTE)d) << 24 ) )
#endif

#define ASF_CODEC_WVC1 ASF_FOURCC('W','V','C','1')

static inline void asf_fourcc_to_char( DWORD fcc, char *strFourcc ) {
    memcpy( strFourcc, &fcc, 4 );
}

/************************************************************************************************************
**                                        Object
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Object ID                  |    GUID           |        128
**        Object Size                |    QWORD          |        64, 24 + 负载长度
**        payload                    |    *              |        *
************************************************************************************************************/
typedef struct t_asf_base_object_header {
    GUID object_id; // 16 BYTES
    QWORD object_size; // 8 BYTES
} T_ASF_BASE_OBJECT_HEADER;

typedef struct t_asf_base_object {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;

    BYTE* object_playload;
} T_ASF_BASE_OBJECT;

/************************************************************************************************************
**                                        Header Object: 所有ASF Object和结构都是以小端字节序存储的
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Object ID                  |    GUID           |        128
**        Object Size                |    QWORD          |        64
**        Number of Header Objects   |    DWORD          |        32
**        Reserved1                  |    BYTE                    8
**        Reserved2                  |    BYTE           |        8
************************************************************************************************************/
typedef struct t_asf_header {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;

    DWORD object_nums;
    BYTE reserved1;
    BYTE reserved2;
} T_ASF_HEADER;

/************************************************************************************************************
**                                        File Properties Object
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Object ID                  |    GUID           |        128
**        Object Size                |    QWORD          |        64
**        File ID                    |    GUID           |        128
**        File Size                  |    QWORD          |        64
**        Creation Date              |    QWORD          |        64
**        Data Packets Count         |    QWORD          |        64
**        Play Duration              |    QWORD          |        64
**        Send Duration              |    QWORD          |        64
**        Preroll                    |    QWORD          |        64
**        Flags                      |    DWORD          |        32
**            Broadcast Flag         |                   |        1(LSB)
**            Seekable Flag          |                   |        1
**            Reserved               |                   |        30
**        Minimum Data Packet Size   |    DWORD          |        32
**        Maximum Data Packet Size   |    DWORD          |        32
**        Maximum Bitrate            |    DWORD          |        32
************************************************************************************************************/
typedef struct t_asf_header_file_properties {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;

    /**
     * Specifies the unique identifier for this file. The value of this field shall be regenerated every time 
     * the file is modified in any way. The value of this field shall be identical to the value of the File ID 
     * field of the Data Object.
     */
    GUID fileID;
    QWORD fielSize;

    /**
     * Specifies the date and time of the initial creation of the file. The value is given as the number of 
     * 100-nanosecond intervals since January 1, 1601, according to Coordinated Universal Time (Greenwich Mean Time). 
     * The value of this field may be invalid if the Broadcast Flag bit in the Flags field is set to 1.
     */
    QWORD creationDate;

    QWORD dataPacketsCount;
    QWORD playDuration;
    QWORD sendDuration;
    QWORD preroll;

    /**
     * 1. The flags are stored in Least Significant Byte (LSB) order;
     * 2. MSB是Most Significant Bit的缩写, 指最高有效位. 在二进制数中, MSB是最高加权位.
     *    与十进制数字中最左边的一位类似. 通常, MSB位于二进制数的最左侧, LSB位于二进制数的最右侧.
     */
    DWORD flags;
    BYTE :6, broadcastFlag:1, seekableFlag:1;
    DWORD minDataPacketSize;
    DWORD maxDataPacketSize;
    DWORD maxBitrate;
} T_ASF_HEADER_FILE_PROPERTIES;

/************************************************************************************************************
**                                        Audio media type(Type-Specific Data of Stream Properties)
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Codec ID/Format Tag        |    WORD           |        16
**        Number of Channels         |    WORD           |        16
**        Samples Per Second         |    DWORD          |        32
**        Avg Num of Bytes Per Sec   |    DWORD          |        32
**        Block Alignment            |    WORD           |        16
**        Bits Per Sample            |    WORD           |        16
**        Codec Specific Data Size   |    WORD           |        16
**        Codec Specific Data        |    BYTE           |        varies
************************************************************************************************************/
typedef struct t_asf_header_audiomedia_type {
    WORD codecID;
    WORD numChannels;
    DWORD samples;
    DWORD avgNumberBytesPerSec;
    WORD blockAlignment;
    WORD bitPerSample;
    WORD codecSpecDataSize;
    BYTE *codecSpecData;
} T_ASF_HEADER_AUDIOMEDIA_TYPE;

/************************************************************************************************************
**                                        video media type(Type-Specific Data of Stream Properties)
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Format Data Size           |    DWORD          |        32
**        Image Width                |    LONG           |        32
**        Image Height               |    LONG           |        32
**        Reserved                   |    WORD           |        16
**        Bits Per Pixel Count       |    WORD           |        16
**        Compression ID             |    DWORD          |        32
**        Image Size                 |    DWORD          |        32
**        Horizontal Pixels Per Meter|    LONG           |        32
**        Vertical Pixels Per Meter  |    LONG           |        32
**        Colors Used Count          |    DWORD          |        32
**        Important Colors Count     |    DWORD          |        32
**        Codec Specific Data        |    BYTE           |        varies
************************************************************************************************************/
typedef struct t_asf_header_videomedia_formatdata_type {
    DWORD formatDataSize;
    DWORD imageWidth;
    DWORD imageHeight;
    WORD reserved;
    WORD bitsPerPixel;

    /**
     * Specifies the type of the compression, using a four-character code. For ISO MPEG-4 video, 
     * this contains MP4S, mp4s, M4S2, or m4s2. In the Compression ID, the first character of the 
     * four-character code appears as the least-significant byte; for instance MP4S uses the 
     * Compression ID 0x5334504D. Defined as the biCompression field of a BITMAPINFOHEADER structure.
     * TODO, FOURCC???
     */
    DWORD compressionID;

    DWORD imageSize;
    DWORD horPixelsPerMeter;
    DWORD verPixelsPerMeter;
    DWORD colorsUsedCount;
    DWORD importantColorsCount;
    BYTE *codecSpecData;
} T_ASF_HEADER_VIDEOMEDIA_FORMATDATA_TYPE;

/************************************************************************************************************
**                                        video media type(Type-Specific Data of Stream Properties)
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Encoded Image Width        |    DWORD          |        32
**        Encoded Image Height       |    DWORD          |        32
**        Reserved Flags             |    BYTE           |        8
**        Format Data Size           |    WORD           |        16
**        Format Data                |    See below      |        varies
************************************************************************************************************/
typedef struct t_asf_header_videomedia_type {
    DWORD encWidth;
    DWORD encHeight;
    BYTE reservedFlags;
    DWORD formatDataSize;
    //BYTE *foramtData;

    T_ASF_HEADER_VIDEOMEDIA_FORMATDATA_TYPE formatdata;
} T_ASF_HEADER_VIDEOMEDIA_TYPE;

/************************************************************************************************************
**                                        Stream Properties Object
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Object ID                  |    GUID           |        128
**        Object Size                |    QWORD          |        64
**        Stream Type                |    GUID           |        128
**        Error Correction Type      |    GUID           |        128
**        Time Offset                |    QWORD          |        64
**        Type-Specific Data Length  |    DWORD          |        32
**        Error Correction Data Len  |    DWORD          |        32
**        Flags                      |    WORD           |        16
**            Stream Number          |                   |        7(LSB)
**            Reserved               |                   |        8
**            Encrypted Content Flag |                   |        1
**        Reserved                   |    DWORD          |        32
**        Type-Specific Data         |    BYTE           |        varies
**        Error Correction Data      |    BYTE           |        varies
************************************************************************************************************/
typedef struct t_asf_header_stream_properties {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;

    GUID streamType;
    GUID errorCorrectionType;

    QWORD timeOffset;
    DWORD typeSpecDataLen;
    DWORD errorCorrectionDataLen;

    DWORD flags;
    BYTE flags_streamNumber;
    BYTE flags_reserved;
    BYTE flags_encContentFlag;

    DWORD reserved;

    //BYTE *typeSpecData;
    //BYTE *errorCorrectionData;

    union 
    {
      T_ASF_HEADER_AUDIOMEDIA_TYPE audiomedia;
      T_ASF_HEADER_VIDEOMEDIA_TYPE videomedia;
    } asf_media;
    
} T_ASF_HEADER_STREAM_PROPERTIES;

/************************************************************************************************************
**                                        Header Extension Object
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Object ID                  |    GUID           |        128
**        Object Size                |    QWORD          |        64
**        Reserved Field 1           |    GUID           |        128
**        Reserved Field 2           |    WORD           |        16
**        Header Extension Data Size |    DWORD          |        32
**        Header Extension Data      |    BYTE           |        varies
************************************************************************************************************/
typedef struct t_asf_header_header_extension {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;

    GUID reservedField1;

    /**
     * This value should be set to 6
     */
    WORD reservedField2;
    DWORD headerExtDataSize;
    BYTE *headerExtData;
} T_ASF_HEADER_HEADER_EXTENSION;

/************************************************************************************************************
**                                        Codec Entries
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Type                       |    WORD           |        16
**        Codec Name Length          |    WORD           |        16
**        Codec Name                 |    WCHAR          |        varies
**        Codec Description Length   |    WORD           |        16
**        Codec Description          |    WCHAR          |        varies
**        Codec Information Length   |    WORD           |        16
**        Codec Information          |    BYTE           |        varies
************************************************************************************************************/
typedef struct t_asf_codeclist_entry {
    WORD type;
    WORD codecNameLen;
    //WCHAR *codecNameUTF16;
    BYTE codecNameUTF8[MAX_NAME_LEN];

    WORD codecDesLen;
    //WCHAR *codecDesUTF16;
    BYTE codecDesUTF8[MAX_NAME_LEN];

    WORD codecInfoLen;
    BYTE codecInfo[MAX_NAME_LEN];
} T_ASF_CODECLIST_ENTRY;

/************************************************************************************************************
**                                        Codec List Object
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Object ID                  |    GUID           |        128
**        Object Size                |    QWORD          |        64
**        Reserved                   |    GUID           |        128
**        Codec Entries Count        |    DWORD          |        32
**        Codec Entries              |    See below      |        varies
************************************************************************************************************/
typedef struct t_asf_header_codeclist {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;

    GUID reserved;
    DWORD codecEntryCount;
    T_ASF_CODECLIST_ENTRY **codecEntries;
} T_ASF_HEADER_CODECLIST;

/************************************************************************************************************
**                                        Content Descriptors
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Descriptors Name Length    |    WORD           |        16
**        Descriptors Name           |    WCHAR          |        varies
**        Descriptors Value Data Type|    WORD           |        16
**        Descriptors Value Length   |    WORD           |        16
**        Descriptors Value          |    See text       |        varies

-------------------------------------------------------------------------------------------------------------
**        Descriptors Value Data Type
**
-------------------------------------------------------------------------------------------------------------
**        Value                     |    Type           |        Descriptor value length
-------------------------------------------------------------------------------------------------------------
**        0x0000                     |    Unicode string  |        varies
**        0x0001                     |    BYTE array      |        varies
**        0x0002                     |    BOOL            |        32
**        0x0003                     |    DWORD           |        32
**        0x0004                     |    QWORD           |        64
**        0x0005                     |    WORD            |        16
************************************************************************************************************/
typedef struct t_asf_extcontentdes_des {
    WORD desNameLen;
    //WCHAR *desNameUTF16;
    BYTE desNameUTF8[MAX_NAME_LEN];

    WORD desValueDataType;

    WORD desValueLen;
    
    /**
     * Specifies the value for the Content Descriptor field. The type for this value is determined by the 
     * Descriptor Value Data Type field. 
     */
    union {
        BYTE bValue[MAX_NAME_LEN];
        DWORD dwValue;
        QWORD qwValue;
        WORD wValue;
    } desValues;
} T_ASF_EXTCONTENTDES_DES;

/************************************************************************************************************
**                                        Extended Content Description Object
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Object ID                  |    GUID           |        128
**        Object Size                |    QWORD          |        64
**        Content Descriptors Count  |    WORD           |        16
**        Content Descriptors        |    See text       |        varies
************************************************************************************************************/
typedef struct t_asf_header_extcontentdes {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;

    WORD contentDesCount;
    DWORD codecEntryCount;

    T_ASF_EXTCONTENTDES_DES **extContentDess;
} T_ASF_HEADER_EXTCONTENTDES;

/************************************************************************************************************
**                                        Bitrate Records
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Flags                      |    WORD           |        16
**            Stream Number          |                   |        7(LSB)
**            Reserved               |                   |        9
**        Average Bitrate            |    DWORD          |        32
************************************************************************************************************/
typedef struct t_asf_header_stream_bitrate_record {
    WORD flags;
    BYTE streamNumber;
    WORD resverved;

    DWORD avgBitrate;
} T_ASF_HEADER_STEAM_BITRATE_RECORD;

/************************************************************************************************************
**                                        Stream Bitrate Properties Object
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Object ID                  |    GUID           |        128
**        Object Size                |    QWORD          |        64
**        Bitrate Records Count      |    WORD           |        16
**        Bitrate Records            |    See below      |        varies
************************************************************************************************************/
typedef struct t_asf_header_stream_bitrate_properties {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;

    WORD bitrateRecordsCount;

    T_ASF_HEADER_STEAM_BITRATE_RECORD **bitrateRecords;
} T_ASF_HEADER_STEAM_BITRATE_PROPERTIES;

/************************************************************************************************************
**                                        Error correction data content
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        First byte – Type          |    BYTE           |        8
**            Type                   |                   |        4(LSB)
**            Number                 |                   |        4
**        Second byte – Cycle        |    BYTE           |        8

-------------------------------------------------------------------------------------------------------------
**                                          Type
**
-------------------------------------------------------------------------------------------------------------
**        Value                     |    Descriptor value length
-------------------------------------------------------------------------------------------------------------
**        00                     |    The data is uncorrected. If there is no Error Correction Object in the Header Object, this is the value that shall be used for this field.
**        01                     |    The type of error correction is XOR data. This field can only be set to this value if there is an Error Correction Object in the Header Object.
**        10                     |    The type of error correction is parity data. This field can only be set to this value if there is an Error Correction Object in the Header Object.
************************************************************************************************************/
/**
 * Specifies an array of bytes containing error correction data. The format of this data is based on the presence 
 * of the Error Correction Object (see section 3.9), and the value of the Error Correction Type field of the Error 
 * Correction Object. In all cases, the format of the first two bytes of Error Correction Data are defined as follows.
 */
typedef struct t_asf_data_packet_errcorrection_data_content {
    BYTE type;
    BYTE number:4, ftype:4;

    BYTE cycle;
} T_ASF_DATA_PACKET_ERRCORRECTION_DATA_CONtent;

/************************************************************************************************************
**                                        Error correction data
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Error Correction Flags     |    BYTE           |        8
**            Err Correction Data Len|                   |        4(LSB)
**            Opaque Data Present    |                   |        1
**            Err Correction Len Type|                   |        2
**            Err Correction Present |                   |        1
**        Error Correction Data      |    BYTE           |        varies
************************************************************************************************************/
typedef struct t_asf_data_packet_errcorrection_data {
    BYTE flags;
    BYTE errCorrPresent:1, lenType:2, opeDataPresent:1, errCorrDataLen:4;

    // BYTE errCorrDataLen;
    // BYTE opeDataPresent;
    // BYTE lenType;
    // BYTE errCorrPresent;

    BYTE *data; // T_ASF_DATA_PACKET_ERRCORRECTION_DATA_CONtent
} T_ASF_DATA_PACKET_ERRCORRECTION_DATA;

/************************************************************************************************************
**                                        Payload parsing information
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Length Type Flags          |    BYTE           |        8
**            Mult Payloads Present  |                   |        1(LSB)
**            Sequence Type          |                   |        2
**            Padding Length Type    |                   |        2
**            Packet Length Type     |                   |        2
**            Err Correction Present |                   |        1
**        Property Flags             |    BYTE           |        8
**            Rep Data Length Type   |                   |        2(LSB)
**            Off Media Obj Len Type |                   |        2
**            Media Obj Num Len Type |                   |        2
**            Stream Num Length Type |                   |        2
**        Packet Length              | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Sequence                   | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Padding Length             | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Send Time                  |    DWORD          |        32
**        Duration                   |    WORD           |        16

-------------------------------------------------------------------------------------------------------------
**        Sequence Type/Padding Length Type/Packet Length Type/Replicated Data Length Type
**        Offset Into Media Object Length Type/Media Object Number Length Type 
**
-------------------------------------------------------------------------------------------------------------
**        Value                     |    Descriptor value length
-------------------------------------------------------------------------------------------------------------
**        00                     |    The Sequence/Padding Length... field does not exist.
**        01                     |    The Sequence/Padding Length... field is coded using a BYTE.
**        10                     |    The Sequence/Padding Length... field is coded using a WORD.
**        11                     |    The Sequence/Padding Length... field is coded using a DWORD.
************************************************************************************************************/
typedef struct t_asf_data_packet_playload_parsing_info {
    BYTE lenTypeFlags;
    BYTE errCorrectionPresent:1, packetLenType:2, paddingLenType:2, sequenceType:2, mulPlayloadsPresent:1;

    BYTE propertyFlags;
    BYTE streamNumLenType:2, meidiaObjNumLenType:2, offsetIntoObjLenType:2, replicatedDataLenType:2;

    // all to DWORD, when parsing discern it.
    DWORD packetLen;
    DWORD sequence;
    DWORD paddingLen;

    DWORD sendTime;
    WORD duration;
} T_ASF_DATA_PACKET_PLAYLOAD_PARSING_INFO;

typedef struct t_asf_data_packet_playload_repdata {
    DWORD allplayloadlen;
    DWORD pts;

    // 
    DWORD realplayloadlen;
} T_ASF_DATA_PACKET_PLAYLOAD_REPDATA;

// many payload create one, payload size is limited
#define MAX_PARSING_OBJ 128 // 128 is ok???
#define MAX_STREAM_NUM 128 // 2^7

typedef struct t_asf_data_packet_playload_objinfo {
    BYTE isParing;

    int mediaObjNum;

    // 
    DWORD allobjlen;
} T_ASF_DATA_PACKET_PLAYLOAD_OBJINFO;

//T_ASF_DATA_PACKET_PLAYLOAD_OBJINFO g_playladobjinfo[MAX_PARSING_OBJ] = {0};
T_ASF_DATA_PACKET_PLAYLOAD_OBJINFO g_playladobjinfo[MAX_STREAM_NUM][MAX_PARSING_OBJ] = {0};

// int getUnusedObjinfoIndex() {
//     int i = 0;
    
//     for (i=0; i<MAX_PARSING_OBJ; i++) {
//         if (g_playladobjinfo[i].isParing == 0) {
//             return i;
//         }
//     }

//     if (i == MAX_PARSING_OBJ) {
//         printf("All obj indeix is used!\n");

//         return -1;
//     }
// }

// void resetObjinfo(T_ASF_DATA_PACKET_PLAYLOAD_OBJINFO* objinfo) {
//     objinfo->allobjlen = 0;
//     objinfo->isParing = 0;
//     objinfo->mediaObjNum = -1; // some obj num is 0, so used -1
// }

// void InitAllObjinfo() {
//     int i = 0;
    
//     for (i=0; i<MAX_PARSING_OBJ; i++) {
//         resetObjinfo(&g_playladobjinfo[i]);
//     }
// }

// T_ASF_DATA_PACKET_PLAYLOAD_OBJINFO* getObjinfoByObjnum(DWORD objnum) {
//     int i = 0;
    
//     for (i=0; i<MAX_PARSING_OBJ; i++) {
//         if (g_playladobjinfo[i].mediaObjNum == objnum) {
//             return &g_playladobjinfo[i];
//         }
//     }

//     if (i == MAX_PARSING_OBJ) {
//         printf("Can't finde obj info: %d!\n", objnum);

//         return NULL;
//     }
// }

int getUnusedObjinfoIndex(DWORD streamid) {
    int i = 0;

    for (i=0; i<MAX_PARSING_OBJ; i++) {
        if (g_playladobjinfo[streamid][i].isParing == 0) {
            return i;
        }
    }

    if (i == MAX_PARSING_OBJ) {
        //printf("All obj indeix is used!\n");

        return -1;
    }
}

void resetObjinfo(T_ASF_DATA_PACKET_PLAYLOAD_OBJINFO* objinfo) {
    objinfo->allobjlen = 0;
    objinfo->isParing = 0;
    objinfo->mediaObjNum = -1; // some obj num is 0, so used -1
}

void InitAllObjinfo() {
    int i = 0;
    int j = 0;

    for (i=0; i<MAX_STREAM_NUM; i++) {
        for (j=0; j<MAX_PARSING_OBJ; j++) {
            resetObjinfo(&g_playladobjinfo[i][j]);
        }
    }
}

T_ASF_DATA_PACKET_PLAYLOAD_OBJINFO* getObjinfoByObjnum(DWORD streamnum, DWORD objnum) {
    int i = 0;

    for (i=0; i<MAX_PARSING_OBJ; i++) {
        if (g_playladobjinfo[streamnum][i].mediaObjNum == objnum) {
            return &g_playladobjinfo[streamnum][i];
        }
    }

    if (i == MAX_PARSING_OBJ) {
        //printf("Can't finde obj info: %d!\n", objnum);

        return NULL;
    }
}

// 23:59:59:999
void asf_changeMs2Str(int ms, char *strtime) {
    //memset(strtime, 0x0, strlen(strtime));

    int h = ms / 3600000;
    int m = (ms - h * 3600000) / 60000;
    int s = (ms - h * 3600000 - m * 60000) / 1000;
    int leftms = ms - h * 3600000 - m * 60000 - s * 1000;

    //printf("ms: %d, h: %d, m: %d, s: %d, left: %d\n", ms, h, m, s, leftms);
    sprintf(strtime, "%02d%s%02d%s%02d%s%03d", h, ":", m, ":", s, ":", leftms);
    //printf("time: %s\n", time);

    return;
}

/************************************************************************************************************
**                                        Single payload
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Stream Number              |    BYTE           |        8
**            Stream Number          |                   |        7(LSB)
**            Key Frame Bit          |                   |        1
**        Media Object Number        | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Offset Into Media Object   | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Replicated Data Length     | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Replicated Data            |    BYTE           |        varies
**        Payload Data               |    BYTE           |        varies
************************************************************************************************************/
typedef struct t_asf_data_packet_single_playload {
    BYTE streamNum;
    BYTE keyFrame1Bit:1, streamNum7Bits:7;

    // all to DWORD, when parsing discern it.
    DWORD mediaObjNum;

    /**
     * Into Media Object value for non-compressed payloads; however, for compressed payloads it is used to express 
     * the Presentation Time value.
     */
    DWORD offIntoMediaObj; // single or Single payload, compressed payload data

    /**
     * Specifies the size, in bytes, of the Replicated Data field. This field shall not be present if the Replicated 
     * Data Length Type field of the payload parsing information structure is set to 00. Whenever present, the 
     * Replicated Data Length field can be coded using either a BYTE, a WORD, or a DWORD. This is specified by the 
     * value of the Replicated Data Length Type field. For content created according to this specification, 
     * this field is coded using a BYTE. If the value of this field is set to 1, the payload should be interpreted 
     * as a compressed payload, as described in section 5.2.3.2. Otherwise, valid values are 0 or values greater 
     * than or equal to 8.
     * if is set to 1, means playload is compressed payload data.
     */
    DWORD repDataLen;

    /**
     * Specifies an array of replicated data. The number of bytes in this array is specified by the Replicated Data 
     * Length field. This data will be identical in value for all payloads for the same Media Object. Whenever present, 
     * this data always starts with a DWORD that contains the size, in bytes, of the Media Object this payload belongs 
     * to, immediately followed by a DWORD that contains the presentation time, in milliseconds, of the Media Object 
     * this payload belongs to. Following those two DWORDs is optional extension data for media samples. For details 
     * on how to use this data, see section 7.3.1.
     */
    BYTE *repData;
    T_ASF_DATA_PACKET_PLAYLOAD_REPDATA detailRepdata;

    BYTE *playloadData;
} T_ASF_DATA_PACKET_SINGLE_PLAYLOAD;

/*************************************************************************************************************
**                                        Sub-Payload Data
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Sub-Payload #0 Data Length |    BYTE           |        8
**        Sub-Payload #0 Data        |    BYTE           |        varies
**        Sub-Payload #1 Data Length |    BYTE           |        8
**        Sub-Payload #1 Data        |    BYTE           |        varies
**        ...
*************************************************************************************************************/
typedef struct t_asf_data_packet_single_compressed_playload_subpayload {
    BYTE subpayloadLen;
    BYTE subpayloadDatal;
} T_ASF_DATA_PACKET_SINGLE_COMPRESSED_PLAYLOAD_SUBPAYLOAD;

/************************************************************************************************************
**                                        Single payload, compressed payload data
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Stream Number              |    BYTE           |        8
**            Stream Number          |                   |        7(LSB)
**            Key Frame Bit          |                   |        1
**        Media Object Number        | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Presentation Time          | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Replicated Data Length     | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Presentation Time Delta    |    BYTE           |        8
**        Sub-Payload Data           |    BYTE           |        varies
************************************************************************************************************/
typedef struct t_asf_data_packet_single_compressed_playload {
    BYTE streamNum;
    BYTE keyFrame1Bit:1, streamNum7Bits:7;

    // all to DWORD, when parsing discern it.
    DWORD mediaObjNum;

    /**
     * Specifies the presentation time, in milliseconds, of the media object that the first sub-payload belongs to. 
     * This field must be present; the Offset Into Media Object Length Type field of the payload parsing information 
     * structure must not be set to 00. The Presentation Time field can be coded using either a BYTE, WORD or a DWORD. 
     * This is specified by the value of the Offset Into Media Object Length Type field. For content created according 
     * to this specification, this field is coded using a DWORD. Note that this field is used to express the Offset 
     * Into Media Object value for non-compressed payloads; however, for compressed payloads it is used to express 
     * the Presentation Time value.
     */
    DWORD presentationTime;
    
    DWORD repDataLen;

    BYTE presentationTimeDelta;
    
    //BYTE *subPayloadData;
    T_ASF_DATA_PACKET_SINGLE_COMPRESSED_PLAYLOAD_SUBPAYLOAD **subpayloads;
} T_ASF_DATA_PACKET_SINGLE_COMPRESSED_PLAYLOAD;

/************************************************************************************************************
**                                        One payload of multiple payloads
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Stream Number              |    BYTE           |        8
**            Stream Number          |                   |        7(LSB)
**            Key Frame Bit          |                   |        1
**        Media Object Number        | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Offset Into Media Object   | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Replicated Data Length     | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Replicated Data            |    BYTE           |        varies
**        Payload Length             | BYTE, WORD, DWORD |        8, 16, 32
**        Payload Data               |    BYTE           |        varies
************************************************************************************************************/
typedef struct t_asf_data_packet_multiple_oneplayload {
    BYTE streamNum;
    BYTE keyFrame1Bit:1, streamNum7Bits:7;

    // all to DWORD, when parsing discern it.
    DWORD mediaObjNum;

    DWORD offIntoMediaObj;

    DWORD repDataLen;
    DWORD playloadLen;

    BYTE *repData;
    T_ASF_DATA_PACKET_PLAYLOAD_REPDATA detailRepdata;

    BYTE *playloadData;
} T_ASF_DATA_PACKET_MULTIPLE_ONEPLAYLOAD;

/************************************************************************************************************
**                                          One compressed payload data of multiple payloads
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Stream Number              |    BYTE           |        8
**            Stream Number          |                   |        7(LSB)
**            Key Frame Bit          |                   |        1
**        Media Object Number        | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Presentation Time          | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Replicated Data Length     | BYTE, WORD, DWORD |        0, 8, 16, 32
**        Presentation Time Delta    |    BYTE           |        8
**        Payload Length             | BYTE, WORD, DWORD |        8, 16, 32
**        Sub-Payload Data           |    BYTE           |        varies
************************************************************************************************************/
typedef struct t_asf_data_packet_multiple_onecompressed_playload {
    BYTE streamNum;
    BYTE keyFrame1Bit:1, streamNum7Bits:7;

    // all to DWORD, when parsing discern it.
    DWORD mediaObjNum;
    DWORD presentationTime;
    
    /**
     * Specifies the size, in bytes, of the Replicated Data field. This field shall not be present if the Replicated 
     * Data Length Type field of the payload parsing information structure is set to 00. Whenever present, 
     * the Replicated Data Length field can be coded using either a BYTE, a WORD, or a DWORD. This is specified by 
     * the value of the Replicated Data Length Type field. For content created according to this specification, 
     * this field is coded using a BYTE. If the value of this field is set to 1, the payload should be interpreted 
     * as a compressed payload, as described in section 5.2.3.4. Otherwise, valid values are 0 or values greater 
     * than or equal to 8.
     */
    DWORD repDataLen;

    DWORD payloadLen;

    BYTE presentationTimeDelta;
    
    BYTE *subPayloadData;
} T_ASF_DATA_PACKET_MULTIPLE_ONECOMPRESSED_PLAYLOAD;

/************************************************************************************************************
**                                        Multiple payloads/Multiple payloads, compressed payload data
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Payload Flags              |    BYTE           |        8
**            Number of Payloads     |                   |        6(LSB)
**            Payload Length Type    |                   |        2
**        Payloads/Compresse Payloads|    See below      |

-------------------------------------------------------------------------------------------------------------
**        Payload Length Type 
**
-------------------------------------------------------------------------------------------------------------
**        Value                     |    Descriptor value length
-------------------------------------------------------------------------------------------------------------
**        01                     |    The Payload Length field is coded using a BYTE.
**        10                     |    The Payload Length field is coded using a WORD.
**        11                     |    The Payload Length field is coded using a DWORD.
************************************************************************************************************/
typedef struct t_asf_data_multipe_playloads {
    BYTE playloadFlags;
    BYTE payloadLenType:2, numOfPlayloads:6;

    // playloads
    // union {
    //     T_ASF_DATA_PACKET_MULTIPLE_ONEPLAYLOAD **playloads;
    //     T_ASF_DATA_PACKET_MULTIPLE_ONECOMPRESSED_PLAYLOAD **compressedPlayloads;
    // } playloads;

    // 
    BYTE oneplayloadNums;
    BYTE compressedplayloadNums;

    T_ASF_DATA_PACKET_MULTIPLE_ONEPLAYLOAD **playloads;
    T_ASF_DATA_PACKET_MULTIPLE_ONECOMPRESSED_PLAYLOAD **compressedPlayloads;
} T_ASF_DATA_PACKET_MULTIPE_PLAYLOADS;

typedef struct t_asf_data_packet {
    T_ASF_DATA_PACKET_ERRCORRECTION_DATA errCorrectionData;

    T_ASF_DATA_PACKET_PLAYLOAD_PARSING_INFO palyloadParsingInfo;

    BYTE isSingleCompressedPlayload;

    //T_ASF_DATA_PACKET_SINGLE_PLAYLOAD palyload;
    union {
        T_ASF_DATA_PACKET_SINGLE_PLAYLOAD singlePlayload;
        T_ASF_DATA_PACKET_SINGLE_COMPRESSED_PLAYLOAD singleCompressedPlayload;
        T_ASF_DATA_PACKET_MULTIPE_PLAYLOADS multipePlayloads;
    } playload;
} T_ASF_DATA_PACKET;

/************************************************************************************************************
**                                        ASF Data Object
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Object ID                  |    GUID           |        128
**        Object Size                |    QWORD          |        64
**        File ID                    |    GUID           |        128
**        Total Data Packets         |    QWORD          |        64
**        Reserved                   |    WORD           |        16
**        Data Packets               |    See below      |        varies
************************************************************************************************************/
typedef struct t_asf_data {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;

    GUID fileID;
    QWORD totalDataPackets;

    /* Specifies a reserved field. The value of this field shall set to 0x0101(257).*/
    WORD reserved;

    T_ASF_DATA_PACKET **packets;
} T_ASF_DATA;

/************************************************************************************************************
**                                        ASF top-level Simple Index Object
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Object ID                  |    GUID           |        128
**        Object Size                |    QWORD          |        64
**        File ID                    |    GUID           |        128
**        Index Entry Time Interval  |    QWORD          |        64
**        Maximum Packet Count       |    DWORD          |        32
**        Index Entries Count        |    DWORD          |        32
**        Index Entries              |    See below      |        varies
************************************************************************************************************/
typedef struct t_asf_simple_index_entry {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;

    DWORD packetNum;
    WORD packetCount;
} T_ASF_SIMPLE_INDEX_ENTRY;

/************************************************************************************************************
**                                        ASF top-level Simple Index Object
**
-------------------------------------------------------------------------------------------------------------
**        Field name                |    Field type    |        Size (bits)
-------------------------------------------------------------------------------------------------------------
**        Object ID                  |    GUID           |        128
**        Object Size                |    QWORD          |        64
**        File ID                    |    GUID           |        128
**        Index Entry Time Interval  |    QWORD          |        64
**        Maximum Packet Count       |    DWORD          |        32
**        Index Entries Count        |    DWORD          |        32
**        Index Entries              |    See below      |        varies
************************************************************************************************************/
typedef struct t_asf_simple_index {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;

    GUID fileID;

    QWORD idexEntryTimeInterval;
    DWORD maxPacketCount;
    DWORD indexEntriesCount;

    T_ASF_SIMPLE_INDEX_ENTRY **simpleIndexEntries;
} T_ASF_SIMPLE_INDEX;

typedef struct t_asf_index {
    T_ASF_BASE_OBJECT_HEADER baseObjHeader;
} T_ASF_INDEX;

typedef struct t_asf_global_info {
    DWORD maxDataPacketSize;
} T_ASF_GLOBAL_INFO;

T_ASF_GLOBAL_INFO g_asfGlobalInfo = {0};
/************************************************************************************************************
**                                        GUIDS:
**
-------------------------------------------------------------------------------------------------------------
**        name                                        |       GUID    
-------------------------------------------------------------------------------------------------------------
** Top-level ASF object GUIDS
**        ASF_Header_Object                             |       75B22630-668E-11CF-A6D9-00AA0062CE6C
**        ASF_Data_Object                               |       75B22636-668E-11CF-A6D9-00AA0062CE6C
**        ASF_Simple_Index_Object                       |       33000890-E5B1-11CF-89F4-00A0C90349CB
**        ASF_Index_Object                              |       D6E229D3-35DA-11D1-9034-00A0C90349BE
**        ASF_Media_Object_Index_Object                 |       FEB103F8-12AD-4C64-840F-2A1D2F7AD48C
**        ASF_Timecode_Index_Object                     |       3CB73FD0-0C4A-4803-953D-EDF7B6228F0C

** Header Object GUIDS
**        ASF_File_Properties_Object                    |       8CABDCA1-A947-11CF-8EE4-00C00C205365
**        ASF_Stream_Properties_Object                  |       B7DC0791-A9B7-11CF-8EE6-00C00C205365
**        ASF_Header_Extension_Object                   |       5FBF03B5-A92E-11CF-8EE3-00C00C205365
**        ASF_Codec_List_Object                         |       86D15240-311D-11D0-A3A4-00A0C90348F6
**        ASF_Script_Command_Object                     |       1EFB1A30-0B62-11D0-A39B-00A0C90348F6
**        ASF_Marker_Object                             |       F487CD01-A951-11CF-8EE6-00C00C205365
**        ASF_Bitrate_Mutual_Exclusion_Object           |       D6E229DC-35DA-11D1-9034-00A0C90349BE
**        ASF_Error_Correction_Object                   |       75B22635-668E-11CF-A6D9-00AA0062CE6C
**        ASF_Content_Description_Object                |       75B22633-668E-11CF-A6D9-00AA0062CE6C
**        ASF_Extended_Content_Description_Object       |       D2D0A440-E307-11D2-97F0-00A0C95EA850
**        ASF_Content_Branding_Object                   |       2211B3FA-BD23-11D2-B4B7-00A0C955FC6E  
**        ASF_Stream_Bitrate_Properties_Object          |       7BF875CE-468D-11D1-8D82-006097C9A2B2  
**        ASF_Content_Encryption_Object                 |       2211B3FB-BD23-11D2-B4B7-00A0C955FC6E  
**        ASF_Extended_Content_Encryption_Object        |       298AE614-2622-4C17-B935-DAE07EE9289C  
**        ASF_Digital_Signature_Object                  |       2211B3FC-BD23-11D2-B4B7-00A0C955FC6E
**        ASF_Padding_Object                            |       1806D474-CADF-4509-A4BA-9AABCB96AAE8

** Stream Properties Object Stream Type GUIDs
**        ASF_Audio_Media                               |       F8699E40-5B4D-11CF-A8FD-00805F5C442B
**        ASF_Video_Media                               |       BC19EFC0-5B4D-11CF-A8FD-00805F5C442B
**        ASF_Command_Media                             |       59DACFC0-59E6-11D0-A3AC-00A0C90348F6
**        ASF_JFIF_Media                                |       B61BE100-5B4E-11CF-A8FD-00805F5C442B
**        ASF_Degradable_JPEG_Media                     |       35907DE0-E415-11CF-A917-00805F5C442B
**        ASF_File_Transfer_Media                       |       91BD222C-F21C-497A-8B6D-5AA86BFC0185
**        ASF_Binary_Media                              |       3AFB65E2-47EF-40F2-AC2C-70A90D71D343

** Stream Properties Object Error Correction Type GUIDs
**        ASF_No_Error_Correction                       |       20FB5700-5B55-11CF-A8FD-00805F5C442B
**        ASF_Audio_Spread                              |       BFC3CD50-618F-11CF-8BB2-00AA00B4E220
************************************************************************************************************/
// Top-level ASF object GUIDS
#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfHeaderObjectV0 = {
    0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C
};
#endif
const GUID asf_header = {
    0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C
};

#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfDataObjectV0 = {
    0x36, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c
};
#endif
const GUID asf_data_header = {
    0x36, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c
};

#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfIndexObjectV2 = {
    0x90, 0x08, 0x00, 0x33, 0xB1, 0xE5, 0xCF, 0x11, 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB
};
#endif
const GUID asf_simple_index_header = {
    0x90, 0x08, 0x00, 0x33, 0xB1, 0xE5, 0xCF, 0x11, 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB
};

#if PRINTF_FROM_ASFVIEW
//const GUID CLSID_CAsfIndexObjectV2 = {
    //0xD3, 0x29, 0xE2, 0xD6, 0xDA, 0x35, 0xD1, 0x11, 0x34, 0x90, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE
//};
#endif
const GUID asf_index_header = {
    0xD3, 0x29, 0xE2, 0xD6, 0xDA, 0x35, 0xD1, 0x11, 0x34, 0x90, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE
};



// Header Object GUIDS(asf_header)
#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfPropertiesObjectV2 = {
    0xA1, 0xDC, 0xAB, 0x8C, 0x47, 0xA9, 0xCF, 0x11, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65
};
#endif
const GUID asf_header_file_properties_header = {
    0xA1, 0xDC, 0xAB, 0x8C, 0x47, 0xA9, 0xCF, 0x11, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65
};

#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfStreamPropertiesObjectV1 = {
    0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65
};
#endif
const GUID asf_header_stream_properties_header = {
    0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65
};

#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfClockObjectV2 = {
    0xb5, 0x03, 0xbf, 0x5f, 0x2E, 0xA9, 0xCF, 0x11, 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65
};
#endif
const GUID asf_header_header_extension_header = {
    0xb5, 0x03, 0xbf, 0x5f, 0x2E, 0xA9, 0xCF, 0x11, 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65
};

#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfCodecObjectV0 = {
    0x40, 0x52, 0xD1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6
};
#endif
const GUID asf_header_codec_list_header = {
    0x40, 0x52, 0xD1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6
};

#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfExtendedContentDescObject = {
    0x40, 0xA4, 0xD0, 0xD2, 0x07, 0xE3, 0xD2, 0x11, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50
};
#endif
const GUID asf_header_extended_content_description_header = {
    0x40, 0xA4, 0xD0, 0xD2, 0x07, 0xE3, 0xD2, 0x11, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50
};

#if PRINTF_FROM_ASFVIEW
static GUID CLSID_CAsfExtendedStreamPropertiesObject = { 
    0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2
};
#endif
static GUID asf_header_stream_bitrate_properties_header = { 
    0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2
};



// Stream Properties Object Stream Type GUIDs
#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfXStreamTypeAcmAudio = {
    0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B
};
#endif
const GUID asf_header_streamproperties_audio_type_header = {
    0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B
};

#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfXStreamTypelcmVideo = {
    0xC0, 0xEF, 0x19, 0xBC, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B
};
#endif
const GUID asf_header_streamproperties_video_type_header = {
    0xC0, 0xEF, 0x19, 0xBC, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B
};

const GUID asf_header_streamproperties_command_media_header = {
    0xC0, 0xCF, 0xDA, 0x59, 0xE6, 0x59, 0xD0, 0x11, 0xA3, 0xAC, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6
};

const GUID asf_header_streamproperties_jfif_media_header = {
    0x00, 0xE1, 0x1B, 0xB6, 0x4E, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B
};

// const GUID asf_header_streamproperties_degradable_jpg_header = {
//     0xC0, 0xCF, 0xDA, 0x59, 0xE6, 0x59, 0xD0, 0x11, 0xA3, 0xAC, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6
// };

// const GUID asf_header_streamproperties_file_transfer_header = {
//     0xC0, 0xCF, 0xDA, 0x59, 0xE6, 0x59, 0xD0, 0x11, 0xA3, 0xAC, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6
// };

// const GUID asf_header_streamproperties_binary_media_header = {
//     0xC0, 0xCF, 0xDA, 0x59, 0xE6, 0x59, 0xD0, 0x11, 0xA3, 0xAC, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6
// };



// Stream Properties Object Error Correction Type GUIDs
#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfXAcmAudioErrorMaskingStrategy = {
    0x50, 0xcd, 0xc3, 0xbf, 0x8f, 0x61, 0xCF, 0x11, 0x8b, 0xb2, 0x00, 0xaa, 0x00, 0xb4, 0xe2, 0x20
};
#endif
const GUID asf_header_streamproperties_aduio_spread_header = {
    0x50, 0xcd, 0xc3, 0xbf, 0x8f, 0x61, 0xCF, 0x11, 0x8b, 0xb2, 0x00, 0xaa, 0x00, 0xb4, 0xe2, 0x20
};

#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfXNullErrorMaskingStrategy = {
    0x00, 0x57, 0xfb, 0x20, 0x55, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B
};
#endif
const GUID asf_header_streamproperties_no_error_header = {
    0x00, 0x57, 0xfb, 0x20, 0x55, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B
};



// Header Extension Object GUIDs
#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfPacketClock1 = {
    0x11, 0xd2, 0xd3, 0xab, 0xba, 0xa9, 0xcf, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65
};
#endif
const GUID asf_header_extension_reserved_1_header = {
    0x11, 0xd2, 0xd3, 0xab, 0xba, 0xa9, 0xcf, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65
};



// Codec List Object GUIDs
#if PRINTF_FROM_ASFVIEW
const GUID CLSID_CAsfXCodexList = {
    0x41, 0x52, 0xd1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6
};
#endif
const GUID asf_codeclist_reserved_2_header = {
    0x41, 0x52, 0xd1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6
};


typedef enum e_asf_object_type {
    ASF_TOP_OBJECT = 0,
    ASF_HEADER_OBJECT
} E_ASF_OBJECT_TYPE;

static void asf_DealObject(T_ASF_BASE_OBJECT *baseObject, E_ASF_OBJECT_TYPE objectType);

static inline int asf_GUIDCmp(const void *g1, const void *g2) {
    return memcmp(g1, g2, sizeof(GUID));
}

#define PRINT_IF_GUID(g, cmp) \
    if (!asf_GUIDCmp(g, &cmp)) \
        printf("%s\n", # cmp)

/**
 * show likes:
 * 0: asf_header_header_extension_heade
 * 1: Object ID: D2D0A440-E307-11D2-97F0-00A0C95EA850, asf_header_extended_content_description_header
 * 2: D2D0A440-E307-11D2-97F0-00A0C95EA850
 */
static void asf_PrintGUID(GUID *g, int showid) {
    int i;

    if (showid == 1) {
        printf("Object ID: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X, ",
            (*g)[3], (*g)[2], (*g)[1], (*g)[0], (*g)[5], (*g)[4], (*g)[7], (*g)[6],
            (*g)[8], (*g)[9], (*g)[10], (*g)[11], (*g)[12], (*g)[13], (*g)[14], (*g)[15]);
    } else if (showid == 2) {
        printf("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
            (*g)[3], (*g)[2], (*g)[1], (*g)[0], (*g)[5], (*g)[4], (*g)[7], (*g)[6],
            (*g)[8], (*g)[9], (*g)[10], (*g)[11], (*g)[12], (*g)[13], (*g)[14], (*g)[15]);

        return;
    }

#if PRINTF_FROM_ASFVIEW
    PRINT_IF_GUID(g, CLSID_CAsfHeaderObjectV0);
    else PRINT_IF_GUID(g, CLSID_CAsfDataObjectV0);
    else PRINT_IF_GUID(g, CLSID_CAsfIndexObjectV2);
    else PRINT_IF_GUID(g, asf_index_header);
    else PRINT_IF_GUID(g, CLSID_CAsfPropertiesObjectV2);
    else PRINT_IF_GUID(g, CLSID_CAsfStreamPropertiesObjectV1);
    else PRINT_IF_GUID(g, CLSID_CAsfClockObjectV2);
    else PRINT_IF_GUID(g, CLSID_CAsfCodecObjectV0);
    else PRINT_IF_GUID(g, CLSID_CAsfExtendedContentDescObject);
    else PRINT_IF_GUID(g, CLSID_CAsfExtendedStreamPropertiesObject);
    else PRINT_IF_GUID(g, CLSID_CAsfXStreamTypeAcmAudio);
    else PRINT_IF_GUID(g, CLSID_CAsfXStreamTypelcmVideo);
    else PRINT_IF_GUID(g, CLSID_CAsfXAcmAudioErrorMaskingStrategy);
    else PRINT_IF_GUID(g, CLSID_CAsfXNullErrorMaskingStrategy);
    else PRINT_IF_GUID(g, CLSID_CAsfXCodexList);
    else PRINT_IF_GUID(g, CLSID_CAsfPacketClock1);
    else
        printf("(GUID: unknown)\n");
#else
    PRINT_IF_GUID(g, asf_header);
    else PRINT_IF_GUID(g, asf_data_header);
    else PRINT_IF_GUID(g, asf_simple_index_header);
    else PRINT_IF_GUID(g, asf_index_header);
    else PRINT_IF_GUID(g, asf_header_file_properties_header);
    else PRINT_IF_GUID(g, asf_header_stream_properties_header);
    else PRINT_IF_GUID(g, asf_header_header_extension_header);
    else PRINT_IF_GUID(g, asf_header_codec_list_header);
    else PRINT_IF_GUID(g, asf_header_extended_content_description_header);
    else PRINT_IF_GUID(g, asf_header_stream_bitrate_properties_header);
    else PRINT_IF_GUID(g, asf_header_streamproperties_audio_type_header);
    else PRINT_IF_GUID(g, asf_header_streamproperties_video_type_header);
    else PRINT_IF_GUID(g, asf_header_streamproperties_command_media_header);
    else PRINT_IF_GUID(g, asf_header_streamproperties_jfif_media_header);
    else PRINT_IF_GUID(g, asf_header_streamproperties_aduio_spread_header);
    else PRINT_IF_GUID(g, asf_header_streamproperties_no_error_header);
    else PRINT_IF_GUID(g, asf_header_codec_list_header);
    else PRINT_IF_GUID(g, asf_header_extension_reserved_1_header);
    else
        printf("(GUID: unknown)\n");
#endif

    //for (i = 0; i < 16; i++)
        //printf(" 0x%02x,", (*g)[i]);
}

// read little 16
WORD asf_rl16(BYTE *data) {
    WORD val;

    val = data[0];
    val |= data[1] << 8;

    return val;
}

DWORD asf_rl32(BYTE *data) {
    DWORD val;

    val = asf_rl16(data);
    val |= asf_rl16(data+2) << 16;

    return val;
}

QWORD asf_rl64(BYTE *data) {
    QWORD val;

    val = (QWORD)asf_rl32(data);
    val |= (QWORD)asf_rl32(data+4) << 32;

    return val;
}

// utf-16 to utf-8, just for ascii, chinase is not support
void asf_getstrl16(BYTE *data, WORD len, BYTE *str) {
    BYTE *tmp = data;

    WORD i = 0;

    for (i=0; i<len; i++) {
        str[i] = asf_rl16(tmp);
        //printf("i: %d, %c\n", i, str[i]);
        tmp += 2;
    }

    str[i] = '\0';
}

static void printfdata(BYTE *data, int len) {
    int i = 0;

    // for (i=0; i<len; i++) {
    //     printf("%02x ", data[i]);

    //     if (i!=0 && (i+1)%32==0) {
    //         printf("\n");
    //     }
    // }

    // printf("\n");

    for (i=0; i<len; i++)
    {
        if (i%16==0)
        {
            if (i!=0)
            {
                printf("\n");
            }

            printf("%08x: ", i);
        }

        printf("%02x ", data[i]);
        }

        printf("\n");
}

static void inline printfNSpace(int num) {
    printf("%*s", num, " ");
}

static void asf_DealHeader(T_ASF_BASE_OBJECT *baseObject) {
    DWORD i = 0;

    BYTE *data = baseObject->object_playload;
    BYTE *subData = NULL;

    T_ASF_HEADER asfHeader = {0};

    T_ASF_BASE_OBJECT **subBaseObject = NULL;

    // copy header first
    asfHeader.baseObjHeader = baseObject->baseObjHeader;

    asfHeader.object_nums = asf_rl32(data);
    
    data += 4;

    asfHeader.reserved1 = data[0];
    asfHeader.reserved2 = data[1];

    data += 2;

    subData = data;

#ifdef PRINTF_DEBUG
    printf("+Header Object\n");
    
    printfNSpace(4);
    printf("Object ID: ");
    asf_PrintGUID(&asfHeader.baseObjHeader.object_id, 0);

    printfNSpace(4);
    printf("Object size: %lld\n", asfHeader.baseObjHeader.object_size);

    printfNSpace(4);
    printf("Header object count: %d\n", asfHeader.object_nums);

    printfNSpace(4);
    printf("Alignment: %d\n", asfHeader.reserved1);

    printfNSpace(4);
    printf("Architecture: %d\n", asfHeader.reserved2);
#endif

    subBaseObject = (T_ASF_BASE_OBJECT **)malloc(sizeof(T_ASF_BASE_OBJECT*) * asfHeader.object_nums);
    if (!subBaseObject) {
        printf("malloc sub objects of head object error!\n");

        return;
    }

    for (i=0; i<asfHeader.object_nums; i++) {
        subBaseObject[i] = (T_ASF_BASE_OBJECT *)malloc(sizeof(T_ASF_BASE_OBJECT));
        if (!subBaseObject[i]) {
            printf("malloc sub object error!\n");

            return;
        }

        memcpy(subBaseObject[i]->baseObjHeader.object_id, subData, MAX_GUID_LEN);

        subData += MAX_GUID_LEN;

        subBaseObject[i]->baseObjHeader.object_size = asf_rl64(subData);

        subData += 8;

        // if (i == 0) {
        //     subBaseObject[i]->object_playload = data + ASF_BASE_OBJECT_HEADER_LEN;
        // } else {
        //     subBaseObject[i]->object_playload = data + subBaseObject[i-1]->baseObjHeader.object_size + ASF_BASE_OBJECT_HEADER_LEN;
        // }

        subBaseObject[i]->object_playload = subData;

        subData += (subBaseObject[i]->baseObjHeader.object_size - ASF_BASE_OBJECT_HEADER_LEN);

        asf_DealObject(subBaseObject[i], ASF_HEADER_OBJECT);
    }
}

// objcets of top-level object(header object)
static void asf_Header_DealFileProperties(T_ASF_BASE_OBJECT *baseObject) {
    BYTE *data = baseObject->object_playload;

    T_ASF_HEADER_FILE_PROPERTIES asfFileProperties = {0};

    // copy header first
    asfFileProperties.baseObjHeader = baseObject->baseObjHeader;

    memcpy(asfFileProperties.fileID, data, MAX_GUID_LEN);

    data += MAX_GUID_LEN;

    asfFileProperties.fielSize = asf_rl64(data);

    data += 8;

    asfFileProperties.creationDate = asf_rl64(data);

    data += 8;

    asfFileProperties.dataPacketsCount = asf_rl64(data);

    data += 8;

    asfFileProperties.playDuration = asf_rl64(data);

    data += 8;

    asfFileProperties.sendDuration = asf_rl64(data);

    data += 8;


    asfFileProperties.preroll = asf_rl64(data);

    data += 8;

    asfFileProperties.flags = asf_rl32(data);

    // asfFileProperties.broadcastFlag = asfFileProperties.flags >> 31 & 0x1;
    // asfFileProperties.seekableFlag = asfFileProperties.flags >> 30 & 0x1;
    asfFileProperties.broadcastFlag = asfFileProperties.flags & 0x1;
    asfFileProperties.seekableFlag = asfFileProperties.flags >> 1 & 0x1;

    data += 4;
    
    asfFileProperties.minDataPacketSize = asf_rl32(data);

    data += 4;

    asfFileProperties.maxDataPacketSize = asf_rl32(data);

    data += 4;

    asfFileProperties.maxBitrate = asf_rl32(data);

    data += 4;

    // used for parse Single payload has Single payload
    g_asfGlobalInfo.maxDataPacketSize = asfFileProperties.maxDataPacketSize;

#ifdef PRINTF_DEBUG
    printfNSpace(4);
    printf("+File Properties Object\n");

    printfNSpace(8);
    printf("Object ID: ");
    asf_PrintGUID(&asfFileProperties.baseObjHeader.object_id, 0);

    printfNSpace(8);
    printf("Object size: %lld\n", asfFileProperties.baseObjHeader.object_size);

    printfNSpace(8);
    printf("File ID: ");
    asf_PrintGUID(&asfFileProperties.fileID, 2);

    printfNSpace(8);
    printf("File size: %lld\n", asfFileProperties.fielSize);

    printfNSpace(8);
    printf("Creation Date: %lld(TODO? Windows timeshift from 1601/1/1)\n", asfFileProperties.creationDate);

    printfNSpace(8);
    printf("Data Packets Count: %lld\n", asfFileProperties.dataPacketsCount);
        
    printfNSpace(8);
    printf("Play Duration: %lld\n", asfFileProperties.playDuration);

    printfNSpace(8);
    printf("Send Duration: %lld\n", asfFileProperties.sendDuration);

    printfNSpace(8);
    printf("Preroll: %lld\n", asfFileProperties.preroll);

    printfNSpace(8);
    printf("Flags: %d\n", asfFileProperties.flags);
    printfNSpace(12);
    printf("Broadcast Flags: %d\n", asfFileProperties.broadcastFlag);
    printfNSpace(12);
    printf("Seekable Flags: %d\n", asfFileProperties.seekableFlag);

    printfNSpace(8);
    printf("Minimum Data Packet Size: %d\n", asfFileProperties.minDataPacketSize);
        
    printfNSpace(8);
    printf("Maximum Data Packet Size: %d\n", asfFileProperties.maxDataPacketSize);

    printfNSpace(8);
    printf("Maximum Bitrate: %d\n", asfFileProperties.maxBitrate);
#endif
}

static void asf_Header_DealStreamProperties(T_ASF_BASE_OBJECT *baseObject) {
    BYTE *data = baseObject->object_playload;

    T_ASF_HEADER_STREAM_PROPERTIES asfStreamProperties = {0};

    // copy header first
    asfStreamProperties.baseObjHeader = baseObject->baseObjHeader;

    memcpy(asfStreamProperties.streamType, data, MAX_GUID_LEN);

    data += MAX_GUID_LEN;

    memcpy(asfStreamProperties.errorCorrectionType, data, MAX_GUID_LEN);

    data += MAX_GUID_LEN;

    asfStreamProperties.timeOffset = asf_rl64(data);

    data += 8;

    asfStreamProperties.typeSpecDataLen = asf_rl32(data);

    data += 4;

    asfStreamProperties.errorCorrectionDataLen = asf_rl32(data);

    data += 4;

    asfStreamProperties.flags = asf_rl16(data);

    // asfStreamProperties.flags_streamNumber = (asfStreamProperties.flags >> 8) & 0x7f;
    // asfStreamProperties.flags_reserved = (asfStreamProperties.flags >> 8) & 0xff;
    // asfStreamProperties.flags_encContentFlag = asfStreamProperties.flags & 0x1;
    // LSB, TODO???
    asfStreamProperties.flags_streamNumber = asfStreamProperties.flags & 0x7f;
    asfStreamProperties.flags_reserved = (asfStreamProperties.flags >> 7) & 0xff;
    asfStreamProperties.flags_encContentFlag = (asfStreamProperties.flags >> 15) & 0x1;

    data += 2;

    asfStreamProperties.reserved = asf_rl32(data);

    data += 4;

    /* Type-Specific Data */
    // audio
    if (!asf_GUIDCmp(asfStreamProperties.streamType, asf_header_streamproperties_audio_type_header)) {
        asfStreamProperties.asf_media.audiomedia.codecID = asf_rl16(data);

        data += 2;

        asfStreamProperties.asf_media.audiomedia.numChannels = asf_rl16(data);

        data += 2;

        asfStreamProperties.asf_media.audiomedia.samples = asf_rl32(data);

        data += 4;

        asfStreamProperties.asf_media.audiomedia.avgNumberBytesPerSec = asf_rl32(data);

        data += 4;

        asfStreamProperties.asf_media.audiomedia.blockAlignment = asf_rl16(data);

        data += 2;

        asfStreamProperties.asf_media.audiomedia.bitPerSample = asf_rl16(data);

        data += 2;

        asfStreamProperties.asf_media.audiomedia.codecSpecDataSize = asf_rl16(data);

        data += 2;

        // TODO, code specific data
    }

    // video
    if (!asf_GUIDCmp(asfStreamProperties.streamType, asf_header_streamproperties_video_type_header)) {
        asfStreamProperties.asf_media.videomedia.encWidth = asf_rl32(data);

        data += 4;

        asfStreamProperties.asf_media.videomedia.encHeight = asf_rl32(data);

        data += 4;

        asfStreamProperties.asf_media.videomedia.reservedFlags = data[0];

        data += 1;

        asfStreamProperties.asf_media.videomedia.formatDataSize = asf_rl16(data);

        data += 2;

        // format data
        asfStreamProperties.asf_media.videomedia.formatdata.formatDataSize = asf_rl32(data);

        data += 4;

        asfStreamProperties.asf_media.videomedia.formatdata.imageWidth = asf_rl32(data);

        data += 4;

        asfStreamProperties.asf_media.videomedia.formatdata.imageHeight = asf_rl32(data);

        data += 4;

        asfStreamProperties.asf_media.videomedia.formatdata.reserved = asf_rl16(data);

        data += 2;

        asfStreamProperties.asf_media.videomedia.formatdata.bitsPerPixel = asf_rl16(data);

        data += 2;

        asfStreamProperties.asf_media.videomedia.formatdata.compressionID = asf_rl32(data);

        data += 4;

        asfStreamProperties.asf_media.videomedia.formatdata.imageSize = asf_rl32(data);

        data += 4;

        asfStreamProperties.asf_media.videomedia.formatdata.horPixelsPerMeter = asf_rl32(data);

        data += 4;

        asfStreamProperties.asf_media.videomedia.formatdata.verPixelsPerMeter = asf_rl32(data);

        data += 4;
                
        asfStreamProperties.asf_media.videomedia.formatdata.colorsUsedCount = asf_rl32(data);

        data += 4;

        asfStreamProperties.asf_media.videomedia.formatdata.importantColorsCount = asf_rl32(data);

        data += 4;

        // TODO, code specific data
    }

    /* TODO, Error Correction Data, for audio is Spread audio */

#ifdef PRINTF_DEBUG
    printfNSpace(4);
    printf("+Stream Properties Object\n");

    printfNSpace(8);
    printf("Object ID: ");
    asf_PrintGUID(&asfStreamProperties.baseObjHeader.object_id, 0);

    printfNSpace(8);
    printf("Object size: %lld\n", asfStreamProperties.baseObjHeader.object_size);

    printfNSpace(8);
    printf("Stream Type: ");
    asf_PrintGUID(&asfStreamProperties.streamType, 0);

    printfNSpace(8);
    printf("Error correction strategy: ");
    asf_PrintGUID(&asfStreamProperties.errorCorrectionType, 0);

    printfNSpace(8);
    printf("Time Offset: %lld\n", asfStreamProperties.timeOffset);

    printfNSpace(8);
    printf("Type-Specifoc Data Length: %d\n", asfStreamProperties.typeSpecDataLen);

    printfNSpace(8);
    printf("Error Correction Data Length: %d\n", asfStreamProperties.errorCorrectionDataLen);

    printfNSpace(8);
    printf("Flags: %d\n", asfStreamProperties.flags);

    printfNSpace(12);
    printf("Stream Number: %d\n", asfStreamProperties.flags_streamNumber);

    printfNSpace(12);
    printf("Reserved: %d\n", asfStreamProperties.flags_reserved);


    printfNSpace(12);
    printf("Encrypted Content Flag: %d\n", asfStreamProperties.flags_encContentFlag);

    printfNSpace(8);
#ifdef PRINTF_FROM_ASFVIEW
    printf("Security ID: %d\n", asfStreamProperties.reserved);
#else
    printf("Reserved: %d\n", asfStreamProperties.reserved);
#endif

    if (!asf_GUIDCmp(asfStreamProperties.streamType, asf_header_streamproperties_audio_type_header)) {
        printfNSpace(8);
        printf("Type: %s\n", "WAVEFORMATEX");

        printfNSpace(8);
        printf("Format tag: %d\n", asfStreamProperties.asf_media.audiomedia.codecID);

        printfNSpace(8);
        printf("Channels: %d\n", asfStreamProperties.asf_media.audiomedia.numChannels);

        printfNSpace(8);
        printf("Samples/second: %d\n", asfStreamProperties.asf_media.audiomedia.samples);

        printfNSpace(8);
        printf("Average bytes/second: %d\n", asfStreamProperties.asf_media.audiomedia.avgNumberBytesPerSec);

        printfNSpace(8);
        printf("Block Alignment: %d\n", asfStreamProperties.asf_media.audiomedia.blockAlignment);

        printfNSpace(8);
        printf("Bits/sample: %d\n", asfStreamProperties.asf_media.audiomedia.bitPerSample);

        printfNSpace(8);
        printf("Extra bytes: %d\n", asfStreamProperties.asf_media.audiomedia.codecSpecDataSize);
    }

    if (!asf_GUIDCmp(asfStreamProperties.streamType, asf_header_streamproperties_video_type_header)) {
        printfNSpace(8);
        printf("Window width: %d\n", asfStreamProperties.asf_media.videomedia.encWidth);

        printfNSpace(8);
        printf("Window height: %d\n", asfStreamProperties.asf_media.videomedia.encHeight);

        printfNSpace(8);
        printf("Flags: %d\n", asfStreamProperties.asf_media.videomedia.reservedFlags);

        printfNSpace(8);
        printf("Image info length: %d\n", asfStreamProperties.asf_media.videomedia.formatDataSize);

        if (asfStreamProperties.asf_media.videomedia.formatDataSize > 0) {
            printfNSpace(8);
            printf("BITMAPINFOHEADER: include\n");

            printfNSpace(12);
            printf("biSize: %d\n", asfStreamProperties.asf_media.videomedia.formatdata.formatDataSize);

            printfNSpace(12);
            printf("biWidth: %d\n", asfStreamProperties.asf_media.videomedia.formatdata.imageWidth);

            printfNSpace(12);
            printf("biHeight: %d\n", asfStreamProperties.asf_media.videomedia.formatdata.imageHeight);

            printfNSpace(12);
            printf("biPlanes: %d\n", asfStreamProperties.asf_media.videomedia.formatdata.reserved);

            printfNSpace(12);
            printf("biBitCount: %d\n", asfStreamProperties.asf_media.videomedia.formatdata.bitsPerPixel);

            printfNSpace(12);
            BYTE strFucc[5] = {0};

            asf_fourcc_to_char(asfStreamProperties.asf_media.videomedia.formatdata.compressionID, strFucc);

            //printf("biCompression: %d\n", asfStreamProperties.asf_media.videomedia.formatdata.compressionID);
            printf("biCompression: %s(%d)\n", strFucc, asfStreamProperties.asf_media.videomedia.formatdata.compressionID);

            printfNSpace(12);
            printf("biSizeImage: %d\n", asfStreamProperties.asf_media.videomedia.formatdata.imageSize);

            printfNSpace(12);
            printf("biXPelsPreMeter: %d\n", asfStreamProperties.asf_media.videomedia.formatdata.horPixelsPerMeter);

            printfNSpace(12);
            printf("biYPelsPreMeter: %d\n", asfStreamProperties.asf_media.videomedia.formatdata.verPixelsPerMeter);

            printfNSpace(12);
            printf("biClrUsed: %d\n", asfStreamProperties.asf_media.videomedia.formatdata.colorsUsedCount);

            printfNSpace(12);
            printf("biClrImportant: %d\n", asfStreamProperties.asf_media.videomedia.formatdata.importantColorsCount);
        }
    }
#endif
}

static void asf_Header_DealHeaderExtension(T_ASF_BASE_OBJECT *baseObject) {
    BYTE *data = baseObject->object_playload;

    T_ASF_HEADER_HEADER_EXTENSION asfHeaderExt = {0};

    // copy header first
    asfHeaderExt.baseObjHeader = baseObject->baseObjHeader;

    memcpy(asfHeaderExt.reservedField1, data, MAX_GUID_LEN);

    data += MAX_GUID_LEN;

    asfHeaderExt.reservedField2 = asf_rl16(data);

    data += 2;

    asfHeaderExt.headerExtDataSize = asf_rl32(data);

    data += 4;

#ifdef PRINTF_DEBUG
    printfNSpace(4);
    printf("+Header Extension Object\n");

    printfNSpace(8);
    printf("Object ID: ");
    asf_PrintGUID(&asfHeaderExt.baseObjHeader.object_id, 0);

    printfNSpace(8);
    printf("Object size: %lld\n", asfHeaderExt.baseObjHeader.object_size);

#ifdef PRINTF_DEBUG_DETAIL
    printfNSpace(8);
    printf("Reserved Field 1: ");
    asf_PrintGUID(&asfHeaderExt.reservedField1, 0);

    printfNSpace(8);
    printf("Reserved Field 2: %d\n", asfHeaderExt.reservedField2);

    printfNSpace(8);
    printf("Header Extension Data size: %d\n", asfHeaderExt.headerExtDataSize);
#else
    printfNSpace(8);
    printf("Packet clock type: ");
    asf_PrintGUID(&asfHeaderExt.reservedField1, 0);

    printfNSpace(8);
    printf("Packet clock size: %d\n", asfHeaderExt.reservedField2);

    printfNSpace(8);
    printf("Clock specifil data length: %d\n", asfHeaderExt.headerExtDataSize);
#endif

#endif
}

static void asf_Header_DealCodecList(T_ASF_BASE_OBJECT *baseObject) {
    DWORD i = 0;

    BYTE *data = baseObject->object_playload;
    BYTE *entriesData = NULL;

    T_ASF_HEADER_CODECLIST asfCodecList = {0};

    // copy header first
    asfCodecList.baseObjHeader = baseObject->baseObjHeader;

    memcpy(asfCodecList.reserved, data, MAX_GUID_LEN);

    data += MAX_GUID_LEN;

    asfCodecList.codecEntryCount = asf_rl32(data);

    data += 4;

    if (asfCodecList.codecEntryCount != 0) {
        asfCodecList.codecEntries = (T_ASF_CODECLIST_ENTRY **)malloc(sizeof(T_ASF_CODECLIST_ENTRY *) * asfCodecList.codecEntryCount);
        if (!asfCodecList.codecEntries) {
            printf("malloc codec list entries error!\n");

            return;
        }
    }

    memset(asfCodecList.codecEntries, 0x0, sizeof(T_ASF_CODECLIST_ENTRY *) * asfCodecList.codecEntryCount);

    entriesData = data;

    for (i=0; i<asfCodecList.codecEntryCount; i++) {
        asfCodecList.codecEntries[i] = (T_ASF_CODECLIST_ENTRY *)malloc(sizeof(T_ASF_CODECLIST_ENTRY));
        if (!asfCodecList.codecEntries[i]) {
            printf("malloc codec list entry error!\n");

            return;
        }

        memset(asfCodecList.codecEntries[i], 0x0, sizeof(T_ASF_CODECLIST_ENTRY));

        asfCodecList.codecEntries[i]->type = asf_rl16(entriesData);

        entriesData += 2;

        // code name, unicode is WCHAR(utf-16, 2个字节代表一个unicode, 因此codecNameLen * 2)
        asfCodecList.codecEntries[i]->codecNameLen = asf_rl16(entriesData);

        entriesData += 2;

        // TODO???
        asf_getstrl16(entriesData, asfCodecList.codecEntries[i]->codecNameLen, asfCodecList.codecEntries[i]->codecNameUTF8);

        entriesData += asfCodecList.codecEntries[i]->codecNameLen * 2;

        // code des
        asfCodecList.codecEntries[i]->codecDesLen = asf_rl16(entriesData);
        
        entriesData += 2;

        // TODO???
        asf_getstrl16(entriesData, asfCodecList.codecEntries[i]->codecDesLen, asfCodecList.codecEntries[i]->codecDesUTF8);

        entriesData += asfCodecList.codecEntries[i]->codecDesLen * 2;

        // code info, byte, so not need * 2
        asfCodecList.codecEntries[i]->codecInfoLen = asf_rl16(entriesData);
        
        entriesData += 2;

        memcpy(asfCodecList.codecEntries[i]->codecInfo, entriesData, asfCodecList.codecEntries[i]->codecInfoLen);

        entriesData += asfCodecList.codecEntries[i]->codecInfoLen;
    }

#ifdef PRINTF_DEBUG
    printfNSpace(4);
    printf("+Codec List Object\n");

    printfNSpace(8);
    printf("Object ID: ");
    asf_PrintGUID(&asfCodecList.baseObjHeader.object_id, 0);

    printfNSpace(8);
    printf("Object size: %lld\n", asfCodecList.baseObjHeader.object_size);

    printfNSpace(8);
#if PRINTF_FROM_ASFVIEW
    printf("Codec ID: ");
    asf_PrintGUID(&asfCodecList.reserved, 0);
#else
    printf("Reserved: ");
    asf_PrintGUID(&asfCodecList.reserved, 0);
#endif

    printfNSpace(8);
    printf("+Codec Entries Count: %d\n", asfCodecList.codecEntryCount);

#ifdef PRINTF_DEBUG_DETAIL
    for (i=0; i<asfCodecList.codecEntryCount; i++) {
        printfNSpace(12);

        if (asfCodecList.codecEntries[i]->type == 0x1) {
            printf("Type: %d, %s\n", asfCodecList.codecEntries[i]->type, "Video codec");
        } else if (asfCodecList.codecEntries[i]->type == 0x2) {
            printf("Type: %d, %s\n", asfCodecList.codecEntries[i]->type, "Audio codec");
        } else {
            printf("Type: %d, %s\n", asfCodecList.codecEntries[i]->type, "Unknown codec");
        }

        printfNSpace(12);
        printf("Codec Name Length: %d\n", asfCodecList.codecEntries[i]->codecNameLen);
        
        printfNSpace(12);
        printf("Codec Name: %s\n", asfCodecList.codecEntries[i]->codecNameUTF8);

        printfNSpace(12);
        printf("Codec Descriptio Length: %d\n", asfCodecList.codecEntries[i]->codecDesLen);
        
        printfNSpace(12);
        printf("Codec Descriptio: %s\n", asfCodecList.codecEntries[i]->codecDesUTF8);

        printfNSpace(12);
        printf("Codec Information Length: %d\n", asfCodecList.codecEntries[i]->codecInfoLen);

        printfNSpace(12);
        printf("Codec Information: %s\n", asfCodecList.codecEntries[i]->codecInfo);

        if (i != (asfCodecList.codecEntryCount-1))
            printf("\n");
    }
#else
    for (i=0; i<asfCodecList.codecEntryCount; i++) {
        printfNSpace(12);

        printf("Type: ");
        if (asfCodecList.codecEntries[i]->type == 0x1) {
            printf("%s\n", "Video codec");
        } else if (asfCodecList.codecEntries[i]->type == 0x2) {
            printf("%s\n", "Audio codec");
        } else {
            printf("%s\n", "Unknown codec");
        }

        if (asfCodecList.codecEntries[i]->type == 0x1) {
            printfNSpace(12);
            printf("Four CC: %s\n", asfCodecList.codecEntries[i]->codecInfo);
        }

        printfNSpace(12);
        printf("Display Name: %s\n", asfCodecList.codecEntries[i]->codecNameUTF8);

        printfNSpace(12);
        printf("Descriptio: %s\n", asfCodecList.codecEntries[i]->codecDesUTF8);

        if (i != (asfCodecList.codecEntryCount-1))
            printf("\n");
    }
#endif
#endif
}

static void asf_Header_DealExtendedContentDescription(T_ASF_BASE_OBJECT *baseObject) {
    WORD i = 0;

    BYTE *desData = NULL;

    BYTE *data = baseObject->object_playload;

    T_ASF_HEADER_EXTCONTENTDES asfExtContentDes = {0};

    // copy header first
    asfExtContentDes.baseObjHeader = baseObject->baseObjHeader;

    asfExtContentDes.contentDesCount = asf_rl16(data);

    data += 2;

    if (asfExtContentDes.contentDesCount != 0) {
        asfExtContentDes.extContentDess = (T_ASF_EXTCONTENTDES_DES **)malloc(sizeof(T_ASF_EXTCONTENTDES_DES *) * asfExtContentDes.contentDesCount);
        if (!asfExtContentDes.extContentDess) {
            printf("malloc content descriptors error!\n");

            return;
        }
    }

    memset(asfExtContentDes.extContentDess, 0x0, sizeof(T_ASF_EXTCONTENTDES_DES *) * asfExtContentDes.contentDesCount);

    desData = data;

    for (i=0; i<asfExtContentDes.contentDesCount; i++) {
        asfExtContentDes.extContentDess[i] = (T_ASF_EXTCONTENTDES_DES *)malloc(sizeof(T_ASF_EXTCONTENTDES_DES));
        if (!asfExtContentDes.extContentDess[i]) {
            printf("malloc descriptors error!\n");

            return;
        }

        memset(asfExtContentDes.extContentDess[i], 0x0, sizeof(T_ASF_EXTCONTENTDES_DES));

        asfExtContentDes.extContentDess[i]->desNameLen = asf_rl16(desData);

        desData += 2;

        /**
         * 1. 这边的unicode已经 * 2!!!
         * 2. 57 00 4d 00 46 00 53 00 44 00 4b 00 56 00 65 00 72 00 73 00 69 00 6f 00 6e
         * 3. Descriptors Name Length: 28
         *    Descriptors Name: WMFSDKVersion(14个Unicode, 因此asfExtContentDes.extContentDess[i]->desNameLen/2)
         */
        asf_getstrl16(desData, asfExtContentDes.extContentDess[i]->desNameLen/2, asfExtContentDes.extContentDess[i]->desNameUTF8);

        desData += asfExtContentDes.extContentDess[i]->desNameLen;

        // type 
        asfExtContentDes.extContentDess[i]->desValueDataType = asf_rl16(desData);
        
        desData += 2;

        asfExtContentDes.extContentDess[i]->desValueLen = asf_rl16(desData);
        
        desData += 2;

        switch (asfExtContentDes.extContentDess[i]->desValueDataType) {
            case 0x0:
                asf_getstrl16(desData, asfExtContentDes.extContentDess[i]->desValueLen, asfExtContentDes.extContentDess[i]->desValues.bValue);

                break;

            case 0x1:
                memcpy(asfExtContentDes.extContentDess[i]->desValues.bValue, desData, asfExtContentDes.extContentDess[i]->desValueLen);

                break;

            case 0x2:
            case 0x3:
                asfExtContentDes.extContentDess[i]->desValues.dwValue = asf_rl32(desData);

                break;

            case 0x4:
                asfExtContentDes.extContentDess[i]->desValues.qwValue = asf_rl64(desData);

                break;

            case 0x5:
                asfExtContentDes.extContentDess[i]->desValues.wValue = asf_rl16(desData);

                break;

            default:
                printf("Unknow des value data type.!\n");

                break;
        }
        
        // 这边的unicode已经 * 2!!!
        //if (asfExtContentDes.extContentDess[i]->desValueDataType == 0x0)
            //desData += asfExtContentDes.extContentDess[i]->desValueLen * 2;
        //else
            desData += asfExtContentDes.extContentDess[i]->desValueLen;
    }

#ifdef PRINTF_DEBUG
    printfNSpace(4);
    printf("+Extended Content Description Object\n");

    printfNSpace(8);
    printf("Object ID: ");
    asf_PrintGUID(&asfExtContentDes.baseObjHeader.object_id, 0);

    printfNSpace(8);
    printf("Object size: %lld\n", asfExtContentDes.baseObjHeader.object_size);

    printfNSpace(8);
    printf("Content Descriptors Count: %d\n", asfExtContentDes.contentDesCount);

#ifdef PRINTF_DEBUG_DETAIL
    for (i=0; i<asfExtContentDes.contentDesCount; i++) {
        printfNSpace(12);
        printf("Descriptors Name Length: %d\n", asfExtContentDes.extContentDess[i]->desNameLen);

        printfNSpace(12);
        printf("Descriptors Name: %s\n", asfExtContentDes.extContentDess[i]->desNameUTF8);

        printfNSpace(12);
        printf("Descriptors Value Data Type: %d\n", asfExtContentDes.extContentDess[i]->desValueDataType);

        printfNSpace(12);
        printf("Descriptors Value Length: %d\n", asfExtContentDes.extContentDess[i]->desNameLen);

        switch (asfExtContentDes.extContentDess[i]->desValueDataType) {
            case 0x0:
            case 0x1:
                printfNSpace(12);
                printf("Descriptor Value: %s\n", asfExtContentDes.extContentDess[i]->desValues.bValue);

                break;

            case 0x2:
            case 0x3:
                printfNSpace(12);
                printf("Descriptor Value: %d\n", asfExtContentDes.extContentDess[i]->desValues.dwValue);

                break;

            case 0x4:
                printfNSpace(12);
                printf("Descriptor Value: %lld\n", asfExtContentDes.extContentDess[i]->desValues.qwValue);

                break;

            case 0x5:
                printfNSpace(12);
                printf("Descriptor Value: %d\n", asfExtContentDes.extContentDess[i]->desValues.wValue);

                break;

            default:
                break;
        }
            
            if (i != (asfExtContentDes.contentDesCount-1))
                printf("\n");
    }
#else
    for (i=0; i<asfExtContentDes.contentDesCount; i++) {
        printfNSpace(12);
        printf("%s: ", asfExtContentDes.extContentDess[i]->desNameUTF8);

        switch (asfExtContentDes.extContentDess[i]->desValueDataType) {
            case 0x0:
            case 0x1:
                printf("%s\n", asfExtContentDes.extContentDess[i]->desValues.bValue);

                break;

            case 0x2:
                if (asfExtContentDes.extContentDess[i]->desValues.dwValue == 0)
                    printf("%s\n", "false");
                else
                    printf("%s\n", "true");

                break;

            case 0x3:
                printf("%d\n", asfExtContentDes.extContentDess[i]->desValues.dwValue);

                break;

            case 0x4:
                printf("%lld\n", asfExtContentDes.extContentDess[i]->desValues.qwValue);

                break;

            case 0x5:
                printf("%d\n", asfExtContentDes.extContentDess[i]->desValues.wValue);

                break;

            default:
                break;
        }
    }
#endif
#endif
}

static void asf_Header_DealStreamBitrateProperties(T_ASF_BASE_OBJECT *baseObject) {
    WORD i =0;

    BYTE *recordData = NULL;

    BYTE *data = baseObject->object_playload;

    T_ASF_HEADER_STEAM_BITRATE_PROPERTIES asfStreamBitratePro = {0};

    // copy header first
    asfStreamBitratePro.baseObjHeader = baseObject->baseObjHeader;

    asfStreamBitratePro.bitrateRecordsCount = asf_rl16(data);

    data += 2;

    if (asfStreamBitratePro.bitrateRecordsCount != 0) {
        asfStreamBitratePro.bitrateRecords = (T_ASF_HEADER_STEAM_BITRATE_RECORD **)malloc(sizeof(T_ASF_HEADER_STEAM_BITRATE_RECORD *) * asfStreamBitratePro.bitrateRecordsCount);
        if (!asfStreamBitratePro.bitrateRecords) {
            printf("malloc bitrate Records error!\n");

            return;
        }
    }

    memset(asfStreamBitratePro.bitrateRecords, 0x0, sizeof(T_ASF_HEADER_STEAM_BITRATE_RECORD *) * asfStreamBitratePro.bitrateRecordsCount);

    recordData = data;

    for (i=0; i<asfStreamBitratePro.bitrateRecordsCount; i++) {
        asfStreamBitratePro.bitrateRecords[i] = (T_ASF_HEADER_STEAM_BITRATE_RECORD *)malloc(sizeof(T_ASF_HEADER_STEAM_BITRATE_RECORD));
        if (!asfStreamBitratePro.bitrateRecords[i]) {
            printf("malloc descriptors error!\n");

            return;
        }

        memset(asfStreamBitratePro.bitrateRecords[i], 0x0, sizeof(T_ASF_HEADER_STEAM_BITRATE_RECORD));

        asfStreamBitratePro.bitrateRecords[i]->flags = asf_rl16(recordData);
        asfStreamBitratePro.bitrateRecords[i]->streamNumber = asfStreamBitratePro.bitrateRecords[i]->flags & 0x7f;

        recordData += 2;
        
        asfStreamBitratePro.bitrateRecords[i]->avgBitrate = asf_rl32(recordData);

        recordData += 4;
    }

#ifdef PRINTF_DEBUG
    printfNSpace(4);
    printf("+Stream Bitrate Properties Object\n");

    printfNSpace(8);
    printf("Object ID: ");
    asf_PrintGUID(&asfStreamBitratePro.baseObjHeader.object_id, 0);

    printfNSpace(8);
    printf("Object size: %lld\n", asfStreamBitratePro.baseObjHeader.object_size);

    printfNSpace(8);
    printf("Stream Count: %d\n", asfStreamBitratePro.bitrateRecordsCount);

    for (i=0; i<asfStreamBitratePro.bitrateRecordsCount; i++) {
        printfNSpace(8);
        printf("Stream Number %d - Bitrate: %d\n", asfStreamBitratePro.bitrateRecords[i]->streamNumber, 
            asfStreamBitratePro.bitrateRecords[i]->avgBitrate);
    }
#endif
}

static void asf_DealData(T_ASF_BASE_OBJECT *baseObject) {
    int objinfoIndex = -1;

    DWORD i = 0;
    DWORD j = 0;
    
    DWORD usedBytes = 0;

    DWORD allErrorCorrectionLen = 0;
    DWORD allPayloadParsingLen = 0;
    DWORD allPayloadDataHeaderLen = 0;
    DWORD allInfoLen = 0;
    
    DWORD tmpMediaObjNum = 0;
    DWORD tmpOffsetMediaObjOrPresentTime = 0;
    DWORD tmpRepDataLen = 0;

    DWORD showPacketCount = 0;
    
    //BYTE beparse = 0;
    //DWORD allpayloadlen = 0;

    BYTE tmpStreamNum = 0;
    BYTE tmpStreamNum7Bits = 0;
    BYTE tmpKeyFrame1Bit = 0;

    BYTE errorCorrectionPresent = 0;
    
    BYTE *packetData = NULL;

    BYTE *data = baseObject->object_playload;

    BYTE strTimeSentTime[13] = {0};
    BYTE strTimeDuration[13] = {0};
    BYTE strTimePresentationTime[13] = {0};

    T_ASF_DATA asfData = {0};

    T_ASF_DATA_PACKET_MULTIPLE_ONEPLAYLOAD *oneplayload = NULL;
    T_ASF_DATA_PACKET_MULTIPLE_ONECOMPRESSED_PLAYLOAD *compressedplayload = NULL;
    T_ASF_DATA_PACKET_PLAYLOAD_OBJINFO *objinfo = NULL;

    // copy header first
    asfData.baseObjHeader = baseObject->baseObjHeader;

    memcpy(asfData.fileID, data, MAX_GUID_LEN);

    data += MAX_GUID_LEN;

    asfData.totalDataPackets = asf_rl64(data);

    data += 8;

    asfData.reserved = asf_rl16(data);

    data += 2;

    if (asfData.totalDataPackets != 0) {
        asfData.packets = (T_ASF_DATA_PACKET **)malloc(sizeof(T_ASF_DATA_PACKET *) * asfData.totalDataPackets);
        if (!asfData.packets) {
            printf("malloc packets error!\n");

            return;
        }
    }

    memset(asfData.packets, 0x0, sizeof(T_ASF_DATA_PACKET *) * asfData.totalDataPackets);

    packetData = data;    

    for (i=0; i<asfData.totalDataPackets; i++) {
        allErrorCorrectionLen = 0;
        allPayloadParsingLen = 0;
        allPayloadDataHeaderLen = 0;

        asfData.packets[i] = (T_ASF_DATA_PACKET *)malloc(sizeof(T_ASF_DATA_PACKET));
        if (!asfData.packets[i]) {
            printf("malloc packet error!\n");

            return;
        }

        // must memset, othrewise data in T_ASF_DATA_PACKET maybe error
        memset(asfData.packets[i], 0x0, sizeof(T_ASF_DATA_PACKET));

        errorCorrectionPresent = packetData[0] >> 7 & 0x1;

        // parse Error Correction Flags
        if (1 == errorCorrectionPresent) {
            asfData.packets[i]->errCorrectionData.flags = packetData[0];

            asfData.packets[i]->errCorrectionData.errCorrDataLen = packetData[0] & 0xf;
            asfData.packets[i]->errCorrectionData.opeDataPresent = packetData[0] >> 4 & 0x1;
            asfData.packets[i]->errCorrectionData.lenType = packetData[0] >> 5 & 0x3;
            asfData.packets[i]->errCorrectionData.errCorrPresent = packetData[0] >> 7 & 0x1;

            //printf("errorCorrectionPresent, p: %d, type: %d, len: %d\n", i, asfData.packets[i]->errCorrectionData.lenType, asfData.packets[i]->errCorrectionData.errCorrDataLen);
            
            packetData += 1;
            allErrorCorrectionLen += 1;

            // Error Correction Data
            packetData += asfData.packets[i]->errCorrectionData.errCorrDataLen;
            allErrorCorrectionLen += asfData.packets[i]->errCorrectionData.errCorrDataLen;
        } 
        
        // Payload parsing information
        asfData.packets[i]->palyloadParsingInfo.lenTypeFlags = packetData[0];

        asfData.packets[i]->palyloadParsingInfo.mulPlayloadsPresent = packetData[0] & 0x1;
        asfData.packets[i]->palyloadParsingInfo.sequenceType = packetData[0] >> 1 & 0x3;
        asfData.packets[i]->palyloadParsingInfo.paddingLenType = packetData[0] >> 3 & 0x3;
        asfData.packets[i]->palyloadParsingInfo.packetLenType = packetData[0] >> 5 & 0x3;
        asfData.packets[i]->palyloadParsingInfo.errCorrectionPresent = packetData[0] >> 7 & 0x1;

        packetData += 1;
        allPayloadParsingLen += 1;

        asfData.packets[i]->palyloadParsingInfo.propertyFlags = packetData[0];
        
        asfData.packets[i]->palyloadParsingInfo.replicatedDataLenType = packetData[0] & 0x3;
        asfData.packets[i]->palyloadParsingInfo.offsetIntoObjLenType = packetData[0] >> 2 & 0x3;
        asfData.packets[i]->palyloadParsingInfo.meidiaObjNumLenType = packetData[0] >> 4 & 0x3;
        asfData.packets[i]->palyloadParsingInfo.streamNumLenType = packetData[0] >> 6 & 0x3;

        packetData += 1;
        allPayloadParsingLen += 1;

        /************************************************************************************************************
        -------------------------------------------------------------------------------------------------------------
        **        Sequence Type/Padding Length Type/Packet Length Type/Replicated Data Length Type
        **        Offset Into Media Object Length Type/Media Object Number Length Type 
        **
        -------------------------------------------------------------------------------------------------------------
        **        Value                     |    Descriptor value length
        -------------------------------------------------------------------------------------------------------------
        **        00                     |    The Sequence/Padding Length... field does not exist.
        **        01                     |    The Sequence/Padding Length... field is coded using a BYTE.
        **        10                     |    The Sequence/Padding Length... field is coded using a WORD.
        **        11                     |    The Sequence/Padding Length... field is coded using a DWORD.
        ************************************************************************************************************/
        switch (asfData.packets[i]->palyloadParsingInfo.packetLenType) {
            case 0:
                asfData.packets[i]->palyloadParsingInfo.packetLen = 0;

                break;

            case 1:
                asfData.packets[i]->palyloadParsingInfo.packetLen = packetData[0];
                packetData += 1;
                allPayloadParsingLen += 1;

                break;

            case 2:
                asfData.packets[i]->palyloadParsingInfo.packetLen = asf_rl16(packetData);
                packetData += 2;
                allPayloadParsingLen += 2;

                break;

            case 3:
                asfData.packets[i]->palyloadParsingInfo.packetLen = asf_rl32(packetData);
                packetData += 4;
                allPayloadParsingLen += 4;

                break;
            
            default:
                asfData.packets[i]->palyloadParsingInfo.packetLen = 0;

                break;
        }

        switch (asfData.packets[i]->palyloadParsingInfo.sequenceType) {
            case 0:
                asfData.packets[i]->palyloadParsingInfo.sequence = 0;
                
                break;

            case 1:
                asfData.packets[i]->palyloadParsingInfo.sequence = packetData[0];
                packetData += 1;
                allPayloadParsingLen += 1;

                break;

            case 2:
                asfData.packets[i]->palyloadParsingInfo.sequence = asf_rl16(packetData);
                packetData += 2;
                allPayloadParsingLen += 2;

                break;

            case 3:
                asfData.packets[i]->palyloadParsingInfo.sequence = asf_rl32(packetData);
                packetData += 4;
                allPayloadParsingLen += 4;

                break;
            
            default:
                asfData.packets[i]->palyloadParsingInfo.sequence = 0;

                break;
        }

        switch (asfData.packets[i]->palyloadParsingInfo.paddingLenType) {
            case 0:
                asfData.packets[i]->palyloadParsingInfo.paddingLen = 0;
                
                break;

            case 1:
                asfData.packets[i]->palyloadParsingInfo.paddingLen = packetData[0];
                packetData += 1;
                allPayloadParsingLen += 1;

                break;

            case 2:
                asfData.packets[i]->palyloadParsingInfo.paddingLen = asf_rl16(packetData);
                packetData += 2;
                allPayloadParsingLen += 2;

                break;

            case 3:
                asfData.packets[i]->palyloadParsingInfo.paddingLen = asf_rl32(packetData);
                packetData += 4;
                allPayloadParsingLen += 4;

                break;
            
            default:
                asfData.packets[i]->palyloadParsingInfo.paddingLen = 0;

                break;
        }

        asfData.packets[i]->palyloadParsingInfo.sendTime = asf_rl32(packetData);
        packetData += 4;
        allPayloadParsingLen += 4;

        asfData.packets[i]->palyloadParsingInfo.duration = asf_rl16(packetData);
        packetData += 2;
        allPayloadParsingLen += 2;

        // printf("palyloadParsingInfo, p: %d, packetLenType:%d, sequenceType: %d, packetLen: %d, paddingLen: %d, sendTime: %d, duration: %d\n", i, 
        //     asfData.packets[i]->palyloadParsingInfo.packetLenType, 
        //     asfData.packets[i]->palyloadParsingInfo.sequenceType,
        //     asfData.packets[i]->palyloadParsingInfo.packetLen,
        //     asfData.packets[i]->palyloadParsingInfo.paddingLen,
        //     asfData.packets[i]->palyloadParsingInfo.sendTime,
        //     asfData.packets[i]->palyloadParsingInfo.duration);

        // if (asfData.packets[i]->palyloadParsingInfo.packetLen == 0)
        //     continue;

        //usedBytes = 0;

        // single playload
        if (asfData.packets[i]->palyloadParsingInfo.mulPlayloadsPresent == 0) {
            tmpStreamNum = packetData[0];

            tmpStreamNum7Bits = packetData[0] & 0x7f;
            tmpKeyFrame1Bit = packetData[0] >> 7 & 0x1;

            packetData += 1;
            //usedBytes += 1;
            allPayloadDataHeaderLen += 1;

            switch (asfData.packets[i]->palyloadParsingInfo.meidiaObjNumLenType) {
                case 0:
                    tmpMediaObjNum = 0;
                    
                    break;

                case 1:
                    tmpMediaObjNum = packetData[0];
                    packetData += 1;
                    //usedBytes += 1;
                    allPayloadDataHeaderLen += 1;

                    break;

                case 2:
                    tmpMediaObjNum = asf_rl16(packetData);
                    packetData += 2;
                    //usedBytes += 2;
                    allPayloadDataHeaderLen += 2;

                    break;

                case 3:
                    tmpMediaObjNum = asf_rl32(packetData);
                    packetData += 4;
                    //usedBytes += 4;
                    allPayloadDataHeaderLen += 4;

                    break;
                
                default:
                    tmpMediaObjNum = 0;

                    break;
            }

            /**
             * 1. in single, means 'Offset Into Media Object';
             * 2. in Single payload, compressed payload data, means 'Presentation Time'.
             */
            switch (asfData.packets[i]->palyloadParsingInfo.offsetIntoObjLenType) {
                case 0:
                    tmpOffsetMediaObjOrPresentTime = 0;
                    
                    break;

                case 1:
                    tmpOffsetMediaObjOrPresentTime = packetData[0];
                    packetData += 1;
                    //usedBytes += 1;
                    allPayloadDataHeaderLen += 1;

                    break;

                case 2:
                    tmpOffsetMediaObjOrPresentTime = asf_rl16(packetData);
                    packetData += 2;
                    //usedBytes += 2;
                    allPayloadDataHeaderLen += 2;

                    break;

                case 3:
                    tmpOffsetMediaObjOrPresentTime = asf_rl32(packetData);
                    packetData += 4;
                    //usedBytes += 4;
                    allPayloadDataHeaderLen += 4;

                    break;
                
                default:
                    tmpOffsetMediaObjOrPresentTime = 0;

                    break;
            }

            switch (asfData.packets[i]->palyloadParsingInfo.replicatedDataLenType) {
                case 0:
                    tmpRepDataLen = 0;
                    
                    break;

                case 1:
                    tmpRepDataLen = packetData[0];
                    packetData += 1;
                    //usedBytes += 1;
                    allPayloadDataHeaderLen += 1;

                    break;

                case 2:
                    tmpRepDataLen = asf_rl16(packetData);
                    packetData += 2;
                    //usedBytes += 2;
                    allPayloadDataHeaderLen += 1;

                    break;

                case 3:
                    tmpRepDataLen = asf_rl32(packetData);
                    packetData += 4;
                    //usedBytes += 4;
                    allPayloadDataHeaderLen += 1;

                    break;
                
                default:
                    tmpRepDataLen = 0;

                    break;
            }

            // Single payload, compressed payload data
            if (1 == tmpRepDataLen) {
                // used for print
                asfData.packets[i]->isSingleCompressedPlayload = 1;

                asfData.packets[i]->playload.singleCompressedPlayload.streamNum = tmpStreamNum;
                asfData.packets[i]->playload.singleCompressedPlayload.streamNum7Bits = tmpStreamNum7Bits;
                asfData.packets[i]->playload.singleCompressedPlayload.keyFrame1Bit = tmpKeyFrame1Bit;

                asfData.packets[i]->playload.singleCompressedPlayload.mediaObjNum = tmpMediaObjNum;
                asfData.packets[i]->playload.singleCompressedPlayload.presentationTime = tmpOffsetMediaObjOrPresentTime;
                asfData.packets[i]->playload.singleCompressedPlayload.repDataLen = tmpRepDataLen;

                asfData.packets[i]->playload.singleCompressedPlayload.presentationTimeDelta = packetData[0];
                
                packetData += 1;
                //usedBytes += 1;
                allPayloadDataHeaderLen += 1;

                // TODO, Sub-Payload Data
                packetData += (asfData.packets[i]->palyloadParsingInfo.packetLen - allPayloadDataHeaderLen);

                // TODO, padding data
                //packetData += asfData.packets[i]->palyloadParsingInfo.paddingLen;

                // printf("Single payload compressed, packet: %d, sid: %d, relen: %d, playloadlen: %d\n", i, 
                //     asfData.packets[i]->playload.singleCompressedPlayload.streamNum7Bits, 
                //     asfData.packets[i]->playload.singleCompressedPlayload.repDataLen,
                //     asfData.packets[i]->palyloadParsingInfo.packetLen);
            } else { // Single payload
                // used for print
                asfData.packets[i]->isSingleCompressedPlayload = 0;

                asfData.packets[i]->playload.singlePlayload.streamNum = tmpStreamNum;
                asfData.packets[i]->playload.singlePlayload.streamNum7Bits = tmpStreamNum7Bits;
                asfData.packets[i]->playload.singlePlayload.keyFrame1Bit = tmpKeyFrame1Bit;

                asfData.packets[i]->playload.singlePlayload.mediaObjNum = tmpMediaObjNum;
                asfData.packets[i]->playload.singlePlayload.offIntoMediaObj = tmpOffsetMediaObjOrPresentTime;
                asfData.packets[i]->playload.singlePlayload.repDataLen = tmpRepDataLen;

                // Replicated Data is DWORD(playloadlen)-DOWRD(pts)-more data
                asfData.packets[i]->playload.singlePlayload.detailRepdata.allplayloadlen = asf_rl32(packetData);
                asfData.packets[i]->playload.singlePlayload.detailRepdata.pts = asf_rl32(packetData+4);

                if (getObjinfoByObjnum(tmpStreamNum7Bits, tmpMediaObjNum) == NULL) {
                    objinfoIndex = getUnusedObjinfoIndex(tmpStreamNum7Bits);

                    g_playladobjinfo[tmpStreamNum7Bits][objinfoIndex].isParing = 1;
                    g_playladobjinfo[tmpStreamNum7Bits][objinfoIndex].mediaObjNum = tmpMediaObjNum;
                    g_playladobjinfo[tmpStreamNum7Bits][objinfoIndex].allobjlen = asfData.packets[i]->playload.singlePlayload.detailRepdata.allplayloadlen;

                    //printf("singal, p: %d, objindx: %d, obj: %d, len: %d\n",
                        //i, objinfoIndex, g_playladobjinfo[tmpStreamNum7Bits][objinfoIndex].mediaObjNum, g_playladobjinfo[tmpStreamNum7Bits][objinfoIndex].allobjlen);
                }

                // if (beparse == 0) {
                //     allpayloadlen = asfData.packets[i]->playload.singlePlayload.detailRepdata.allplayloadlen;

                //     beparse = 1;
                // }

                // TODO, more Replicated Data
                packetData += tmpRepDataLen;
                //usedBytes += tmpRepDataLen;
                allPayloadDataHeaderLen += tmpRepDataLen;

                //printfdata(packetData, asfData.packets[i]->playload.singlePlayload.detailRepdata.allplayloadlen);
                // TODO, playload data, real playloadlen is from Replicated Data
                //packetData += (asfData.packets[i]->palyloadParsingInfo.packetLen - usedBytes);

                allInfoLen = allErrorCorrectionLen + allPayloadParsingLen + allPayloadDataHeaderLen + asfData.packets[i]->palyloadParsingInfo.paddingLen;

                // if (allpayloadlen > (g_asfGlobalInfo.maxDataPacketSize - allInfoLen)) {

                //     asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen = g_asfGlobalInfo.maxDataPacketSize - allInfoLen;
                    
                //     printf("000, p: %d, max: %d, allinfo: %d, allpayloadlen: %d, afterlen: %d\n",
                //         i, g_asfGlobalInfo.maxDataPacketSize, allInfoLen, allpayloadlen,
                //         allpayloadlen - asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen);
                //     allpayloadlen -= asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen;
                // } else {
 
                //     asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen = allpayloadlen;
                //    printf("111, p: %d, max: %d, allinfo: %d, allpayloadlen: %d\n",
                //         i, g_asfGlobalInfo.maxDataPacketSize, allInfoLen, allpayloadlen);
                    
                //     allpayloadlen = 0;
                //     beparse = 0;
                // }

                objinfo = getObjinfoByObjnum(tmpStreamNum7Bits, tmpMediaObjNum);
                if (objinfo) {
                    if (objinfo->allobjlen > (g_asfGlobalInfo.maxDataPacketSize - allInfoLen)) {
                        asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen = g_asfGlobalInfo.maxDataPacketSize - allInfoLen;
                    
                        //                 printf("000, p: %d, max: %d, allinfo: %d, allpayloadlen: %d, afterlen: %d, obj: %d\n",
                        // i, g_asfGlobalInfo.maxDataPacketSize, allInfoLen, objinfo->allobjlen ,
                        // objinfo->allobjlen  - asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen,
                        // objinfo->mediaObjNum);

                        objinfo->allobjlen -= asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen;
                    } else {
                        asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen = objinfo->allobjlen;

                        //    printf("111, p: %d, max: %d, allinfo: %d, allpayloadlen: %d, obj: %d\n",
                        //         i, g_asfGlobalInfo.maxDataPacketSize, allInfoLen, objinfo->allobjlen,
                        //         objinfo->mediaObjNum);

                        //memset(objinfo, 0x0, sizeof(T_ASF_DATA_PACKET_PLAYLOAD_OBJINFO));

                        resetObjinfo(objinfo);
                    }
                }

                packetData += asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen;

                // TODO, padding data
                //packetData += asfData.packets[i]->palyloadParsingInfo.paddingLen;

                // printf("Single payload, packet: %d, sid: %d, oid: %d, offset: %d, relen: %d, allplayloadlen: %d, realplayloadlen: %d, allinfolen: %d\n", i, 
                //     asfData.packets[i]->playload.singlePlayload.streamNum7Bits,
                //     asfData.packets[i]->playload.singlePlayload.mediaObjNum,
                //     asfData.packets[i]->playload.singlePlayload.offIntoMediaObj,
                //     asfData.packets[i]->playload.singlePlayload.repDataLen,
                //     asfData.packets[i]->playload.singlePlayload.detailRepdata.allplayloadlen,
                //     asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen,
                //     allInfoLen);
            }
        } else { // Multiple payloads
            //printfdata(packetData, 100);
            asfData.packets[i]->playload.multipePlayloads.playloadFlags = packetData[0];

            asfData.packets[i]->playload.multipePlayloads.numOfPlayloads = packetData[0] & 0x3f;
            asfData.packets[i]->playload.multipePlayloads.payloadLenType = packetData[0] >> 6 & 0x3;

            packetData += 1;

            // is here ok?
            if (asfData.packets[i]->playload.multipePlayloads.numOfPlayloads != 0) {
                asfData.packets[i]->playload.multipePlayloads.playloads = (T_ASF_DATA_PACKET_MULTIPLE_ONEPLAYLOAD **)malloc(sizeof(T_ASF_DATA_PACKET_MULTIPLE_ONEPLAYLOAD *) * asfData.packets[i]->playload.multipePlayloads.numOfPlayloads);
                if (!asfData.packets[i]->playload.multipePlayloads.playloads) {
                    printf("malloc playloads for multipePlayloads error!\n");

                    return;
                }
            }

            if (asfData.packets[i]->playload.multipePlayloads.numOfPlayloads != 0) {
                asfData.packets[i]->playload.multipePlayloads.compressedPlayloads = (T_ASF_DATA_PACKET_MULTIPLE_ONECOMPRESSED_PLAYLOAD **)malloc(sizeof(T_ASF_DATA_PACKET_MULTIPLE_ONECOMPRESSED_PLAYLOAD *) * asfData.packets[i]->playload.multipePlayloads.numOfPlayloads);
                if (!asfData.packets[i]->playload.multipePlayloads.compressedPlayloads) {
                    printf("malloc compressedplayloads for multipePlayloads error!\n");

                    return;
                }
            }

            for (j=0; j<asfData.packets[i]->playload.multipePlayloads.numOfPlayloads; j++) {
                //printf("multipePlayloads, j: %d\n", j);
                //printfdata(packetData, 100);
                tmpStreamNum = packetData[0];

                tmpStreamNum7Bits = packetData[0] & 0x7f;
                tmpKeyFrame1Bit = packetData[0] >> 7 & 0x1;

                packetData += 1;
                //usedBytes += 1;

                switch (asfData.packets[i]->palyloadParsingInfo.meidiaObjNumLenType) {
                    case 0:
                        tmpMediaObjNum = 0;
                        
                        break;

                    case 1:
                        tmpMediaObjNum = packetData[0];
                        packetData += 1;
                        //usedBytes += 1;

                        break;

                    case 2:
                        tmpMediaObjNum = asf_rl16(packetData);
                        packetData += 2;
                        //usedBytes += 2;

                        break;

                    case 3:
                        tmpMediaObjNum = asf_rl32(packetData);
                        packetData += 4;
                        //usedBytes += 4;

                        break;
                    
                    default:
                        tmpMediaObjNum = 0;

                        break;
                }

                /**
                 * 1. in single, means 'Offset Into Media Object';
                 * 2. in Single payload, compressed payload data, means 'Presentation Time'.
                 */
                switch (asfData.packets[i]->palyloadParsingInfo.offsetIntoObjLenType) {
                    case 0:
                        tmpOffsetMediaObjOrPresentTime = 0;
                        
                        break;

                    case 1:
                        tmpOffsetMediaObjOrPresentTime = packetData[0];
                        packetData += 1;
                        //usedBytes += 1;

                        break;

                    case 2:
                        tmpOffsetMediaObjOrPresentTime = asf_rl16(packetData);
                        packetData += 2;
                        //usedBytes += 2;

                        break;

                    case 3:
                        tmpOffsetMediaObjOrPresentTime = asf_rl32(packetData);
                        packetData += 4;
                        //usedBytes += 4;

                        break;
                    
                    default:
                        tmpOffsetMediaObjOrPresentTime = 0;

                        break;
                }

                switch (asfData.packets[i]->palyloadParsingInfo.replicatedDataLenType) {
                    case 0:
                        tmpRepDataLen = 0;
                        
                        break;

                    case 1:
                        tmpRepDataLen = packetData[0];
                        packetData += 1;
                        //usedBytes += 1;

                        break;

                    case 2:
                        tmpRepDataLen = asf_rl16(packetData);
                        packetData += 2;
                        //usedBytes += 2;

                        break;

                    case 3:
                        tmpRepDataLen = asf_rl32(packetData);
                        packetData += 4;
                        //usedBytes += 4;

                        break;
                    
                    default:
                        tmpRepDataLen = 0;

                        break;
                }

                // Multiple payloads, compressed payload data
                if (1 == tmpRepDataLen) {
                    compressedplayload = (T_ASF_DATA_PACKET_MULTIPLE_ONECOMPRESSED_PLAYLOAD *)malloc(sizeof(T_ASF_DATA_PACKET_MULTIPLE_ONECOMPRESSED_PLAYLOAD));
                    if (!compressedplayload) {
                        printf("malloc compressedplayload error!\n");

                        return;
                    }

                    compressedplayload->streamNum = tmpStreamNum;
                    compressedplayload->streamNum7Bits = tmpStreamNum7Bits;
                    compressedplayload->keyFrame1Bit = tmpKeyFrame1Bit;

                    compressedplayload->mediaObjNum = tmpMediaObjNum;
                    compressedplayload->presentationTime = tmpOffsetMediaObjOrPresentTime;
                    compressedplayload->repDataLen = tmpRepDataLen;

                    compressedplayload->presentationTimeDelta = packetData[0];

                    packetData += 1;

                    switch (asfData.packets[i]->playload.multipePlayloads.payloadLenType) {
                        case 1:
                            compressedplayload->payloadLen = packetData[0];
                            packetData += 1;
                            //usedBytes += 1;

                            break;

                        case 2:
                            compressedplayload->payloadLen = asf_rl16(packetData);
                            packetData += 2;
                            //usedBytes += 2;

                            break;

                        case 3:
                            compressedplayload->payloadLen = asf_rl32(packetData);
                            packetData += 4;
                            //usedBytes += 4;

                            break;
                        
                        default:
                            compressedplayload->payloadLen = 0;

                            break;
                    }

                    // TODO, playload data
                    packetData += compressedplayload->payloadLen;

                    // TODO, Sub-Payload Data

                    // next playload
                    asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[asfData.packets[i]->playload.multipePlayloads.compressedplayloadNums] = compressedplayload;
                    
                    // printf("Multipe payload compressed, packet: %d(%d-%d), sid: %d, relen: %d, playloadlen: %d\n", i, j,
                    //     asfData.packets[i]->playload.multipePlayloads.compressedplayloadNums,
                    //     asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[asfData.packets[i]->playload.multipePlayloads.compressedplayloadNums]->streamNum7Bits,
                    //     asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[asfData.packets[i]->playload.multipePlayloads.compressedplayloadNums]->repDataLen,
                    //     asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[asfData.packets[i]->playload.multipePlayloads.compressedplayloadNums]->payloadLen);
                    
                    asfData.packets[i]->playload.multipePlayloads.compressedplayloadNums++;

                    // printf("Multipe payload compressed, packet: %d, sid: %d, relen: %d, playloadlen: %d\n", i, 
                    //     compressedplayload->streamNum7Bits,
                    //     compressedplayload->repDataLen,
                    //     compressedplayload->payloadLen);
                } else { // Multiple payloads
                    oneplayload = (T_ASF_DATA_PACKET_MULTIPLE_ONEPLAYLOAD *)malloc(sizeof(T_ASF_DATA_PACKET_MULTIPLE_ONEPLAYLOAD));
                    if (!oneplayload) {
                        printf("malloc oneplayload error!\n");

                        return;
                    }

                    oneplayload->streamNum = tmpStreamNum;
                    oneplayload->streamNum7Bits = tmpStreamNum7Bits;
                    oneplayload->keyFrame1Bit = tmpKeyFrame1Bit;

                    oneplayload->mediaObjNum = tmpMediaObjNum;
                    oneplayload->offIntoMediaObj = tmpOffsetMediaObjOrPresentTime;
                    oneplayload->repDataLen = tmpRepDataLen;
                    
                    // Replicated Data is DWORD(playloadlen)-DOWRD(pts)-more data
                    oneplayload->detailRepdata.allplayloadlen = asf_rl32(packetData);
                    oneplayload->detailRepdata.pts = asf_rl32(packetData+4);

                    // TODO, Replicated Data
                    packetData += tmpRepDataLen;
                    //usedBytes += tmpRepDataLen;

                    // if (beparse == 0) {
                    //     allpayloadlen = oneplayload->detailRepdata.allplayloadlen;

                    //     beparse = 1;
                    // }


                    if (getObjinfoByObjnum(tmpStreamNum7Bits, tmpMediaObjNum) == NULL) {
                        objinfoIndex = getUnusedObjinfoIndex(tmpStreamNum7Bits);

                        g_playladobjinfo[tmpStreamNum7Bits][objinfoIndex].isParing = 1;
                        g_playladobjinfo[tmpStreamNum7Bits][objinfoIndex].mediaObjNum = tmpMediaObjNum;
                        g_playladobjinfo[tmpStreamNum7Bits][objinfoIndex].allobjlen = oneplayload->detailRepdata.allplayloadlen;

                        // printf("multile, p: %d, objindx: %d, obj: %d, len: %d\n",
                        // i, objinfoIndex, g_playladobjinfo[tmpStreamNum7Bits][objinfoIndex].mediaObjNum, g_playladobjinfo[tmpStreamNum7Bits][objinfoIndex].allobjlen);
                    }


                    switch (asfData.packets[i]->playload.multipePlayloads.payloadLenType) {
                        case 1:
                            oneplayload->playloadLen = packetData[0];
                            packetData += 1;
                            //usedBytes += 1;

                            break;

                        case 2:
                            oneplayload->playloadLen = asf_rl16(packetData);
                            packetData += 2;
                            //usedBytes += 2;

                            break;

                        case 3:
                            oneplayload->playloadLen = asf_rl32(packetData);
                            packetData += 4;
                            //usedBytes += 4;

                            break;
                        
                        default:
                            oneplayload->playloadLen = 0;

                            break;
                    }

                    // if (allpayloadlen != 0) {
                    //     printf("single is here, p: %d, allis: %d, oneis: %d(%d)\n", i, 
                    //     allpayloadlen, oneplayload->playloadLen, allpayloadlen - oneplayload->playloadLen);
                    //     if (allpayloadlen - oneplayload->playloadLen == 0) {
                    //         allpayloadlen = 0;
                    //         beparse = 0;
                    //     } else {
                    //         allpayloadlen -= oneplayload->playloadLen;
                    //     }
                    // }

                    objinfo = getObjinfoByObjnum(tmpStreamNum7Bits, tmpMediaObjNum);
                    if (objinfo) {
                        // printf("single is here, p: %d, allis: %d, oneis: %d(%d)\n", i, 
                        //     objinfo->allobjlen, oneplayload->playloadLen, objinfo->allobjlen  - oneplayload->playloadLen);
                        if ((objinfo->allobjlen - oneplayload->playloadLen) == 0 ) {
                            //memset(objinfo, 0, sizeof(T_ASF_DATA_PACKET_PLAYLOAD_OBJINFO));
                            resetObjinfo(objinfo);
                        } else {
                            objinfo->allobjlen -= oneplayload->playloadLen;
                        }
                    }

                    //printf("2222, p: %d, allpayloadlen: %d, afterlen: %d\n",
                        //i, oneplayload->detailRepdata.allplayloadlen, allpayloadlen);

                    // TODO, playload data
                    packetData += oneplayload->playloadLen;

                    // next playload
                    asfData.packets[i]->playload.multipePlayloads.playloads[asfData.packets[i]->playload.multipePlayloads.oneplayloadNums] = oneplayload;

                    // printf("Multipe payload, packet: %d(%d-%d), sid: %d, relen: %d, playloadlen: %d\n", i, j,
                    //     asfData.packets[i]->playload.multipePlayloads.oneplayloadNums,
                    //     asfData.packets[i]->playload.multipePlayloads.playloads[asfData.packets[i]->playload.multipePlayloads.oneplayloadNums]->streamNum7Bits,
                    //     asfData.packets[i]->playload.multipePlayloads.playloads[asfData.packets[i]->playload.multipePlayloads.oneplayloadNums]->repDataLen,
                    //     asfData.packets[i]->playload.multipePlayloads.playloads[asfData.packets[i]->playload.multipePlayloads.oneplayloadNums]->playloadLen);

                    asfData.packets[i]->playload.multipePlayloads.oneplayloadNums++;

                    // printf("Multipe payload, packet: %d, sid: %d, relen: %d, playloadlen: %d\n", i, 
                    //     oneplayload->streamNum7Bits,
                    //     oneplayload->repDataLen,
                    //     oneplayload->playloadLen);
                }
            }
        }

        // TODO, padding data
        packetData += asfData.packets[i]->palyloadParsingInfo.paddingLen;
    }

#ifdef PRINTF_DEBUG
    printf("+Data Object\n");
    
    printfNSpace(4);
    printf("Object ID: ");
    asf_PrintGUID(&asfData.baseObjHeader.object_id, 0);

    printfNSpace(4);
    printf("File ID: ");
    asf_PrintGUID(&asfData.fileID, 2);

    showPacketCount = asfData.totalDataPackets > SHOW_PACKET_COUNT ? SHOW_PACKET_COUNT : asfData.totalDataPackets;

    printfNSpace(4);
    printf("Interleaved packet count: %lld(only show %d now)\n", asfData.totalDataPackets, showPacketCount);
    
    //for (i=0; i<asfData.totalDataPackets; i++) {
    for (i=0; i<showPacketCount; i++) {
        printf("\n");
        
        printfNSpace(4);

        // printf("+Packet        SCR         Duration\n");

        // printfNSpace(4);
        // printf("%-14d %-11d %-16d\n", i, asfData.packets[i]->palyloadParsingInfo.sendTime, asfData.packets[i]->palyloadParsingInfo.duration);


        // printf("++Packet: %d, SCR: %, Duration: %d\n", i, asfData.packets[i]->palyloadParsingInfo.sendTime, asfData.packets[i]->palyloadParsingInfo.duration);
        memset(strTimeSentTime, 0x0, sizeof(strTimeSentTime));
        asf_changeMs2Str(asfData.packets[i]->palyloadParsingInfo.sendTime, strTimeSentTime);
        
        memset(strTimeDuration, 0x0, sizeof(strTimeDuration));
        asf_changeMs2Str(asfData.packets[i]->palyloadParsingInfo.duration, strTimeDuration);

        printf("++Packet: %d, SCR: %s, Duration: %s\n", i, strTimeSentTime, strTimeDuration);

        // printfNSpace(4);
        // printf("%-14d %-11d %-16d\n", i, asfData.packets[i]->palyloadParsingInfo.sendTime, asfData.packets[i]->palyloadParsingInfo.duration);

        if (asfData.packets[i]->palyloadParsingInfo.mulPlayloadsPresent == 1) {
            printfNSpace(8);
            printf("SID    OID     Offset     RepData    PayloadLen     ObjectSize     PresentationTime        Key\n");

            // printf("mul, one: %d\n", asfData.packets[i]->playload.multipePlayloads.oneplayloadNums);
            for (j=0; j<asfData.packets[i]->playload.multipePlayloads.oneplayloadNums; j++) {
                printfNSpace(8);

                if (asfData.packets[i]->playload.multipePlayloads.playloads[j]->keyFrame1Bit) {   
                    memset(strTimePresentationTime, 0x0, sizeof(strTimePresentationTime));
                    asf_changeMs2Str(asfData.packets[i]->playload.multipePlayloads.playloads[j]->detailRepdata.pts, strTimePresentationTime);

                    printf("%-6d %-7d %-10d %-10d %-14d %-14d %-23s %-7s\n",
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->streamNum7Bits,
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->mediaObjNum,
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->offIntoMediaObj,
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->repDataLen,
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->playloadLen,
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->detailRepdata.allplayloadlen,
                        // asfData.packets[i]->playload.multipePlayloads.playloads[j]->detailRepdata.pts,
                        strTimePresentationTime,
                        "yes");
                } else {
                    memset(strTimePresentationTime, 0x0, sizeof(strTimePresentationTime));
                    asf_changeMs2Str(asfData.packets[i]->playload.multipePlayloads.playloads[j]->detailRepdata.pts, strTimePresentationTime);

                    printf("%-6d %-7d %-10d %-10d %-14d %-14d %-23s %-7s\n",
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->streamNum7Bits,
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->mediaObjNum,
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->offIntoMediaObj,
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->repDataLen,
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->playloadLen,
                        asfData.packets[i]->playload.multipePlayloads.playloads[j]->detailRepdata.allplayloadlen,
                        strTimePresentationTime,
                        "no");
                }
            }

            // printf("mul, compress: %d\n", asfData.packets[i]->playload.multipePlayloads.compressedplayloadNums);

            for (j=0; j<asfData.packets[i]->playload.multipePlayloads.compressedplayloadNums; j++) {
                printfNSpace(8);

                if (asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->keyFrame1Bit) {
                    memset(strTimePresentationTime, 0x0, sizeof(strTimePresentationTime));
                    asf_changeMs2Str(asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->presentationTime, strTimePresentationTime);


                    printf("%-6d %-7d %-10d %-10d %-14d %-14s %-22s %-7s\n",
                        asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->streamNum7Bits,
                        asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->mediaObjNum,
                        asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->presentationTime,
                        asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->repDataLen,
                        asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->payloadLen,
                        //asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->payloadLen,
                        "",
                        //strTimePresentationTime,
                        "",
                        "yes");
                } else {
                    memset(strTimePresentationTime, 0x0, sizeof(strTimePresentationTime));
                    asf_changeMs2Str(asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->presentationTime, strTimePresentationTime);

                    printf("%-6d %-7d %-10d %-10d %-14d %-14s %-22s %-7s\n",
                        asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->streamNum7Bits,
                        asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->mediaObjNum,
                        asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->presentationTime,
                        asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->repDataLen,
                        asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->payloadLen,
                        //asfData.packets[i]->playload.multipePlayloads.compressedPlayloads[j]->payloadLen,
                        "",
                        //strTimePresentationTime,
                        "",
                        "no");
                }
            }
        } else {
            printfNSpace(8);
            printf("SID    OID     Offset     RepData    PayloadLen     ObjectSize     PresentationTime        Key\n");

            if (asfData.packets[i]->isSingleCompressedPlayload) {
                printfNSpace(8);

                if (asfData.packets[i]->playload.singleCompressedPlayload.keyFrame1Bit) {
                    memset(strTimePresentationTime, 0x0, sizeof(strTimePresentationTime));
                    asf_changeMs2Str(asfData.packets[i]->playload.singleCompressedPlayload.presentationTime, strTimePresentationTime);

                    printf("%-6d %-7d %-10d %-10d %-14d %-14s %-23s %-7s\n",
                        asfData.packets[i]->playload.singleCompressedPlayload.streamNum7Bits,
                        asfData.packets[i]->playload.singleCompressedPlayload.mediaObjNum,
                        asfData.packets[i]->playload.singleCompressedPlayload.presentationTime,
                        asfData.packets[i]->playload.singleCompressedPlayload.repDataLen,
                        asfData.packets[i]->palyloadParsingInfo.packetLen,
                        //asfData.packets[i]->palyloadParsingInfo.packetLen,
                        "",
                        //strTimePresentationTime,
                        "",
                        "yes");
                } else {
                    memset(strTimePresentationTime, 0x0, sizeof(strTimePresentationTime));
                    asf_changeMs2Str(asfData.packets[i]->playload.singleCompressedPlayload.presentationTime, strTimePresentationTime);

                    printf("%-6d %-7d %-10d %-10d %-14d %-14s %-23s %-7s\n",
                        asfData.packets[i]->playload.singleCompressedPlayload.streamNum7Bits,
                        asfData.packets[i]->playload.singleCompressedPlayload.mediaObjNum,
                        asfData.packets[i]->playload.singleCompressedPlayload.presentationTime,
                        asfData.packets[i]->playload.singleCompressedPlayload.repDataLen,
                        asfData.packets[i]->palyloadParsingInfo.packetLen,
                        //asfData.packets[i]->palyloadParsingInfo.packetLen,
                        "",
                        //strTimePresentationTime,
                        "",
                        "no");
                }
            } else {
                printfNSpace(8);

                if (asfData.packets[i]->playload.singlePlayload.keyFrame1Bit) {
                    memset(strTimePresentationTime, 0x0, sizeof(strTimePresentationTime));
                    asf_changeMs2Str(asfData.packets[i]->playload.singlePlayload.detailRepdata.pts, strTimePresentationTime);

                    printf("%-6d %-7d %-10d %-10d %-14d %-14d %-22s %-7s\n",
                        asfData.packets[i]->playload.singlePlayload.streamNum7Bits,
                        asfData.packets[i]->playload.singlePlayload.mediaObjNum,
                        asfData.packets[i]->playload.singlePlayload.offIntoMediaObj,
                        asfData.packets[i]->playload.singlePlayload.repDataLen,
                        asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen,
                        asfData.packets[i]->playload.singlePlayload.detailRepdata.allplayloadlen,
                        strTimePresentationTime,
                        "yes");
                } else {
                    memset(strTimePresentationTime, 0x0, sizeof(strTimePresentationTime));
                    asf_changeMs2Str(asfData.packets[i]->playload.singlePlayload.detailRepdata.pts, strTimePresentationTime);

                    printf("%-6d %-7d %-10d %-10d %-14d %-14d %-22s %-7s\n",
                        asfData.packets[i]->playload.singlePlayload.streamNum7Bits,
                        asfData.packets[i]->playload.singlePlayload.mediaObjNum,
                        asfData.packets[i]->playload.singlePlayload.offIntoMediaObj,
                        asfData.packets[i]->playload.singlePlayload.repDataLen,
                        asfData.packets[i]->playload.singlePlayload.detailRepdata.realplayloadlen,
                        asfData.packets[i]->playload.singlePlayload.detailRepdata.allplayloadlen,
                        strTimePresentationTime,
                        "no");
                } 
                
            }
        }
    }
#endif

// TODO, after used, free malloced...

}

static void asf_DealSimpleIndex(T_ASF_BASE_OBJECT *baseObject) {
    DWORD i = 0;
    
    DWORD showIndexEntryCount = 0;

    BYTE *entryData = NULL;

    BYTE *data = baseObject->object_playload;

    T_ASF_SIMPLE_INDEX asfSimpleIndex = {0};

    // copy header first
    asfSimpleIndex.baseObjHeader = baseObject->baseObjHeader;


    memcpy(asfSimpleIndex.fileID, data, MAX_GUID_LEN);

    data += MAX_GUID_LEN;

    asfSimpleIndex.idexEntryTimeInterval = asf_rl64(data);

    data += 8;

    asfSimpleIndex.maxPacketCount = asf_rl32(data);

    data += 4;

    asfSimpleIndex.indexEntriesCount = asf_rl32(data);

    data += 4;

    if (asfSimpleIndex.indexEntriesCount != 0) {
        asfSimpleIndex.simpleIndexEntries = (T_ASF_SIMPLE_INDEX_ENTRY **)malloc(sizeof(T_ASF_SIMPLE_INDEX_ENTRY *) * asfSimpleIndex.indexEntriesCount);
        if (!asfSimpleIndex.simpleIndexEntries) {
            printf("malloc simple index entries error!\n");

            return;
        }
    }

    memset(asfSimpleIndex.simpleIndexEntries, 0x0, sizeof(T_ASF_SIMPLE_INDEX_ENTRY *) * asfSimpleIndex.indexEntriesCount);

    entryData = data;

    for (i=0; i<asfSimpleIndex.indexEntriesCount; i++) {
        asfSimpleIndex.simpleIndexEntries[i] = (T_ASF_SIMPLE_INDEX_ENTRY *)malloc(sizeof(T_ASF_SIMPLE_INDEX_ENTRY));
        if (!asfSimpleIndex.simpleIndexEntries[i] ) {
            printf("malloc simple index entry error!\n");

            return;
        }

        memset(asfSimpleIndex.simpleIndexEntries[i], 0x0, sizeof(T_ASF_SIMPLE_INDEX_ENTRY));

        asfSimpleIndex.simpleIndexEntries[i]->packetNum = asf_rl32(entryData);

        entryData += 4;
        
        asfSimpleIndex.simpleIndexEntries[i]->packetCount = asf_rl16(entryData);

        entryData += 2;
    }

#ifdef PRINTF_DEBUG
    printf("+Simple Index Object\n");
    
    printfNSpace(4);
    printf("Object ID: ");
    asf_PrintGUID(&asfSimpleIndex.baseObjHeader.object_id, 0);

    printfNSpace(4);
    printf("Object size: %lld\n", asfSimpleIndex.baseObjHeader.object_size);

    printfNSpace(4);
    printf("File ID: ");
    asf_PrintGUID(&asfSimpleIndex.fileID, 2);

    printfNSpace(4);
    printf("Time delta: %lld\n", asfSimpleIndex.idexEntryTimeInterval);

    printfNSpace(4);
    printf("Max entry packet count: %d\n", asfSimpleIndex.maxPacketCount);

    printfNSpace(4);
    if (asfSimpleIndex.indexEntriesCount > SHOW_SIMPLE_INDEX_ENTRY_COUNT)
        printf("Index entry count: %d(only show %d)\n", asfSimpleIndex.indexEntriesCount, SHOW_SIMPLE_INDEX_ENTRY_COUNT);
    else
        printf("Index entry count: %d\n", asfSimpleIndex.indexEntriesCount);
    
    showIndexEntryCount = (asfSimpleIndex.indexEntriesCount > SHOW_SIMPLE_INDEX_ENTRY_COUNT) ? SHOW_SIMPLE_INDEX_ENTRY_COUNT : asfSimpleIndex.indexEntriesCount;
    
    for (i=0; i<showIndexEntryCount; i++) {
        printf("\n");

        printfNSpace(4);
        printf("Index Entry: %d\n", i);

        printfNSpace(4);
        printf("Packet: %d\n", asfSimpleIndex.simpleIndexEntries[i]->packetNum);

        printfNSpace(4);
        printf("Span: %d\n", asfSimpleIndex.simpleIndexEntries[i]->packetCount);
    }
#endif
}

static void asf_DealIndex(T_ASF_BASE_OBJECT *baseObject) {
    BYTE *data = baseObject->object_playload;

    T_ASF_INDEX asfIndex = {0};

    // copy header first
    asfIndex.baseObjHeader = baseObject->baseObjHeader;

#ifdef PRINTF_DEBUG
    printf("+Index Object\n");
    
    printfNSpace(4);
    printf("Object ID: ");
    asf_PrintGUID(&asfIndex.baseObjHeader.object_id, 0);

    printfNSpace(4);
    printf("Object size: %lld\n", asfIndex.baseObjHeader.object_size);
#endif
}

static void asf_DealObject(T_ASF_BASE_OBJECT *baseObject, E_ASF_OBJECT_TYPE objectType) {
    if (!baseObject) {
        printf("object is null!\n");

        return;
    }

    // Top-level objects
    if (objectType == ASF_TOP_OBJECT) {
        if (asf_GUIDCmp(&baseObject->baseObjHeader.object_id, &asf_header) == 0) { // ASF Header Object
            asf_DealHeader(baseObject);
        } else if (asf_GUIDCmp(&baseObject->baseObjHeader.object_id, &asf_data_header) == 0) { // ASF Data Object
            asf_DealData(baseObject);
        } else if (asf_GUIDCmp(&baseObject->baseObjHeader.object_id, &asf_simple_index_header) == 0) { // ASF Simple Object
            asf_DealSimpleIndex(baseObject);
        } else if (asf_GUIDCmp(&baseObject->baseObjHeader.object_id, &asf_index_header) == 0) { // ASF Index Object
            asf_DealIndex(baseObject);
        } else {
            printf("GUID: unknown\n");
        }
    }

    // objects belong to header object
    if (objectType == ASF_HEADER_OBJECT) {
        if (asf_GUIDCmp(&baseObject->baseObjHeader.object_id, &asf_header_file_properties_header) == 0) { // ASF File Properties Object
            asf_Header_DealFileProperties(baseObject);
        } else if (asf_GUIDCmp(&baseObject->baseObjHeader.object_id, &asf_header_stream_properties_header) == 0) { // ASF Cocec List Object
            asf_Header_DealStreamProperties(baseObject);
        } else if (asf_GUIDCmp(&baseObject->baseObjHeader.object_id, &asf_header_header_extension_header) == 0) { // ASF Cocec List Object
            asf_Header_DealHeaderExtension(baseObject);
        } else if (asf_GUIDCmp(&baseObject->baseObjHeader.object_id, &asf_header_codec_list_header) == 0) { // ASF Cocec List Object
            asf_Header_DealCodecList(baseObject);
        } else if (asf_GUIDCmp(&baseObject->baseObjHeader.object_id, &asf_header_extended_content_description_header) == 0) { // ASF Cocec List Object
            asf_Header_DealExtendedContentDescription(baseObject);
        } else if (asf_GUIDCmp(&baseObject->baseObjHeader.object_id, &asf_header_stream_bitrate_properties_header) == 0) { // ASF Cocec List Object
            asf_Header_DealStreamBitrateProperties(baseObject);
        } else {
             asf_PrintGUID(&baseObject->baseObjHeader.object_id, 0);
             //printf("Object size: %lld\n", baseObject->baseObjHeader.object_size);
        }
    }
}

int main(int argc, char *argv[]) {
    int dataLen = 0;

    FILE *fp = NULL;

    BYTE baseObjectHeaderdata[ASF_BASE_OBJECT_HEADER_LEN] = {0};

    T_ASF_BASE_OBJECT baseObject = {0};

    if (2 != argc) {
        printf("Usage: asfparse **.asf/wmv/wma\n");

        return -1;
    }

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

        return -1;
    }

    InitAllObjinfo();

    while (1) {
        memset(&baseObject, 0x0, sizeof(T_ASF_BASE_OBJECT));

        if (fread(baseObjectHeaderdata, 1, ASF_BASE_OBJECT_HEADER_LEN, fp) <= 0) {
            break;
        }

        memcpy(baseObject.baseObjHeader.object_id, baseObjectHeaderdata, MAX_GUID_LEN);

        baseObject.baseObjHeader.object_size = asf_rl64(baseObjectHeaderdata + MAX_GUID_LEN);

        baseObject.object_playload = (BYTE*)malloc(baseObject.baseObjHeader.object_size - ASF_BASE_OBJECT_HEADER_LEN);
        if (!baseObject.object_playload) {
            printf("malloc data error!\n");
            
            break;
        }

        fread(baseObject.object_playload, 1, baseObject.baseObjHeader.object_size - ASF_BASE_OBJECT_HEADER_LEN, fp);
        
        /* deal object data */
        asf_DealObject(&baseObject, ASF_TOP_OBJECT);
        
        /* free box */
        free(baseObject.object_playload);
        
        baseObject.object_playload = NULL;
    }

    fclose(fp);


// TODO, free all malloced...

    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlightYe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值