X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Fes_out.c;h=bb94572046ea32b84d4f20a278c3b22c0cc456dd;hb=92410cb5c3ae0f983ddd61c784d8eb78fe13a2f6;hp=5568b6f71c259caff328b6db89569e1ca2430911;hpb=79d33ce2a7c9c5dde99b1b5acd15fd08673bdf8f;p=vlc diff --git a/src/input/es_out.c b/src/input/es_out.c index 5568b6f71c..bb94572046 100644 --- a/src/input/es_out.c +++ b/src/input/es_out.c @@ -71,8 +71,6 @@ typedef struct char *psz_name; char *psz_now_playing; char *psz_publisher; - - vlc_epg_t *p_epg; } es_out_pgrm_t; struct es_out_id_t @@ -187,6 +185,7 @@ static void EsOutDecodersChangePause( es_out_t *out, bool b_paused, mtime_t i_da static void EsOutProgramChangePause( es_out_t *out, bool b_paused, mtime_t i_date ); static void EsOutProgramsChangeRate( es_out_t *out ); static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced ); + static char *LanguageGetName( const char *psz_code ); static char *LanguageGetCode( const char *psz_lang ); static char **LanguageSplit( const char *psz_langs ); @@ -244,7 +243,7 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate ) p_sys->p_input = p_input; p_sys->b_active = false; - p_sys->i_mode = ES_OUT_MODE_AUTO; + p_sys->i_mode = ES_OUT_MODE_NONE; TAB_INIT( p_sys->i_pgrm, p_sys->pgrm ); @@ -368,12 +367,14 @@ static void EsOutDelete( es_out_t *out ) free( p_pgrm->psz_now_playing ); free( p_pgrm->psz_publisher ); free( p_pgrm->psz_name ); - if( p_pgrm->p_epg ) - vlc_epg_Delete( p_pgrm->p_epg ); free( p_pgrm ); } TAB_CLEAN( p_sys->i_pgrm, p_sys->pgrm ); + + input_item_SetEpgOffline( p_sys->p_input->p->p_item ); + input_SendEventMetaEpg( p_sys->p_input ); + vlc_mutex_destroy( &p_sys->lock ); free( p_sys ); @@ -463,11 +464,15 @@ static int EsOutSetRecord( es_out_t *out, bool b_record ) if( b_record ) { - char *psz_path = var_CreateGetString( p_input, "input-record-path" ); - if( !psz_path || *psz_path == '\0' ) + char *psz_path = var_CreateGetNonEmptyString( p_input, "input-record-path" ); + if( !psz_path ) { - free( psz_path ); - psz_path = strdup( config_GetHomeDir() ); + if( var_CountChoices( p_input, "video-es" ) ) + psz_path = config_GetUserDir( VLC_VIDEOS_DIR ); + else if( var_CountChoices( p_input, "audio-es" ) ) + psz_path = config_GetUserDir( VLC_MUSIC_DIR ); + else + psz_path = config_GetUserDir( VLC_DOWNLOAD_DIR ); } char *psz_sout = NULL; // TODO conf @@ -573,9 +578,7 @@ static void EsOutChangeRate( es_out_t *out, int i_rate ) es_out_sys_t *p_sys = out->p_sys; p_sys->i_rate = i_rate; - - if( !p_sys->b_paused ) - EsOutProgramsChangeRate( out ); + EsOutProgramsChangeRate( out ); } static void EsOutChangePosition( es_out_t *out ) @@ -676,7 +679,8 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced ) const mtime_t i_wakeup_delay = 10*1000; /* FIXME CLEANUP thread wake up time*/ const mtime_t i_current_date = p_sys->b_paused ? p_sys->i_pause_date : mdate(); - input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_clock, i_current_date + i_wakeup_delay - i_buffering_duration ); + input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_clock, true, + i_current_date + i_wakeup_delay - i_buffering_duration ); for( int i = 0; i < p_sys->i_es; i++ ) { @@ -707,6 +711,32 @@ static void EsOutDecodersChangePause( es_out_t *out, bool b_paused, mtime_t i_da } } } + +static bool EsOutIsExtraBufferingAllowed( es_out_t *out ) +{ + es_out_sys_t *p_sys = out->p_sys; + + size_t i_size = 0; + for( int i = 0; i < p_sys->i_es; i++ ) + { + es_out_id_t *p_es = p_sys->es[i]; + + if( p_es->p_dec ) + i_size += input_DecoderGetFifoSize( p_es->p_dec ); + if( p_es->p_dec_record ) + i_size += input_DecoderGetFifoSize( p_es->p_dec_record ); + } + //fprintf( stderr, "----- EsOutIsExtraBufferingAllowed =% 5d kbytes -- ", i_size / 1024 ); + + /* TODO maybe we want to be able to tune it ? */ +#if defined(OPTIMIZE_MEMORY) + const size_t i_level_high = 500000; /* 0.5 Mbytes */ +#else + const size_t i_level_high = 10000000; /* 10 Mbytes */ +#endif + return i_size < i_level_high; +} + static void EsOutProgramChangePause( es_out_t *out, bool b_paused, mtime_t i_date ) { es_out_sys_t *p_sys = out->p_sys; @@ -898,10 +928,9 @@ static void EsOutESVarUpdateGeneric( es_out_t *out, int i_id, { if( psz_language && *psz_language ) { - text.psz_string = malloc( strlen( fmt->psz_description) + - strlen( psz_language ) + 10 ); - sprintf( text.psz_string, "%s - [%s]", fmt->psz_description, - psz_language ); + if( asprintf( &text.psz_string, "%s - [%s]", fmt->psz_description, + psz_language ) == -1 ) + text.psz_string = NULL; } else text.psz_string = strdup( fmt->psz_description ); } @@ -1023,7 +1052,6 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group ) p_pgrm->psz_name = NULL; p_pgrm->psz_now_playing = NULL; p_pgrm->psz_publisher = NULL; - p_pgrm->p_epg = NULL; p_pgrm->p_clock = input_clock_New( p_sys->i_rate ); if( !p_pgrm->p_clock ) { @@ -1086,8 +1114,6 @@ static int EsOutProgramDel( es_out_t *out, int i_group ) free( p_pgrm->psz_name ); free( p_pgrm->psz_now_playing ); free( p_pgrm->psz_publisher ); - if( p_pgrm->p_epg ) - vlc_epg_Delete( p_pgrm->p_epg ); free( p_pgrm ); /* Update "program" variable */ @@ -1128,7 +1154,7 @@ static char *EsOutProgramGetMetaName( es_out_pgrm_t *p_pgrm ) return psz; } -static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta ) +static void EsOutProgramMeta( es_out_t *out, int i_group, const vlc_meta_t *p_meta ) { es_out_sys_t *p_sys = out->p_sys; es_out_pgrm_t *p_pgrm; @@ -1144,7 +1170,7 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta ) if( !vlc_meta_Get( p_meta, vlc_meta_Title) && !vlc_meta_Get( p_meta, vlc_meta_NowPlaying) && !vlc_meta_Get( p_meta, vlc_meta_Publisher) && - vlc_dictionary_keys_count( &p_meta->extra_tags ) <= 0 ) + vlc_meta_GetExtraCount( p_meta ) <= 0 ) { return; } @@ -1189,7 +1215,8 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta ) { input_SendEventProgramDel( p_input, i_group ); input_SendEventProgramAdd( p_input, i_group, psz_text ); - + if( p_sys->p_pgrm == p_pgrm ) + input_SendEventProgramSelect( p_input, i_group ); free( psz_text ); } } @@ -1202,15 +1229,14 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta ) input_item_SetPublisher( p_input->p->p_item, psz_provider ); input_SendEventMeta( p_input ); } - input_Control( p_input, INPUT_ADD_INFO, psz_cat, input_MetaTypeToLocalizedString(vlc_meta_Publisher), psz_provider ); + input_Control( p_input, INPUT_ADD_INFO, psz_cat, vlc_meta_TypeToLocalizedString(vlc_meta_Publisher), psz_provider ); } - char ** ppsz_all_keys = vlc_dictionary_all_keys( &p_meta->extra_tags ); + char ** ppsz_all_keys = vlc_meta_CopyExtraNames(p_meta ); for( i = 0; ppsz_all_keys[i]; i++ ) { input_Control( p_input, INPUT_ADD_INFO, psz_cat, vlc_gettext(ppsz_all_keys[i]), - vlc_dictionary_value_for_key( &p_meta->extra_tags, - ppsz_all_keys[i] ) ); + vlc_meta_GetExtra( p_meta, ppsz_all_keys[i] ) ); free( ppsz_all_keys[i] ); } free( ppsz_all_keys ); @@ -1218,56 +1244,11 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta ) free( psz_cat ); } -static void vlc_epg_Merge( vlc_epg_t *p_dst, const vlc_epg_t *p_src ) -{ - int i; - - /* Add new event */ - for( i = 0; i < p_src->i_event; i++ ) - { - vlc_epg_event_t *p_evt = p_src->pp_event[i]; - bool b_add = true; - int j; - - for( j = 0; j < p_dst->i_event; j++ ) - { - if( p_dst->pp_event[j]->i_start == p_evt->i_start && p_dst->pp_event[j]->i_duration == p_evt->i_duration ) - { - b_add = false; - break; - } - if( p_dst->pp_event[j]->i_start > p_evt->i_start ) - break; - } - if( b_add ) - { - vlc_epg_event_t *p_copy = calloc( 1, sizeof(vlc_epg_event_t) ); - if( !p_copy ) - break; - p_copy->i_start = p_evt->i_start; - p_copy->i_duration = p_evt->i_duration; - p_copy->psz_name = p_evt->psz_name ? strdup( p_evt->psz_name ) : NULL; - p_copy->psz_short_description = p_evt->psz_short_description ? strdup( p_evt->psz_short_description ) : NULL; - p_copy->psz_description = p_evt->psz_description ? strdup( p_evt->psz_description ) : NULL; - TAB_INSERT( p_dst->i_event, p_dst->pp_event, p_copy, j ); - } - } - /* Update current */ - if( p_src->p_current ) - vlc_epg_SetCurrent( p_dst, p_src->p_current->i_start ); - - /* Keep only 1 old event */ - if( p_dst->p_current ) - { - while( p_dst->i_event > 1 && p_dst->pp_event[0] != p_dst->p_current && p_dst->pp_event[1] != p_dst->p_current ) - TAB_REMOVE( p_dst->i_event, p_dst->pp_event, p_dst->pp_event[0] ); - } -} - -static void EsOutProgramEpg( es_out_t *out, int i_group, vlc_epg_t *p_epg ) +static void EsOutProgramEpg( es_out_t *out, int i_group, const vlc_epg_t *p_epg ) { es_out_sys_t *p_sys = out->p_sys; input_thread_t *p_input = p_sys->p_input; + input_item_t *p_item = p_input->p->p_item; es_out_pgrm_t *p_pgrm; char *psz_cat; @@ -1276,28 +1257,36 @@ static void EsOutProgramEpg( es_out_t *out, int i_group, vlc_epg_t *p_epg ) if( !p_pgrm ) return; - /* Merge EPG */ - if( !p_pgrm->p_epg ) - p_pgrm->p_epg = vlc_epg_New( p_pgrm->psz_name ); - vlc_epg_Merge( p_pgrm->p_epg, p_epg ); - /* Update info */ - msg_Dbg( p_input, "EsOutProgramEpg: number=%d name=%s", i_group, p_pgrm->p_epg->psz_name ); - psz_cat = EsOutProgramGetMetaName( p_pgrm ); + msg_Dbg( p_input, "EsOutProgramEpg: number=%d name=%s", i_group, psz_cat ); - char *psz_epg; - if( asprintf( &psz_epg, "EPG %s", psz_cat ) >= 0 ) - { - input_item_SetEpg( p_input->p->p_item, psz_epg, p_pgrm->p_epg ); - free( psz_epg ); - } + /* Merge EPG */ + vlc_epg_t epg; + + epg = *p_epg; + epg.psz_name = psz_cat; + + input_item_SetEpg( p_item, &epg ); + input_SendEventMetaEpg( p_sys->p_input ); /* Update now playing */ free( p_pgrm->psz_now_playing ); p_pgrm->psz_now_playing = NULL; - if( p_pgrm->p_epg->p_current && p_pgrm->p_epg->p_current->psz_name && *p_pgrm->p_epg->p_current->psz_name ) - p_pgrm->psz_now_playing = strdup( p_pgrm->p_epg->p_current->psz_name ); + + vlc_mutex_lock( &p_item->lock ); + for( int i = 0; i < p_item->i_epg; i++ ) + { + const vlc_epg_t *p_tmp = p_item->pp_epg[i]; + + if( p_tmp->psz_name && !strcmp(p_tmp->psz_name, psz_cat) ) + { + if( p_tmp->p_current && p_tmp->p_current->psz_name && *p_tmp->p_current->psz_name ) + p_pgrm->psz_now_playing = strdup( p_tmp->p_current->psz_name ); + break; + } + } + vlc_mutex_unlock( &p_item->lock ); if( p_pgrm == p_sys->p_pgrm ) { @@ -1308,13 +1297,13 @@ static void EsOutProgramEpg( es_out_t *out, int i_group, vlc_epg_t *p_epg ) if( p_pgrm->psz_now_playing ) { input_Control( p_input, INPUT_ADD_INFO, psz_cat, - input_MetaTypeToLocalizedString(vlc_meta_NowPlaying), + vlc_meta_TypeToLocalizedString(vlc_meta_NowPlaying), p_pgrm->psz_now_playing ); } else { input_Control( p_input, INPUT_DEL_INFO, psz_cat, - input_MetaTypeToLocalizedString(vlc_meta_NowPlaying) ); + vlc_meta_TypeToLocalizedString(vlc_meta_NowPlaying) ); } free( psz_cat ); @@ -1348,6 +1337,58 @@ static void EsOutProgramUpdateScrambled( es_out_t *p_out, es_out_pgrm_t *p_pgrm input_SendEventProgramScrambled( p_input, p_pgrm->i_id, b_scrambled ); } +static void EsOutMeta( es_out_t *p_out, const vlc_meta_t *p_meta ) +{ + es_out_sys_t *p_sys = p_out->p_sys; + input_thread_t *p_input = p_sys->p_input; + + input_item_t *p_item = input_GetItem( p_input ); + + char *psz_title = NULL; + char *psz_arturl = input_item_GetArtURL( p_item ); + + vlc_mutex_lock( &p_item->lock ); + + if( vlc_meta_Get( p_meta, vlc_meta_Title ) && !p_item->b_fixed_name ) + psz_title = strdup( vlc_meta_Get( p_meta, vlc_meta_Title ) ); + + vlc_meta_Merge( p_item->p_meta, p_meta ); + + if( !psz_arturl || *psz_arturl == '\0' ) + { + const char *psz_tmp = vlc_meta_Get( p_item->p_meta, vlc_meta_ArtworkURL ); + if( psz_tmp ) + psz_arturl = strdup( psz_tmp ); + } + vlc_mutex_unlock( &p_item->lock ); + + if( psz_arturl && *psz_arturl ) + { + input_item_SetArtURL( p_item, psz_arturl ); + + if( !strncmp( psz_arturl, "attachment://", strlen("attachment") ) ) + { + /* Don't look for art cover if sout + * XXX It can change when sout has meta data support */ + if( p_out->b_sout && !p_input->b_preparsing ) + input_item_SetArtURL( p_item, "" ); + else + input_ExtractAttachmentAndCacheArt( p_input ); + } + } + free( psz_arturl ); + + if( psz_title ) + { + input_item_SetName( p_item, psz_title ); + free( psz_title ); + } + input_item_SetPreparsed( p_item, true ); + + input_SendEventMeta( p_input ); + /* TODO handle sout meta ? */ +} + /* EsOutAdd: * Add an es_out */ @@ -1864,7 +1905,7 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block ) if( p_sys->i_preroll_end >= 0 ) { int64_t i_date = p_block->i_pts; - if( i_date <= 0 ) + if( p_block->i_pts <= VLC_TS_INVALID ) i_date = p_block->i_dts; if( i_date < p_sys->i_preroll_end ) @@ -2070,10 +2111,13 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) *pb = EsIsSelected( es ); return VLC_SUCCESS; - case ES_OUT_SET_ACTIVE: + case ES_OUT_SET_MODE: { - b = (bool) va_arg( args, int ); - if( b && !p_sys->b_active && p_sys->i_es > 0 ) + const int i_mode = va_arg( args, int ); + assert( i_mode == ES_OUT_MODE_NONE || i_mode == ES_OUT_MODE_ALL || + i_mode == ES_OUT_MODE_AUTO || i_mode == ES_OUT_MODE_PARTIAL ); + + if( i_mode != ES_OUT_MODE_NONE && !p_sys->b_active && p_sys->i_es > 0 ) { /* XXX Terminate vout if there are tracks but no video one. * This one is not mandatory but is he earliest place where it @@ -2087,33 +2131,20 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) if( i >= p_sys->i_es ) input_resource_TerminateVout( p_sys->p_input->p->p_resource ); } - p_sys->b_active = b; - return VLC_SUCCESS; - } + p_sys->b_active = i_mode != ES_OUT_MODE_NONE; + p_sys->i_mode = i_mode; - case ES_OUT_SET_MODE: - i = (int) va_arg( args, int ); - if( i == ES_OUT_MODE_NONE || i == ES_OUT_MODE_ALL || - i == ES_OUT_MODE_AUTO || i == ES_OUT_MODE_PARTIAL ) + /* Reapply policy mode */ + for( i = 0; i < p_sys->i_es; i++ ) { - p_sys->i_mode = i; - - /* Reapply policy mode */ - for( i = 0; i < p_sys->i_es; i++ ) - { - if( EsIsSelected( p_sys->es[i] ) ) - { - EsUnselect( out, p_sys->es[i], - p_sys->es[i]->p_pgrm == p_sys->p_pgrm ); - } - } - for( i = 0; i < p_sys->i_es; i++ ) - { - EsOutSelect( out, p_sys->es[i], false ); - } - return VLC_SUCCESS; + if( EsIsSelected( p_sys->es[i] ) ) + EsUnselect( out, p_sys->es[i], + p_sys->es[i]->p_pgrm == p_sys->p_pgrm ); } - return VLC_EGENERIC; + for( i = 0; i < p_sys->i_es; i++ ) + EsOutSelect( out, p_sys->es[i], false ); + return VLC_SUCCESS; + } case ES_OUT_SET_ES: case ES_OUT_RESTART_ES: @@ -2238,7 +2269,9 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) bool b_late; input_clock_Update( p_pgrm->p_clock, VLC_OBJECT(p_sys->p_input), &b_late, - p_sys->p_input->p->b_can_pace_control || p_sys->b_buffering, i_pcr, mdate() ); + p_sys->p_input->p->b_can_pace_control || p_sys->b_buffering, + EsOutIsExtraBufferingAllowed( out ), + i_pcr, mdate() ); if( p_pgrm == p_sys->p_pgrm ) { @@ -2247,7 +2280,8 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) /* Check buffering state on master clock update */ EsOutDecodersStopBuffering( out, false ); } - else if( b_late ) + else if( b_late && ( !out->b_sout || + !p_sys->p_input->p->b_out_pace_control ) ) { mtime_t i_pts_delay = input_clock_GetJitter( p_pgrm->p_clock ); @@ -2305,7 +2339,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) if( p_fmt->i_extra ) { es->fmt.i_extra = p_fmt->i_extra; - es->fmt.p_extra = realloc( es->fmt.p_extra, p_fmt->i_extra ); + es->fmt.p_extra = xrealloc( es->fmt.p_extra, p_fmt->i_extra ); memcpy( es->fmt.p_extra, p_fmt->p_extra, p_fmt->i_extra ); if( !es->p_dec ) @@ -2317,7 +2351,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) #else es->p_dec->fmt_in.i_extra = p_fmt->i_extra; es->p_dec->fmt_in.p_extra = - realloc( es->p_dec->fmt_in.p_extra, p_fmt->i_extra ); + xrealloc( es->p_dec->fmt_in.p_extra, p_fmt->i_extra ); memcpy( es->p_dec->fmt_in.p_extra, p_fmt->p_extra, p_fmt->i_extra ); #endif @@ -2353,7 +2387,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) case ES_OUT_SET_GROUP_META: { int i_group = (int)va_arg( args, int ); - vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t * ); + const vlc_meta_t *p_meta = va_arg( args, const vlc_meta_t * ); EsOutProgramMeta( out, i_group, p_meta ); return VLC_SUCCESS; @@ -2361,7 +2395,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) case ES_OUT_SET_GROUP_EPG: { int i_group = (int)va_arg( args, int ); - vlc_epg_t *p_epg = (vlc_epg_t*)va_arg( args, vlc_epg_t * ); + const vlc_epg_t *p_epg = va_arg( args, const vlc_epg_t * ); EsOutProgramEpg( out, i_group, p_epg ); return VLC_SUCCESS; @@ -2374,6 +2408,14 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) return EsOutProgramDel( out, i_group ); } + case ES_OUT_SET_META: + { + const vlc_meta_t *p_meta = va_arg( args, const vlc_meta_t * ); + + EsOutMeta( out, p_meta ); + return VLC_SUCCESS; + } + case ES_OUT_GET_WAKE_UP: { mtime_t *pi_wakeup = (mtime_t*)va_arg( args, mtime_t* ); @@ -2407,6 +2449,32 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) return i_ret; } + case ES_OUT_GET_ES_OBJECTS_BY_ID: + { + const int i_id = va_arg( args, int ); + es_out_id_t *p_es = EsOutGetFromID( out, i_id ); + if( !p_es ) + return VLC_EGENERIC; + + vlc_object_t **pp_decoder = va_arg( args, vlc_object_t ** ); + vout_thread_t **pp_vout = va_arg( args, vout_thread_t ** ); + aout_instance_t **pp_aout = va_arg( args, aout_instance_t ** ); + if( es->p_dec ) + { + if( pp_decoder ) + *pp_decoder = vlc_object_hold( es->p_dec ); + input_DecoderGetObjects( es->p_dec, pp_vout, pp_aout ); + } + else + { + if( pp_vout ) + *pp_vout = NULL; + if( pp_aout ) + *pp_aout = NULL; + } + return VLC_SUCCESS; + } + case ES_OUT_GET_BUFFERING: pb = (bool *)va_arg( args, bool* ); *pb = p_sys->b_buffering; @@ -2476,8 +2544,13 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) if( !p_sys->b_buffering ) { + mtime_t i_delay; + /* Fix for buffering delay */ - const mtime_t i_delay = EsOutGetBuffering( out ); + if( !out->b_sout || !p_sys->p_input->p->b_out_pace_control ) + i_delay = EsOutGetBuffering( out ); + else + i_delay = 0; i_time -= i_delay; if( i_time < 0 ) @@ -2510,6 +2583,35 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) return VLC_SUCCESS; } + case ES_OUT_GET_PCR_SYSTEM: + { + if( p_sys->b_buffering ) + return VLC_EGENERIC; + + es_out_pgrm_t *p_pgrm = p_sys->p_pgrm; + if( !p_pgrm ) + return VLC_EGENERIC; + + mtime_t *pi_system = va_arg( args, mtime_t *); + *pi_system = input_clock_GetSystemOrigin( p_pgrm->p_clock ); + return VLC_SUCCESS; + } + + case ES_OUT_MODIFY_PCR_SYSTEM: + { + if( p_sys->b_buffering ) + return VLC_EGENERIC; + + es_out_pgrm_t *p_pgrm = p_sys->p_pgrm; + if( !p_pgrm ) + return VLC_EGENERIC; + + const bool b_absolute = va_arg( args, int ); + const mtime_t i_system = va_arg( args, mtime_t ); + input_clock_ChangeSystemOrigin( p_pgrm->p_clock, b_absolute, i_system ); + return VLC_SUCCESS; + } + default: msg_Err( p_sys->p_input, "unknown query in es_out_Control" ); return VLC_EGENERIC; @@ -2815,11 +2917,11 @@ static void EsOutUpdateInfo( es_out_t *out, es_out_id_t *es, const es_format_t * /* Append generic meta */ if( p_meta ) { - char **ppsz_all_keys = vlc_dictionary_all_keys( &p_meta->extra_tags ); + char **ppsz_all_keys = vlc_meta_CopyExtraNames( p_meta ); for( int i = 0; ppsz_all_keys && ppsz_all_keys[i]; i++ ) { char *psz_key = ppsz_all_keys[i]; - char *psz_value = vlc_dictionary_value_for_key( &p_meta->extra_tags, psz_key ); + const char *psz_value = vlc_meta_GetExtra( p_meta, psz_key ); if( psz_value ) input_Control( p_input, INPUT_ADD_INFO, psz_cat,