00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdlib.h>
00026
00027 #include <vlc/vlc.h>
00028 #include <vlc/input.h>
00029
00030 #include "codecs.h"
00031 #include "libasf.h"
00032
00033 #define ASF_DEBUG 1
00034
00035 #define FREE( p ) \
00036 if( p ) {free( p ); p = NULL; }
00037
00038 #define GUID_FMT "0x%x-0x%x-0x%x-0x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x"
00039 #define GUID_PRINT( guid ) \
00040 (guid).v1, \
00041 (guid).v2, \
00042 (guid).v3, \
00043 (guid).v4[0],(guid).v4[1],(guid).v4[2],(guid).v4[3], \
00044 (guid).v4[4],(guid).v4[5],(guid).v4[6],(guid).v4[7]
00045
00046
00047
00048
00049 static int ASF_ReadObject( stream_t *, asf_object_t *, asf_object_t * );
00050
00051
00052
00053
00054 void ASF_GetGUID( guid_t *p_guid, uint8_t *p_data )
00055 {
00056 p_guid->v1 = GetDWLE( p_data );
00057 p_guid->v2 = GetWLE( p_data + 4);
00058 p_guid->v3 = GetWLE( p_data + 6);
00059 memcpy( p_guid->v4, p_data + 8, 8 );
00060 }
00061
00062 int ASF_CmpGUID( const guid_t *p_guid1, const guid_t *p_guid2 )
00063 {
00064 if( (p_guid1->v1 != p_guid2->v1 )||
00065 (p_guid1->v2 != p_guid2->v2 )||
00066 (p_guid1->v3 != p_guid2->v3 )||
00067 ( memcmp( p_guid1->v4, p_guid2->v4,8 )) )
00068 {
00069 return( 0 );
00070 }
00071 return( 1 );
00072 }
00073
00074
00075
00076
00077 static int ASF_ReadObjectCommon( stream_t *s, asf_object_t *p_obj )
00078 {
00079 asf_object_common_t *p_common = (asf_object_common_t*)p_obj;
00080 uint8_t *p_peek;
00081
00082 if( stream_Peek( s, &p_peek, 24 ) < 24 )
00083 {
00084 return( VLC_EGENERIC );
00085 }
00086 ASF_GetGUID( &p_common->i_object_id, p_peek );
00087 p_common->i_object_size = GetQWLE( p_peek + 16 );
00088 p_common->i_object_pos = stream_Tell( s );
00089 p_common->p_next = NULL;
00090
00091 #ifdef ASF_DEBUG
00092 msg_Dbg( s,
00093 "found object guid: " GUID_FMT " size:"I64Fd,
00094 GUID_PRINT( p_common->i_object_id ),
00095 p_common->i_object_size );
00096 #endif
00097
00098 return( VLC_SUCCESS );
00099 }
00100
00101 static int ASF_NextObject( stream_t *s, asf_object_t *p_obj )
00102 {
00103 asf_object_t obj;
00104 if( p_obj == NULL )
00105 {
00106 if( ASF_ReadObjectCommon( s, &obj ) )
00107 {
00108 return( VLC_EGENERIC );
00109 }
00110 p_obj = &obj;
00111 }
00112
00113 if( p_obj->common.i_object_size <= 0 )
00114 {
00115 return VLC_EGENERIC;
00116 }
00117 if( p_obj->common.p_father &&
00118 p_obj->common.p_father->common.i_object_size != 0 )
00119 {
00120 if( p_obj->common.p_father->common.i_object_pos +
00121 p_obj->common.p_father->common.i_object_size <
00122 p_obj->common.i_object_pos + p_obj->common.i_object_size + 24 )
00123
00124 {
00125 return VLC_EGENERIC;
00126 }
00127
00128 }
00129
00130 return stream_Seek( s, p_obj->common.i_object_pos +
00131 p_obj->common.i_object_size );
00132 }
00133
00134 static void ASF_FreeObject_Null( asf_object_t *pp_obj )
00135 {
00136 return;
00137 }
00138
00139 static int ASF_ReadObject_Header( stream_t *s, asf_object_t *p_obj )
00140 {
00141 asf_object_header_t *p_hdr = (asf_object_header_t*)p_obj;
00142 asf_object_t *p_subobj;
00143 int i_peek;
00144 uint8_t *p_peek;
00145
00146 if( ( i_peek = stream_Peek( s, &p_peek, 30 ) ) < 30 )
00147 {
00148 return( VLC_EGENERIC );
00149 }
00150
00151 p_hdr->i_sub_object_count = GetDWLE( p_peek + 24 );
00152 p_hdr->i_reserved1 = p_peek[28];
00153 p_hdr->i_reserved2 = p_peek[29];
00154 p_hdr->p_first = NULL;
00155 p_hdr->p_last = NULL;
00156
00157 #ifdef ASF_DEBUG
00158 msg_Dbg( s,
00159 "read \"header object\" subobj:%d, reserved1:%d, reserved2:%d",
00160 p_hdr->i_sub_object_count,
00161 p_hdr->i_reserved1,
00162 p_hdr->i_reserved2 );
00163 #endif
00164
00165
00166 stream_Read( s, NULL, 30 );
00167
00168
00169 for( ; ; )
00170 {
00171 p_subobj = malloc( sizeof( asf_object_t ) );
00172
00173 if( ASF_ReadObject( s, p_subobj, (asf_object_t*)p_hdr ) )
00174 {
00175 free( p_subobj );
00176 break;
00177 }
00178 if( ASF_NextObject( s, p_subobj ) )
00179 {
00180 break;
00181 }
00182 }
00183 return VLC_SUCCESS;
00184 }
00185
00186 static int ASF_ReadObject_Data( stream_t *s, asf_object_t *p_obj )
00187 {
00188 asf_object_data_t *p_data = (asf_object_data_t*)p_obj;
00189 int i_peek;
00190 uint8_t *p_peek;
00191
00192 if( ( i_peek = stream_Peek( s, &p_peek, 50 ) ) < 50 )
00193 {
00194 return VLC_EGENERIC;
00195 }
00196 ASF_GetGUID( &p_data->i_file_id, p_peek + 24 );
00197 p_data->i_total_data_packets = GetQWLE( p_peek + 40 );
00198 p_data->i_reserved = GetWLE( p_peek + 48 );
00199
00200 #ifdef ASF_DEBUG
00201 msg_Dbg( s,
00202 "read \"data object\" file_id:" GUID_FMT " total data packet:"
00203 I64Fd" reserved:%d",
00204 GUID_PRINT( p_data->i_file_id ),
00205 p_data->i_total_data_packets,
00206 p_data->i_reserved );
00207 #endif
00208
00209 return VLC_SUCCESS;
00210 }
00211
00212 static int ASF_ReadObject_Index( stream_t *s, asf_object_t *p_obj )
00213 {
00214 asf_object_index_t *p_index = (asf_object_index_t*)p_obj;
00215 int i_peek;
00216 uint8_t *p_peek;
00217
00218 if( ( i_peek = stream_Peek( s, &p_peek, 56 ) ) < 56 )
00219 {
00220 return VLC_EGENERIC;
00221 }
00222 ASF_GetGUID( &p_index->i_file_id, p_peek + 24 );
00223 p_index->i_index_entry_time_interval = GetQWLE( p_peek + 40 );
00224 p_index->i_max_packet_count = GetDWLE( p_peek + 48 );
00225 p_index->i_index_entry_count = GetDWLE( p_peek + 52 );
00226 p_index->index_entry = NULL;
00227
00228 #ifdef ASF_DEBUG
00229 msg_Dbg( s,
00230 "read \"index object\" file_id:" GUID_FMT
00231 " index_entry_time_interval:"I64Fd" max_packet_count:%d "
00232 "index_entry_count:%ld",
00233 GUID_PRINT( p_index->i_file_id ),
00234 p_index->i_index_entry_time_interval,
00235 p_index->i_max_packet_count,
00236 (long int)p_index->i_index_entry_count );
00237 #endif
00238
00239 return VLC_SUCCESS;
00240 }
00241
00242 static void ASF_FreeObject_Index( asf_object_t *p_obj )
00243 {
00244 asf_object_index_t *p_index = (asf_object_index_t*)p_obj;
00245
00246 FREE( p_index->index_entry );
00247 }
00248
00249 static int ASF_ReadObject_file_properties( stream_t *s, asf_object_t *p_obj )
00250 {
00251 asf_object_file_properties_t *p_fp = (asf_object_file_properties_t*)p_obj;
00252 int i_peek;
00253 uint8_t *p_peek;
00254
00255 if( ( i_peek = stream_Peek( s, &p_peek, 92) ) < 92 )
00256 {
00257 return VLC_EGENERIC;
00258 }
00259 ASF_GetGUID( &p_fp->i_file_id, p_peek + 24 );
00260 p_fp->i_file_size = GetQWLE( p_peek + 40 );
00261 p_fp->i_creation_date = GetQWLE( p_peek + 48 );
00262 p_fp->i_data_packets_count = GetQWLE( p_peek + 56 );
00263 p_fp->i_play_duration = GetQWLE( p_peek + 64 );
00264 p_fp->i_send_duration = GetQWLE( p_peek + 72 );
00265 p_fp->i_preroll = GetQWLE( p_peek + 80 );
00266 p_fp->i_flags = GetDWLE( p_peek + 88 );
00267 p_fp->i_min_data_packet_size = GetDWLE( p_peek + 92 );
00268 p_fp->i_max_data_packet_size = GetDWLE( p_peek + 96 );
00269 p_fp->i_max_bitrate = GetDWLE( p_peek + 100 );
00270
00271 #ifdef ASF_DEBUG
00272 msg_Dbg( s,
00273 "read \"file properties object\" file_id:" GUID_FMT
00274 " file_size:"I64Fd" creation_date:"I64Fd" data_packets_count:"
00275 I64Fd" play_duration:"I64Fd" send_duration:"I64Fd" preroll:"
00276 I64Fd" flags:%d min_data_packet_size:%d max_data_packet_size:%d "
00277 "max_bitrate:%d",
00278 GUID_PRINT( p_fp->i_file_id ), p_fp->i_file_size,
00279 p_fp->i_creation_date, p_fp->i_data_packets_count,
00280 p_fp->i_play_duration, p_fp->i_send_duration,
00281 p_fp->i_preroll, p_fp->i_flags,
00282 p_fp->i_min_data_packet_size, p_fp->i_max_data_packet_size,
00283 p_fp->i_max_bitrate );
00284 #endif
00285
00286 return VLC_SUCCESS;
00287 }
00288
00289 static void ASF_FreeObject_metadata( asf_object_t *p_obj )
00290 {
00291 asf_object_metadata_t *p_meta =
00292 (asf_object_metadata_t *)p_obj;
00293 unsigned int i;
00294
00295 for( i = 0; i < p_meta->i_record_entries_count; i++ )
00296 {
00297 if( p_meta->record[i].psz_name ) free( p_meta->record[i].psz_name );
00298 if( p_meta->record[i].p_data ) free( p_meta->record[i].p_data );
00299 }
00300 if( p_meta->record ) free( p_meta->record );
00301 }
00302
00303 static int ASF_ReadObject_metadata( stream_t *s, asf_object_t *p_obj )
00304 {
00305 asf_object_metadata_t *p_meta =
00306 (asf_object_metadata_t *)p_obj;
00307
00308 int i_peek, i_entries, i;
00309 uint8_t *p_peek;
00310 #ifdef ASF_DEBUG
00311 unsigned int j;
00312 #endif
00313
00314 p_meta->i_record_entries_count = 0;
00315 p_meta->record = 0;
00316
00317 if( stream_Peek( s, &p_peek, p_meta->i_object_size ) <
00318 (int)p_meta->i_object_size )
00319 {
00320 return VLC_EGENERIC;
00321 }
00322
00323 i_peek = 24;
00324 i_entries = GetWLE( p_peek + i_peek ); i_peek += 2;
00325 for( i = 0; i < i_entries && i_peek < (int)p_meta->i_object_size -12; i++ )
00326 {
00327 asf_metadata_record_t record;
00328 int i_name, i_data, j;
00329
00330 if( GetWLE( p_peek + i_peek ) != 0 )
00331 {
00332 ASF_FreeObject_metadata( p_obj );
00333 return VLC_EGENERIC;
00334 }
00335
00336 i_peek += 2;
00337 record.i_stream = GetWLE( p_peek + i_peek ); i_peek += 2;
00338 i_name = GetWLE( p_peek + i_peek ); i_peek += 2;
00339 record.i_type = GetWLE( p_peek + i_peek ); i_peek += 2;
00340 i_data = GetDWLE( p_peek + i_peek ); i_peek += 4;
00341
00342 if( record.i_type > ASF_METADATA_TYPE_WORD ||
00343 i_peek + i_data + i_name > (int)p_meta->i_object_size )
00344 {
00345 ASF_FreeObject_metadata( p_obj );
00346 return VLC_EGENERIC;
00347 }
00348
00349 record.i_val = 0;
00350 record.i_data = 0;
00351 record.p_data = 0;
00352
00353
00354 record.psz_name = malloc( i_name/2 + 1 );
00355 for( j = 0; j < i_name/2; j++ )
00356 {
00357 record.psz_name[j] = GetWLE( p_peek + i_peek ); i_peek += 2;
00358 }
00359 record.psz_name[j] = 0;
00360
00361
00362 if( record.i_type == ASF_METADATA_TYPE_STRING )
00363 {
00364 record.p_data = malloc( i_data/2 + 1 );
00365 record.i_data = i_data/2;
00366 for( j = 0; j < i_data/2; j++ )
00367 {
00368 record.p_data[j] = GetWLE( p_peek + i_peek ); i_peek += 2;
00369 }
00370 record.p_data[j] = 0;
00371 }
00372 else if( record.i_type == ASF_METADATA_TYPE_BYTE )
00373 {
00374 record.p_data = malloc( i_data );
00375 record.i_data = i_data;
00376 memcpy( record.p_data, p_peek + i_peek, i_data );
00377 p_peek += i_data;
00378 }
00379 else
00380 {
00381 if( record.i_type == ASF_METADATA_TYPE_QWORD )
00382 {
00383 record.i_val = GetQWLE( p_peek + i_peek ); i_peek += 8;
00384 }
00385 else if( record.i_type == ASF_METADATA_TYPE_DWORD )
00386 {
00387 record.i_val = GetDWLE( p_peek + i_peek ); i_peek += 4;
00388 }
00389 else
00390 {
00391 record.i_val = GetWLE( p_peek + i_peek ); i_peek += 2;
00392 }
00393 }
00394
00395 p_meta->i_record_entries_count++;
00396 p_meta->record =
00397 realloc( p_meta->record, p_meta->i_record_entries_count *
00398 sizeof(asf_metadata_record_t) );
00399 memcpy( &p_meta->record[p_meta->i_record_entries_count-1],
00400 &record, sizeof(asf_metadata_record_t) );
00401 }
00402
00403 #ifdef ASF_DEBUG
00404 msg_Dbg( s,
00405 "read \"metadata object\" %d entries",
00406 p_meta->i_record_entries_count );
00407 for( j = 0; j < p_meta->i_record_entries_count; j++ )
00408 {
00409 asf_metadata_record_t *p_rec = &p_meta->record[j];
00410
00411 if( p_rec->i_type == ASF_METADATA_TYPE_STRING )
00412 msg_Dbg( s, " - %s=%s",
00413 p_rec->psz_name, p_rec->p_data );
00414 else if( p_rec->i_type == ASF_METADATA_TYPE_BYTE )
00415 msg_Dbg( s, " - %s (%i bytes)",
00416 p_rec->psz_name, p_rec->i_data );
00417 else
00418 msg_Dbg( s, " - %s="I64Fd,
00419 p_rec->psz_name, p_rec->i_val );
00420 }
00421 #endif
00422
00423 return VLC_SUCCESS;
00424 }
00425
00426 static int ASF_ReadObject_header_extension( stream_t *s, asf_object_t *p_obj )
00427 {
00428 asf_object_header_extension_t *p_he =
00429 (asf_object_header_extension_t *)p_obj;
00430 int i_peek;
00431 uint8_t *p_peek;
00432
00433 if( ( i_peek = stream_Peek( s, &p_peek, p_he->i_object_size ) ) < 46)
00434 {
00435 return VLC_EGENERIC;
00436 }
00437 ASF_GetGUID( &p_he->i_reserved1, p_peek + 24 );
00438 p_he->i_reserved2 = GetWLE( p_peek + 40 );
00439 p_he->i_header_extension_size = GetDWLE( p_peek + 42 );
00440 if( p_he->i_header_extension_size )
00441 {
00442 p_he->p_header_extension_data =
00443 malloc( p_he->i_header_extension_size );
00444 memcpy( p_he->p_header_extension_data, p_peek + 46,
00445 p_he->i_header_extension_size );
00446 }
00447 else
00448 {
00449 p_he->p_header_extension_data = NULL;
00450 }
00451
00452 #ifdef ASF_DEBUG
00453 msg_Dbg( s,
00454 "read \"header extension object\" reserved1:" GUID_FMT
00455 " reserved2:%d header_extension_size:%d",
00456 GUID_PRINT( p_he->i_reserved1 ), p_he->i_reserved2,
00457 p_he->i_header_extension_size );
00458 #endif
00459
00460 if( !p_he->i_header_extension_size ) return VLC_SUCCESS;
00461
00462
00463 stream_Read( s, NULL, 46 );
00464 for( ; ; )
00465 {
00466 asf_object_t *p_obj = malloc( sizeof( asf_object_t ) );
00467
00468 if( ASF_ReadObject( s, p_obj, (asf_object_t*)p_he ) )
00469 {
00470 free( p_obj );
00471 break;
00472 }
00473
00474 if( ASF_NextObject( s, p_obj ) )
00475 {
00476 break;
00477 }
00478 }
00479
00480 return VLC_SUCCESS;
00481 }
00482
00483 static void ASF_FreeObject_header_extension( asf_object_t *p_obj )
00484 {
00485 asf_object_header_extension_t *p_he =
00486 (asf_object_header_extension_t *)p_obj;
00487
00488 FREE( p_he->p_header_extension_data );
00489 }
00490
00491 static int ASF_ReadObject_stream_properties( stream_t *s, asf_object_t *p_obj )
00492 {
00493 asf_object_stream_properties_t *p_sp =
00494 (asf_object_stream_properties_t*)p_obj;
00495 int i_peek;
00496 uint8_t *p_peek;
00497
00498 if( ( i_peek = stream_Peek( s, &p_peek, p_sp->i_object_size ) ) < 74 )
00499 {
00500 return VLC_EGENERIC;
00501 }
00502 ASF_GetGUID( &p_sp->i_stream_type, p_peek + 24 );
00503 ASF_GetGUID( &p_sp->i_error_correction_type, p_peek + 40 );
00504 p_sp->i_time_offset = GetQWLE( p_peek + 56 );
00505 p_sp->i_type_specific_data_length = GetDWLE( p_peek + 64 );
00506 p_sp->i_error_correction_data_length = GetDWLE( p_peek + 68 );
00507 p_sp->i_flags = GetWLE( p_peek + 72 );
00508 p_sp->i_stream_number = p_sp->i_flags&0x07f;
00509 p_sp->i_reserved = GetDWLE( p_peek + 74 );
00510 if( p_sp->i_type_specific_data_length )
00511 {
00512 p_sp->p_type_specific_data =
00513 malloc( p_sp->i_type_specific_data_length );
00514 memcpy( p_sp->p_type_specific_data, p_peek + 78,
00515 p_sp->i_type_specific_data_length );
00516 }
00517 else
00518 {
00519 p_sp->p_type_specific_data = NULL;
00520 }
00521 if( p_sp->i_error_correction_data_length )
00522 {
00523 p_sp->p_error_correction_data =
00524 malloc( p_sp->i_error_correction_data_length );
00525 memcpy( p_sp->p_error_correction_data,
00526 p_peek + 78 + p_sp->i_type_specific_data_length,
00527 p_sp->i_error_correction_data_length );
00528 }
00529 else
00530 {
00531 p_sp->p_error_correction_data = NULL;
00532 }
00533
00534 #ifdef ASF_DEBUG
00535 msg_Dbg( s,
00536 "read \"stream Properties object\" stream_type:" GUID_FMT
00537 " error_correction_type:" GUID_FMT " time_offset:"I64Fd
00538 " type_specific_data_length:%d error_correction_data_length:%d"
00539 " flags:0x%x stream_number:%d",
00540 GUID_PRINT( p_sp->i_stream_type ),
00541 GUID_PRINT( p_sp->i_error_correction_type ),
00542 p_sp->i_time_offset,
00543 p_sp->i_type_specific_data_length,
00544 p_sp->i_error_correction_data_length,
00545 p_sp->i_flags,
00546 p_sp->i_stream_number );
00547
00548 #endif
00549 return VLC_SUCCESS;
00550 }
00551
00552 static void ASF_FreeObject_stream_properties( asf_object_t *p_obj )
00553 {
00554 asf_object_stream_properties_t *p_sp =
00555 (asf_object_stream_properties_t*)p_obj;
00556
00557 FREE( p_sp->p_type_specific_data );
00558 FREE( p_sp->p_error_correction_data );
00559 }
00560
00561
00562 static int ASF_ReadObject_codec_list( stream_t *s, asf_object_t *p_obj )
00563 {
00564 asf_object_codec_list_t *p_cl = (asf_object_codec_list_t*)p_obj;
00565 int i_peek;
00566 uint8_t *p_peek, *p_data;
00567
00568 unsigned int i_codec;
00569
00570 if( ( i_peek = stream_Peek( s, &p_peek, p_cl->i_object_size ) ) < 44 )
00571 {
00572 return VLC_EGENERIC;
00573 }
00574
00575 ASF_GetGUID( &p_cl->i_reserved, p_peek + 24 );
00576 p_cl->i_codec_entries_count = GetWLE( p_peek + 40 );
00577 if( p_cl->i_codec_entries_count > 0 )
00578 {
00579 p_cl->codec = calloc( p_cl->i_codec_entries_count,
00580 sizeof( asf_codec_entry_t ) );
00581 memset( p_cl->codec, 0,
00582 p_cl->i_codec_entries_count * sizeof( asf_codec_entry_t ) );
00583
00584 p_data = p_peek + 44;
00585 for( i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
00586 {
00587 #define codec p_cl->codec[i_codec]
00588 int i_len, i;
00589
00590 codec.i_type = GetWLE( p_data ); p_data += 2;
00591
00592 i_len = GetWLE( p_data ); p_data += 2;
00593 codec.psz_name = calloc( sizeof( char ), i_len + 1);
00594 for( i = 0; i < i_len; i++ )
00595 {
00596 codec.psz_name[i] = GetWLE( p_data + 2*i );
00597 }
00598 codec.psz_name[i_len] = '\0';
00599 p_data += 2 * i_len;
00600
00601
00602 i_len = GetWLE( p_data ); p_data += 2;
00603 codec.psz_description = calloc( sizeof( char ), i_len + 1);
00604 for( i = 0; i < i_len; i++ )
00605 {
00606 codec.psz_description[i] = GetWLE( p_data + 2*i );
00607 }
00608 codec.psz_description[i_len] = '\0';
00609 p_data += 2 * i_len;
00610
00611
00612 codec.i_information_length = GetWLE( p_data ); p_data += 2;
00613 if( codec.i_information_length > 0 )
00614 {
00615 codec.p_information = malloc( codec.i_information_length );
00616 memcpy( codec.p_information, p_data, codec.i_information_length );
00617 p_data += codec.i_information_length;
00618 }
00619 else
00620 {
00621 codec.p_information = NULL;
00622 }
00623 #undef codec
00624 }
00625 }
00626 else
00627 {
00628 p_cl->codec = NULL;
00629 }
00630
00631 #ifdef ASF_DEBUG
00632 msg_Dbg( s, "read \"codec list object\" reserved_guid:" GUID_FMT
00633 " codec_entries_count:%d",
00634 GUID_PRINT( p_cl->i_reserved ), p_cl->i_codec_entries_count );
00635
00636 for( i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
00637 {
00638 #define codec p_cl->codec[i_codec]
00639 msg_Dbg( s, " - codec[%d] %s name:\"%s\" "
00640 "description:\"%s\" information_length:%d",
00641 i_codec, ( codec.i_type == ASF_CODEC_TYPE_VIDEO ) ?
00642 "video" : ( ( codec.i_type == ASF_CODEC_TYPE_AUDIO ) ?
00643 "audio" : "unknown" ),
00644 codec.psz_name, codec.psz_description,
00645 codec.i_information_length );
00646 #undef codec
00647 }
00648 #endif
00649
00650 return VLC_SUCCESS;
00651 }
00652
00653 static void ASF_FreeObject_codec_list( asf_object_t *p_obj )
00654 {
00655 asf_object_codec_list_t *p_cl = (asf_object_codec_list_t*)p_obj;
00656 unsigned int i_codec;
00657
00658 for( i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
00659 {
00660 #define codec p_cl->codec[i_codec]
00661 FREE( codec.psz_name );
00662 FREE( codec.psz_description );
00663 FREE( codec.p_information );
00664 #undef codec
00665 }
00666 FREE( p_cl->codec );
00667 }
00668
00669
00670
00671 static int ASF_ReadObject_content_description(stream_t *s, asf_object_t *p_obj)
00672 {
00673 asf_object_content_description_t *p_cd =
00674 (asf_object_content_description_t *)p_obj;
00675 uint8_t *p_peek, *p_data;
00676 int i_peek;
00677 int i_len, i_title, i_author, i_copyright, i_description, i_rating;
00678
00679 #define GETSTRINGW( psz_str, i_size ) \
00680 psz_str = calloc( i_size/2 + 1, sizeof( char ) ); \
00681 for( i_len = 0; i_len < i_size/2; i_len++ ) \
00682 { \
00683 psz_str[i_len] = GetWLE( p_data + 2*i_len ); \
00684 } \
00685 psz_str[i_size/2] = '\0'; \
00686 p_data += i_size;
00687
00688 if( ( i_peek = stream_Peek( s, &p_peek, p_cd->i_object_size ) ) < 34 )
00689 {
00690 return VLC_EGENERIC;
00691 }
00692 p_data = p_peek + 24;
00693
00694 i_title = GetWLE( p_data ); p_data += 2;
00695 i_author= GetWLE( p_data ); p_data += 2;
00696 i_copyright = GetWLE( p_data ); p_data += 2;
00697 i_description = GetWLE( p_data ); p_data += 2;
00698 i_rating = GetWLE( p_data ); p_data += 2;
00699
00700 GETSTRINGW( p_cd->psz_title, i_title );
00701 GETSTRINGW( p_cd->psz_author, i_author );
00702 GETSTRINGW( p_cd->psz_copyright, i_copyright );
00703 GETSTRINGW( p_cd->psz_description, i_description );
00704 GETSTRINGW( p_cd->psz_rating, i_rating );
00705
00706 #undef GETSTRINGW
00707
00708 #ifdef ASF_DEBUG
00709 msg_Dbg( s,
00710 "Read \"content description object\" title:\"%s\" author:\"%s\" copyright:\"%s\" description:\"%s\" rating:\"%s\"",
00711 p_cd->psz_title,
00712 p_cd->psz_author,
00713 p_cd->psz_copyright,
00714 p_cd->psz_description,
00715 p_cd->psz_rating );
00716 #endif
00717 return VLC_SUCCESS;
00718 }
00719
00720 static void ASF_FreeObject_content_description( asf_object_t *p_obj)
00721 {
00722 asf_object_content_description_t *p_cd =
00723 (asf_object_content_description_t *)p_obj;
00724
00725 FREE( p_cd->psz_title );
00726 FREE( p_cd->psz_author );
00727 FREE( p_cd->psz_copyright );
00728 FREE( p_cd->psz_description );
00729 FREE( p_cd->psz_rating );
00730 }
00731
00732
00733 static int ASF_ReadObject_language_list(stream_t *s, asf_object_t *p_obj)
00734 {
00735 asf_object_language_list_t *p_ll =
00736 (asf_object_language_list_t*)p_obj;
00737 uint8_t *p_peek, *p_data;
00738 int i_peek;
00739 int i;
00740
00741 if( ( i_peek = stream_Peek( s, &p_peek, p_ll->i_object_size ) ) < 26 )
00742 return VLC_EGENERIC;
00743
00744 p_data = &p_peek[24];
00745
00746 p_ll->i_language = GetWLE( &p_data[0] ); p_data += 2;
00747 if( p_ll->i_language > 0 )
00748 {
00749 p_ll->ppsz_language = calloc( p_ll->i_language, sizeof( char *) );
00750
00751 for( i = 0; i < p_ll->i_language; i++ )
00752 {
00753 char *psz;
00754 int i_size = *p_data++;
00755 int i_len;
00756
00757 psz = calloc( i_size/2 + 1, sizeof( char ) );
00758 for( i_len = 0; i_len < i_size/2; i_len++ )
00759 {
00760 psz[i_len] = GetWLE( p_data + 2*i_len );
00761 }
00762 psz[i_size/2] = '\0'; \
00763 p_data += i_size;
00764
00765 p_ll->ppsz_language[i] = psz;
00766 }
00767 }
00768
00769 #ifdef ASF_DEBUG
00770 msg_Dbg( s, "Read \"language list object\" %d entries",
00771 p_ll->i_language );
00772 for( i = 0; i < p_ll->i_language; i++ )
00773 msg_Dbg( s, " - '%s'",
00774 p_ll->ppsz_language[i] );
00775 #endif
00776 return VLC_SUCCESS;
00777 }
00778
00779 static void ASF_FreeObject_language_list( asf_object_t *p_obj)
00780 {
00781 asf_object_language_list_t *p_ll =
00782 (asf_object_language_list_t *)p_obj;
00783 int i;
00784
00785 for( i = 0; i < p_ll->i_language; i++ )
00786 FREE( p_ll->ppsz_language[i] );
00787 FREE( p_ll->ppsz_language );
00788 }
00789
00790
00791 static int ASF_ReadObject_stream_bitrate_properties( stream_t *s,
00792 asf_object_t *p_obj)
00793 {
00794 asf_object_stream_bitrate_properties_t *p_sb =
00795 (asf_object_stream_bitrate_properties_t *)p_obj;
00796 uint8_t *p_peek, *p_data;
00797 int i_peek;
00798 int i;
00799
00800 if( ( i_peek = stream_Peek( s, &p_peek, p_sb->i_object_size ) ) < 26 )
00801 return VLC_EGENERIC;
00802
00803 p_data = &p_peek[24];
00804
00805 p_sb->i_bitrate = GetWLE( &p_data[0] ); p_data += 2;
00806 if( p_sb->i_bitrate > 127 ) p_sb->i_bitrate = 127;
00807 for( i = 0; i < p_sb->i_bitrate; i++ )
00808 {
00809 p_sb->bitrate[i].i_stream_number = GetWLE( &p_data[0] )& 0x7f;
00810 p_sb->bitrate[i].i_avg_bitrate = GetDWLE( &p_data[2] );
00811
00812 p_data += 2+4;
00813 }
00814
00815 #ifdef ASF_DEBUG
00816 msg_Dbg( s,"Read \"stream bitrate properties object\"" );
00817 for( i = 0; i < p_sb->i_bitrate; i++ )
00818 {
00819 msg_Dbg( s," - stream=%d bitrate=%d",
00820 p_sb->bitrate[i].i_stream_number,
00821 p_sb->bitrate[i].i_avg_bitrate );
00822 }
00823 #endif
00824 return VLC_SUCCESS;
00825 }
00826 static void ASF_FreeObject_stream_bitrate_properties( asf_object_t *p_obj)
00827 {
00828 }
00829
00830 static int ASF_ReadObject_extended_stream_properties( stream_t *s,
00831 asf_object_t *p_obj)
00832 {
00833 asf_object_extended_stream_properties_t *p_esp =
00834 (asf_object_extended_stream_properties_t*)p_obj;
00835 uint8_t *p_peek, *p_data;
00836 int i_peek, i;
00837
00838 if( ( i_peek = stream_Peek( s, &p_peek, p_esp->i_object_size ) ) < 88 )
00839 return VLC_EGENERIC;
00840
00841 p_data = &p_peek[24];
00842
00843 p_esp->i_start_time = GetQWLE( &p_data[0] );
00844 p_esp->i_end_time = GetQWLE( &p_data[8] );
00845 p_esp->i_data_bitrate = GetDWLE( &p_data[16] );
00846 p_esp->i_buffer_size = GetDWLE( &p_data[20] );
00847 p_esp->i_initial_buffer_fullness = GetDWLE( &p_data[24] );
00848 p_esp->i_alternate_data_bitrate = GetDWLE( &p_data[28] );
00849 p_esp->i_alternate_buffer_size = GetDWLE( &p_data[32] );
00850 p_esp->i_alternate_initial_buffer_fullness = GetDWLE( &p_data[36] );
00851 p_esp->i_maximum_object_size = GetDWLE( &p_data[40] );
00852 p_esp->i_flags = GetDWLE( &p_data[44] );
00853 p_esp->i_stream_number = GetWLE( &p_data[48] );
00854 p_esp->i_language_index = GetWLE( &p_data[50] );
00855 p_esp->i_average_time_per_frame= GetQWLE( &p_data[52] );
00856 p_esp->i_stream_name_count = GetWLE( &p_data[60] );
00857 p_esp->i_payload_extention_system_count = GetWLE( &p_data[62] );
00858
00859 p_data += 64;
00860
00861 p_esp->pi_stream_name_language = calloc( sizeof(int),
00862 p_esp->i_stream_name_count );
00863 p_esp->ppsz_stream_name = calloc( sizeof(char*),
00864 p_esp->i_stream_name_count );
00865 for( i = 0; i < p_esp->i_stream_name_count; i++ )
00866 {
00867 int i_size;
00868 char *psz;
00869 int i_len;
00870
00871 p_esp->pi_stream_name_language[i] = GetWLE( &p_data[0] );
00872 i_size = GetWLE( &p_data[2] );
00873 p_data += 2;
00874
00875 psz = calloc( i_size/2 + 1, sizeof( char ) );
00876 for( i_len = 0; i_len < i_size/2; i_len++ )
00877 {
00878 psz[i_len] = GetWLE( p_data + 2*i_len );
00879 }
00880 psz[i_size/2] = '\0'; \
00881 p_data += i_size;
00882
00883 p_esp->ppsz_stream_name[i] = psz;
00884 }
00885
00886 for( i = 0; i < p_esp->i_payload_extention_system_count; i++ )
00887 {
00888
00889 int i_size = GetDWLE( &p_data[16 + 2] );
00890
00891 p_data += 16+2+4+i_size;
00892 }
00893
00894 p_esp->p_sp = NULL;
00895 if( p_data < &p_peek[i_peek] )
00896 {
00897 asf_object_t *p_sp;
00898
00899 stream_Read( s, NULL, p_data - p_peek );
00900
00901 p_sp = malloc( sizeof( asf_object_t ) );
00902
00903 if( ASF_ReadObject( s, p_sp, NULL ) )
00904 {
00905 free( p_sp );
00906 }
00907 else
00908 {
00909
00910 p_esp->p_sp = (asf_object_stream_properties_t*)p_sp;
00911 }
00912 }
00913
00914 #ifdef ASF_DEBUG
00915 msg_Dbg( s, "Read \"extended stream properties object\":" );
00916 msg_Dbg( s, " - start="I64Fd" end="I64Fd,
00917 p_esp->i_start_time, p_esp->i_end_time );
00918 msg_Dbg( s, " - data bitrate=%d buffer=%d initial fullness=%d",
00919 p_esp->i_data_bitrate,
00920 p_esp->i_buffer_size,
00921 p_esp->i_initial_buffer_fullness );
00922 msg_Dbg( s, " - alternate data bitrate=%d buffer=%d initial fullness=%d",
00923 p_esp->i_alternate_data_bitrate,
00924 p_esp->i_alternate_buffer_size,
00925 p_esp->i_alternate_initial_buffer_fullness );
00926 msg_Dbg( s, " - maximum object size=%d", p_esp->i_maximum_object_size );
00927 msg_Dbg( s, " - flags=0x%x", p_esp->i_flags );
00928 msg_Dbg( s, " - stream number=%d language=%d",
00929 p_esp->i_stream_number, p_esp->i_language_index );
00930 msg_Dbg( s, " - average time per frame="I64Fd,
00931 p_esp->i_average_time_per_frame );
00932 msg_Dbg( s, " - stream name count=%d", p_esp->i_stream_name_count );
00933 for( i = 0; i < p_esp->i_stream_name_count; i++ )
00934 msg_Dbg( s, " - lang id=%d name=%s",
00935 p_esp->pi_stream_name_language[i],
00936 p_esp->ppsz_stream_name[i] );
00937 msg_Dbg( s, " - payload extention system count=%d",
00938 p_esp->i_payload_extention_system_count );
00939 #endif
00940 return VLC_SUCCESS;
00941 }
00942 static void ASF_FreeObject_extended_stream_properties( asf_object_t *p_obj)
00943 {
00944 asf_object_extended_stream_properties_t *p_esp =
00945 (asf_object_extended_stream_properties_t *)p_obj;
00946 int i;
00947
00948 for( i = 0; i < p_esp->i_stream_name_count; i++ )
00949 FREE( p_esp->ppsz_stream_name[i] );
00950 FREE( p_esp->pi_stream_name_language );
00951 FREE( p_esp->ppsz_stream_name );
00952 }
00953
00954
00955 static int ASF_ReadObject_advanced_mutual_exclusion( stream_t *s,
00956 asf_object_t *p_obj)
00957 {
00958 asf_object_advanced_mutual_exclusion_t *p_ae =
00959 (asf_object_advanced_mutual_exclusion_t *)p_obj;
00960 uint8_t *p_peek, *p_data;
00961 int i_peek;
00962 int i;
00963
00964 if( ( i_peek = stream_Peek( s, &p_peek, p_ae->i_object_size ) ) < 42 )
00965 return VLC_EGENERIC;
00966
00967 p_data = &p_peek[24];
00968
00969 ASF_GetGUID( &p_ae->type, &p_data[0] );
00970 p_ae->i_stream_number_count = GetWLE( &p_data[16] );
00971
00972 p_data += 16 + 2;
00973 p_ae->pi_stream_number = calloc( sizeof(int),
00974 p_ae->i_stream_number_count );
00975 for( i = 0; i < p_ae->i_stream_number_count; i++ )
00976 {
00977 p_ae->pi_stream_number[i] = GetWLE( p_data );
00978 p_data += 2;
00979 }
00980
00981 #ifdef ASF_DEBUG
00982 msg_Dbg( s, "Read \"advanced mutual exclusion object\"" );
00983 for( i = 0; i < p_ae->i_stream_number_count; i++ )
00984 msg_Dbg( s, " - stream=%d", p_ae->pi_stream_number[i] );
00985 #endif
00986 return VLC_SUCCESS;
00987 }
00988 static void ASF_FreeObject_advanced_mutual_exclusion( asf_object_t *p_obj)
00989 {
00990 asf_object_advanced_mutual_exclusion_t *p_ae =
00991 (asf_object_advanced_mutual_exclusion_t *)p_obj;
00992
00993 FREE( p_ae->pi_stream_number );
00994 }
00995
00996
00997 static int ASF_ReadObject_stream_prioritization( stream_t *s,
00998 asf_object_t *p_obj)
00999 {
01000 asf_object_stream_prioritization_t *p_sp =
01001 (asf_object_stream_prioritization_t *)p_obj;
01002 uint8_t *p_peek, *p_data;
01003 int i_peek;
01004 int i;
01005
01006 if( ( i_peek = stream_Peek( s, &p_peek, p_sp->i_object_size ) ) < 26 )
01007 return VLC_EGENERIC;
01008
01009 p_data = &p_peek[24];
01010
01011 p_sp->i_priority_count = GetWLE( &p_data[0] );
01012 p_data += 2;
01013
01014 p_sp->pi_priority_flag = calloc( sizeof(int), p_sp->i_priority_count );
01015 p_sp->pi_priority_stream_number =
01016 calloc( sizeof(int), p_sp->i_priority_count );
01017
01018 for( i = 0; i < p_sp->i_priority_count; i++ )
01019 {
01020 p_sp->pi_priority_stream_number[i] = GetWLE( p_data ); p_data += 2;
01021 p_sp->pi_priority_flag[i] = GetWLE( p_data ); p_data += 2;
01022 }
01023 #ifdef ASF_DEBUG
01024 msg_Dbg( s, "Read \"stream prioritization object\"" );
01025 for( i = 0; i < p_sp->i_priority_count; i++ )
01026 msg_Dbg( s, " - Stream:%d flags=0x%x",
01027 p_sp->pi_priority_stream_number[i],
01028 p_sp->pi_priority_flag[i] );
01029 #endif
01030 return VLC_SUCCESS;
01031 }
01032 static void ASF_FreeObject_stream_prioritization( asf_object_t *p_obj)
01033 {
01034 asf_object_stream_prioritization_t *p_sp =
01035 (asf_object_stream_prioritization_t *)p_obj;
01036
01037 FREE( p_sp->pi_priority_stream_number );
01038 FREE( p_sp->pi_priority_flag );
01039 }
01040
01041
01042 static int ASF_ReadObject_extended_content_description( stream_t *s,
01043 asf_object_t *p_obj)
01044 {
01045 asf_object_extended_content_description_t *p_ec =
01046 (asf_object_extended_content_description_t *)p_obj;
01047 uint8_t *p_peek, *p_data;
01048 int i_peek;
01049 int i;
01050
01051 if( ( i_peek = stream_Peek( s, &p_peek, p_ec->i_object_size ) ) < 26 )
01052 return VLC_EGENERIC;
01053
01054 p_data = &p_peek[24];
01055
01056 p_ec->i_count = GetWLE( p_data ); p_data += 2;
01057 p_ec->ppsz_name = calloc( sizeof(char*), p_ec->i_count );
01058 p_ec->ppsz_value = calloc( sizeof(char*), p_ec->i_count );
01059 for( i = 0; i < p_ec->i_count; i++ )
01060 {
01061 int i_size;
01062 int i_type;
01063 int i_len;
01064 #define GETSTRINGW( psz_str, i_size ) \
01065 psz_str = calloc( i_size/2 + 1, sizeof( char ) ); \
01066 for( i_len = 0; i_len < i_size/2; i_len++ ) \
01067 { \
01068 psz_str[i_len] = GetWLE( p_data + 2*i_len ); \
01069 } \
01070 psz_str[i_size/2] = '\0';
01071
01072 i_size = GetWLE( p_data ); p_data += 2;
01073 GETSTRINGW( p_ec->ppsz_name[i], i_size );
01074 p_data += i_size;
01075
01076
01077 i_type = GetWLE( p_data ); p_data += 2;
01078 i_size = GetWLE( p_data ); p_data += 2;
01079 if( i_type == 0 )
01080 {
01081 GETSTRINGW( p_ec->ppsz_value[i], i_size );
01082 }
01083 else if( i_type == 1 )
01084 {
01085 int j;
01086
01087 p_ec->ppsz_value[i] = malloc( 2*i_size + 1 );
01088 for( j = 0; j < i_size; j++ )
01089 {
01090 static const char hex[16] = "0123456789ABCDEF";
01091 p_ec->ppsz_value[i][2*j+0] = hex[p_data[0]>>4];
01092 p_ec->ppsz_value[i][2*j+1] = hex[p_data[0]&0xf];
01093 }
01094 p_ec->ppsz_value[i][2*i_size] = '\0';
01095 }
01096 else if( i_type == 2 )
01097 {
01098
01099 p_ec->ppsz_value[i] = strdup( *p_data ? "true" : "false" );
01100 }
01101 else if( i_type == 3 )
01102 {
01103
01104 asprintf( &p_ec->ppsz_value[i], "%d", GetDWLE(p_data));
01105 }
01106 else if( i_type == 4 )
01107 {
01108
01109 asprintf( &p_ec->ppsz_value[i], I64Fd, GetQWLE(p_data));
01110 }
01111 else if( i_type == 5 )
01112 {
01113
01114 asprintf( &p_ec->ppsz_value[i], "%d", GetWLE(p_data));
01115 }
01116 else
01117 p_ec->ppsz_value[i] = NULL;
01118
01119 p_data += i_size;
01120
01121
01122
01123 #undef GETSTRINGW
01124
01125 }
01126
01127 #ifdef ASF_DEBUG
01128 msg_Dbg( s, "Read \"extended content description object\"" );
01129 for( i = 0; i < p_ec->i_count; i++ )
01130 msg_Dbg( s, " - '%s' = '%s'",
01131 p_ec->ppsz_name[i],
01132 p_ec->ppsz_value[i] );
01133 #endif
01134 return VLC_SUCCESS;
01135 }
01136 static void ASF_FreeObject_extended_content_description( asf_object_t *p_obj)
01137 {
01138 asf_object_extended_content_description_t *p_ec =
01139 (asf_object_extended_content_description_t *)p_obj;
01140 int i;
01141
01142 for( i = 0; i < p_ec->i_count; i++ )
01143 {
01144 FREE( p_ec->ppsz_name[i] );
01145 FREE( p_ec->ppsz_value[i] );
01146 }
01147 }
01148
01149
01150 #if 0
01151 static int ASF_ReadObject_XXX(stream_t *s, asf_object_t *p_obj)
01152 {
01153 asf_object_XXX_t *p_XX =
01154 (asf_object_XXX_t *)p_obj;
01155 uint8_t *p_peek, *p_data;
01156 int i_peek;
01157
01158 if( ( i_peek = stream_Peek( s, &p_peek, p_XX->i_object_size ) ) < XXX )
01159 return VLC_EGENERIC;
01160
01161 p_data = &p_peek[24];
01162
01163 #ifdef ASF_DEBUG
01164 msg_Dbg( s,
01165 "Read \"XXX object\"" );
01166 #endif
01167 return VLC_SUCCESS;
01168 }
01169 static void ASF_FreeObject_XXX( asf_object_t *p_obj)
01170 {
01171 asf_object_XXX_t *p_XX =
01172 (asf_object_XXX_t *)p_obj;
01173 }
01174 #endif
01175
01176
01177
01178 static struct
01179 {
01180 const guid_t *p_id;
01181 int i_type;
01182 int (*ASF_ReadObject_function)( stream_t *, asf_object_t *p_obj );
01183 void (*ASF_FreeObject_function)( asf_object_t *p_obj );
01184
01185 } ASF_Object_Function [] =
01186 {
01187 { &asf_object_header_guid, ASF_OBJECT_HEADER,
01188 ASF_ReadObject_Header, ASF_FreeObject_Null },
01189 { &asf_object_data_guid, ASF_OBJECT_DATA,
01190 ASF_ReadObject_Data, ASF_FreeObject_Null },
01191 { &asf_object_index_guid, ASF_OBJECT_INDEX,
01192 ASF_ReadObject_Index, ASF_FreeObject_Index },
01193 { &asf_object_file_properties_guid, ASF_OBJECT_FILE_PROPERTIES,
01194 ASF_ReadObject_file_properties, ASF_FreeObject_Null },
01195 { &asf_object_stream_properties_guid, ASF_OBJECT_STREAM_PROPERTIES,
01196 ASF_ReadObject_stream_properties,ASF_FreeObject_stream_properties },
01197 { &asf_object_header_extension_guid, ASF_OBJECT_HEADER_EXTENSION,
01198 ASF_ReadObject_header_extension, ASF_FreeObject_header_extension},
01199 { &asf_object_metadata_guid, ASF_OBJECT_METADATA,
01200 ASF_ReadObject_metadata, ASF_FreeObject_metadata},
01201 { &asf_object_codec_list_guid, ASF_OBJECT_CODEC_LIST,
01202 ASF_ReadObject_codec_list, ASF_FreeObject_codec_list },
01203 { &asf_object_marker_guid, ASF_OBJECT_MARKER, NULL, NULL },
01204 { &asf_object_padding, ASF_OBJECT_PADDING, NULL, NULL },
01205 { &asf_object_content_description_guid, ASF_OBJECT_CONTENT_DESCRIPTION,
01206 ASF_ReadObject_content_description, ASF_FreeObject_content_description },
01207 { &asf_object_language_list, ASF_OBJECT_OTHER,
01208 ASF_ReadObject_language_list, ASF_FreeObject_language_list },
01209 { &asf_object_stream_bitrate_properties, ASF_OBJECT_OTHER,
01210 ASF_ReadObject_stream_bitrate_properties,
01211 ASF_FreeObject_stream_bitrate_properties },
01212 { &asf_object_extended_stream_properties, ASF_OBJECT_OTHER,
01213 ASF_ReadObject_extended_stream_properties,
01214 ASF_FreeObject_extended_stream_properties },
01215 { &asf_object_advanced_mutual_exclusion, ASF_OBJECT_OTHER,
01216 ASF_ReadObject_advanced_mutual_exclusion,
01217 ASF_FreeObject_advanced_mutual_exclusion },
01218 { &asf_object_stream_prioritization, ASF_OBJECT_OTHER,
01219 ASF_ReadObject_stream_prioritization,
01220 ASF_FreeObject_stream_prioritization },
01221 { &asf_object_extended_content_description, ASF_OBJECT_OTHER,
01222 ASF_ReadObject_extended_content_description,
01223 ASF_FreeObject_extended_content_description },
01224
01225 { &asf_object_null_guid, 0, NULL, NULL }
01226 };
01227
01228 static int ASF_ReadObject( stream_t *s, asf_object_t *p_obj,
01229 asf_object_t *p_father )
01230 {
01231 int i_result;
01232 int i_index;
01233
01234 if( !p_obj )
01235 return( 0 );
01236
01237 memset( p_obj, 0, sizeof( p_obj ) );
01238
01239 if( ASF_ReadObjectCommon( s, p_obj ) )
01240 {
01241 msg_Warn( s, "cannot read one asf object" );
01242 return VLC_EGENERIC;
01243 }
01244 p_obj->common.p_father = p_father;
01245 p_obj->common.p_first = NULL;
01246 p_obj->common.p_next = NULL;
01247 p_obj->common.p_last = NULL;
01248
01249 if( p_obj->common.i_object_size < 24 )
01250 {
01251 msg_Warn( s, "found a corrupted asf object (size<24)" );
01252 return VLC_EGENERIC;
01253 }
01254
01255
01256 for( i_index = 0; ; i_index++ )
01257 {
01258 if( ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
01259 &p_obj->common.i_object_id ) ||
01260 ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
01261 &asf_object_null_guid ) )
01262 {
01263 break;
01264 }
01265 }
01266 p_obj->common.i_type = ASF_Object_Function[i_index].i_type;
01267
01268
01269 if( ASF_Object_Function[i_index].ASF_ReadObject_function == NULL )
01270 {
01271 msg_Warn( s, "unknown asf object (not loaded)" );
01272 i_result = VLC_SUCCESS;
01273 }
01274 else
01275 {
01276
01277 i_result =
01278 (ASF_Object_Function[i_index].ASF_ReadObject_function)( s, p_obj );
01279 }
01280
01281
01282 if( p_father )
01283 {
01284 if( p_father->common.p_first )
01285 {
01286 p_father->common.p_last->common.p_next = p_obj;
01287 }
01288 else
01289 {
01290 p_father->common.p_first = p_obj;
01291 }
01292 p_father->common.p_last = p_obj;
01293 }
01294
01295 return( i_result );
01296 }
01297
01298 static void ASF_FreeObject( stream_t *s, asf_object_t *p_obj )
01299 {
01300 int i_index;
01301 asf_object_t *p_child;
01302
01303 if( !p_obj ) return;
01304
01305
01306 p_child = p_obj->common.p_first;
01307 while( p_child )
01308 {
01309 asf_object_t *p_next;
01310 p_next = p_child->common.p_next;
01311 ASF_FreeObject( s, p_child );
01312 p_child = p_next;
01313 }
01314
01315
01316 for( i_index = 0; ; i_index++ )
01317 {
01318 if( ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
01319 &p_obj->common.i_object_id )||
01320 ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
01321 &asf_object_null_guid ) )
01322 {
01323 break;
01324 }
01325 }
01326
01327
01328 if( ASF_Object_Function[i_index].ASF_FreeObject_function == NULL )
01329 {
01330 msg_Warn( s,
01331 "unknown asf object " GUID_FMT,
01332 GUID_PRINT( p_obj->common.i_object_id ) );
01333 }
01334 else
01335 {
01336 #ifdef ASF_DEBUG
01337 msg_Dbg( s,
01338 "free asf object " GUID_FMT,
01339 GUID_PRINT( p_obj->common.i_object_id ) );
01340 #endif
01341 (ASF_Object_Function[i_index].ASF_FreeObject_function)( p_obj );
01342 }
01343 free( p_obj );
01344 return;
01345 }
01346
01347
01348
01349
01350 static const struct
01351 {
01352 const guid_t *p_id;
01353 char *psz_name;
01354 } ASF_ObjectDumpDebugInfo[] =
01355 {
01356 { &asf_object_header_guid, "Header" },
01357 { &asf_object_data_guid, "Data" },
01358 { &asf_object_index_guid, "Index" },
01359 { &asf_object_file_properties_guid, "File Properties" },
01360 { &asf_object_stream_properties_guid, "Stream Properties" },
01361 { &asf_object_content_description_guid, "Content Description" },
01362 { &asf_object_header_extension_guid, "Header Extention" },
01363 { &asf_object_metadata_guid, "Metadata" },
01364 { &asf_object_codec_list_guid, "Codec List" },
01365 { &asf_object_marker_guid, "Marker" },
01366 { &asf_object_stream_type_audio, "Stream Type Audio" },
01367 { &asf_object_stream_type_video, "Stream Type Video" },
01368 { &asf_object_stream_type_command, "Stream Type Command" },
01369 { &asf_object_language_list, "Language List" },
01370 { &asf_object_stream_bitrate_properties, "Stream Bitrate Propoerties" },
01371 { &asf_object_padding, "Padding" },
01372 { &asf_object_extended_stream_properties, "Extended Stream Properties" },
01373 { &asf_object_advanced_mutual_exclusion, "Advanced Mutual Exclusion" },
01374 { &asf_object_stream_prioritization, "Stream Prioritization" },
01375 { &asf_object_extended_content_description, "Extended content description"},
01376
01377 { NULL, "Unknown" },
01378 };
01379
01380
01381 static void ASF_ObjectDumpDebug( vlc_object_t *p_obj,
01382 asf_object_common_t *p_node, int i_level )
01383 {
01384 char str[1024];
01385 int i;
01386 union asf_object_u *p_child;
01387 char *psz_name;
01388
01389
01390 for( i = 0; ASF_ObjectDumpDebugInfo[i].p_id != NULL; i++ )
01391 {
01392 if( ASF_CmpGUID( ASF_ObjectDumpDebugInfo[i].p_id,
01393 &p_node->i_object_id ) )
01394 break;
01395 }
01396 psz_name = ASF_ObjectDumpDebugInfo[i].psz_name;
01397
01398 memset( str, ' ', sizeof( str ) );
01399 for( i = 1; i < i_level; i++ )
01400 {
01401 str[i * 5] = '|';
01402 }
01403 snprintf( str + 5*i_level, 1024,
01404 "+ '%s' GUID "GUID_FMT" size:"I64Fu"pos:"I64Fu,
01405 psz_name,
01406 GUID_PRINT( p_node->i_object_id ),
01407 p_node->i_object_size, p_node->i_object_pos );
01408
01409 msg_Dbg( p_obj, "%s", str );
01410
01411 for( p_child = p_node->p_first; p_child != NULL;
01412 p_child = p_child->common.p_next )
01413 {
01414 ASF_ObjectDumpDebug( p_obj, &p_child->common, i_level + 1 );
01415 }
01416 }
01417
01418
01419
01420
01421 asf_object_root_t *ASF_ReadObjectRoot( stream_t *s, int b_seekable )
01422 {
01423 asf_object_root_t *p_root = malloc( sizeof( asf_object_root_t ) );
01424 asf_object_t *p_obj;
01425
01426 p_root->i_type = ASF_OBJECT_ROOT;
01427 memcpy( &p_root->i_object_id, &asf_object_null_guid, sizeof( guid_t ) );
01428 p_root->i_object_pos = stream_Tell( s );
01429 p_root->i_object_size = 0;
01430 p_root->p_first = NULL;
01431 p_root->p_last = NULL;
01432 p_root->p_next = NULL;
01433 p_root->p_hdr = NULL;
01434 p_root->p_data = NULL;
01435 p_root->p_fp = NULL;
01436 p_root->p_index = NULL;
01437 p_root->p_metadata = NULL;
01438
01439 for( ; ; )
01440 {
01441 p_obj = malloc( sizeof( asf_object_t ) );
01442
01443 if( ASF_ReadObject( s, p_obj, (asf_object_t*)p_root ) )
01444 {
01445 free( p_obj );
01446 break;
01447 }
01448 switch( p_obj->common.i_type )
01449 {
01450 case( ASF_OBJECT_HEADER ):
01451 p_root->p_hdr = (asf_object_header_t*)p_obj;
01452 break;
01453 case( ASF_OBJECT_DATA ):
01454 p_root->p_data = (asf_object_data_t*)p_obj;
01455 break;
01456 case( ASF_OBJECT_INDEX ):
01457 p_root->p_index = (asf_object_index_t*)p_obj;
01458 break;
01459 default:
01460 msg_Warn( s, "unknow object found" );
01461 break;
01462 }
01463 if( p_obj->common.i_type == ASF_OBJECT_DATA &&
01464 p_obj->common.i_object_size <= 50 )
01465 {
01466
01467 break;
01468 }
01469 if( !b_seekable && p_root->p_hdr && p_root->p_data )
01470 {
01471
01472 break;
01473 }
01474
01475 if( ASF_NextObject( s, p_obj ) )
01476 {
01477 break;
01478 }
01479 }
01480
01481 if( p_root->p_hdr != NULL && p_root->p_data != NULL )
01482 {
01483 p_root->p_fp = ASF_FindObject( p_root->p_hdr,
01484 &asf_object_file_properties_guid, 0 );
01485
01486 if( p_root->p_fp )
01487 {
01488 asf_object_t *p_hdr_ext =
01489 ASF_FindObject( p_root->p_hdr,
01490 &asf_object_header_extension_guid, 0 );
01491 if( p_hdr_ext )
01492 {
01493 int i_ext_stream;
01494 int i;
01495
01496 p_root->p_metadata =
01497 ASF_FindObject( p_hdr_ext,
01498 &asf_object_metadata_guid, 0 );
01499
01500 i_ext_stream = ASF_CountObject( p_hdr_ext,
01501 &asf_object_extended_stream_properties );
01502 for( i = 0; i < i_ext_stream; i++ )
01503 {
01504 asf_object_t *p_esp =
01505 ASF_FindObject( p_hdr_ext,
01506 &asf_object_extended_stream_properties, i );
01507 if( p_esp->ext_stream.p_sp )
01508 {
01509 asf_object_t *p_sp =
01510 (asf_object_t*)p_esp->ext_stream.p_sp;
01511
01512
01513 p_root->p_hdr->p_last->common.p_next = p_sp;
01514 p_root->p_hdr->p_last = p_sp;
01515
01516 p_sp->common.p_father = (asf_object_t*)p_root->p_hdr;
01517 }
01518 }
01519 }
01520
01521 ASF_ObjectDumpDebug( VLC_OBJECT(s),
01522 (asf_object_common_t*)p_root, 0 );
01523 return p_root;
01524 }
01525 msg_Warn( s, "cannot find file properties object" );
01526 }
01527
01528
01529 ASF_FreeObjectRoot( s, p_root );
01530 return NULL;
01531 }
01532
01533 void ASF_FreeObjectRoot( stream_t *s, asf_object_root_t *p_root )
01534 {
01535 asf_object_t *p_obj;
01536
01537 p_obj = p_root->p_first;
01538 while( p_obj )
01539 {
01540 asf_object_t *p_next;
01541 p_next = p_obj->common.p_next;
01542 ASF_FreeObject( s, p_obj );
01543 p_obj = p_next;
01544 }
01545 free( p_root );
01546 }
01547
01548 int __ASF_CountObject( asf_object_t *p_obj, const guid_t *p_guid )
01549 {
01550 int i_count;
01551 asf_object_t *p_child;
01552
01553 if( !p_obj ) return( 0 );
01554
01555 i_count = 0;
01556 p_child = p_obj->common.p_first;
01557 while( p_child )
01558 {
01559 if( ASF_CmpGUID( &p_child->common.i_object_id, p_guid ) )
01560 {
01561 i_count++;
01562 }
01563 p_child = p_child->common.p_next;
01564 }
01565 return( i_count );
01566 }
01567
01568 void *__ASF_FindObject( asf_object_t *p_obj, const guid_t *p_guid,
01569 int i_number )
01570 {
01571 asf_object_t *p_child;
01572
01573 p_child = p_obj->common.p_first;
01574
01575 while( p_child )
01576 {
01577 if( ASF_CmpGUID( &p_child->common.i_object_id, p_guid ) )
01578 {
01579 if( i_number == 0 )
01580 {
01581
01582 return( p_child );
01583 }
01584
01585 i_number--;
01586 }
01587 p_child = p_child->common.p_next;
01588 }
01589 return( NULL );
01590 }