X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fasf%2Fasf.c;h=e408296e25a703dc4e2934be5d96473489a49f5b;hb=8812a3c881e5a70068e2a5d74cc72b00b999a919;hp=18c293d3cae52e0d931594e2d7abfce877bb809e;hpb=52c18c4dec68158eedd655e0502820b7d7b6128f;p=vlc diff --git a/modules/demux/asf/asf.c b/modules/demux/asf/asf.c index 18c293d3ca..e408296e25 100644 --- a/modules/demux/asf/asf.c +++ b/modules/demux/asf/asf.c @@ -175,7 +175,7 @@ static int Demux( demux_t *p_demux ) if( DemuxInit( p_demux ) ) { msg_Err( p_demux, "failed to load the new header" ); - dialog_Fatal( p_demux, _("Could not demux ASF stream"), + dialog_Fatal( p_demux, _("Could not demux ASF stream"), "%s", _("VLC failed to load the ASF header.") ); return 0; } @@ -225,24 +225,38 @@ static void Close( vlc_object_t * p_this ) /***************************************************************************** * SeekIndex: goto to i_date or i_percent *****************************************************************************/ +static int SeekPercent( demux_t *p_demux, int i_query, va_list args ) +{ + demux_sys_t *p_sys = p_demux->p_sys; + return demux_vaControlHelper( p_demux->s, p_sys->i_data_begin, + p_sys->i_data_end, p_sys->i_bitrate, + p_sys->p_fp->i_min_data_packet_size, + i_query, args ); +} + static int SeekIndex( demux_t *p_demux, mtime_t i_date, float f_pos ) { demux_sys_t *p_sys = p_demux->p_sys; asf_object_index_t *p_index; - int64_t i_pos; msg_Dbg( p_demux, "seek with index: %i seconds, position %f", - (int)(i_date/1000000), f_pos ); + i_date >= 0 ? (int)(i_date/1000000) : -1, f_pos ); - p_index = ASF_FindObject( p_sys->p_root, &asf_object_index_guid, 0 ); + if( i_date < 0 ) + i_date = p_sys->i_length * f_pos; - if( i_date < 0 ) i_date = p_sys->i_length * f_pos; + p_index = ASF_FindObject( p_sys->p_root, &asf_object_index_guid, 0 ); - i_pos = i_date * 10 / p_index->i_index_entry_time_interval; - i_pos = p_index->index_entry[i_pos].i_packet_number * - p_sys->p_fp->i_min_data_packet_size; + uint64_t i_entry = i_date * 10 / p_index->i_index_entry_time_interval; + if( i_entry >= p_index->i_index_entry_count ) + { + msg_Warn( p_demux, "Incomplete index" ); + return VLC_EGENERIC; + } - return stream_Seek( p_demux->s, p_sys->i_data_begin + i_pos ); + uint64_t i_offset = (uint64_t)p_index->index_entry[i_entry].i_packet_number * + p_sys->p_fp->i_min_data_packet_size; + return stream_Seek( p_demux->s, p_sys->i_data_begin + i_offset ); } static void SeekPrepare( demux_t *p_demux ) @@ -291,16 +305,15 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) if( p_sys->b_index && p_sys->i_length > 0 ) { - i64 = (int64_t)va_arg( args, int64_t ); - return SeekIndex( p_demux, i64, -1 ); - } - else - { - return demux_vaControlHelper( p_demux->s, p_sys->i_data_begin, - p_sys->i_data_end, p_sys->i_bitrate, - p_sys->p_fp->i_min_data_packet_size, - i_query, args ); + va_list acpy; + va_copy( acpy, args ); + i64 = (int64_t)va_arg( acpy, int64_t ); + va_end( acpy ); + + if( !SeekIndex( p_demux, i64, -1 ) ) + return VLC_SUCCESS; } + return SeekPercent( p_demux, i_query, args ); case DEMUX_GET_POSITION: if( p_sys->i_time < 0 ) return VLC_EGENERIC; @@ -320,16 +333,15 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) if( p_sys->b_index && p_sys->i_length > 0 ) { - f = (double)va_arg( args, double ); - return SeekIndex( p_demux, -1, f ); - } - else - { - return demux_vaControlHelper( p_demux->s, p_sys->i_data_begin, - p_sys->i_data_end, p_sys->i_bitrate, - p_sys->p_fp->i_min_data_packet_size, - i_query, args ); + va_list acpy; + va_copy( acpy, args ); + f = (double)va_arg( acpy, double ); + va_end( acpy ); + + if( !SeekIndex( p_demux, -1, f ) ) + return VLC_SUCCESS; } + return SeekPercent( p_demux, i_query, args ); case DEMUX_GET_META: p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* ); @@ -360,7 +372,6 @@ static mtime_t GetMoviePTS( demux_sys_t *p_sys ) { if( i_time < 0 ) i_time = tk->i_time; else i_time = __MIN( i_time, tk->i_time ); - break; } } @@ -595,8 +606,11 @@ static int DemuxPacket( demux_t *p_demux ) /* send complete packet to decoder */ block_t *p_gather = block_ChainGather( tk->p_frame ); + if( p_gather->i_dts > VLC_TS_INVALID ) + tk->i_time = p_gather->i_dts - VLC_TS_0; + if( p_sys->i_time < 0 ) - es_out_Control( p_demux->out, ES_OUT_SET_PCR, tk->i_time ); + es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + tk->i_time ); es_out_Send( p_demux->out, tk->p_es, p_gather ); @@ -616,17 +630,13 @@ static int DemuxPacket( demux_t *p_demux ) if( tk->p_frame == NULL ) { - tk->i_time = - ( (mtime_t)i_pts + i_payload * (mtime_t)i_pts_delta ); - - p_frag->i_pts = tk->i_time; - + p_frag->i_pts = VLC_TS_0 + i_pts + i_payload * (mtime_t)i_pts_delta; if( tk->i_cat != VIDEO_ES ) - p_frag->i_dts = p_frag->i_pts; + p_frag->i_dts = VLC_TS_0 + p_frag->i_pts; else { - p_frag->i_dts = p_frag->i_pts; - p_frag->i_pts = 0; + p_frag->i_dts = VLC_TS_0 + p_frag->i_pts; + p_frag->i_pts = VLC_TS_INVALID; } } @@ -687,11 +697,6 @@ loop_error_recovery: static int DemuxInit( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; - bool b_seekable; - unsigned int i_stream; - asf_object_content_description_t *p_cd; - asf_object_index_t *p_index; - bool b_index; /* init context */ p_sys->i_time = -1; @@ -710,6 +715,7 @@ static int DemuxInit( demux_t *p_demux ) p_sys->meta = NULL; /* Now load all object ( except raw data ) */ + bool b_seekable; stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b_seekable ); if( !(p_sys->p_root = ASF_ReadObjectRoot(p_demux->s, b_seekable)) ) { @@ -731,19 +737,26 @@ static int DemuxInit( demux_t *p_demux ) msg_Warn( p_demux, "ASF plugin discarded (cannot find any stream!)" ); goto error; } + msg_Dbg( p_demux, "found %d streams", p_sys->i_track ); /* check if index is available */ - p_index = ASF_FindObject( p_sys->p_root, &asf_object_index_guid, 0 ); - b_index = p_index && p_index->i_index_entry_count; + asf_object_index_t *p_index = ASF_FindObject( p_sys->p_root, + &asf_object_index_guid, 0 ); + const bool b_index = p_index && p_index->i_index_entry_count; - msg_Dbg( p_demux, "found %d streams", p_sys->i_track ); + /* Find the extended header if any */ + asf_object_t *p_hdr_ext = ASF_FindObject( p_sys->p_root->p_hdr, + &asf_object_header_extension_guid, 0 ); + + asf_object_language_list_t *p_languages = NULL; + if( p_hdr_ext ) + p_languages = ASF_FindObject( p_hdr_ext, &asf_object_language_list, 0 ); - for( i_stream = 0; i_stream < p_sys->i_track; i_stream ++ ) + for( unsigned i_stream = 0; i_stream < p_sys->i_track; i_stream++ ) { asf_track_t *tk; asf_object_stream_properties_t *p_sp; asf_object_extended_stream_properties_t *p_esp; - asf_object_t *p_hdr_ext; bool b_access_selected; p_sp = ASF_FindObject( p_sys->p_root->p_hdr, @@ -771,8 +784,6 @@ static int DemuxInit( demux_t *p_demux ) } /* Find the associated extended_stream_properties if any */ - p_hdr_ext = ASF_FindObject( p_sys->p_root->p_hdr, - &asf_object_header_extension_guid, 0 ); if( p_hdr_ext ) { int i_ext_stream = ASF_CountObject( p_hdr_ext, @@ -790,10 +801,11 @@ static int DemuxInit( demux_t *p_demux ) } } + es_format_t fmt; + if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_audio ) && p_sp->i_type_specific_data_length >= sizeof( WAVEFORMATEX ) - 2 ) { - es_format_t fmt; uint8_t *p_data = p_sp->p_type_specific_data; int i_format; @@ -818,10 +830,6 @@ static int DemuxInit( demux_t *p_demux ) fmt.i_extra ); } - tk->i_cat = AUDIO_ES; - tk->p_es = es_out_Add( p_demux->out, &fmt ); - es_format_Clean( &fmt ); - msg_Dbg( p_demux, "added new audio stream(codec:0x%x,ID:%d)", GetWLE( p_data ), p_sp->i_stream_number ); } @@ -830,7 +838,6 @@ static int DemuxInit( demux_t *p_demux ) p_sp->i_type_specific_data_length >= 11 + sizeof( BITMAPINFOHEADER ) ) { - es_format_t fmt; uint8_t *p_data = &p_sp->p_type_specific_data[11]; es_format_Init( &fmt, VIDEO_ES, @@ -890,16 +897,11 @@ static int DemuxInit( demux_t *p_demux ) if( i_aspect_x && i_aspect_y ) { - fmt.video.i_aspect = i_aspect_x * - (int64_t)fmt.video.i_width * VOUT_ASPECT_FACTOR / - fmt.video.i_height / i_aspect_y; + fmt.video.i_sar_num = i_aspect_x; + fmt.video.i_sar_den = i_aspect_y; } } - tk->i_cat = VIDEO_ES; - tk->p_es = es_out_Add( p_demux->out, &fmt ); - es_format_Clean( &fmt ); - /* If there is a video track then use the index for seeking */ p_sys->b_index = b_index; @@ -910,7 +912,6 @@ static int DemuxInit( demux_t *p_demux ) p_sp->i_type_specific_data_length >= 64 ) { /* Now follows a 64 byte header of which we don't know much */ - es_format_t fmt; guid_t *p_ref = (guid_t *)p_sp->p_type_specific_data; uint8_t *p_data = p_sp->p_type_specific_data + 64; unsigned int i_data = p_sp->i_type_specific_data_length - 64; @@ -945,20 +946,40 @@ static int DemuxInit( demux_t *p_demux ) fmt.i_extra ); } - tk->i_cat = AUDIO_ES; - tk->p_es = es_out_Add( p_demux->out, &fmt ); - es_format_Clean( &fmt ); - msg_Dbg( p_demux, "added new audio stream (codec:0x%x,ID:%d)", i_format, p_sp->i_stream_number ); } + else + { + es_format_Init( &fmt, UNKNOWN_ES, 0 ); + } + } + else + { + es_format_Init( &fmt, UNKNOWN_ES, 0 ); + } + + tk->i_cat = fmt.i_cat; + if( fmt.i_cat != UNKNOWN_ES ) + { + if( p_esp && p_languages && + p_esp->i_language_index >= 0 && + p_esp->i_language_index < p_languages->i_language ) + { + fmt.psz_language = strdup( p_languages->ppsz_language[p_esp->i_language_index] ); + char *p; + if( fmt.psz_language && (p = strchr( fmt.psz_language, '-' )) ) + *p = '\0'; + } + + tk->p_es = es_out_Add( p_demux->out, &fmt ); } else { - tk->i_cat = UNKNOWN_ES; msg_Dbg( p_demux, "ignoring unknown stream(ID:%d)", p_sp->i_stream_number ); } + es_format_Clean( &fmt ); } p_sys->i_data_begin = p_sys->p_root->p_data->i_object_pos + 50; @@ -993,7 +1014,9 @@ static int DemuxInit( demux_t *p_demux ) /* calculate the time duration in micro-s */ p_sys->i_length = (mtime_t)p_sys->p_fp->i_play_duration / 10 * (mtime_t)i_count / - (mtime_t)p_sys->p_fp->i_data_packets_count; + (mtime_t)p_sys->p_fp->i_data_packets_count - p_sys->p_fp->i_preroll * 1000; + if( p_sys->i_length < 0 ) + p_sys->i_length = 0; if( p_sys->i_length > 0 ) { @@ -1004,6 +1027,7 @@ static int DemuxInit( demux_t *p_demux ) /* Create meta information */ p_sys->meta = vlc_meta_New(); + asf_object_content_description_t *p_cd; if( ( p_cd = ASF_FindObject( p_sys->p_root->p_hdr, &asf_object_content_description_guid, 0 ) ) ) {