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
00026
00027 #include <stdlib.h>
00028
00029 #include <vlc/vlc.h>
00030 #include <vlc/input.h>
00031
00032 #include "vlc_meta.h"
00033
00034 #include "codecs.h"
00035 #include "libasf.h"
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 static int Open ( vlc_object_t * );
00046 static void Close ( vlc_object_t * );
00047
00048 vlc_module_begin();
00049 set_category( CAT_INPUT );
00050 set_subcategory( SUBCAT_INPUT_DEMUX );
00051 set_description( _("ASF v1.0 demuxer") );
00052 set_capability( "demux2", 200 );
00053 set_callbacks( Open, Close );
00054 add_shortcut( "asf" );
00055 vlc_module_end();
00056
00057
00058
00059
00060
00061 static int Demux ( demux_t * );
00062 static int Control( demux_t *, int i_query, va_list args );
00063
00064 typedef struct
00065 {
00066 int i_cat;
00067
00068 es_out_id_t *p_es;
00069
00070 asf_object_stream_properties_t *p_sp;
00071
00072 mtime_t i_time;
00073
00074 block_t *p_frame;
00075
00076 } asf_track_t;
00077
00078 struct demux_sys_t
00079 {
00080 mtime_t i_time;
00081 mtime_t i_length;
00082 int64_t i_bitrate;
00083
00084 asf_object_root_t *p_root;
00085 asf_object_file_properties_t *p_fp;
00086
00087 unsigned int i_track;
00088 asf_track_t *track[128];
00089
00090 int64_t i_data_begin;
00091 int64_t i_data_end;
00092
00093 vlc_meta_t *meta;
00094 };
00095
00096 static mtime_t GetMoviePTS( demux_sys_t * );
00097 static int DemuxInit( demux_t * );
00098 static void DemuxEnd( demux_t * );
00099 static int DemuxPacket( demux_t * );
00100
00101
00102
00103
00104 static int Open( vlc_object_t * p_this )
00105 {
00106 demux_t *p_demux = (demux_t *)p_this;
00107 demux_sys_t *p_sys;
00108 guid_t guid;
00109 uint8_t *p_peek;
00110
00111
00112 if( stream_Peek( p_demux->s, &p_peek, 16 ) < 16 ) return VLC_EGENERIC;
00113
00114 ASF_GetGUID( &guid, p_peek );
00115 if( !ASF_CmpGUID( &guid, &asf_object_header_guid ) ) return VLC_EGENERIC;
00116
00117
00118 p_demux->pf_demux = Demux;
00119 p_demux->pf_control = Control;
00120 p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
00121 memset( p_sys, 0, sizeof( demux_sys_t ) );
00122
00123
00124 if( DemuxInit( p_demux ) )
00125 {
00126 return VLC_EGENERIC;
00127 }
00128 return VLC_SUCCESS;
00129 }
00130
00131
00132
00133
00134
00135 static int Demux( demux_t *p_demux )
00136 {
00137 demux_sys_t *p_sys = p_demux->p_sys;
00138
00139 for( ;; )
00140 {
00141 uint8_t *p_peek;
00142 mtime_t i_length;
00143 mtime_t i_time_begin = GetMoviePTS( p_sys );
00144 int i_result;
00145
00146 if( p_demux->b_die )
00147 {
00148 break;
00149 }
00150
00151
00152 if( stream_Peek( p_demux->s, &p_peek, 16 ) == 16 )
00153 {
00154 guid_t guid;
00155
00156 ASF_GetGUID( &guid, p_peek );
00157 if( ASF_CmpGUID( &guid, &asf_object_header_guid ) )
00158 {
00159 msg_Warn( p_demux, "Found a new ASF header" );
00160
00161 DemuxEnd( p_demux );
00162
00163
00164 if( DemuxInit( p_demux ) )
00165 {
00166 msg_Err( p_demux, "failed to load the new header" );
00167 return 0;
00168 }
00169 continue;
00170 }
00171 }
00172
00173
00174 if( ( i_result = DemuxPacket( p_demux ) ) <= 0 )
00175 {
00176 return i_result;
00177 }
00178 if( i_time_begin == -1 )
00179 {
00180 i_time_begin = GetMoviePTS( p_sys );
00181 }
00182 else
00183 {
00184 i_length = GetMoviePTS( p_sys ) - i_time_begin;
00185 if( i_length < 0 || i_length >= 40 * 1000 )
00186 {
00187 break;
00188 }
00189 }
00190 }
00191
00192
00193 p_sys->i_time = GetMoviePTS( p_sys );
00194 if( p_sys->i_time >= 0 )
00195 {
00196 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time );
00197 }
00198
00199 return 1;
00200 }
00201
00202
00203
00204
00205 static void Close( vlc_object_t * p_this )
00206 {
00207 demux_t *p_demux = (demux_t *)p_this;
00208
00209 DemuxEnd( p_demux );
00210
00211 free( p_demux->p_sys );
00212 }
00213
00214
00215
00216
00217 static int Control( demux_t *p_demux, int i_query, va_list args )
00218 {
00219 demux_sys_t *p_sys = p_demux->p_sys;
00220 int64_t *pi64;
00221 int i;
00222 vlc_meta_t **pp_meta;
00223
00224 switch( i_query )
00225 {
00226 case DEMUX_SET_TIME:
00227 return VLC_EGENERIC;
00228
00229 case DEMUX_GET_LENGTH:
00230 pi64 = (int64_t*)va_arg( args, int64_t * );
00231 *pi64 = p_sys->i_length;
00232 return VLC_SUCCESS;
00233
00234 case DEMUX_GET_META:
00235 pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
00236 *pp_meta = vlc_meta_Duplicate( p_sys->meta );
00237 return VLC_SUCCESS;
00238
00239 case DEMUX_SET_POSITION:
00240 p_sys->i_time = -1;
00241 for( i = 0; i < 128 ; i++ )
00242 {
00243 asf_track_t *tk = p_sys->track[i];
00244 if( tk ) tk->i_time = -1;
00245 }
00246
00247 default:
00248 return demux2_vaControlHelper( p_demux->s,
00249 p_sys->i_data_begin, p_sys->i_data_end,
00250 p_sys->i_bitrate, p_sys->p_fp->i_min_data_packet_size,
00251 i_query, args );
00252 }
00253 }
00254
00255
00256
00257
00258 static mtime_t GetMoviePTS( demux_sys_t *p_sys )
00259 {
00260 mtime_t i_time;
00261 int i;
00262
00263 i_time = -1;
00264 for( i = 0; i < 128 ; i++ )
00265 {
00266 asf_track_t *tk = p_sys->track[i];
00267
00268 if( tk && tk->p_es && tk->i_time > 0)
00269 {
00270 if( i_time < 0 )
00271 {
00272 i_time = tk->i_time;
00273 }
00274 else
00275 {
00276 i_time = __MIN( i_time, tk->i_time );
00277 }
00278 }
00279 }
00280
00281 return i_time;
00282 }
00283
00284 #define GETVALUE2b( bits, var, def ) \
00285 switch( (bits)&0x03 ) \
00286 { \
00287 case 1: var = p_peek[i_skip]; i_skip++; break; \
00288 case 2: var = GetWLE( p_peek + i_skip ); i_skip+= 2; break; \
00289 case 3: var = GetDWLE( p_peek + i_skip ); i_skip+= 4; break; \
00290 case 0: \
00291 default: var = def; break;\
00292 }
00293
00294 static int DemuxPacket( demux_t *p_demux )
00295 {
00296 demux_sys_t *p_sys = p_demux->p_sys;
00297 int i_data_packet_min = p_sys->p_fp->i_min_data_packet_size;
00298 uint8_t *p_peek;
00299 int i_skip;
00300
00301 int i_packet_size_left;
00302 int i_packet_flags;
00303 int i_packet_property;
00304
00305 int b_packet_multiple_payload;
00306 int i_packet_length;
00307 int i_packet_sequence;
00308 int i_packet_padding_length;
00309
00310 uint32_t i_packet_send_time;
00311 uint16_t i_packet_duration;
00312 int i_payload;
00313 int i_payload_count;
00314 int i_payload_length_type;
00315
00316
00317 if( stream_Peek( p_demux->s, &p_peek,i_data_packet_min)<i_data_packet_min )
00318 {
00319 msg_Warn( p_demux, "cannot peek while getting new packet, EOF ?" );
00320 return 0;
00321 }
00322 i_skip = 0;
00323
00324
00325 if( p_peek[0]&0x80 )
00326 {
00327 unsigned int i_error_correction_length_type;
00328 unsigned int i_error_correction_data_length;
00329 unsigned int i_opaque_data_present;
00330
00331 i_error_correction_data_length = p_peek[0] & 0x0f;
00332 i_opaque_data_present = ( p_peek[0] >> 4 )& 0x01;
00333 i_error_correction_length_type = ( p_peek[0] >> 5 ) & 0x03;
00334 i_skip += 1;
00335
00336 if( i_error_correction_length_type != 0x00 ||
00337 i_opaque_data_present != 0 ||
00338 i_error_correction_data_length != 0x02 )
00339 {
00340 goto loop_error_recovery;
00341 }
00342
00343 i_skip += i_error_correction_data_length;
00344 }
00345 else
00346 {
00347 msg_Warn( p_demux, "p_peek[0]&0x80 != 0x80" );
00348 }
00349
00350
00351 if( i_skip + 2 >= i_data_packet_min )
00352 {
00353 goto loop_error_recovery;
00354 }
00355
00356 i_packet_flags = p_peek[i_skip]; i_skip++;
00357 i_packet_property = p_peek[i_skip]; i_skip++;
00358
00359 b_packet_multiple_payload = i_packet_flags&0x01;
00360
00361
00362 GETVALUE2b( i_packet_flags >> 5, i_packet_length, i_data_packet_min );
00363 GETVALUE2b( i_packet_flags >> 1, i_packet_sequence, 0 );
00364 GETVALUE2b( i_packet_flags >> 3, i_packet_padding_length, 0 );
00365
00366 i_packet_send_time = GetDWLE( p_peek + i_skip ); i_skip += 4;
00367 i_packet_duration = GetWLE( p_peek + i_skip ); i_skip += 2;
00368
00369
00370
00371 i_packet_size_left = i_data_packet_min;
00372
00373 if( b_packet_multiple_payload )
00374 {
00375 i_payload_count = p_peek[i_skip] & 0x3f;
00376 i_payload_length_type = ( p_peek[i_skip] >> 6 )&0x03;
00377 i_skip++;
00378 }
00379 else
00380 {
00381 i_payload_count = 1;
00382 i_payload_length_type = 0x02;
00383 }
00384
00385 for( i_payload = 0; i_payload < i_payload_count ; i_payload++ )
00386 {
00387 asf_track_t *tk;
00388
00389 int i_stream_number;
00390 int i_media_object_number;
00391 int i_media_object_offset;
00392 int i_replicated_data_length;
00393 int i_payload_data_length;
00394 int i_payload_data_pos;
00395 int i_sub_payload_data_length;
00396 int i_tmp;
00397
00398 mtime_t i_pts;
00399 mtime_t i_pts_delta;
00400
00401 if( i_skip >= i_packet_size_left )
00402 {
00403
00404 break;
00405 }
00406
00407 i_stream_number = p_peek[i_skip] & 0x7f;
00408 i_skip++;
00409
00410 GETVALUE2b( i_packet_property >> 4, i_media_object_number, 0 );
00411 GETVALUE2b( i_packet_property >> 2, i_tmp, 0 );
00412 GETVALUE2b( i_packet_property, i_replicated_data_length, 0 );
00413
00414 if( i_replicated_data_length > 1 )
00415 {
00416 i_pts = (mtime_t)GetDWLE( p_peek + i_skip + 4 ) * 1000;
00417 i_skip += i_replicated_data_length;
00418 i_pts_delta = 0;
00419
00420 i_media_object_offset = i_tmp;
00421
00422 if( i_skip >= i_packet_size_left )
00423 {
00424 break;
00425 }
00426 }
00427 else if( i_replicated_data_length == 1 )
00428 {
00429
00430
00431 i_pts = (mtime_t)i_tmp * 1000;
00432 i_pts_delta = (mtime_t)p_peek[i_skip] * 1000; i_skip++;
00433
00434 i_media_object_offset = 0;
00435 }
00436 else
00437 {
00438 i_pts = (mtime_t)i_packet_send_time * 1000;
00439 i_pts_delta = 0;
00440
00441 i_media_object_offset = i_tmp;
00442 }
00443
00444 i_pts = __MAX( i_pts - p_sys->p_fp->i_preroll * 1000, 0 );
00445 if( b_packet_multiple_payload )
00446 {
00447 GETVALUE2b( i_payload_length_type, i_payload_data_length, 0 );
00448 }
00449 else
00450 {
00451 i_payload_data_length = i_packet_length -
00452 i_packet_padding_length - i_skip;
00453 }
00454
00455 if( i_payload_data_length < 0 || i_skip + i_payload_data_length > i_packet_size_left )
00456 {
00457 break;
00458 }
00459 #if 0
00460 msg_Dbg( p_demux,
00461 "payload(%d/%d) stream_number:%d media_object_number:%d media_object_offset:%d replicated_data_length:%d payload_data_length %d",
00462 i_payload + 1, i_payload_count, i_stream_number, i_media_object_number,
00463 i_media_object_offset, i_replicated_data_length, i_payload_data_length );
00464 #endif
00465
00466 if( ( tk = p_sys->track[i_stream_number] ) == NULL )
00467 {
00468 msg_Warn( p_demux,
00469 "undeclared stream[Id 0x%x]", i_stream_number );
00470 i_skip += i_payload_data_length;
00471 continue;
00472 }
00473
00474 if( !tk->p_es )
00475 {
00476 i_skip += i_payload_data_length;
00477 continue;
00478 }
00479
00480
00481 for( i_payload_data_pos = 0;
00482 i_payload_data_pos < i_payload_data_length &&
00483 i_packet_size_left > 0;
00484 i_payload_data_pos += i_sub_payload_data_length )
00485 {
00486 block_t *p_frag;
00487 int i_read;
00488
00489
00490 if( i_replicated_data_length == 1 )
00491 {
00492 i_sub_payload_data_length = p_peek[i_skip]; i_skip++;
00493 i_payload_data_pos++;
00494 }
00495 else
00496 {
00497 i_sub_payload_data_length = i_payload_data_length;
00498 }
00499
00500
00501 if( tk->p_frame && i_media_object_offset == 0 )
00502 {
00503
00504 block_t *p_gather = block_ChainGather( tk->p_frame );
00505
00506 es_out_Send( p_demux->out, tk->p_es, p_gather );
00507
00508 tk->p_frame = NULL;
00509 }
00510
00511 i_read = i_sub_payload_data_length + i_skip;
00512 if( ( p_frag = stream_Block( p_demux->s, i_read ) ) == NULL )
00513 {
00514 msg_Warn( p_demux, "cannot read data" );
00515 return 0;
00516 }
00517 i_packet_size_left -= i_read;
00518
00519 p_frag->p_buffer += i_skip;
00520 p_frag->i_buffer -= i_skip;
00521
00522 if( tk->p_frame == NULL )
00523 {
00524 tk->i_time =
00525 ( (mtime_t)i_pts + i_payload * (mtime_t)i_pts_delta );
00526
00527 p_frag->i_pts = tk->i_time;
00528
00529 if( tk->i_cat != VIDEO_ES )
00530 p_frag->i_dts = p_frag->i_pts;
00531 else
00532 {
00533 p_frag->i_dts = p_frag->i_pts;
00534 p_frag->i_pts = 0;
00535 }
00536 }
00537
00538 block_ChainAppend( &tk->p_frame, p_frag );
00539
00540 i_skip = 0;
00541 if( i_packet_size_left > 0 )
00542 {
00543 if( stream_Peek( p_demux->s, &p_peek, i_packet_size_left )
00544 < i_packet_size_left )
00545 {
00546 msg_Warn( p_demux, "cannot peek, EOF ?" );
00547 return 0;
00548 }
00549 }
00550 }
00551 }
00552
00553 if( i_packet_size_left > 0 )
00554 {
00555 if( stream_Read( p_demux->s, NULL, i_packet_size_left )
00556 < i_packet_size_left )
00557 {
00558 msg_Warn( p_demux, "cannot skip data, EOF ?" );
00559 return 0;
00560 }
00561 }
00562
00563 return 1;
00564
00565 loop_error_recovery:
00566 msg_Warn( p_demux, "unsupported packet header" );
00567 if( p_sys->p_fp->i_min_data_packet_size != p_sys->p_fp->i_max_data_packet_size )
00568 {
00569 msg_Err( p_demux, "unsupported packet header, fatal error" );
00570 return -1;
00571 }
00572 stream_Read( p_demux->s, NULL, i_data_packet_min );
00573
00574 return 1;
00575 }
00576
00577
00578
00579
00580 static int DemuxInit( demux_t *p_demux )
00581 {
00582 demux_sys_t *p_sys = p_demux->p_sys;
00583 vlc_bool_t b_seekable;
00584 int i;
00585
00586 unsigned int i_stream;
00587 asf_object_content_description_t *p_cd;
00588
00589
00590 p_sys->i_time = -1;
00591 p_sys->i_length = 0;
00592 p_sys->i_bitrate = 0;
00593 p_sys->p_root = NULL;
00594 p_sys->p_fp = NULL;
00595 p_sys->i_track = 0;
00596 for( i = 0; i < 128; i++ )
00597 {
00598 p_sys->track[i] = NULL;
00599 }
00600 p_sys->i_data_begin = -1;
00601 p_sys->i_data_end = -1;
00602 p_sys->meta = NULL;
00603
00604
00605 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b_seekable );
00606 if( (p_sys->p_root = ASF_ReadObjectRoot( p_demux->s, b_seekable )) == NULL )
00607 {
00608 msg_Warn( p_demux, "ASF plugin discarded (not a valid file)" );
00609 return VLC_EGENERIC;
00610 }
00611 p_sys->p_fp = p_sys->p_root->p_fp;
00612
00613 if( p_sys->p_fp->i_min_data_packet_size != p_sys->p_fp->i_max_data_packet_size )
00614 {
00615 msg_Warn( p_demux, "ASF plugin discarded (invalid file_properties object)" );
00616 goto error;
00617 }
00618
00619 p_sys->i_track = ASF_CountObject( p_sys->p_root->p_hdr,
00620 &asf_object_stream_properties_guid );
00621 if( p_sys->i_track <= 0 )
00622 {
00623 msg_Warn( p_demux, "ASF plugin discarded (cannot find any stream!)" );
00624 goto error;
00625 }
00626
00627 msg_Dbg( p_demux, "found %d streams", p_sys->i_track );
00628
00629 for( i_stream = 0; i_stream < p_sys->i_track; i_stream ++ )
00630 {
00631 asf_track_t *tk;
00632 asf_object_stream_properties_t *p_sp;
00633 vlc_bool_t b_access_selected;
00634
00635 p_sp = ASF_FindObject( p_sys->p_root->p_hdr,
00636 &asf_object_stream_properties_guid,
00637 i_stream );
00638
00639 tk = p_sys->track[p_sp->i_stream_number] = malloc( sizeof( asf_track_t ) );
00640 memset( tk, 0, sizeof( asf_track_t ) );
00641
00642 tk->i_time = -1;
00643 tk->p_sp = p_sp;
00644 tk->p_es = NULL;
00645 tk->p_frame = NULL;
00646
00647
00648 if( !stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, ACCESS_GET_PRIVATE_ID_STATE,
00649 p_sp->i_stream_number, &b_access_selected ) &&
00650 !b_access_selected )
00651 {
00652 tk->i_cat = UNKNOWN_ES;
00653 msg_Dbg( p_demux, "ignoring not selected stream(ID:%d) (by access)",
00654 p_sp->i_stream_number );
00655 continue;
00656 }
00657
00658 if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_audio ) &&
00659 p_sp->i_type_specific_data_length >= sizeof( WAVEFORMATEX ) - 2 )
00660 {
00661 es_format_t fmt;
00662 uint8_t *p_data = p_sp->p_type_specific_data;
00663 int i_format;
00664
00665 es_format_Init( &fmt, AUDIO_ES, 0 );
00666 i_format = GetWLE( &p_data[0] );
00667 wf_tag_to_fourcc( i_format, &fmt.i_codec, NULL );
00668 fmt.audio.i_channels = GetWLE( &p_data[2] );
00669 fmt.audio.i_rate = GetDWLE( &p_data[4] );
00670 fmt.i_bitrate = GetDWLE( &p_data[8] ) * 8;
00671 fmt.audio.i_blockalign = GetWLE( &p_data[12] );
00672 fmt.audio.i_bitspersample = GetWLE( &p_data[14] );
00673
00674 if( p_sp->i_type_specific_data_length > sizeof( WAVEFORMATEX ) &&
00675 i_format != WAVE_FORMAT_MPEGLAYER3 &&
00676 i_format != WAVE_FORMAT_MPEG )
00677 {
00678 fmt.i_extra = __MIN( GetWLE( &p_data[16] ),
00679 p_sp->i_type_specific_data_length -
00680 sizeof( WAVEFORMATEX ) );
00681 fmt.p_extra = malloc( fmt.i_extra );
00682 memcpy( fmt.p_extra, &p_data[sizeof( WAVEFORMATEX )],
00683 fmt.i_extra );
00684 }
00685
00686 tk->i_cat = AUDIO_ES;
00687 tk->p_es = es_out_Add( p_demux->out, &fmt );
00688 es_format_Clean( &fmt );
00689
00690 msg_Dbg( p_demux, "added new audio stream(codec:0x%x,ID:%d)",
00691 GetWLE( p_data ), p_sp->i_stream_number );
00692 }
00693 else if( ASF_CmpGUID( &p_sp->i_stream_type,
00694 &asf_object_stream_type_video ) &&
00695 p_sp->i_type_specific_data_length >= 11 +
00696 sizeof( BITMAPINFOHEADER ) )
00697 {
00698 es_format_t fmt;
00699 uint8_t *p_data = &p_sp->p_type_specific_data[11];
00700
00701 es_format_Init( &fmt, VIDEO_ES,
00702 VLC_FOURCC( p_data[16], p_data[17],
00703 p_data[18], p_data[19] ) );
00704 fmt.video.i_width = GetDWLE( p_data + 4 );
00705 fmt.video.i_height= GetDWLE( p_data + 8 );
00706
00707 if( p_sp->i_type_specific_data_length > 11 +
00708 sizeof( BITMAPINFOHEADER ) )
00709 {
00710 fmt.i_extra = __MIN( GetDWLE( p_data ),
00711 p_sp->i_type_specific_data_length - 11 -
00712 sizeof( BITMAPINFOHEADER ) );
00713 fmt.p_extra = malloc( fmt.i_extra );
00714 memcpy( fmt.p_extra, &p_data[sizeof( BITMAPINFOHEADER )],
00715 fmt.i_extra );
00716 }
00717
00718
00719 if( p_sys->p_root->p_metadata )
00720 {
00721 asf_object_metadata_t *p_meta = p_sys->p_root->p_metadata;
00722 int i_aspect_x = 0, i_aspect_y = 0;
00723 unsigned int i;
00724
00725 for( i = 0; i < p_meta->i_record_entries_count; i++ )
00726 {
00727 if( !strcmp( p_meta->record[i].psz_name, "AspectRatioX" ) )
00728 {
00729 if( (!i_aspect_x && !p_meta->record[i].i_stream) ||
00730 p_meta->record[i].i_stream ==
00731 p_sp->i_stream_number )
00732 i_aspect_x = p_meta->record[i].i_val;
00733 }
00734 if( !strcmp( p_meta->record[i].psz_name, "AspectRatioY" ) )
00735 {
00736 if( (!i_aspect_y && !p_meta->record[i].i_stream) ||
00737 p_meta->record[i].i_stream ==
00738 p_sp->i_stream_number )
00739 i_aspect_y = p_meta->record[i].i_val;
00740 }
00741 }
00742
00743 if( i_aspect_x && i_aspect_y )
00744 {
00745 fmt.video.i_aspect = i_aspect_x *
00746 (int64_t)fmt.video.i_width * VOUT_ASPECT_FACTOR /
00747 fmt.video.i_height / i_aspect_y;
00748 }
00749 }
00750
00751 tk->i_cat = VIDEO_ES;
00752 tk->p_es = es_out_Add( p_demux->out, &fmt );
00753 es_format_Clean( &fmt );
00754
00755 msg_Dbg( p_demux, "added new video stream(ID:%d)",
00756 p_sp->i_stream_number );
00757 }
00758 else
00759 {
00760 tk->i_cat = UNKNOWN_ES;
00761 msg_Dbg( p_demux, "ignoring unknown stream(ID:%d)",
00762 p_sp->i_stream_number );
00763 }
00764 }
00765
00766 p_sys->i_data_begin = p_sys->p_root->p_data->i_object_pos + 50;
00767 if( p_sys->p_root->p_data->i_object_size != 0 )
00768 {
00769 p_sys->i_data_end = p_sys->p_root->p_data->i_object_pos +
00770 p_sys->p_root->p_data->i_object_size;
00771 }
00772 else
00773 {
00774 p_sys->i_data_end = -1;
00775 }
00776
00777
00778
00779 stream_Seek( p_demux->s, p_sys->i_data_begin );
00780
00781
00782 if( p_sys->p_fp->i_data_packets_count > 0 )
00783 {
00784 int64_t i_count;
00785 int64_t i_size = stream_Size( p_demux->s );
00786
00787 if( p_sys->i_data_end > 0 && i_size > p_sys->i_data_end )
00788 {
00789 i_size = p_sys->i_data_end;
00790 }
00791
00792
00793 i_count = ( i_size - p_sys->i_data_begin ) /
00794 p_sys->p_fp->i_min_data_packet_size;
00795
00796
00797 p_sys->i_length = (mtime_t)p_sys->p_fp->i_play_duration / 10 *
00798 (mtime_t)i_count /
00799 (mtime_t)p_sys->p_fp->i_data_packets_count;
00800
00801 if( p_sys->i_length > 0 )
00802 {
00803 p_sys->i_bitrate = 8 * i_size * (int64_t)1000000 / p_sys->i_length;
00804 }
00805 }
00806
00807
00808 p_sys->meta = vlc_meta_New();
00809
00810 if( ( p_cd = ASF_FindObject( p_sys->p_root->p_hdr,
00811 &asf_object_content_description_guid, 0 ) ) )
00812 {
00813 if( p_cd->psz_title && *p_cd->psz_title )
00814 {
00815 vlc_meta_Add( p_sys->meta, VLC_META_TITLE, p_cd->psz_title );
00816 }
00817 if( p_cd->psz_author && *p_cd->psz_author )
00818 {
00819 vlc_meta_Add( p_sys->meta, VLC_META_AUTHOR, p_cd->psz_author );
00820 }
00821 if( p_cd->psz_copyright && *p_cd->psz_copyright )
00822 {
00823 vlc_meta_Add( p_sys->meta, VLC_META_COPYRIGHT, p_cd->psz_copyright );
00824 }
00825 if( p_cd->psz_description && *p_cd->psz_description )
00826 {
00827 vlc_meta_Add( p_sys->meta, VLC_META_DESCRIPTION, p_cd->psz_description );
00828 }
00829 if( p_cd->psz_rating && *p_cd->psz_rating )
00830 {
00831 vlc_meta_Add( p_sys->meta, VLC_META_RATING, p_cd->psz_rating );
00832 }
00833 }
00834 for( i_stream = 0, i = 0; i < 128; i++ )
00835 {
00836 asf_object_codec_list_t *p_cl = ASF_FindObject( p_sys->p_root->p_hdr,
00837 &asf_object_codec_list_guid, 0 );
00838
00839 if( p_sys->track[i] )
00840 {
00841 vlc_meta_t *tk = vlc_meta_New();
00842 TAB_APPEND( p_sys->meta->i_track, p_sys->meta->track, tk );
00843
00844 if( p_cl && i_stream < p_cl->i_codec_entries_count )
00845 {
00846 if( p_cl->codec[i_stream].psz_name &&
00847 *p_cl->codec[i_stream].psz_name )
00848 {
00849 vlc_meta_Add( tk, VLC_META_CODEC_NAME,
00850 p_cl->codec[i_stream].psz_name );
00851 }
00852 if( p_cl->codec[i_stream].psz_description &&
00853 *p_cl->codec[i_stream].psz_description )
00854 {
00855 vlc_meta_Add( tk, VLC_META_CODEC_DESCRIPTION,
00856 p_cl->codec[i_stream].psz_description );
00857 }
00858 }
00859 i_stream++;
00860 }
00861 }
00862
00863 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
00864 return VLC_SUCCESS;
00865
00866 error:
00867 ASF_FreeObjectRoot( p_demux->s, p_sys->p_root );
00868 return VLC_EGENERIC;
00869 }
00870
00871
00872
00873 static void DemuxEnd( demux_t *p_demux )
00874 {
00875 demux_sys_t *p_sys = p_demux->p_sys;
00876 int i;
00877
00878 if( p_sys->p_root )
00879 {
00880 ASF_FreeObjectRoot( p_demux->s, p_sys->p_root );
00881 p_sys->p_root = NULL;
00882 }
00883 if( p_sys->meta )
00884 {
00885 vlc_meta_Delete( p_sys->meta );
00886 p_sys->meta = NULL;
00887 }
00888
00889 for( i = 0; i < 128; i++ )
00890 {
00891 asf_track_t *tk = p_sys->track[i];
00892
00893 if( tk )
00894 {
00895 if( tk->p_frame )
00896 {
00897 block_ChainRelease( tk->p_frame );
00898 }
00899 if( tk->p_es )
00900 {
00901 es_out_Del( p_demux->out, tk->p_es );
00902 }
00903 free( tk );
00904 }
00905 p_sys->track[i] = 0;
00906 }
00907 }
00908