Index: libmpdemux/asf.h =================================================================== --- libmpdemux/asf.h £¨ÐÞ¶©°æ 21485£© +++ libmpdemux/asf.h £¨¹¤×÷¿½±´£© @@ -84,6 +84,20 @@ } ASF_content_description_t; //////////////////////// +// ASF Metadata Record +//////////////////////// +typedef struct { + // must be 0 for metadata record, might be non-zero for metadata lib record + uint16_t lang_list_index; + uint16_t stream_num; + uint16_t name_length; + uint16_t data_type; + uint32_t data_length; + uint16_t* name; + void* data; +} ASF_meta_record_t; + +//////////////////////// // ASF Segment Header //////////////////////// typedef struct __attribute__((packed)) { @@ -127,6 +141,17 @@ ASF_Authenticate_e } ASF_StreamType_e; +// Data types are usually represented by a uint16_t of following values +typedef enum { + ASF_UCS16LEs_e, // Unicode string encoded as UCS16LE + ASF_Bytes_e, // Array of bytes + ASF_Bool_e, // BOOL represented by a uint32_t + ASF_DWORD_e, + ASF_QWORD_e, + ASF_WORD_e, + ASF_GUID_e +} ASF_DataType_e; + typedef struct { ASF_StreamType_e streaming_type; int request; Index: libmpdemux/asfheader.c =================================================================== --- libmpdemux/asfheader.c £¨ÐÞ¶©°æ 21485£© +++ libmpdemux/asfheader.c £¨¹¤×÷¿½±´£© @@ -60,6 +60,8 @@ 0xe1, 0x03, 0x28, 0x45, 0xb5, 0x82, 0x3d, 0xf9, 0xdb, 0x22, 0xf5, 0x03}; const char asf_ext_stream_header[16] = {0xCB, 0xA5, 0xE6, 0x14, 0x72, 0xC6, 0x32, 0x43, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A}; +const char asf_metadata_header[16] = {0xea, 0xcb, 0xf8, 0xc5, + 0xaf, 0x5b, 0x77, 0x48, 0x84, 0x67, 0xaa, 0x8c, 0x44, 0xfa, 0x4c, 0xca}; static char* get_ucs2str(const uint16_t* inbuf, uint16_t inlen) { @@ -205,6 +207,86 @@ return 0; } +static char* read_meta_record(ASF_meta_record_t* dest, char* buf) +{ + dest->lang_list_index = LE_16(buf); + buf += sizeof(uint16_t); + dest->stream_num = LE_16(buf); + buf += sizeof(uint16_t); + dest->name_length = LE_16(buf); + buf += sizeof(uint16_t); + dest->data_type = LE_16(buf); + buf += sizeof(uint16_t); + dest->data_length = LE_32(buf); + buf += sizeof(uint32_t); + dest->name = (uint16_t*)buf; + buf += dest->name_length; + dest->data = buf; + buf += dest->data_length; + return buf; +} + +static int get_meta(char *buf, int buf_len, int this_stream_num, + float* asp_ratio) +{ + int pos = 0; + uint16_t records_count, i; + uint32_t x = 0, y = 0; + + if ((pos = find_asf_guid(buf, asf_metadata_header, pos, buf_len)) < 0) + return 0; + + buf += pos; + records_count = LE_16(buf); + buf += sizeof(uint16_t); + + for (i = 0; i < records_count; i++) { + ASF_meta_record_t record_entry; + uint32_t data; + uint16_t name_len; + char* name; + + buf = read_meta_record(&record_entry, buf); + /* reserved, must be zero */ + if (record_entry.lang_list_index) + continue; + /* match stream number: 0 to match all */ + if (record_entry.stream_num && record_entry.stream_num != this_stream_num) + continue; + /* match name length */ + if ((name_len = record_entry.name_length) != + 2 * strlen("AspectRatioX") + 2) + continue; + if (!(name = get_ucs2str(record_entry.name, name_len))) { + mp_msg(MSGT_HEADER, MSGL_ERR, MSGTR_MemAllocFailed); + continue; + } + if (strncmp(name, "AspectRatio", strlen("AspectRatio")) == 0) { + switch (record_entry.data_type) { + case ASF_DWORD_e: + data = LE_32(record_entry.data); + break; + case ASF_WORD_e: + data = LE_16(record_entry.data); + break; + default: + free(name); + continue; + } + } + if (name[strlen("AspectRatio")] == 'X') + x = data; + else if (name[strlen("AspectRatio")] == 'Y') + y = data; + free(name); + if (x && y) { + *asp_ratio = (float)x / (float)y; + return 1; + } + } + return 0; +} + static int asf_init_audio_stream(demuxer_t *demuxer,struct asf_priv* asf, sh_audio_t* sh_audio, ASF_stream_header_t *streamh, int *ppos, uint8_t** buf, char *hdr, unsigned int hdr_len) { uint8_t *buffer = *buf; @@ -336,6 +418,7 @@ case ASF_GUID_PREFIX_video_stream: { sh_video_t* sh_video=new_sh_video(demuxer,streamh->stream_no & 0x7F); unsigned int len=streamh->type_size-(4+4+1+2); + float asp_ratio; ++video_streams; // sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize); sh_video->bih=calloc((lenfps=1000.0f; sh_video->frametime=0.001f; } + if (get_meta(hdr, hdr_len, streamh->stream_no, &asp_ratio)) { + sh_video->aspect = asp_ratio * sh_video->bih->biWidth / + sh_video->bih->biHeight; + } if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V); //asf_video_id=streamh.stream_no & 0x7F;