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;
}