/* */
bool b_paused;
+ mtime_t i_pause_date;
/* Current preroll */
mtime_t i_preroll_end;
static void EsOutDelete ( es_out_t * );
static void EsOutSelect( es_out_t *, es_out_id_t *es, bool b_force );
-static void EsOutUpdateInfo( es_out_t *, es_out_id_t *es, const es_format_t * );
+static void EsOutUpdateInfo( es_out_t *, es_out_id_t *es, const es_format_t *, const vlc_meta_t * );
static int EsOutSetRecord( es_out_t *, bool b_record );
static bool EsIsSelected( es_out_id_t *es );
p_sys->i_spu_delay = 0;
p_sys->b_paused = false;
+ p_sys->i_pause_date = -1;
p_sys->i_rate = i_rate;
EsOutProgramsChangeRate( out );
}
p_sys->b_paused = b_paused;
+ p_sys->i_pause_date = i_date;
}
static void EsOutChangeRate( es_out_t *out, int i_rate )
{
es_out_sys_t *p_sys = out->p_sys;
+ input_SendEventCache( p_sys->p_input, 0.0 );
+
for( int i = 0; i < p_sys->i_es; i++ )
{
es_out_id_t *p_es = p_sys->es[i];
const mtime_t i_buffering_duration = p_sys->p_input->i_pts_delay +
i_preroll_duration +
- p_sys->i_buffering_extra_stream;
+ p_sys->i_buffering_extra_stream - p_sys->i_buffering_extra_initial;
if( i_stream_duration <= i_buffering_duration && !b_forced )
{
- msg_Dbg( p_sys->p_input, "Buffering %d%%",
- (int)(100 * i_stream_duration / i_buffering_duration ) );
+ const double f_level = (double)i_stream_duration / i_buffering_duration;
+ input_SendEventCache( p_sys->p_input, f_level );
+
+ msg_Dbg( p_sys->p_input, "Buffering %d%%", (int)(100 * f_level) );
return;
}
+ input_SendEventCache( p_sys->p_input, 1.0 );
msg_Dbg( p_sys->p_input, "Stream buffering done (%d ms in %d ms)",
(int)(i_stream_duration/1000), (int)(i_system_duration/1000) );
msg_Dbg( p_sys->p_input, "Decoder buffering done in %d ms",
(int)(mdate() - i_decoder_buffering_start)/1000 );
- const mtime_t i_ts_delay = 10*1000 + /* FIXME CLEANUP thread wake up time*/
- mdate();
- //msg_Dbg( p_sys->p_input, "==> %lld", i_ts_delay - p_sys->p_input->i_pts_delay );
- input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_clock, i_ts_delay - i_buffering_duration );
+ 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 );
for( int i = 0; i < p_sys->i_es; i++ )
{
p_sys->i_preroll_end = -1;
}
+static mtime_t EsOutGetBuffering( es_out_t *out )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+
+ if( !p_sys->p_pgrm )
+ return 0;
+
+ int i_ret;
+ mtime_t i_stream_start;
+ mtime_t i_system_start;
+ mtime_t i_stream_duration;
+ mtime_t i_system_duration;
+ i_ret = input_clock_GetState( p_sys->p_pgrm->p_clock,
+ &i_stream_start, &i_system_start,
+ &i_stream_duration, &i_system_duration );
+
+ if( i_ret )
+ return 0;
+ mtime_t i_delay;
+
+ if( p_sys->b_buffering && p_sys->i_buffering_extra_initial <= 0 )
+ {
+ i_delay = i_stream_duration;
+ }
+ else
+ {
+ mtime_t i_system_duration;
+ if( p_sys->b_paused )
+ {
+ i_system_duration = p_sys->i_pause_date - i_system_start;
+ if( p_sys->i_buffering_extra_initial > 0 )
+ i_system_duration += p_sys->i_buffering_extra_system - p_sys->i_buffering_extra_initial;
+ }
+ else
+ {
+ i_system_duration = mdate() - i_system_start;
+ }
+ const mtime_t i_consumed = i_system_duration * INPUT_RATE_DEFAULT / p_sys->i_rate - i_stream_duration;
+ i_delay = p_sys->p_input->i_pts_delay - i_consumed;
+ }
+ if( i_delay < 0 )
+ return 0;
+ return i_delay;
+}
static void EsOutESVarUpdateGeneric( es_out_t *out, int i_id, es_format_t *fmt, const char *psz_language,
bool b_delete )
}
/* Update now playing */
- input_item_SetNowPlaying( p_input->p->input.p_item,
- p_pgrm->psz_now_playing );
- input_item_SetPublisher( p_input->p->input.p_item,
- p_pgrm->psz_publisher );
+ input_item_SetNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
+ input_item_SetPublisher( p_input->p->p_item, p_pgrm->psz_publisher );
input_SendEventMeta( p_input );
}
p_pgrm->psz_now_playing = NULL;
p_pgrm->psz_publisher = NULL;
p_pgrm->p_epg = NULL;
- p_pgrm->p_clock = input_clock_New( p_input->p->input.i_cr_average, p_sys->i_rate );
+ p_pgrm->p_clock = input_clock_New( p_input->p->i_cr_average, p_sys->i_rate );
if( !p_pgrm->p_clock )
{
free( p_pgrm );
{
if( p_sys->p_pgrm == p_pgrm )
{
- input_item_SetPublisher( p_input->p->input.p_item, psz_provider );
+ 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 );
if( p_pgrm == p_sys->p_pgrm )
{
- input_item_SetNowPlaying( p_input->p->input.p_item, p_pgrm->psz_now_playing );
+ input_item_SetNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
input_SendEventMeta( p_input );
}
es->i_channel = p_sys->i_audio;
memset( &rg, 0, sizeof(rg) );
- vlc_mutex_lock( &p_input->p->input.p_item->lock );
- vlc_audio_replay_gain_MergeFromMeta( &rg, p_input->p->input.p_item->p_meta );
- vlc_mutex_unlock( &p_input->p->input.p_item->lock );
+ vlc_mutex_lock( &p_input->p->p_item->lock );
+ vlc_audio_replay_gain_MergeFromMeta( &rg, p_input->p->p_item->p_meta );
+ vlc_mutex_unlock( &p_input->p->p_item->lock );
for( i = 0; i < AUDIO_REPLAY_GAIN_MAX; i++ )
{
break;
}
- EsOutUpdateInfo( out, es, &es->fmt );
+ EsOutUpdateInfo( out, es, &es->fmt, NULL );
vlc_mutex_unlock( &p_sys->lock );
input_DecoderDecode( es->p_dec, p_block );
es_format_t fmt_dsc;
- if( input_DecoderHasFormatChanged( es->p_dec, &fmt_dsc ) )
+ vlc_meta_t *p_meta_dsc;
+ if( input_DecoderHasFormatChanged( es->p_dec, &fmt_dsc, &p_meta_dsc ) )
{
- EsOutUpdateInfo( out, es, &fmt_dsc );
+ EsOutUpdateInfo( out, es, &fmt_dsc, p_meta_dsc );
+
es_format_Clean( &fmt_dsc );
+ if( p_meta_dsc )
+ vlc_meta_Delete( p_meta_dsc );
}
/* Check CC status */
}
case ES_OUT_GET_BUFFERING:
- {
-#warning "TODO ES_OUT_GET_BUFFERING"
- bool *pb = (bool *)va_arg( args, bool* );
- mtime_t *pi_delay = (mtime_t*)va_arg( args, mtime_t* );
+ pb = (bool *)va_arg( args, bool* );
*pb = p_sys->b_buffering;
- *pi_delay = 0;
return VLC_SUCCESS;
- }
case ES_OUT_GET_EMPTY:
pb = (bool *)va_arg( args, bool* );
EsOutFrameNext( out );
return VLC_SUCCESS;
+ case ES_OUT_SET_TIMES:
+ {
+ double f_position = (double)va_arg( args, double );
+ mtime_t i_time = (mtime_t)va_arg( args, mtime_t );
+ mtime_t i_length = (mtime_t)va_arg( args, mtime_t );
+
+ /* Fix for buffering delay */
+ const mtime_t i_delay = EsOutGetBuffering( out );
+
+ i_time -= i_delay;
+ if( i_time < 0 )
+ i_time = 0;
+
+ if( i_length > 0 )
+ f_position -= (double)i_delay / i_length;
+ if( f_position < 0 )
+ f_position = 0;
+
+ input_SendEventTimes( p_sys->p_input, f_position, i_time, i_length );
+ return VLC_SUCCESS;
+ }
+
default:
msg_Err( p_sys->p_input, "unknown query in es_out_Control" );
return VLC_EGENERIC;
* EsOutUpdateInfo:
* - add meta info to the playlist item
****************************************************************************/
-static void EsOutUpdateInfo( es_out_t *out, es_out_id_t *es, const es_format_t *fmt )
+static void EsOutUpdateInfo( es_out_t *out, es_out_id_t *es, const es_format_t *fmt, const vlc_meta_t *p_meta )
{
es_out_sys_t *p_sys = out->p_sys;
input_thread_t *p_input = p_sys->p_input;
break;
}
+ /* Append generic meta */
+ if( p_meta )
+ {
+ char **ppsz_all_keys = vlc_dictionary_all_keys( &p_meta->extra_tags );
+ 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 );
+
+ if( psz_value )
+ input_Control( p_input, INPUT_ADD_INFO, psz_cat, _(psz_key), _(psz_value) );
+ free( psz_key );
+ }
+ free( ppsz_all_keys );
+ }
+
free( psz_cat );
}