diff --git a/modules/access/dvb/access.c b/modules/access/dvb/access.c index 1461302..745da6e 100644 --- a/modules/access/dvb/access.c +++ b/modules/access/dvb/access.c @@ -421,6 +421,8 @@ static int Open( vlc_object_t *p_this ) else p_sys->i_read_once = DVB_READ_ONCE_START; + free( p_access->psz_demux ); + p_access->psz_demux = strdup( "ts" ); return VLC_SUCCESS; } diff --git a/modules/gui/qt4/components/interface_widgets.cpp b/modules/gui/qt4/components/interface_widgets.cpp index 895d528..5c38426 100644 --- a/modules/gui/qt4/components/interface_widgets.cpp +++ b/modules/gui/qt4/components/interface_widgets.cpp @@ -506,7 +506,6 @@ void TimeLabel::setCaching( float f_cache ) { QString amount; amount.setNum( (int)(100 * f_cache) ); - msg_Dbg( p_intf, "New caching: %d", (int)(100*f_cache)); setText( "Buff: " + amount + "%" ); } diff --git a/src/config/file.c b/src/config/file.c index 01c0332..e2c92ec 100644 --- a/src/config/file.c +++ b/src/config/file.c @@ -117,6 +117,9 @@ static FILE *config_OpenConfigFile( vlc_object_t *p_obj ) } free( psz_readme ); } + /* Remove the old configuration file so that --reset-config + * can work properly. */ + unlink( psz_old ); } free( psz_old ); } diff --git a/src/input/clock.c b/src/input/clock.c index dc010e5..a26b9c4 100644 --- a/src/input/clock.c +++ b/src/input/clock.c @@ -86,6 +86,19 @@ * my dice --Meuuh */ #define CR_MEAN_PTS_GAP (300000) +/* Rate (in 1/256) at which we will read faster to try to increase our + * internal buffer (if we control the pace of the source). + */ +#define CR_BUFFERING_RATE (48) + +/* Extra internal buffer value (in CLOCK_FREQ) + * It is 60s max, remember as it is limited by the size it takes by es_out.c + * it can be really large. + */ +//#define CR_BUFFERING_TARGET (60000000) +/* Due to some problems in es_out, we cannot use a large value yet */ +#define CR_BUFFERING_TARGET (100000) + /***************************************************************************** * Structures *****************************************************************************/ @@ -123,6 +136,9 @@ static inline clock_point_t clock_point_Create( mtime_t i_stream, mtime_t i_syst } /* */ +#define INPUT_CLOCK_LATE_COUNT (3) + +/* */ struct input_clock_t { /* */ @@ -139,10 +155,20 @@ struct input_clock_t /* Maximal timestamp returned by input_clock_ConvertTS (in system unit) */ mtime_t i_ts_max; + /* Amount of extra buffering expressed in stream clock */ + mtime_t i_buffering_duration; + /* Clock drift */ mtime_t i_next_drift_update; average_t drift; + /* Late statistics */ + struct + { + mtime_t pi_value[INPUT_CLOCK_LATE_COUNT]; + unsigned i_index; + } late; + /* Current modifiers */ int i_rate; mtime_t i_pts_delay; @@ -153,6 +179,8 @@ struct input_clock_t static mtime_t ClockStreamToSystem( input_clock_t *, mtime_t i_stream ); static mtime_t ClockSystemToStream( input_clock_t *, mtime_t i_system ); +static mtime_t ClockGetTsOffset( input_clock_t * ); + /***************************************************************************** * input_clock_New: create a new clock *****************************************************************************/ @@ -170,9 +198,15 @@ input_clock_t *input_clock_New( int i_rate ) cl->i_ts_max = VLC_TS_INVALID; + cl->i_buffering_duration = 0; + cl->i_next_drift_update = VLC_TS_INVALID; AvgInit( &cl->drift, 10 ); + cl->late.i_index = 0; + for( int i = 0; i < INPUT_CLOCK_LATE_COUNT; i++ ) + cl->late.pi_value[i] = 0; + cl->i_rate = i_rate; cl->i_pts_delay = 0; cl->b_paused = false; @@ -197,8 +231,9 @@ void input_clock_Delete( input_clock_t *cl ) * i_ck_stream: date in stream clock * i_ck_system: date in system clock *****************************************************************************/ -void input_clock_Update( input_clock_t *cl, - vlc_object_t *p_log, bool b_can_pace_control, +void input_clock_Update( input_clock_t *cl, vlc_object_t *p_log, + bool *pb_late, + bool b_can_pace_control, bool b_buffering_allowed, mtime_t i_ck_stream, mtime_t i_ck_system ) { bool b_reset_reference = false; @@ -226,6 +261,8 @@ void input_clock_Update( input_clock_t *cl, msg_Warn( p_log, "feeding synchro with a new reference point trying to recover from clock gap" ); b_reset_reference= true; } + + /* */ if( b_reset_reference ) { cl->i_next_drift_update = VLC_TS_INVALID; @@ -237,6 +274,8 @@ void input_clock_Update( input_clock_t *cl, __MAX( cl->i_ts_max + CR_MEAN_PTS_GAP, i_ck_system ) ); } + /* Compute the drift between the stream clock and the system clock + * when we don't control the source pace */ if( !b_can_pace_control && cl->i_next_drift_update < i_ck_system ) { const mtime_t i_converted = ClockSystemToStream( cl, i_ck_system ); @@ -245,8 +284,39 @@ void input_clock_Update( input_clock_t *cl, cl->i_next_drift_update = i_ck_system + CLOCK_FREQ/5; /* FIXME why that */ } + + /* Update the extra buffering value */ + if( !b_can_pace_control || b_reset_reference ) + { + cl->i_buffering_duration = 0; + } + else if( b_buffering_allowed ) + { + /* Try to bufferize more than necessary by reading + * CR_BUFFERING_RATE/256 faster until we have CR_BUFFERING_TARGET. + */ + const mtime_t i_duration = __MAX( i_ck_stream - cl->last.i_stream, 0 ); + + cl->i_buffering_duration += ( i_duration * CR_BUFFERING_RATE + 255 ) / 256; + if( cl->i_buffering_duration > CR_BUFFERING_TARGET ) + cl->i_buffering_duration = CR_BUFFERING_TARGET; + } + //fprintf( stderr, "input_clock_Update: %d :: %lld\n", b_buffering_allowed, cl->i_buffering_duration/1000 ); + + /* */ cl->last = clock_point_Create( i_ck_stream, i_ck_system ); + /* It does not take the decoder latency into account but it is not really + * the goal of the clock here */ + const mtime_t i_system_expected = ClockStreamToSystem( cl, i_ck_stream + AvgGet( &cl->drift ) ); + const mtime_t i_late = ( i_ck_system - cl->i_pts_delay ) - i_system_expected; + *pb_late = i_late > 0; + if( i_late > 0 ) + { + cl->late.pi_value[cl->late.i_index] = i_late; + cl->late.i_index = ( cl->late.i_index + 1 ) % INPUT_CLOCK_LATE_COUNT; + } + vlc_mutex_unlock( &cl->lock ); } @@ -271,13 +341,12 @@ void input_clock_ChangeRate( input_clock_t *cl, int i_rate ) { vlc_mutex_lock( &cl->lock ); - /* Move the reference point */ if( cl->b_has_reference ) { - cl->last.i_system = ClockStreamToSystem( cl, cl->last.i_stream ); - cl->ref = cl->last; + /* Move the reference point (as if we were playing at the new rate + * from the start */ + cl->ref.i_system = cl->last.i_system - (cl->last.i_system - cl->ref.i_system) * i_rate / cl->i_rate; } - cl->i_rate = i_rate; vlc_mutex_unlock( &cl->lock ); @@ -318,7 +387,7 @@ mtime_t input_clock_GetWakeup( input_clock_t *cl ) /* Synchronized, we can wait */ if( cl->b_has_reference ) - i_wakeup = ClockStreamToSystem( cl, cl->last.i_stream ); + i_wakeup = ClockStreamToSystem( cl, cl->last.i_stream + AvgGet( &cl->drift ) - cl->i_buffering_duration ); vlc_mutex_unlock( &cl->lock ); @@ -332,8 +401,6 @@ int input_clock_ConvertTS( input_clock_t *cl, int *pi_rate, mtime_t *pi_ts0, mtime_t *pi_ts1, mtime_t i_ts_bound ) { - mtime_t i_pts_delay; - assert( pi_ts0 ); vlc_mutex_lock( &cl->lock ); @@ -350,27 +417,30 @@ int input_clock_ConvertTS( input_clock_t *cl, } /* */ + const mtime_t i_ts_buffering = cl->i_buffering_duration * cl->i_rate / INPUT_RATE_DEFAULT; + const mtime_t i_ts_delay = cl->i_pts_delay + ClockGetTsOffset( cl ); + + /* */ if( *pi_ts0 > VLC_TS_INVALID ) { *pi_ts0 = ClockStreamToSystem( cl, *pi_ts0 + AvgGet( &cl->drift ) ); if( *pi_ts0 > cl->i_ts_max ) cl->i_ts_max = *pi_ts0; - *pi_ts0 += cl->i_pts_delay; + *pi_ts0 += i_ts_delay; } /* XXX we do not ipdate i_ts_max on purpose */ if( pi_ts1 && *pi_ts1 > VLC_TS_INVALID ) { *pi_ts1 = ClockStreamToSystem( cl, *pi_ts1 + AvgGet( &cl->drift ) ) + - cl->i_pts_delay; + i_ts_delay; } - i_pts_delay = cl->i_pts_delay; vlc_mutex_unlock( &cl->lock ); /* Check ts validity */ if( i_ts_bound != INT64_MAX && - *pi_ts0 > VLC_TS_INVALID && *pi_ts0 >= mdate() + cl->i_pts_delay + i_ts_bound ) + *pi_ts0 > VLC_TS_INVALID && *pi_ts0 >= mdate() + i_ts_delay + i_ts_buffering + i_ts_bound ) return VLC_EGENERIC; return VLC_SUCCESS; @@ -417,7 +487,7 @@ void input_clock_ChangeSystemOrigin( input_clock_t *cl, mtime_t i_system ) vlc_mutex_lock( &cl->lock ); assert( cl->b_has_reference ); - const mtime_t i_offset = i_system - cl->ref.i_system; + const mtime_t i_offset = i_system - cl->ref.i_system - ClockGetTsOffset( cl ); cl->ref.i_system += i_offset; cl->last.i_system += i_offset; @@ -431,6 +501,24 @@ void input_clock_SetJitter( input_clock_t *cl, { vlc_mutex_lock( &cl->lock ); + /* Update late observations */ + const mtime_t i_delay_delta = i_pts_delay - cl->i_pts_delay; + mtime_t pi_late[INPUT_CLOCK_LATE_COUNT]; + for( int i = 0; i < INPUT_CLOCK_LATE_COUNT; i++ ) + pi_late[i] = __MAX( cl->late.pi_value[(cl->late.i_index + 1 + i)%INPUT_CLOCK_LATE_COUNT] - i_delay_delta, 0 ); + + for( int i = 0; i < INPUT_CLOCK_LATE_COUNT; i++ ) + cl->late.pi_value[i] = 0; + cl->late.i_index = 0; + + for( int i = 0; i < INPUT_CLOCK_LATE_COUNT; i++ ) + { + if( pi_late[i] <= 0 ) + continue; + cl->late.pi_value[cl->late.i_index] = pi_late[i]; + cl->late.i_index = ( cl->late.i_index + 1 ) % INPUT_CLOCK_LATE_COUNT; + } + /* TODO always save the value, and when rebuffering use the new one if smaller * TODO when increasing -> force rebuffering */ @@ -447,6 +535,28 @@ void input_clock_SetJitter( input_clock_t *cl, vlc_mutex_unlock( &cl->lock ); } +mtime_t input_clock_GetJitter( input_clock_t *cl ) +{ + vlc_mutex_lock( &cl->lock ); + +#if INPUT_CLOCK_LATE_COUNT != 3 +# error "unsupported INPUT_CLOCK_LATE_COUNT" +#endif + /* Find the median of the last late values + * It works pretty well at rejecting bad values + * + * XXX we only increase pts_delay over time, decreasing it is + * not that easy if we want to be robust. + */ + const mtime_t *p = cl->late.pi_value; + mtime_t i_late_median = p[0] + p[1] + p[2] - __MIN(__MIN(p[0],p[1]),p[2]) - __MAX(__MAX(p[0],p[1]),p[2]); + mtime_t i_pts_delay = cl->i_pts_delay ; + + vlc_mutex_unlock( &cl->lock ); + + return i_pts_delay + i_late_median; +} + /***************************************************************************** * ClockStreamToSystem: converts a movie clock to system date *****************************************************************************/ @@ -471,6 +581,15 @@ static mtime_t ClockSystemToStream( input_clock_t *cl, mtime_t i_system ) cl->ref.i_stream; } +/** + * It returns timestamp display offset due to ref/last modfied on rate changes + * It ensures that currently converted dates are not changed. + */ +static mtime_t ClockGetTsOffset( input_clock_t *cl ) +{ + return cl->i_pts_delay * ( cl->i_rate - INPUT_RATE_DEFAULT ) / INPUT_RATE_DEFAULT; +} + /***************************************************************************** * Long term average helpers *****************************************************************************/ diff --git a/src/input/clock.h b/src/input/clock.h index 1384793..ff50c82 100644 --- a/src/input/clock.h +++ b/src/input/clock.h @@ -52,9 +52,15 @@ void input_clock_Delete( input_clock_t * ); /** * This function will update a input_clock_t with a new clock reference point. + * It will also tell if the clock point is late regarding our buffering. + * + * \param b_buffering_allowed tells if we are allowed to bufferize more data in + * advanced (if possible). */ void input_clock_Update( input_clock_t *, vlc_object_t *p_log, - bool b_can_pace_control, mtime_t i_clock, mtime_t i_system ); + bool *pb_late, + bool b_can_pace_control, bool b_buffering_allowed, + mtime_t i_clock, mtime_t i_system ); /** * This function will reset the drift of a input_clock_t. * @@ -119,5 +125,11 @@ int input_clock_GetState( input_clock_t *, void input_clock_SetJitter( input_clock_t *, mtime_t i_pts_delay, int i_cr_average ); +/** + * This function returns an estimation of the pts_delay needed to avoid rebufferization. + * XXX in the current implementation, the pts_delay will never be decreased. + */ +mtime_t input_clock_GetJitter( input_clock_t * ); + #endif diff --git a/src/input/decoder.c b/src/input/decoder.c index b110a1e..c0e9fb5 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -386,7 +386,11 @@ void input_DecoderDecode( decoder_t *p_dec, block_t *p_block, bool b_do_pace ) if( !p_owner->b_buffering ) block_FifoPace( p_owner->p_fifo, 10, SIZE_MAX ); } +#ifdef __arm__ else if( block_FifoSize( p_owner->p_fifo ) > 50000000 /* 50 MB */ ) +#else + else if( block_FifoSize( p_owner->p_fifo ) > 400000000 /* 400 MB, ie ~ 50mb/s for 60s */ ) +#endif { /* FIXME: ideally we would check the time amount of data * in the FIFO instead of its size. */ @@ -633,6 +637,13 @@ bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt, vlc_me return b_changed; } +size_t input_DecoderGetFifoSize( decoder_t *p_dec ) +{ + decoder_owner_sys_t *p_owner = p_dec->p_owner; + + return block_FifoSize( p_owner->p_fifo ); +} + /***************************************************************************** * Internal functions *****************************************************************************/ diff --git a/src/input/decoder.h b/src/input/decoder.h index d47119d..fe99b42 100644 --- a/src/input/decoder.h +++ b/src/input/decoder.h @@ -99,4 +99,9 @@ void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration ); */ bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt, vlc_meta_t **pp_meta ); +/** + * This function returns the current size in bytes of the decoder fifo + */ +size_t input_DecoderGetFifoSize( decoder_t *p_dec ); + #endif diff --git a/src/input/es_out.c b/src/input/es_out.c index b67aa36..6f12b18 100644 --- a/src/input/es_out.c +++ b/src/input/es_out.c @@ -186,6 +186,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 ); @@ -585,9 +586,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 ) @@ -719,6 +718,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; @@ -1360,6 +1385,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 */ @@ -2226,6 +2303,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) int i_group = 0; int64_t i_pcr; + /* Search program */ if( i_query == ES_OUT_SET_PCR ) { p_pgrm = p_sys->p_pgrm; @@ -2247,14 +2325,42 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) return VLC_EGENERIC; } - /* search program - * TODO do not use mdate() but proper stream acquisition date */ + /* TODO do not use mdate() but proper stream acquisition date */ + bool b_late; input_clock_Update( p_pgrm->p_clock, VLC_OBJECT(p_sys->p_input), - p_sys->p_input->p->b_can_pace_control || p_sys->b_buffering, i_pcr, mdate() ); - /* Check buffering state on master clock update */ - if( p_sys->b_buffering && p_pgrm == p_sys->p_pgrm ) - EsOutDecodersStopBuffering( out, false ); + &b_late, + 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 ) + { + if( p_sys->b_buffering ) + { + /* Check buffering state on master clock update */ + EsOutDecodersStopBuffering( out, false ); + } + else if( b_late ) + { + mtime_t i_pts_delay = input_clock_GetJitter( p_pgrm->p_clock ); + + /* Avoid dangerously high value */ + const mtime_t i_pts_delay_max = 30000000; + if( i_pts_delay > i_pts_delay_max ) + i_pts_delay = __MAX( i_pts_delay_max, p_sys->i_pts_delay ); + + /* Force a rebufferization when we are too late */ + msg_Err( p_sys->p_input, + "ES_OUT_SET_(GROUP_)PCR is called too late, increasing pts_delay to %d ms", + (int)(i_pts_delay/1000) ); + + /* It is not really good, as we throw away already buffered data + * TODO have a mean to correctly reenter bufferization */ + es_out_Control( out, ES_OUT_RESET_PCR ); + + es_out_Control( out, ES_OUT_SET_JITTER, i_pts_delay, p_sys->i_cr_average ); + } + } return VLC_SUCCESS; } @@ -2361,6 +2467,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* ); diff --git a/src/input/es_out_timeshift.c b/src/input/es_out_timeshift.c index a48d365..19f4d21 100644 --- a/src/input/es_out_timeshift.c +++ b/src/input/es_out_timeshift.c @@ -599,6 +599,7 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args ) case ES_OUT_SET_GROUP_EPG: case ES_OUT_SET_ES_SCRAMBLED_STATE: case ES_OUT_DEL_GROUP: + case ES_OUT_SET_META: case ES_OUT_SET_ES: case ES_OUT_RESTART_ES: case ES_OUT_SET_ES_DEFAULT: @@ -1315,9 +1316,11 @@ static int CmdInitControl( ts_cmd_t *p_cmd, int i_query, va_list args, bool b_co case ES_OUT_RESET_PCR: /* no arg */ break; + case ES_OUT_SET_META: /* arg1=const vlc_meta_t* */ case ES_OUT_SET_GROUP_META: /* arg1=int i_group arg2=vlc_meta_t* */ { - p_cmd->control.int_meta.i_int = (int)va_arg( args, int ); + if( i_query == ES_OUT_SET_GROUP_META ) + p_cmd->control.int_meta.i_int = (int)va_arg( args, int ); vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t * ); if( b_copy ) @@ -1459,6 +1462,9 @@ static int CmdExecuteControl( es_out_t *p_out, ts_cmd_t *p_cmd ) return es_out_Control( p_out, i_query, p_cmd->control.es_bool.p_es->p_es, p_cmd->control.es_bool.b_bool ); + case ES_OUT_SET_META: /* arg1=const vlc_meta_t* */ + return es_out_Control( p_out, i_query, p_cmd->control.int_meta.p_meta ); + /* Modified control */ case ES_OUT_SET_ES: /* arg1= es_out_id_t* */ case ES_OUT_RESTART_ES: /* arg1= es_out_id_t* */ @@ -1488,7 +1494,8 @@ static int CmdExecuteControl( es_out_t *p_out, ts_cmd_t *p_cmd ) } static void CmdCleanControl( ts_cmd_t *p_cmd ) { - if( p_cmd->control.i_query == ES_OUT_SET_GROUP_META && + if( ( p_cmd->control.i_query == ES_OUT_SET_GROUP_META || + p_cmd->control.i_query == ES_OUT_SET_META ) && p_cmd->control.int_meta.p_meta ) { vlc_meta_Delete( p_cmd->control.int_meta.p_meta ); diff --git a/src/input/input.c b/src/input/input.c index be4eb7b..d003625 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -763,7 +763,7 @@ static void MainLoop( input_thread_t *p_input ) * is paused -> this may cause problem with some of them * The same problem can be seen when seeking while paused */ b_paused = p_input->p->i_state == PAUSE_S && - !es_out_GetBuffering( p_input->p->p_es_out ); + ( !es_out_GetBuffering( p_input->p->p_es_out ) || p_input->p->input.b_eof ); if( !b_paused ) { @@ -773,7 +773,7 @@ static void MainLoop( input_thread_t *p_input ) i_wakeup = es_out_GetWakeup( p_input->p->p_es_out ); } - else if( !p_input->b_eof && !es_out_GetEmpty( p_input->p->p_es_out ) ) + else if( !es_out_GetEmpty( p_input->p->p_es_out ) ) { msg_Dbg( p_input, "waiting decoder fifos to empty" ); i_wakeup = mdate() + INPUT_IDLE_SLEEP; @@ -816,13 +816,9 @@ static void MainLoop( input_thread_t *p_input ) i_statistic_update = i_current + INT64_C(1000000); } - /* Check if i_wakeup is still valid */ + /* Update the wakeup time */ if( i_wakeup != 0 ) - { - mtime_t i_new_wakeup = es_out_GetWakeup( p_input->p->p_es_out ); - if( !i_new_wakeup ) - i_wakeup = 0; - } + i_wakeup = es_out_GetWakeup( p_input->p->p_es_out ); } while( i_current < i_wakeup ); } @@ -1668,9 +1664,8 @@ static bool Control( input_thread_t *p_input, int64_t i_length; /* Emulate it with a SET_POS */ - demux_Control( p_input->p->input.p_demux, - DEMUX_GET_LENGTH, &i_length ); - if( i_length > 0 ) + if( !demux_Control( p_input->p->input.p_demux, + DEMUX_GET_LENGTH, &i_length ) && i_length > 0 ) { double f_pos = (double)i_time / (double)i_length; i_ret = demux_Control( p_input->p->input.p_demux, @@ -2430,8 +2425,9 @@ static int InputSourceInit( input_thread_t *p_input, if( in->p_demux ) { /* Get infos from access_demux */ - demux_Control( in->p_demux, - DEMUX_GET_PTS_DELAY, &in->i_pts_delay ); + int i_ret = demux_Control( in->p_demux, + DEMUX_GET_PTS_DELAY, &in->i_pts_delay ); + assert( !i_ret ); in->i_pts_delay = __MAX( 0, __MIN( in->i_pts_delay, INPUT_PTS_DELAY_MAX ) ); @@ -2885,54 +2881,8 @@ static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta ) *****************************************************************************/ static void InputUpdateMeta( input_thread_t *p_input, vlc_meta_t *p_meta ) { - input_item_t *p_item = p_input->p->p_item; - - 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 ); - + es_out_ControlSetMeta( p_input->p->p_es_out, p_meta ); vlc_meta_Delete( 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_input->p->p_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 */ } static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_attachment, diff --git a/share/lua/playlist/youtube.lua b/share/lua/playlist/youtube.lua index 238d3eb..9b165e0 100644 --- a/share/lua/playlist/youtube.lua +++ b/share/lua/playlist/youtube.lua @@ -1,7 +1,7 @@ --[[ $Id$ - Copyright © 2007 the VideoLAN team + Copyright © 2007-2009 the VideoLAN team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -74,7 +74,8 @@ function parse() end -- OLD: var swfArgs = {hl:'en',BASE_YT_URL:'http://youtube.com/',video_id:'XPJ7d8dq0t8',l:'292',t:'OEgsToPDskLFdOYrrlDm3FQPoQBYaCP1',sk:'0gnr-AE6QZJEZmCMd3lq_AC'}; -- NEW: var swfArgs = { "BASE_YT_URL": "http://youtube.com", "video_id": "OHVvVmUNBFc", "l": 88, "sk": "WswKuJzDBsdD6oG3IakCXgC", "t": "OEgsToPDskK3zO44y0QN8Fr5ZSAZwCQp", "plid": "AARGnwWMrmGkbpOxAAAA4AT4IAA", "tk": "mEL4E7PqHeaZp5OG19NQThHt9mXJU4PbRTOw6lz9osHi4Hixp7RE1w=="}; - if string.match( line, "swfArgs" ) and string.match( line, "video_id" ) then + -- NEWER: 'SWF_ARGS': { [a lot of stuff...], "video_id": "OHVvVmUNBFc", "sk": "WswKuJzDBsdD6oG3IakCXgC", "t": "OEgsToPDskK3zO44y0QN8Fr5ZSAZwCQp", "plid": "AARGnwWMrmGkbpOxAAAA4AT4IAA"}; + if ( string.match( line, "SWF_ARGS" ) or string.match( line, "swfArgs" ) ) and string.match( line, "video_id" ) then if string.match( line, "BASE_YT_URL" ) then _,_,base_yt_url = string.find( line, "\"BASE_YT_URL\": \"(.-)\"" ) end diff --git a/include/vlc_es_out.h b/include/vlc_es_out.h index 043e557..fdde1c9 100644 --- a/include/vlc_es_out.h +++ b/include/vlc_es_out.h @@ -90,6 +90,9 @@ enum es_out_query_e * XXX You SHALL call ES_OUT_RESET_PCR before any other es_out_Control/Send calls. */ ES_OUT_GET_EMPTY, /* arg1=bool* res=cannot fail */ + /* Set global meta data (The vlc_meta_t is not modified nor released) */ + ES_OUT_SET_META, /* arg1=const vlc_meta_t * */ + /* First value usable for private control */ ES_OUT_PRIVATE_START = 0x10000, }; @@ -145,6 +148,11 @@ static inline void es_out_Delete( es_out_t *p_out ) p_out->pf_destroy( p_out ); } +static inline int es_out_ControlSetMeta( es_out_t *out, const vlc_meta_t *p_meta ) +{ + return es_out_Control( out, ES_OUT_SET_META, p_meta ); +} + /** * @} */