return out;
}
-void input_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 );
-}
-
-void input_EsOutChangePause( es_out_t *out, bool b_paused, mtime_t i_date )
-{
- es_out_sys_t *p_sys = out->p_sys;
-
- /* XXX the order is important */
- if( b_paused )
- {
- EsOutDecodersChangePause( out, true, i_date );
- EsOutProgramChangePause( out, true, i_date );
- }
- else
- {
- if( p_sys->i_buffering_extra_initial > 0 )
- {
- mtime_t i_stream_start;
- mtime_t i_system_start;
- mtime_t i_stream_duration;
- mtime_t i_system_duration;
- int i_ret;
- 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 )
- {
- /* FIXME pcr != exactly what wanted */
- const mtime_t i_used = /*(i_stream_duration - p_sys->p_input->i_pts_delay)*/ p_sys->i_buffering_extra_system - p_sys->i_buffering_extra_initial;
- i_date -= i_used;
- }
- p_sys->i_buffering_extra_initial = 0;
- p_sys->i_buffering_extra_stream = 0;
- p_sys->i_buffering_extra_system = 0;
- }
- EsOutProgramChangePause( out, false, i_date );
- EsOutDecodersChangePause( out, false, i_date );
-
- EsOutProgramsChangeRate( out );
- }
- p_sys->b_paused = b_paused;
-}
-void input_EsOutChangePosition( es_out_t *out )
-{
- es_out_sys_t *p_sys = out->p_sys;
-
- 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 )
- continue;
-
- input_DecoderStartBuffering( p_es->p_dec );
-
- if( p_es->p_dec_record )
- input_DecoderStartBuffering( p_es->p_dec );
- }
-
- for( int i = 0; i < p_sys->i_pgrm; i++ )
- input_clock_Reset( p_sys->pgrm[i]->p_clock );
-
- p_sys->b_buffering = true;
- p_sys->i_buffering_extra_initial = 0;
- p_sys->i_buffering_extra_stream = 0;
- p_sys->i_buffering_extra_system = 0;
- p_sys->i_preroll_end = -1;
-}
-
-void input_EsOutFrameNext( es_out_t *out )
-{
- es_out_sys_t *p_sys = out->p_sys;
- es_out_id_t *p_es_video = NULL;
-
- if( p_sys->b_buffering )
- {
- msg_Warn( p_sys->p_input, "buffering, ignoring 'frame next'" );
- return;
- }
-
- assert( p_sys->b_paused );
-
- for( int i = 0; i < p_sys->i_es; i++ )
- {
- es_out_id_t *p_es = p_sys->es[i];
-
- if( p_es->fmt.i_cat == VIDEO_ES && p_es->p_dec )
- {
- p_es_video = p_es;
- break;
- }
- }
-
- if( !p_es_video )
- {
- msg_Warn( p_sys->p_input, "No video track selected, ignoring 'frame next'" );
- return;
- }
-
- mtime_t i_duration;
- input_DecoderFrameNext( p_es_video->p_dec, &i_duration );
-
- msg_Dbg( out->p_sys->p_input, "input_EsOutFrameNext consummed %d ms", (int)(i_duration/1000) );
-
- if( i_duration <= 0 )
- i_duration = 40*1000;
-
- /* FIXME it is not a clean way ? */
- if( p_sys->i_buffering_extra_initial <= 0 )
- {
- mtime_t i_stream_start;
- mtime_t i_system_start;
- mtime_t i_stream_duration;
- mtime_t i_system_duration;
- int i_ret;
-
- 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;
-
- p_sys->i_buffering_extra_initial = 1 + i_stream_duration - p_sys->p_input->i_pts_delay; /* FIXME < 0 ? */
- p_sys->i_buffering_extra_system =
- p_sys->i_buffering_extra_stream = p_sys->i_buffering_extra_initial;
- }
-
- const int i_rate = input_clock_GetRate( p_sys->p_pgrm->p_clock );
-
- p_sys->b_buffering = true;
- p_sys->i_buffering_extra_system += i_duration;
- p_sys->i_buffering_extra_stream = p_sys->i_buffering_extra_initial +
- ( p_sys->i_buffering_extra_system - p_sys->i_buffering_extra_initial ) *
- INPUT_RATE_DEFAULT / i_rate;
-
- p_sys->i_preroll_end = -1;
-}
-
-void input_EsOutLock( es_out_t *out )
-{
- vlc_mutex_lock( &out->p_sys->lock );
-}
-void input_EsOutUnlock( es_out_t *out )
-{
- vlc_mutex_unlock( &out->p_sys->lock );
-}
-
/*****************************************************************************
*
*****************************************************************************/
return VLC_SUCCESS;
}
+static void EsOutChangePause( es_out_t *out, bool b_paused, mtime_t i_date )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+
+ /* XXX the order is important */
+ if( b_paused )
+ {
+ EsOutDecodersChangePause( out, true, i_date );
+ EsOutProgramChangePause( out, true, i_date );
+ }
+ else
+ {
+ if( p_sys->i_buffering_extra_initial > 0 )
+ {
+ mtime_t i_stream_start;
+ mtime_t i_system_start;
+ mtime_t i_stream_duration;
+ mtime_t i_system_duration;
+ int i_ret;
+ 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 )
+ {
+ /* FIXME pcr != exactly what wanted */
+ const mtime_t i_used = /*(i_stream_duration - p_sys->p_input->i_pts_delay)*/ p_sys->i_buffering_extra_system - p_sys->i_buffering_extra_initial;
+ i_date -= i_used;
+ }
+ p_sys->i_buffering_extra_initial = 0;
+ p_sys->i_buffering_extra_stream = 0;
+ p_sys->i_buffering_extra_system = 0;
+ }
+ EsOutProgramChangePause( out, false, i_date );
+ EsOutDecodersChangePause( out, false, i_date );
+
+ EsOutProgramsChangeRate( out );
+ }
+ p_sys->b_paused = b_paused;
+}
+
+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 );
+}
+
+static void EsOutChangePosition( es_out_t *out )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+
+ 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 )
+ continue;
+
+ input_DecoderStartBuffering( p_es->p_dec );
+
+ if( p_es->p_dec_record )
+ input_DecoderStartBuffering( p_es->p_dec );
+ }
+
+ for( int i = 0; i < p_sys->i_pgrm; i++ )
+ input_clock_Reset( p_sys->pgrm[i]->p_clock );
+
+ p_sys->b_buffering = true;
+ p_sys->i_buffering_extra_initial = 0;
+ p_sys->i_buffering_extra_stream = 0;
+ p_sys->i_buffering_extra_system = 0;
+ p_sys->i_preroll_end = -1;
+}
+
static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
input_clock_ChangeRate( p_sys->pgrm[i]->p_clock, p_sys->i_rate );
}
+static void EsOutFrameNext( es_out_t *out )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+ es_out_id_t *p_es_video = NULL;
+
+ if( p_sys->b_buffering )
+ {
+ msg_Warn( p_sys->p_input, "buffering, ignoring 'frame next'" );
+ return;
+ }
+
+ assert( p_sys->b_paused );
+
+ for( int i = 0; i < p_sys->i_es; i++ )
+ {
+ es_out_id_t *p_es = p_sys->es[i];
+
+ if( p_es->fmt.i_cat == VIDEO_ES && p_es->p_dec )
+ {
+ p_es_video = p_es;
+ break;
+ }
+ }
+
+ if( !p_es_video )
+ {
+ msg_Warn( p_sys->p_input, "No video track selected, ignoring 'frame next'" );
+ return;
+ }
+
+ mtime_t i_duration;
+ input_DecoderFrameNext( p_es_video->p_dec, &i_duration );
+
+ msg_Dbg( out->p_sys->p_input, "EsOutFrameNext consummed %d ms", (int)(i_duration/1000) );
+
+ if( i_duration <= 0 )
+ i_duration = 40*1000;
+
+ /* FIXME it is not a clean way ? */
+ if( p_sys->i_buffering_extra_initial <= 0 )
+ {
+ mtime_t i_stream_start;
+ mtime_t i_system_start;
+ mtime_t i_stream_duration;
+ mtime_t i_system_duration;
+ int i_ret;
+
+ 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;
+
+ p_sys->i_buffering_extra_initial = 1 + i_stream_duration - p_sys->p_input->i_pts_delay; /* FIXME < 0 ? */
+ p_sys->i_buffering_extra_system =
+ p_sys->i_buffering_extra_stream = p_sys->i_buffering_extra_initial;
+ }
+
+ const int i_rate = input_clock_GetRate( p_sys->p_pgrm->p_clock );
+
+ p_sys->b_buffering = true;
+ p_sys->i_buffering_extra_system += i_duration;
+ p_sys->i_buffering_extra_stream = p_sys->i_buffering_extra_initial +
+ ( p_sys->i_buffering_extra_system - p_sys->i_buffering_extra_initial ) *
+ INPUT_RATE_DEFAULT / i_rate;
+
+ p_sys->i_preroll_end = -1;
+}
+
+
+
static void EsOutESVarUpdateGeneric( es_out_t *out, int i_id, es_format_t *fmt, const char *psz_language,
bool b_delete )
{
if( input_DecoderIsEmpty( es->p_dec ) &&
( !es->p_dec_record || input_DecoderIsEmpty( es->p_dec_record ) ))
break;
+ /* FIXME there should be a way to have auto deleted es, but there will be
+ * a problem when another codec of the same type is created (mainly video) */
msleep( 20*1000 );
}
EsUnselect( out, es, es->p_pgrm == p_sys->p_pgrm );
case ES_OUT_RESET_PCR:
msg_Err( p_sys->p_input, "ES_OUT_RESET_PCR called" );
- input_EsOutChangePosition( out );
+ EsOutChangePosition( out );
return VLC_SUCCESS;
case ES_OUT_GET_TS:
b = (bool) va_arg( args, int );
return EsOutSetRecord( out, b );
+ case ES_OUT_SET_PAUSE_STATE:
+ {
+ const bool b = (bool)va_arg( args, int );
+ const mtime_t i_date = (mtime_t) va_arg( args, mtime_t );
+ EsOutChangePause( out, b, i_date );
+
+ return VLC_SUCCESS;
+ }
+
+ case ES_OUT_SET_RATE:
+ {
+ const int i_rate = (int)va_arg( args, int );
+ EsOutChangeRate( out, i_rate );
+
+ return VLC_SUCCESS;
+ }
+
+ case ES_OUT_SET_TIME:
+ {
+ const mtime_t i_date = (mtime_t)va_arg( args, mtime_t );
+ assert( i_date == -1 );
+ EsOutChangePosition( out );
+
+ return VLC_SUCCESS;
+ }
+
+ case ES_OUT_SET_FRAME_NEXT:
+ EsOutFrameNext( out );
+ return VLC_SUCCESS;
+
+ case ES_OUT_LOCK:
+ vlc_mutex_lock( &p_sys->lock );
+ return VLC_SUCCESS;
+
+ case ES_OUT_UNLOCK:
+ vlc_mutex_unlock( &p_sys->lock );
+ return VLC_SUCCESS;
+
default:
msg_Err( p_sys->p_input, "unknown query in es_out_Control" );
return VLC_EGENERIC;
/* Check if es_out has still data to play */
ES_OUT_GET_EMPTY, /* arg1=bool* res=cannot fail */
- /* */
+ /* Set delay for a ES category */
ES_OUT_SET_DELAY, /* arg1=es_category_e, res=can fail */
- /* */
+ /* Set record state */
ES_OUT_SET_RECORD_STATE, /* arg1=bool res=can fail */
+
+ /* Set pause state */
+ ES_OUT_SET_PAUSE_STATE, /* arg1=bool arg2=mtime_t res=can fail */
+
+ /* Set rate */
+ ES_OUT_SET_RATE, /* arg1=int i_rate res=can fail */
+
+ /* Set a new time */
+ ES_OUT_SET_TIME, /* arg1=mtime_t res=can fail */
+
+ /* Set next frame */
+ ES_OUT_SET_FRAME_NEXT, /* res=can fail */
+
+ /* Lock/Unlock es_out
+ * XXX es_out is safe without them, but they ensure coherency between
+ * calls if needed (if es_out is called outside of the main thread) */
+ ES_OUT_LOCK, /* res=cannot fail */
+ ES_OUT_UNLOCK, /* res=cannot fail */
};
static inline mtime_t es_out_GetWakeup( es_out_t *p_out )
{
return es_out_Control( p_out, ES_OUT_SET_RECORD_STATE, b_record );
}
+static inline int es_out_SetPauseState( es_out_t *p_out, bool b_paused, mtime_t i_date )
+{
+ return es_out_Control( p_out, ES_OUT_SET_PAUSE_STATE, b_paused, i_date );
+}
+static inline int es_out_SetRate( es_out_t *p_out, int i_rate )
+{
+ return es_out_Control( p_out, ES_OUT_SET_RATE, i_rate );
+}
+static inline int es_out_SetTime( es_out_t *p_out, mtime_t i_date )
+{
+ return es_out_Control( p_out, ES_OUT_SET_TIME, i_date );
+}
+static inline int es_out_SetFrameNext( es_out_t *p_out )
+{
+ return es_out_Control( p_out, ES_OUT_SET_FRAME_NEXT );
+}
+static inline void es_out_Lock( es_out_t *p_out )
+{
+ int i_ret = es_out_Control( p_out, ES_OUT_LOCK );
+ assert( !i_ret );
+}
+static inline void es_out_Unlock( es_out_t *p_out )
+{
+ int i_ret = es_out_Control( p_out, ES_OUT_UNLOCK );
+ assert( !i_ret );
+}
es_out_t *input_EsOutNew( input_thread_t *, int i_rate );
-void input_EsOutChangeRate( es_out_t *, int );
-void input_EsOutChangePause( es_out_t *, bool b_paused, mtime_t i_date );
-void input_EsOutChangePosition( es_out_t * );
-void input_EsOutFrameNext( es_out_t * );
-
-void input_EsOutLock( es_out_t * );
-void input_EsOutUnlock( es_out_t * );
-
#endif
/* */
if( !i_ret )
- input_EsOutChangePause( p_input->p->p_es_out, true, i_control_date );
+ es_out_SetPauseState( p_input->p->p_es_out, true, i_control_date );
}
static void ControlUnpause( input_thread_t *p_input, mtime_t i_control_date )
{
/* */
if( !i_ret )
- input_EsOutChangePause( p_input->p->p_es_out, false, i_control_date );
+ es_out_SetPauseState( p_input->p->p_es_out, false, i_control_date );
}
static bool Control( input_thread_t *p_input, int i_type,
if( !p_input )
return b_force_update;
- input_EsOutLock( p_input->p->p_es_out );
+ es_out_Lock( p_input->p->p_es_out );
switch( i_type )
{
if( f_pos < 0.0 ) f_pos = 0.0;
if( f_pos > 1.0 ) f_pos = 1.0;
/* Reset the decoders states and clock sync (before calling the demuxer */
- input_EsOutChangePosition( p_input->p->p_es_out );
+ es_out_SetTime( p_input->p->p_es_out, -1 );
if( demux_Control( p_input->p->input.p_demux, DEMUX_SET_POSITION,
f_pos ) )
{
if( i_time < 0 ) i_time = 0;
/* Reset the decoders states and clock sync (before calling the demuxer */
- input_EsOutChangePosition( p_input->p->p_es_out );
+ es_out_SetTime( p_input->p->p_es_out, -1 );
i_ret = demux_Control( p_input->p->input.p_demux,
DEMUX_SET_TIME, i_time );
/* FIXME do we need a RESET_PCR when !p_input->p->input.b_rescale_ts ? */
if( p_input->p->input.b_rescale_ts )
- input_EsOutChangeRate( p_input->p->p_es_out, i_rate );
+ es_out_SetRate( p_input->p->p_es_out, i_rate );
b_force_update = true;
}
if( i_title >= 0 && i_title < p_input->p->input.i_title )
{
- input_EsOutChangePosition( p_input->p->p_es_out );
+ es_out_SetTime( p_input->p->p_es_out, -1 );
demux_Control( p_demux, DEMUX_SET_TITLE, i_title );
input_ControlVarTitle( p_input, i_title );
if( i_title >= 0 && i_title < p_input->p->input.i_title )
{
- input_EsOutChangePosition( p_input->p->p_es_out );
+ es_out_SetTime( p_input->p->p_es_out, -1 );
access_Control( p_access, ACCESS_SET_TITLE, i_title );
stream_AccessReset( p_input->p->input.p_stream );
p_input->p->input.title[p_demux->info.i_title]->i_seekpoint )
{
- input_EsOutChangePosition( p_input->p->p_es_out );
+ es_out_SetTime( p_input->p->p_es_out, -1 );
demux_Control( p_demux, DEMUX_SET_SEEKPOINT, i_seekpoint );
}
if( i_seekpoint >= 0 && i_seekpoint <
p_input->p->input.title[p_access->info.i_title]->i_seekpoint )
{
- input_EsOutChangePosition( p_input->p->p_es_out );
+ es_out_SetTime( p_input->p->p_es_out, -1 );
access_Control( p_access, ACCESS_SET_SEEKPOINT,
i_seekpoint );
if( p_input->i_state == PAUSE_S )
{
- input_EsOutFrameNext( p_input->p->p_es_out );
+ es_out_SetFrameNext( p_input->p->p_es_out );
}
else if( p_input->i_state == PLAYING_S )
{
break;
}
- input_EsOutUnlock( p_input->p->p_es_out );
+ es_out_Unlock( p_input->p->p_es_out );
return b_force_update;
}