/******************************************************************************
* SIMPLE ASF PARSER by fanoble (fanoblem@gmail.com)
* 2005.8.10
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#ifdef WIN32
#define FS_FILE FILE
#define fs_fopen fopen
#define fs_fclose fclose
#define fs_fseek fseek
#define fs_fread fread
#define fs_ftell ftell
#endif
#define ASF_DEBUGOUT
#define GUID_ASF_NONE (-1)
#define GUID_ASF_HEADER_OBJECT 0
#define GUID_ASF_DATA_OBJECT 1
#define GUID_ASF_SIMPLE_INDEX_OBJECT 2
#define GUID_ASF_INDEX_OBJECT 3
#define GUID_ASF_MEDIA_OBJECT_INDEX_OBJECT 4
#define GUID_ASF_TIMECODE_INDEX_OBJECT 5
#define GUID_ASF_FILE_PROPERTIES_OBJECT 6
#define GUID_ASF_STREAM_PROPERTIES_OBJECT 7
#define GUID_ASF_HEADER_EXTENSION_OBJECT 8
#define GUID_ASF_CODEC_LIST_OBJECT 9
#define GUID_ASF_SCRIPT_COMMAND_OBJECT 10
#define GUID_ASF_MARKER_OBJECT 11
#define GUID_ASF_BITRATE_MUTUAL_EXCLUSION_OBJECT 12
#define GUID_ASF_ERROR_CORRECTION_OBJECT 13
#define GUID_ASF_CONTENT_DESCRIPTION_OBJECT 14
#define GUID_ASF_EXTENDED_CONTENT_DESCRIPTION_OBJECT 15
#define GUID_ASF_CONTENT_BRANDING_OBJECT 16
#define GUID_ASF_STREAM_BITRATE_PROPERTIES_OBJECT 17
#define GUID_ASF_CONTENT_ENCRYPTION_OBJECT 18
#define GUID_ASF_EXTENDED_CONTENT_ENCRYPTION_OBJECT 19
#define GUID_ASF_DIGITAL_SIGNATURE_OBJECT 20
#define GUID_ASF_PADDING_OBJECT 21
#define GUID_ASF_EXTENDED_STREAM_PROPERTIES_OBJECT 22
#define GUID_ASF_ADVANCED_MUTUAL_EXCLUSION_OBJECT 23
#define GUID_ASF_GROUP_MUTUAL_EXCLUSION_OBJECT 24
#define GUID_ASF_STREAM_PRIORITIZATION_OBJECT 25
#define GUID_ASF_BANDWIDTH_SHARING_OBJECT 26
#define GUID_ASF_LANGUAGE_LIST_OBJECT 27
#define GUID_ASF_METADATA_OBJECT 28
#define GUID_ASF_METADATA_LIBRARY_OBJECT 29
#define GUID_ASF_INDEX_PARAMETERS_OBJECT 30
#define GUID_ASF_MEDIA_OBJECT_INDEX_PARAMETERS_OBJECT 31
#define GUID_ASF_TIMECODE_INDEX_PARAMETERS_OBJECT 32
#define GUID_ASF_COMPATIBILITY_OBJECT 33
#define GUID_ASF_ADVANCED_CONTENT_ENCRYPTION_OBJECT 34
#define GUID_ASF_AUDIO_MEDIA 35
#define GUID_ASF_VIDEO_MEDIA 36
#define GUID_ASF_COMMAND_MEDIA 37
#define GUID_ASF_JFIF_MEDIA 38
#define GUID_ASF_DEGRADABLE_JPEG_MEDIA 39
#define GUID_ASF_FILE_TRANSFER_MEDIA 40
#define GUID_ASF_BINARY_MEDIA 41
#define GUID_ASF_WEB_STREAM_MEDIA_SUBTYPE 42
#define GUID_ASF_WEB_STREAM_FORMAT 43
#define GUID_ASF_NO_ERROR_CORRECTION 44
#define GUID_ASF_AUDIO_SPREAD 45
#define GUID_ASF_RESERVED_1 46
#define GUID_ASF_RESERVED_2 47
#define GUID_ASF_RESERVED_3 48
#define GUID_ASF_RESERVED_4 49
#define GUID_ASF_MUTEX_LANGUAGE 50
#define GUID_ASF_MUTEX_BITRATE 51
#define GUID_ASF_MUTEX_UNKNOWN 52
#define GUID_ASF_BANDWIDTH_SHARING_EXCLUSIVE 53
#define GUID_ASF_BANDWIDTH_SHARING_PARTIAL 54
#define GUID_ASF_PAYLOAD_EXTENSION_SYSTEM_TIMECODE 55
#define GUID_ASF_PAYLOAD_EXTENSION_SYSTEM_FILE_NAME 56
#define GUID_ASF_PAYLOAD_EXTENSION_SYSTEM_CONTENT_TYPE 57
#define GUID_ASF_PAYLOAD_EXTENSION_SYSTEM_PIXEL_ASPECT_RATIO 58
#define GUID_ASF_PAYLOAD_EXTENSION_SYSTEM_SAMPLE_DURATION 59
#define GUID_ASF_PAYLOAD_EXTENSION_SYSTEM_ENCRYPTION_SAMPLE_ID 60
#define GUID_ASF_CONTENT_ENCRYPTION_SYSTEM_WINDOWS_MEDIA_DRM_NETWORK_DEVICES 61
#pragma pack(push)
#pragma pack(1)
typedef struct tagASF_FILE_HEADER_OBJECT
{
unsigned long SizeLo;
unsigned long SizeHi;
unsigned long NumOfObjects;
unsigned char Reserved1;
unsigned char Reserved2;
} ASF_FILE_HEADER_OBJECT;
typedef struct tagASF_FILE_PROPERTIES_OBJECT
{
unsigned long SizeLo;
unsigned long SizeHi;
unsigned char FileID[16];
unsigned long FileSizeLo;
unsigned long FileSizeHi;
unsigned long FileDateLo;
unsigned long FileDateHi;
unsigned long DataPacketsCountLo;
unsigned long DataPacketsCountHi;
unsigned long PlayDurationLo;
unsigned long PlayDurationHi;
unsigned long SendDurationLo;
unsigned long SendDurationHi;
unsigned long PrerollLo;
unsigned long PrerollHi;
unsigned long Flags;
unsigned long MinDataPacketSize;
unsigned long MaxDataPacketSize;
unsigned long MaxBitrate;
} ASF_FILE_PROPERTIES_OBJECT;
#pragma pack(pop)
static const
unsigned char ASF_GUID_Table [][16] =
{
{ 0x30,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C }, // ASF_Header_Object
{ 0x36,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C }, // ASF_Data_Object
{ 0x90,0x08,0x00,0x33,0xB1,0xE5,0xCF,0x11,0x89,0xF4,0x00,0xA0,0xC9,0x03,0x49,0xCB }, // ASF_Simple_Index_Object
{ 0xD3,0x29,0xE2,0xD6,0xDA,0x35,0xD1,0x11,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE }, // ASF_Index_Object
{ 0xF8,0x03,0xB1,0xFE,0xAD,0x12,0x64,0x4C,0x84,0x0F,0x2A,0x1D,0x2F,0x7A,0xD4,0x8C }, // ASF_Media_Object_Index_Object
{ 0xD0,0x3F,0xB7,0x3C,0x4A,0x0C,0x03,0x48,0x95,0x3D,0xED,0xF7,0xB6,0x22,0x8F,0x0C }, // ASF_Timecode_Index_Object
{ 0xA1,0xDC,0xAB,0x8C,0x47,0xA9,0xCF,0x11,0x8E,0xE4,0x00,0xC0,0x0C,0x20,0x53,0x65 }, // ASF_File_Properties_Object
{ 0x91,0x07,0xDC,0xB7,0xB7,0xA9,0xCF,0x11,0x8E,0xE6,0x00,0xC0,0x0C,0x20,0x53,0x65 }, // ASF_Stream_Properties_Object
{ 0xB5,0x03,0xBF,0x5F,0x2E,0xA9,0xCF,0x11,0x8E,0xE3,0x00,0xC0,0x0C,0x20,0x53,0x65 }, // ASF_Header_Extension_Object
{ 0x40,0x52,0xD1,0x86,0x1D,0x31,0xD0,0x11,0xA3,0xA4,0x00,0xA0,0xC9,0x03,0x48,0xF6 }, // ASF_Codec_List_Object
{ 0x30,0x1A,0xFB,0x1E,0x62,0x0B,0xD0,0x11,0xA3,0x9B,0x00,0xA0,0xC9,0x03,0x48,0xF6 }, // ASF_Script_Command_Object
{ 0x01,0xCD,0x87,0xF4,0x51,0xA9,0xCF,0x11,0x8E,0xE6,0x00,0xC0,0x0C,0x20,0x53,0x65 }, // ASF_Marker_Object
{ 0xDC,0x29,0xE2,0xD6,0xDA,0x35,0xD1,0x11,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE }, // ASF_Bitrate_Mutual_Exclusion_Object
{ 0x35,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C }, // ASF_Error_Correction_Object
{ 0x33,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C }, // ASF_Content_Description_Object
{ 0x40,0xA4,0xD0,0xD2,0x07,0xE3,0xD2,0x11,0x97,0xF0,0x00,0xA0,0xC9,0x5E,0xA8,0x50 }, // ASF_Extended_Content_Description_Object
{ 0xFA,0xB3,0x11,0x22,0x23,0xBD,0xD2,0x11,0xB4,0xB7,0x00,0xA0,0xC9,0x55,0xFC,0x6E }, // ASF_Content_Branding_Object
{ 0xCE,0x75,0xF8,0x7B,0x8D,0x46,0xD1,0x11,0x8D,0x82,0x00,0x60,0x97,0xC9,0xA2,0xB2 }, // ASF_Stream_Bitrate_Properties_Object
{ 0xFB,0xB3,0x11,0x22,0x23,0xBD,0xD2,0x11,0xB4,0xB7,0x00,0xA0,0xC9,0x55,0xFC,0x6E }, // ASF_Content_Encryption_Object
{ 0x14,0xE6,0x8A,0x29,0x22,0x26,0x17,0x4C,0xB9,0x35,0xDA,0xE0,0x7E,0xE9,0x28,0x9C }, // ASF_Extended_Content_Encryption_Object
{ 0xFC,0xB3,0x11,0x22,0x23,0xBD,0xD2,0x11,0xB4,0xB7,0x00,0xA0,0xC9,0x55,0xFC,0x6E }, // ASF_Digital_Signature_Object
{ 0x74,0xD4,0x06,0x18,0xDF,0xCA,0x09,0x45,0xA4,0xBA,0x9A,0xAB,0xCB,0x96,0xAA,0xE8 }, // ASF_Padding_Object
{ 0xCB,0xA5,0xE6,0x14,0x72,0xC6,0x32,0x43,0x83,0x99,0xA9,0x69,0x52,0x06,0x5B,0x5A }, // ASF_Extended_Stream_Properties_Object
{ 0xCF,0x49,0x86,0xA0,0x75,0x47,0x70,0x46,0x8A,0x16,0x6E,0x35,0x35,0x75,0x66,0xCD }, // ASF_Advanced_Mutual_Exclusion_Object
{ 0x40,0x5A,0x46,0xD1,0x79,0x5A,0x38,0x43,0xB7,0x1B,0xE3,0x6B,0x8F,0xD6,0xC2,0x49 }, // ASF_Group_Mutual_Exclusion_Object
{ 0x5B,0xD1,0xFE,0xD4,0xD3,0x88,0x4F,0x45,0x81,0xF0,0xED,0x5C,0x45,0x99,0x9E,0x24 }, // ASF_Stream_Prioritization_Object
{ 0xE6,0x09,0x96,0xA6,0x7B,0x51,0xD2,0x11,0xB6,0xAF,0x00,0xC0,0x4F,0xD9,0x08,0xE9 }, // ASF_Bandwidth_Sharing_Object
{ 0xA9,0x46,0x43,0x7C,0xE0,0xEF,0xFC,0x4B,0xB2,0x29,0x39,0x3E,0xDE,0x41,0x5C,0x85 }, // ASF_Language_List_Object
{ 0xEA,0xCB,0xF8,0xC5,0xAF,0x5B,0x77,0x48,0x84,0x67,0xAA,0x8C,0x44,0xFA,0x4C,0xCA }, // ASF_Metadata_Object
{ 0x94,0x1C,0x23,0x44,0x98,0x94,0xD1,0x49,0xA1,0x41,0x1D,0x13,0x4E,0x45,0x70,0x54 }, // ASF_Metadata_Library_Object
{ 0xDF,0x29,0xE2,0xD6,0xDA,0x35,0xD1,0x11,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE }, // ASF_Index_Parameters_Object
{ 0xAD,0x3B,0x20,0x6B,0x11,0x3F,0xE4,0x48,0xAC,0xA8,0xD7,0x61,0x3D,0xE2,0xCF,0xA7 }, // ASF_Media_Object_Index_Parameters_Object
{ 0x6D,0x49,0x5E,0xF5,0x97,0x97,0x5D,0x4B,0x8C,0x8B,0x60,0x4D,0xFE,0x9B,0xFB,0x24 }, // ASF_Timecode_Index_Parameters_Object
{ 0x30,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C }, // ASF_Compatibility_Object
{ 0x33,0x85,0x05,0x43,0x81,0x69,0xE6,0x49,0x9B,0x74,0xAD,0x12,0xCB,0x86,0xD5,0x8C }, // ASF_Advanced_Content_Encryption_Object
{ 0x40,0x9E,0x69,0xF8,0x4D,0x5B,0xCF,0x11,0xA8,0xFD,0x00,0x80,0x5F,0x5C,0x44,0x2B }, // ASF_Audio_Media
{ 0xC0,0xEF,0x19,0xBC,0x4D,0x5B,0xCF,0x11,0xA8,0xFD,0x00,0x80,0x5F,0x5C,0x44,0x2B }, // ASF_Video_Media
{ 0xC0,0xCF,0xDA,0x59,0xE6,0x59,0xD0,0x11,0xA3,0xAC,0x00,0xA0,0xC9,0x03,0x48,0xF6 }, // ASF_Command_Media
{ 0x00,0xE1,0x1B,0xB6,0x4E,0x5B,0xCF,0x11,0xA8,0xFD,0x00,0x80,0x5F,0x5C,0x44,0x2B }, // ASF_JFIF_Media
{ 0xE0,0x7D,0x90,0x35,0x15,0xE4,0xCF,0x11,0xA9,0x17,0x00,0x80,0x5F,0x5C,0x44,0x2B }, // ASF_Degradable_JPEG_Media
{ 0x2C,0x22,0xBD,0x91,0x1C,0xF2,0x7A,0x49,0x8B,0x6D,0x5A,0xA8,0x6B,0xFC,0x01,0x85 }, // ASF_File_Transfer_Media
{ 0xE2,0x65,0xFB,0x3A,0xEF,0x47,0xF2,0x40,0xAC,0x2C,0x70,0xA9,0x0D,0x71,0xD3,0x43 }, // ASF_Binary_Media
{ 0xD4,0x57,0x62,0x77,0x27,0xC6,0xCB,0x41,0x8F,0x81,0x7A,0xC7,0xFF,0x1C,0x40,0xCC }, // ASF_Web_Stream_Media_Subtype
{ 0x13,0x6B,0x1E,0xDA,0x59,0x83,0x50,0x40,0xB3,0x98,0x38,0x8E,0x96,0x5B,0xF0,0x0C }, // ASF_Web_Stream_Format
{ 0x00,0x57,0xFB,0x20,0x55,0x5B,0xCF,0x11,0xA8,0xFD,0x00,0x80,0x5F,0x5C,0x44,0x2B }, // ASF_No_Error_Correction
{ 0x50,0xCD,0xC3,0xBF,0x8F,0x61,0xCF,0x11,0x8B,0xB2,0x00,0xAA,0x00,0xB4,0xE2,0x20 }, // ASF_Audio_Spread
{ 0x11,0xD2,0xD3,0xAB,0xBA,0xA9,0xCF,0x11,0x8E,0xE6,0x00,0xC0,0x0C,0x20,0x53,0x65 }, // ASF_Reserved_1
{ 0x41,0x52,0xD1,0x86,0x1D,0x31,0xD0,0x11,0xA3,0xA4,0x00,0xA0,0xC9,0x03,0x48,0xF6 }, // ASF_Reserved_2
{ 0xE3,0xCB,0x1A,0x4B,0x0B,0x10,0xD0,0x11,0xA3,0x9B,0x00,0xA0,0xC9,0x03,0x48,0xF6 }, // ASF_Reserved_3
{ 0x20,0xDB,0xFE,0x4C,0xF6,0x75,0xCF,0x11,0x9C,0x0F,0x00,0xA0,0xC9,0x03,0x49,0xCB }, // ASF_Reserved_4
{ 0x00,0x2A,0xE2,0xD6,0xDA,0x35,0xD1,0x11,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE }, // ASF_Mutex_Language
{ 0x01,0x2A,0xE2,0xD6,0xDA,0x35,0xD1,0x11,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE }, // ASF_Mutex_Bitrate
{ 0x02,0x2A,0xE2,0xD6,0xDA,0x35,0xD1,0x11,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE }, // ASF_Mutex_Unknown
{ 0xAA,0x60,0x60,0xAF,0x97,0x51,0xD2,0x11,0xB6,0xAF,0x00,0xC0,0x4F,0xD9,0x08,0xE9 }, // ASF_Bandwidth_Sharing_Exclusive
{ 0xAB,0x60,0x60,0xAF,0x97,0x51,0xD2,0x11,0xB6,0xAF,0x00,0xC0,0x4F,0xD9,0x08,0xE9 }, // ASF_Bandwidth_Sharing_Partial
{ 0xEC,0x95,0x95,0x39,0x67,0x86,0x2D,0x4E,0x8F,0xDB,0x98,0x81,0x4C,0xE7,0x6C,0x1E }, // ASF_Payload_Extension_System_Timecode
{ 0x0E,0xEC,0x65,0xE1,0xED,0x19,0xD7,0x45,0xB4,0xA7,0x25,0xCB,0xD1,0xE2,0x8E,0x9B }, // ASF_Payload_Extension_System_File_Name
{ 0x20,0xDC,0x90,0xD5,0xBC,0x07,0x6C,0x43,0x9C,0xF7,0xF3,0xBB,0xFB,0xF1,0xA4,0xDC }, // ASF_Payload_Extension_System_Content_Type
{ 0x54,0xE5,0x1E,0x1B,0xEA,0xF9,0xC8,0x4B,0x82,0x1A,0x37,0x6B,0x74,0xE4,0xC4,0xB8 }, // ASF_Payload_Extension_System_Pixel_Aspect_Ratio
{ 0x50,0x94,0xBD,0xC6,0x7F,0x86,0x07,0x49,0x83,0xA3,0xC7,0x79,0x21,0xB7,0x33,0xAD }, // ASF_Payload_Extension_System_Sample_Duration
{ 0x4E,0xB8,0x98,0x66,0xFA,0x0A,0x30,0x43,0xAE,0xB2,0x1C,0x0A,0x98,0xD7,0xA4,0x4D }, // ASF_Payload_Extension_System_Encryption_Sample_ID
{ 0xB6,0x9B,0x07,0x7A,0xA4,0xDA,0x12,0x4E,0xA5,0xCA,0x91,0xD3,0x8D,0xC1,0x1A,0x8D } // ASF_Content_Encryption_System_Windows_Media_DRM_Network_Devices
};
static const
char ASF_GUID_Name[][60] =
{
"Header_Object",
"Data_Object",
"Simple_Index_Object",
"Index_Object",
"Media_Object_Index_Object",
"Timecode_Index_Object",
"File_Properties_Object",
"Stream_Properties_Object",
"Header_Extension_Object",
"Codec_List_Object",
"Script_Command_Object",
"Marker_Object",
"Bitrate_Mutual_Exclusion_Object",
"Error_Correction_Object",
"Content_Description_Object",
"Extended_Content_Description_Object",
"Content_Branding_Object",
"Stream_Bitrate_Properties_Object",
"Content_Encryption_Object",
"Extended_Content_Encryption_Object",
"Digital_Signature_Object",
"Padding_Object",
"Extended_Stream_Properties_Object",
"Advanced_Mutual_Exclusion_Object",
"Group_Mutual_Exclusion_Object",
"Stream_Prioritization_Object",
"Bandwidth_Sharing_Object",
"Language_List_Object",
"Metadata_Object",
"Metadata_Library_Object",
"Index_Parameters_Object",
"Media_Object_Index_Parameters_Object",
"Timecode_Index_Parameters_Object",
"Compatibility_Object",
"Advanced_Content_Encryption_Object",
"Audio_Media",
"Video_Media",
"Command_Media",
"JFIF_Media",
"Degradable_JPEG_Media",
"File_Transfer_Media",
"Binary_Media",
"Web_Stream_Media_Subtype",
"Web_Stream_Format",
"No_Error_Correction",
"Audio_Spread",
"Reserved_1",
"Reserved_2",
"Reserved_3",
"Reserved_4",
"Mutex_Language",
"Mutex_Bitrate",
"Mutex_Unknown",
"Bandwidth_Sharing_Exclusive",
"Bandwidth_Sharing_Partial",
"Payload_Extension_System_Timecode",
"Payload_Extension_System_File_Name",
"Payload_Extension_System_Content_Type",
"Payload_Extension_System_Pixel_Aspect_Ratio",
"Payload_Extension_System_Sample_Duration",
"Payload_Extension_System_Encryption_Sample_ID",
"Content_Encryption_System_Windows_Media_DRM_Network_Devices"
};
static int ASF_GetGUID(void);
static int ASF_ParseFile(void);
static int ASF_SkipObject(void);
static int ASF_PraseCodecListObject(void);
static int ASF_PraseDataObject(void);
static int ASF_PraseIndexObject(void);
static int ASF_PraseSimpleIndexObject(void);
static int ASF_PraseExtContentDescObject(void);
static int ASF_PraseStreamPropertiesObject(void);
static FS_FILE* fp_asf;
static unsigned long asf_file_length;
static unsigned long asf_total_time;
static unsigned long asf_max_bitrate;
static unsigned long asf_packet_count;
static unsigned long asf_packet_size;
#ifdef ASF_DEBUGOUT
static int is_show_packet = 0;
#endif // ASF_DEBUGOUT
int main(int argc, char* argv[])
{
if (argc < 2)
{
printf("Arguments Missing.");
return 1;
}
fp_asf = fs_fopen(argv[1], "rb");
if (0 == fp_asf)
{
printf("Open file error.");
return 1;
}
#ifdef ASF_DEBUGOUT
if (argc > 2)
is_show_packet = 1;
#endif // ASF_DEBUGOUT
if (0 == ASF_ParseFile())
printf("Prase file OK.");
else
printf("Prase file error.");
fs_fclose(fp_asf);
int i;
// scanf("%d",&i);
return 0;
}
static
int ASF_ParseFile(void)//asf解析文件
{
ASF_FILE_HEADER_OBJECT afho;
ASF_FILE_PROPERTIES_OBJECT afpo;
size_t length;
int id;
// get file header object
if (GUID_ASF_HEADER_OBJECT != ASF_GetGUID())
return -1;
length = fs_fread(&afho, 1, sizeof(ASF_FILE_HEADER_OBJECT), fp_asf);
if (sizeof(ASF_FILE_HEADER_OBJECT) != length)
return -1;
// get reserved data, must be 0x02, ignore Reserved1
if (0x02 != afho.Reserved2)
return -1;
// find file properties object
if (0 == afho.NumOfObjects)
return -1;
#ifdef ASF_DEBUGOUT
printf("\tHeader contains %d objects\n", afho.NumOfObjects);
#endif // ASF_DEBUGOUT
do
{
id = ASF_GetGUID();
if (GUID_ASF_NONE == id)
return -1;
if (GUID_ASF_FILE_PROPERTIES_OBJECT == id)
break;
if (GUID_ASF_EXTENDED_CONTENT_DESCRIPTION_OBJECT == id)
{
if (-1 == ASF_PraseExtContentDescObject())
return -1;
}
else if (GUID_ASF_CODEC_LIST_OBJECT == id)
{
if (-1 == ASF_PraseCodecListObject())
return -1;
}
else if (GUID_ASF_STREAM_PROPERTIES_OBJECT == id)
{
if (-1 == ASF_PraseStreamPropertiesObject())
return -1;
}
else
{
if (-1 == ASF_SkipObject())
return -1;
}
} while(--afho.NumOfObjects);
// file properties object not found
if (0 == afho.NumOfObjects)
return -1;
// get file properties object
length = fs_fread(&afpo, 1, sizeof(ASF_FILE_PROPERTIES_OBJECT), fp_asf);
if (sizeof(ASF_FILE_PROPERTIES_OBJECT) != length)
return -1;
asf_file_length = afpo.FileSizeLo;
asf_total_time = afpo.PlayDurationLo / 10000; // ms
asf_total_time += afpo.PlayDurationHi * 429497L;
asf_max_bitrate = afpo.MaxBitrate;
asf_packet_count = afpo.DataPacketsCountLo;
asf_packet_size = afpo.MinDataPacketSize;
#ifdef ASF_DEBUGOUT
printf("\tFile length : %d bytes\n", asf_file_length);
printf("\tTotal time : %02d:%02d.%03d\n", asf_total_time / 1000 / 60,
(asf_total_time / 1000) % 60, asf_total_time % 1000);
printf("\tMax bitrate : %d bps\n", asf_max_bitrate);
printf("\tPacket count: %d\n", asf_packet_count);
printf("\tPacket size : %d bytes\n", asf_packet_size);
#endif // ASF_DEBUGOUT
// see if this file is seekable
if (afpo.Flags & 2)
{
#ifdef ASF_DEBUGOUT
printf("\t---Seekable---\n");
#endif // ASF_DEBUGOUT
}
else
{
#ifdef ASF_DEBUGOUT
printf("\t---UnSeekable---\n");
#endif // ASF_DEBUGOUT
}
// remain objects in head
while(--afho.NumOfObjects)
{
id = ASF_GetGUID();
if (GUID_ASF_NONE == id)
return -1;
if (GUID_ASF_CODEC_LIST_OBJECT == id)
{
if (-1 == ASF_PraseCodecListObject())
return -1;
}
else if (GUID_ASF_EXTENDED_CONTENT_DESCRIPTION_OBJECT == id)
{
if (-1 == ASF_PraseExtContentDescObject())
return -1;
}
else if (GUID_ASF_STREAM_PROPERTIES_OBJECT == id)
{
if (-1 == ASF_PraseStreamPropertiesObject())
return -1;
}
else
{
if (-1 == ASF_SkipObject())
return -1;
}
}
// data object & index object (if exist)
for (;;)
{
id = ASF_GetGUID();
if (GUID_ASF_DATA_OBJECT == id)
{
if (-1 == ASF_PraseDataObject())
return -1;
}
else if (GUID_ASF_INDEX_OBJECT == id)
{
if (-1 == ASF_PraseIndexObject())
return -1;
}
else if (GUID_ASF_SIMPLE_INDEX_OBJECT == id)
{
if (-1 == ASF_PraseSimpleIndexObject())
return -1;
}
else if (GUID_ASF_NONE == id)
{
break;
}
else
{
if (-1 == ASF_SkipObject())
return -1;
}
}
return 0;
}
static
int ASF_GetGUID(void)
{
int i;
size_t length;
unsigned char guid[16];
length = fs_fread(guid, 1, 16, fp_asf);//oxoo429af0
if (16 != length)
return GUID_ASF_NONE;
for (i = 0; i < sizeof(ASF_GUID_Table) / 16; i++)
{
if (0 == memcmp(guid, ASF_GUID_Table + i, 16))
{
#ifdef ASF_DEBUGOUT
long pos = fs_ftell(fp_asf) - 16;
printf("Found %s at %d (0x%X)\n", ASF_GUID_Name[i], pos, pos);
#endif // ASF_DEBUGOUT
return i;
}
}
return GUID_ASF_NONE;
}
static
int ASF_SkipObject(void)
{
unsigned long length;
if (4 != fs_fread(&length, 1, 4, fp_asf))
return -1;
fs_fseek(fp_asf, length - 16 - 4, SEEK_CUR);
return 0;
}
static
int ASF_PraseDataObject(void)//asf解析数据项
{
unsigned char errc;
unsigned char type;
unsigned long cur_packet_size;
unsigned long i;
unsigned long packet_start;
unsigned short duration;
unsigned short dummy16;
// skip size, file id, packets count area
fs_fseek(fp_asf, 8 + 16 + 8, SEEK_CUR);
// get reserved data, must be 0x0101
fs_fread(&dummy16, 1, 2, fp_asf);
if (0x0101 != dummy16)
return -1;
packet_start = fs_ftell(fp_asf);
// Data Packets
for (i = 0; i < asf_packet_count; i++)
{
// Error correction data
if (0 == fs_fread(&errc, 1, 1, fp_asf))
return -1;
// error correction present
if (errc & 0x80)
{
// Opaque data or type not supported
if (errc & 0x70)
{
#ifdef ASF_DEBUGOUT
printf("\t---error correction not supported @ %d---\n", fs_ftell(fp_asf) - 1);
#endif // ASF_DEBUGOUT
return -1;
}
// skip error correction data
fs_fseek(fp_asf, errc & 0x0F, SEEK_CUR);
if (0 == fs_fread(&errc, 1, 1, fp_asf))
return -1;
}
// Packet Length Type
type = (errc >> 5) & 3;
// debug ...
// type = 0;
// skip Property Flags
// fs_fseek(fp_asf, 1, SEEK_CUR);
unsigned char PropertyFlags;
if (0 == fs_fread(&PropertyFlags, 1, 1, fp_asf))
return -1;
if (0 == type)
{
cur_packet_size = asf_packet_size;
}
else
{
cur_packet_size = 0;
if (1 == type) // BYTE
{
// if (1 != fs_fread(&cur_packet_size, 1, 1, fp_asf))
// return -1;
fs_fseek(fp_asf, 1, SEEK_CUR);
}
else if (2== type) // WORD
{
// if (2 != fs_fread(&cur_packet_size, 1, 2, fp_asf))
// return -1;
fs_fseek(fp_asf, 2, SEEK_CUR);
}
else // DWORD
{
// if (4 != fs_fread(&cur_packet_size, 1, 4, fp_asf))
// return -1;
fs_fseek(fp_asf, 4, SEEK_CUR);
}
}
if (0 == cur_packet_size)
cur_packet_size = asf_packet_size;
{
// skip Send Time
unsigned long skip_bytes = 4;
int key_frame;
// Sequence Type
type = (errc >> 1) & 3;
// skip Sequence Length
if (1 == type)
skip_bytes += 1;
else if (2 == type)
skip_bytes += 2;
else if (3 == type)
skip_bytes += 4;
// Padding Length Type
type = (errc >> 3) & 3;
// skip Padding Length
if (1 == type)
skip_bytes += 1;
else if (2 == type)
skip_bytes += 2;
else if (3 == type)
skip_bytes += 4;
fs_fseek(fp_asf, skip_bytes, SEEK_CUR);
// get packet duration
if (2 != fs_fread(&duration, 1, 2, fp_asf))
return -1;
if (1 != fs_fread(&key_frame, 1, 1, fp_asf))
return -1;
key_frame &= 0xFF;
// printf("%02X ", key_frame);
if ((PropertyFlags >> 4) & 0x03)
{
int MediaObjectNumber = 0;
if (1 == ((PropertyFlags >> 4) & 0x03))
{
if (1 != fs_fread(&MediaObjectNumber, 1, 1, fp_asf))
return -1;
}
if (2 == ((PropertyFlags >> 4) & 0x03))
{
if (2 != fs_fread(&MediaObjectNumber, 1, 2, fp_asf))
return -1;
}
if (3 == ((PropertyFlags >> 4) & 0x03))
{
if (4 != fs_fread(&MediaObjectNumber, 1, 4, fp_asf))
return -1;
}
// printf("MediaObjectNumber = %d\r\n", MediaObjectNumber);
}
if ((PropertyFlags >> 2) & 0x03)
{
int OffsetToObject = 0;
if (1 == ((PropertyFlags >> 2) & 0x03))
{
if (1 != fs_fread(&OffsetToObject, 1, 1, fp_asf))
return -1;
}
if (2 == ((PropertyFlags >> 2) & 0x03))
{
if (2 != fs_fread(&OffsetToObject, 1, 2, fp_asf))
return -1;
}
if (3 == ((PropertyFlags >> 2) & 0x03))
{
if (4 != fs_fread(&OffsetToObject, 1, 4, fp_asf))
return -1;
}
// printf("OffsetToObject = %d\r\n", OffsetToObject);
}
if (PropertyFlags & 0x03)
{
size_t RepDataLen = 0;
if (1 == (PropertyFlags & 0x03))
{
if (1 != fs_fread(&RepDataLen, 1, 1, fp_asf))
return -1;
}
if (2 == (PropertyFlags & 0x03))
{
if (2 != fs_fread(&RepDataLen, 1, 2, fp_asf))
return -1;
}
if (3 == (PropertyFlags & 0x03))
{
if (4 != fs_fread(&RepDataLen, 1, 4, fp_asf))
return -1;
}
// printf("RepDataLen = %d\r\n", RepDataLen);
if (RepDataLen)
{
unsigned char* rep_data = new unsigned char [RepDataLen];
if (RepDataLen != fs_fread(rep_data, 1, RepDataLen, fp_asf))
{
delete [] rep_data;
return -1;
}
// printf("Size=%d, ", *(DWORD*)rep_data);
// printf("Time=%d\r\n ", *((DWORD*)rep_data + 1));
delete [] rep_data;
}
}
}
#ifdef ASF_DEBUGOUT
if (is_show_packet)
printf("\t-Found packet %04d @ %d, length=%d, duration=%dms\n", i, packet_start, cur_packet_size, duration);
#endif // ASF_DEBUGOUT
// seek to next packet
packet_start += cur_packet_size;
fs_fseek(fp_asf, packet_start, SEEK_SET);
}
return 0;
}
static
int ASF_PraseIndexObject(void)
{
unsigned long entry_time_interval;
unsigned short specifiers_count;
unsigned long blocks_count, i;
unsigned long index_entry_count, j;
unsigned long offset;
// skip object size
fs_fseek(fp_asf, 8, SEEK_CUR);
// get Index Entry Time Interval
if (4 != fs_fread(&entry_time_interval, 1, 4, fp_asf))
return -1;
printf("+++Time Interval:%d+++\n", entry_time_interval);
// get Index Specifiers Count
if (2 != fs_fread(&specifiers_count, 1, 2, fp_asf))
return -1;
// get Index Blocks Count
if (4 != fs_fread(&blocks_count, 1, 4, fp_asf))
return -1;
// skip Index Specifiers (stream number & index type)
fs_fseek(fp_asf, specifiers_count * (2 + 2), SEEK_CUR);
// Index Blocks
for (i = 0; i < blocks_count; i++)
{
if (4 != fs_fread(&index_entry_count, 1, 4, fp_asf))
return -1;
// skip block positions (QWORD)
fs_fseek(fp_asf, specifiers_count * 8, SEEK_CUR);
// index entries
for (j = 0; j < index_entry_count; j++)
{
// only read the 1st offset
if (4 != fs_fread(&offset, 1, 4, fp_asf))
return -1;
if (is_show_packet)
printf("+++offset:%d+++\n", offset);
// skip rest offsets
if (specifiers_count > 1)
fs_fseek(fp_asf, (specifiers_count - 1) * 4, SEEK_CUR);
}
}
return 0;
}
static
int ASF_PraseSimpleIndexObject(void)
{
unsigned long time_interval;
unsigned long time_interval_lo;
unsigned long time_interval_hi;
unsigned long entries_count, i;
unsigned long packet_num;
unsigned short packet_cnt;
// skip object size & file ID (GUID)
fs_fseek(fp_asf, 8 + 16, SEEK_CUR);
// get time interval (DWORD)
if (4 != fs_fread(&time_interval_lo, 1, 4, fp_asf))
return -1;
if (4 != fs_fread(&time_interval_hi, 1, 4, fp_asf))
return -1;
time_interval = time_interval_lo / 10000; // ms
time_interval += time_interval_hi * 429497L;
printf("+++Time Interval:%d+++\n", time_interval);
// skip Maximum Packet Count
fs_fseek(fp_asf, 4, SEEK_CUR);
if (4 != fs_fread(&entries_count, 1, 4, fp_asf))
return -1;
for (i = 0; i < entries_count; i++)
{
// associated Data Packet
if (4 != fs_fread(&packet_num, 1, 4, fp_asf))
return -1;
if (2 != fs_fread(&packet_cnt, 1, 2, fp_asf))
return -1;
if (is_show_packet)
printf("+++packet:%d(%d)+++\n", packet_num, packet_cnt);
}
return 0;
}
static
int ASF_PraseCodecListObject(void)//
{
unsigned long entries_count, i;
unsigned short codec_type;
unsigned short codec_name_len;
unsigned short codec_desc_len;
unsigned short codec_info_len;
char* buf_string;
// skip object size & reserved GUID
fs_fseek(fp_asf, 8 + 16, SEEK_CUR);
if (4 != fs_fread(&entries_count, 1, 4, fp_asf))
return -1;
// Codec Entries
for (i = 0; i < entries_count; i++)
{
// get codec type
if (2 != fs_fread(&codec_type, 1, 2, fp_asf))
return -1;
if (0x01 == codec_type)
printf("\t**Video Codec***\n");
else if (0x02 == codec_type)
printf("\t**Audio Codec**\n");
else
printf("\t**Unknown Codec**\n");
// get codec name length
if (2 != fs_fread(&codec_name_len, 1, 2, fp_asf))
return -1;
// get codec name
if (codec_name_len)
{
buf_string = (char*)malloc(codec_name_len * 4); // WCHAR & CHAR
if (codec_name_len != fs_fread(buf_string, 2, codec_name_len, fp_asf))
{
free(buf_string);
return -1;
}
WideCharToMultiByte(CP_ACP, 0,
(const unsigned short*)buf_string, codec_name_len,
buf_string + codec_name_len * 2, codec_name_len * 2,
NULL, NULL);
printf("\t ***%s***\n", buf_string + codec_name_len * 2);
free(buf_string);
}
// get codec description length
if (2 != fs_fread(&codec_desc_len, 1, 2, fp_asf))
return -1;
// get codec description
if (codec_desc_len)
{
buf_string = (char*)malloc(codec_desc_len * 4); // WCHAR & CHAR
if (codec_desc_len != fs_fread(buf_string, 2, codec_desc_len, fp_asf))
{
free(buf_string);
return -1;
}
WideCharToMultiByte(CP_ACP, 0,
(const unsigned short*)buf_string, codec_desc_len,
buf_string + codec_desc_len * 2, codec_desc_len * 2,
NULL, NULL);
if (*(buf_string + codec_desc_len * 2))
printf("\t ***%s***\n", buf_string + codec_desc_len * 2);
free(buf_string);
}
// get codec information length
if (2 != fs_fread(&codec_info_len, 1, 2, fp_asf))
return -1;
// skip codec information
fs_fseek(fp_asf, codec_info_len, SEEK_CUR);
}
return 0;
}
// function : see if it's a VBR file.
static
int ASF_PraseExtContentDescObject(void)
{
unsigned short desc_count, i;
unsigned short desc_name_len;
unsigned short desc_value_type;
unsigned short desc_value_len;
char* buf_string;
// skip object size
fs_fseek(fp_asf, 8, SEEK_CUR);
// get Content Descriptors Count
if (2 != fs_fread(&desc_count, 1, 2, fp_asf))
return -1;
// prase each Content Descriptor
for (i = 0; i < desc_count; i++)
{
// get Descriptor Name Length
if (2 != fs_fread(&desc_name_len, 1, 2, fp_asf))
return -1;
// get Descriptor Name
if (desc_name_len)
{
desc_name_len /= 2; // CHAR -> WCHAR
buf_string = (char*)malloc(desc_name_len * 4); // WCHAR & CHAR
if (desc_name_len != fs_fread(buf_string, 2, desc_name_len, fp_asf))
{
free(buf_string);
return -1;
}
WideCharToMultiByte(CP_ACP, 0,
(const unsigned short*)buf_string, desc_name_len,
buf_string + desc_name_len * 2, desc_name_len * 2,
NULL, NULL);
printf("\t==%s==\n", buf_string + desc_name_len * 2);
free(buf_string);
}
// get Descriptor Value Data Type
if (2 != fs_fread(&desc_value_type, 1, 2, fp_asf))
return -1;
// get Descriptor Value Length
if (2 != fs_fread(&desc_value_len, 1, 2, fp_asf))
return -1;
if (0 == desc_value_type) // unicode string
{
// get Descriptor Value
if (desc_value_len)
{
desc_value_len /= 2; // CHAR -> WCHAR
buf_string = (char*)malloc(desc_value_len * 4); // WCHAR & CHAR
if (desc_value_len != fs_fread(buf_string, 2, desc_value_len, fp_asf))
{
free(buf_string);
return -1;
}
WideCharToMultiByte(CP_ACP, 0,
(const unsigned short*)buf_string, desc_value_len,
buf_string + desc_value_len * 2, desc_value_len * 2,
NULL, NULL);
printf("\t ===%s===\n", buf_string + desc_value_len * 2);
free(buf_string);
}
}
else if (0x02 == desc_value_type) // BOOL
{
unsigned long val;
if (4 != fs_fread(&val, 1, 4, fp_asf))
return -1;
if (val) // TRUE
printf("\t ===True===\n");
else // FALSE
printf("\t ===False===\n");
}
else // ignore
{
fs_fseek(fp_asf, desc_value_len, SEEK_CUR);
}
}
return 0;
}
static
int ASF_PraseStreamPropertiesObject(void)
{
unsigned long TypeSpecificDataLength;
unsigned long ErrorCorrectionDataLength;
unsigned short Flags;
int guid;
unsigned long size;
if (4 != fs_fread(&size, 1, 4, fp_asf))
return -1;
fs_fseek(fp_asf, 4, SEEK_CUR);
guid = ASF_GetGUID();
if (-1 == guid) return -1;
if (GUID_ASF_AUDIO_MEDIA != guid)
{
fs_fseek(fp_asf, size - 16 - 8 - 16, SEEK_CUR);
return 0;
}
// skip Error Correction Type & Time Offset
fs_fseek(fp_asf, 16 + 8, SEEK_CUR);
if (4 != fs_fread(&TypeSpecificDataLength, 1, 4, fp_asf))
return -1;
if (4 != fs_fread(&ErrorCorrectionDataLength, 1, 4, fp_asf))
return -1;
if (2 != fs_fread(&Flags, 1, 2, fp_asf))
return -1;
if (Flags & 0x8000)
{
printf("\t!!! Encrypted !!!\n");
}
// skip Reserved field
fs_fseek(fp_asf, 4, SEEK_CUR);
// read TypeSpecificData, assume this is a audio file
// printf("\tTypeSpecData@%d\r\n", fs_ftell(fp_asf) + 4);
unsigned short id, channel, align, sbit;
unsigned long sps, bps;
if (2 != fs_fread(&id, 1, 2, fp_asf))
return -1;
if (2 != fs_fread(&channel, 1, 2, fp_asf))
return -1;
if (4 != fs_fread(&sps, 1, 4, fp_asf))
return -1;
if (4 != fs_fread(&bps, 1, 4, fp_asf))
return -1;
if (2 != fs_fread(&align, 1, 2, fp_asf))
return -1;
if (2 != fs_fread(&sbit, 1, 2, fp_asf))
return -1;
printf("\tCodecID:%04X\r\n", id);
printf("\tChannel:%d\r\n", channel);
printf("\tSampleRate:%d\r\n", sps);
printf("\tBytePerSecond:%d\r\n", bps);
printf("\tBlockAlign:%d\r\n", align);
printf("\tBitsOfSample:%d\r\n", sbit);
TypeSpecificDataLength -= 16;
// skip Error Correction Data
fs_fseek(fp_asf, TypeSpecificDataLength + ErrorCorrectionDataLength, SEEK_CUR);
return 0;
}
/******************************************************************************
* END OF FILE
******************************************************************************/
// #include "stdio.h"
// int main(int argc, char **argv)
// {
// printf("%s",argv[0]);
// printf("%s",argv[1]);
// //printf("%s",argv[2]);
// int i;
// scanf("%d",&i);
// }