Commit adb694f5 authored by Rafaël Carré's avatar Rafaël Carré

EsOutControlLocked: align case on same level than switch

parent 05a4b8a6
...@@ -2127,582 +2127,582 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) ...@@ -2127,582 +2127,582 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
switch( i_query ) switch( i_query )
{ {
case ES_OUT_SET_ES_STATE: case ES_OUT_SET_ES_STATE:
{
es_out_id_t *es = va_arg( args, es_out_id_t * );
bool b = va_arg( args, int );
if( b && !EsIsSelected( es ) )
{ {
es_out_id_t *es = va_arg( args, es_out_id_t * ); EsSelect( out, es );
bool b = va_arg( args, int ); return EsIsSelected( es ) ? VLC_SUCCESS : VLC_EGENERIC;
if( b && !EsIsSelected( es ) )
{
EsSelect( out, es );
return EsIsSelected( es ) ? VLC_SUCCESS : VLC_EGENERIC;
}
else if( !b && EsIsSelected( es ) )
{
EsUnselect( out, es, es->p_pgrm == p_sys->p_pgrm );
return VLC_SUCCESS;
}
return VLC_SUCCESS;
} }
else if( !b && EsIsSelected( es ) )
case ES_OUT_GET_ES_STATE:
{ {
es_out_id_t *es = va_arg( args, es_out_id_t * ); EsUnselect( out, es, es->p_pgrm == p_sys->p_pgrm );
bool *pb = va_arg( args, bool * );
*pb = EsIsSelected( es );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
return VLC_SUCCESS;
}
case ES_OUT_GET_GROUP_FORCED: case ES_OUT_GET_ES_STATE:
{ {
int *pi_group = va_arg( args, int * ); es_out_id_t *es = va_arg( args, es_out_id_t * );
*pi_group = p_sys->i_group_id; bool *pb = va_arg( args, bool * );
return VLC_SUCCESS;
}
case ES_OUT_SET_MODE: *pb = EsIsSelected( es );
{ return VLC_SUCCESS;
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 ||
i_mode == ES_OUT_MODE_END );
if( i_mode != ES_OUT_MODE_NONE && !p_sys->b_active && p_sys->i_es > 0 ) case ES_OUT_GET_GROUP_FORCED:
{ {
/* XXX Terminate vout if there are tracks but no video one. int *pi_group = va_arg( args, int * );
* This one is not mandatory but is he earliest place where it *pi_group = p_sys->i_group_id;
* can be done */ return VLC_SUCCESS;
int i; }
for( i = 0; i < p_sys->i_es; i++ )
{ case ES_OUT_SET_MODE:
es_out_id_t *p_es = p_sys->es[i]; {
if( p_es->fmt.i_cat == VIDEO_ES ) const int i_mode = va_arg( args, int );
break; 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 >= p_sys->i_es ) i_mode == ES_OUT_MODE_END );
input_resource_TerminateVout( p_sys->p_input->p->p_resource );
}
p_sys->b_active = i_mode != ES_OUT_MODE_NONE;
p_sys->i_mode = i_mode;
/* Reapply policy mode */ if( i_mode != ES_OUT_MODE_NONE && !p_sys->b_active && p_sys->i_es > 0 )
for( int i = 0; i < p_sys->i_es; i++ ) {
/* XXX Terminate vout if there are tracks but no video one.
* This one is not mandatory but is he earliest place where it
* can be done */
int i;
for( i = 0; i < p_sys->i_es; i++ )
{ {
if( EsIsSelected( p_sys->es[i] ) ) es_out_id_t *p_es = p_sys->es[i];
EsUnselect( out, p_sys->es[i], if( p_es->fmt.i_cat == VIDEO_ES )
p_sys->es[i]->p_pgrm == p_sys->p_pgrm ); break;
} }
for( int i = 0; i < p_sys->i_es; i++ ) if( i >= p_sys->i_es )
EsOutSelect( out, p_sys->es[i], false ); input_resource_TerminateVout( p_sys->p_input->p->p_resource );
if( i_mode == ES_OUT_MODE_END )
EsOutTerminate( out );
return VLC_SUCCESS;
} }
p_sys->b_active = i_mode != ES_OUT_MODE_NONE;
p_sys->i_mode = i_mode;
case ES_OUT_SET_ES: /* Reapply policy mode */
case ES_OUT_RESTART_ES: for( int i = 0; i < p_sys->i_es; i++ )
{ {
es_out_id_t *es = va_arg( args, es_out_id_t * ); if( EsIsSelected( p_sys->es[i] ) )
EsUnselect( out, p_sys->es[i],
p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
}
for( int i = 0; i < p_sys->i_es; i++ )
EsOutSelect( out, p_sys->es[i], false );
if( i_mode == ES_OUT_MODE_END )
EsOutTerminate( out );
return VLC_SUCCESS;
}
int i_cat; case ES_OUT_SET_ES:
if( es == NULL ) case ES_OUT_RESTART_ES:
i_cat = UNKNOWN_ES; {
else if( es == (es_out_id_t*)((uint8_t*)NULL+AUDIO_ES) ) es_out_id_t *es = va_arg( args, es_out_id_t * );
i_cat = AUDIO_ES;
else if( es == (es_out_id_t*)((uint8_t*)NULL+VIDEO_ES) ) int i_cat;
i_cat = VIDEO_ES; if( es == NULL )
else if( es == (es_out_id_t*)((uint8_t*)NULL+SPU_ES) ) i_cat = UNKNOWN_ES;
i_cat = SPU_ES; else if( es == (es_out_id_t*)((uint8_t*)NULL+AUDIO_ES) )
else i_cat = AUDIO_ES;
i_cat = -1; else if( es == (es_out_id_t*)((uint8_t*)NULL+VIDEO_ES) )
i_cat = VIDEO_ES;
else if( es == (es_out_id_t*)((uint8_t*)NULL+SPU_ES) )
i_cat = SPU_ES;
else
i_cat = -1;
for( int i = 0; i < p_sys->i_es; i++ ) for( int i = 0; i < p_sys->i_es; i++ )
{
if( i_cat == -1 )
{ {
if( i_cat == -1 ) if( es == p_sys->es[i] )
{ {
if( es == p_sys->es[i] ) EsOutSelect( out, es, true );
{ break;
EsOutSelect( out, es, true );
break;
}
} }
else }
else
{
if( i_cat == UNKNOWN_ES || p_sys->es[i]->fmt.i_cat == i_cat )
{ {
if( i_cat == UNKNOWN_ES || p_sys->es[i]->fmt.i_cat == i_cat ) if( EsIsSelected( p_sys->es[i] ) )
{ {
if( EsIsSelected( p_sys->es[i] ) ) if( i_query == ES_OUT_RESTART_ES )
{ {
if( i_query == ES_OUT_RESTART_ES ) if( p_sys->es[i]->p_dec )
{ {
if( p_sys->es[i]->p_dec ) EsDestroyDecoder( out, p_sys->es[i] );
{ EsCreateDecoder( out, p_sys->es[i] );
EsDestroyDecoder( out, p_sys->es[i] );
EsCreateDecoder( out, p_sys->es[i] );
}
}
else
{
EsUnselect( out, p_sys->es[i],
p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
} }
} }
else
{
EsUnselect( out, p_sys->es[i],
p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
}
} }
} }
} }
return VLC_SUCCESS;
} }
return VLC_SUCCESS;
case ES_OUT_SET_ES_DEFAULT: }
{
es_out_id_t *es = va_arg( args, es_out_id_t * );
if( es == NULL ) case ES_OUT_SET_ES_DEFAULT:
{ {
/*p_sys->i_default_video_id = -1;*/ es_out_id_t *es = va_arg( args, es_out_id_t * );
/*p_sys->i_default_audio_id = -1;*/
p_sys->i_default_sub_id = -1; if( es == NULL )
} {
else if( es == (es_out_id_t*)((uint8_t*)NULL+AUDIO_ES) ) /*p_sys->i_default_video_id = -1;*/
{ /*p_sys->i_default_audio_id = -1;*/
/*p_sys->i_default_video_id = -1;*/ p_sys->i_default_sub_id = -1;
} }
else if( es == (es_out_id_t*)((uint8_t*)NULL+VIDEO_ES) ) else if( es == (es_out_id_t*)((uint8_t*)NULL+AUDIO_ES) )
{ {
/*p_sys->i_default_audio_id = -1;*/ /*p_sys->i_default_video_id = -1;*/
} }
else if( es == (es_out_id_t*)((uint8_t*)NULL+SPU_ES) ) else if( es == (es_out_id_t*)((uint8_t*)NULL+VIDEO_ES) )
{ {
p_sys->i_default_sub_id = -1; /*p_sys->i_default_audio_id = -1;*/
} }
else if( es == (es_out_id_t*)((uint8_t*)NULL+SPU_ES) )
{
p_sys->i_default_sub_id = -1;
}
else
{
/*if( es->fmt.i_cat == VIDEO_ES )
p_sys->i_default_video_id = es->i_id;
else else
{ if( es->fmt.i_cat == AUDIO_ES )
/*if( es->fmt.i_cat == VIDEO_ES ) p_sys->i_default_audio_id = es->i_id;
p_sys->i_default_video_id = es->i_id; else*/
else if( es->fmt.i_cat == SPU_ES )
if( es->fmt.i_cat == AUDIO_ES ) p_sys->i_default_sub_id = es->i_id;
p_sys->i_default_audio_id = es->i_id;
else*/
if( es->fmt.i_cat == SPU_ES )
p_sys->i_default_sub_id = es->i_id;
}
return VLC_SUCCESS;
} }
return VLC_SUCCESS;
}
case ES_OUT_SET_PCR: case ES_OUT_SET_PCR:
case ES_OUT_SET_GROUP_PCR: case ES_OUT_SET_GROUP_PCR:
{ {
es_out_pgrm_t *p_pgrm = NULL; es_out_pgrm_t *p_pgrm = NULL;
int i_group = 0; int i_group = 0;
int64_t i_pcr; int64_t i_pcr;
/* Search program */ /* Search program */
if( i_query == ES_OUT_SET_PCR ) if( i_query == ES_OUT_SET_PCR )
{ {
p_pgrm = p_sys->p_pgrm; p_pgrm = p_sys->p_pgrm;
if( !p_pgrm )
p_pgrm = EsOutProgramAdd( out, i_group ); /* Create it */
}
else
{
i_group = (int)va_arg( args, int );
p_pgrm = EsOutProgramFind( out, i_group );
}
if( !p_pgrm ) if( !p_pgrm )
return VLC_EGENERIC; p_pgrm = EsOutProgramAdd( out, i_group ); /* Create it */
}
else
{
i_group = (int)va_arg( args, int );
p_pgrm = EsOutProgramFind( out, i_group );
}
if( !p_pgrm )
return VLC_EGENERIC;
i_pcr = (int64_t)va_arg( args, int64_t ); i_pcr = (int64_t)va_arg( args, int64_t );
if( i_pcr <= VLC_TS_INVALID ) if( i_pcr <= VLC_TS_INVALID )
{ {
msg_Err( p_sys->p_input, "Invalid PCR value in ES_OUT_SET_(GROUP_)PCR !" ); msg_Err( p_sys->p_input, "Invalid PCR value in ES_OUT_SET_(GROUP_)PCR !" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* TODO do not use mdate() but proper stream acquisition date */ /* TODO do not use mdate() but proper stream acquisition date */
bool b_late; bool b_late;
input_clock_Update( p_pgrm->p_clock, VLC_OBJECT(p_sys->p_input), input_clock_Update( p_pgrm->p_clock, VLC_OBJECT(p_sys->p_input),
&b_late, &b_late,
p_sys->p_input->p->b_can_pace_control || p_sys->b_buffering, p_sys->p_input->p->b_can_pace_control || p_sys->b_buffering,
EsOutIsExtraBufferingAllowed( out ), EsOutIsExtraBufferingAllowed( out ),
i_pcr, mdate() ); i_pcr, mdate() );
if( p_pgrm == p_sys->p_pgrm ) 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 && ( !p_sys->p_input->p->p_sout ||
!p_sys->p_input->p->b_out_pace_control ) )
{ {
if( p_sys->b_buffering ) const mtime_t i_pts_delay_base = p_sys->i_pts_delay - p_sys->i_pts_jitter;
mtime_t i_pts_delay = input_clock_GetJitter( p_pgrm->p_clock );
/* Avoid dangerously high value */
const mtime_t i_jitter_max = INT64_C(1000) * var_InheritInteger( p_sys->p_input, "clock-jitter" );
if( i_pts_delay > __MIN( i_pts_delay_base + i_jitter_max, INPUT_PTS_DELAY_MAX ) )
{ {
/* Check buffering state on master clock update */ msg_Err( p_sys->p_input,
EsOutDecodersStopBuffering( out, false ); "ES_OUT_SET_(GROUP_)PCR is called too late (jitter of %d ms ignored)",
(int)(i_pts_delay - i_pts_delay_base) / 1000 );
i_pts_delay = p_sys->i_pts_delay;
} }
else if( b_late && ( !p_sys->p_input->p->p_sout || else
!p_sys->p_input->p->b_out_pace_control ) )
{ {
const mtime_t i_pts_delay_base = p_sys->i_pts_delay - p_sys->i_pts_jitter; msg_Err( p_sys->p_input,
mtime_t i_pts_delay = input_clock_GetJitter( p_pgrm->p_clock ); "ES_OUT_SET_(GROUP_)PCR is called too late (pts_delay increased to %d ms)",
(int)(i_pts_delay/1000) );
/* Avoid dangerously high value */ }
const mtime_t i_jitter_max = INT64_C(1000) * var_InheritInteger( p_sys->p_input, "clock-jitter" );
if( i_pts_delay > __MIN( i_pts_delay_base + i_jitter_max, INPUT_PTS_DELAY_MAX ) )
{
msg_Err( p_sys->p_input,
"ES_OUT_SET_(GROUP_)PCR is called too late (jitter of %d ms ignored)",
(int)(i_pts_delay - i_pts_delay_base) / 1000 );
i_pts_delay = p_sys->i_pts_delay;
}
else
{
msg_Err( p_sys->p_input,
"ES_OUT_SET_(GROUP_)PCR is called too late (pts_delay increased to %d ms)",
(int)(i_pts_delay/1000) );
}
/* Force a rebufferization when we are too late */ /* Force a rebufferization when we are too late */
/* It is not really good, as we throw away already buffered data /* It is not really good, as we throw away already buffered data
* TODO have a mean to correctly reenter bufferization */ * TODO have a mean to correctly reenter bufferization */
es_out_Control( out, ES_OUT_RESET_PCR ); es_out_Control( out, ES_OUT_RESET_PCR );
es_out_SetJitter( out, i_pts_delay_base, i_pts_delay - i_pts_delay_base, p_sys->i_cr_average ); es_out_SetJitter( out, i_pts_delay_base, i_pts_delay - i_pts_delay_base, p_sys->i_cr_average );
}
} }
return VLC_SUCCESS;
} }
return VLC_SUCCESS;
}
case ES_OUT_RESET_PCR: case ES_OUT_RESET_PCR:
msg_Err( p_sys->p_input, "ES_OUT_RESET_PCR called" ); msg_Err( p_sys->p_input, "ES_OUT_RESET_PCR called" );
EsOutChangePosition( out ); EsOutChangePosition( out );
return VLC_SUCCESS; return VLC_SUCCESS;
case ES_OUT_SET_GROUP: case ES_OUT_SET_GROUP:
{
int i = va_arg( args, int );
for( int j = 0; j < p_sys->i_pgrm; j++ )
{ {
int i = va_arg( args, int ); es_out_pgrm_t *p_pgrm = p_sys->pgrm[j];
for( int j = 0; j < p_sys->i_pgrm; j++ ) if( p_pgrm->i_id == i )
{ {
es_out_pgrm_t *p_pgrm = p_sys->pgrm[j]; EsOutProgramSelect( out, p_pgrm );
if( p_pgrm->i_id == i ) return VLC_SUCCESS;
{
EsOutProgramSelect( out, p_pgrm );
return VLC_SUCCESS;
}
} }
return VLC_EGENERIC;
} }
return VLC_EGENERIC;
}
case ES_OUT_SET_ES_FMT: case ES_OUT_SET_ES_FMT:
{ {
/* This ain't pretty but is need by some demuxers (eg. Ogg ) /* This ain't pretty but is need by some demuxers (eg. Ogg )
* to update the p_extra data */ * to update the p_extra data */
es_out_id_t *es = va_arg( args, es_out_id_t * ); es_out_id_t *es = va_arg( args, es_out_id_t * );
es_format_t *p_fmt = va_arg( args, es_format_t * ); es_format_t *p_fmt = va_arg( args, es_format_t * );
if( es == NULL ) if( es == NULL )
return VLC_EGENERIC; return VLC_EGENERIC;
if( p_fmt->i_extra ) if( p_fmt->i_extra )
{ {
es->fmt.i_extra = p_fmt->i_extra; es->fmt.i_extra = p_fmt->i_extra;
es->fmt.p_extra = xrealloc( 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 ); memcpy( es->fmt.p_extra, p_fmt->p_extra, p_fmt->i_extra );
if( !es->p_dec ) if( !es->p_dec )
return VLC_SUCCESS; return VLC_SUCCESS;
#if 1 #if 1
EsDestroyDecoder( out, es ); EsDestroyDecoder( out, es );
EsCreateDecoder( out, es ); EsCreateDecoder( out, es );
#else #else
es->p_dec->fmt_in.i_extra = p_fmt->i_extra; es->p_dec->fmt_in.i_extra = p_fmt->i_extra;
es->p_dec->fmt_in.p_extra = es->p_dec->fmt_in.p_extra =
xrealloc( 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, memcpy( es->p_dec->fmt_in.p_extra,
p_fmt->p_extra, p_fmt->i_extra ); p_fmt->p_extra, p_fmt->i_extra );
#endif #endif
}
return VLC_SUCCESS;
} }
case ES_OUT_SET_ES_SCRAMBLED_STATE: return VLC_SUCCESS;
{ }
es_out_id_t *es = va_arg( args, es_out_id_t * );
bool b_scrambled = (bool)va_arg( args, int );
if( !es->b_scrambled != !b_scrambled ) case ES_OUT_SET_ES_SCRAMBLED_STATE:
{ {
es->b_scrambled = b_scrambled; es_out_id_t *es = va_arg( args, es_out_id_t * );
EsOutProgramUpdateScrambled( out, es->p_pgrm ); bool b_scrambled = (bool)va_arg( args, int );
}
return VLC_SUCCESS;
}
case ES_OUT_SET_NEXT_DISPLAY_TIME: if( !es->b_scrambled != !b_scrambled )
{ {
const int64_t i_date = (int64_t)va_arg( args, int64_t ); es->b_scrambled = b_scrambled;
EsOutProgramUpdateScrambled( out, es->p_pgrm );
if( i_date < 0 )
return VLC_EGENERIC;
p_sys->i_preroll_end = i_date;
return VLC_SUCCESS;
} }
case ES_OUT_SET_GROUP_META: return VLC_SUCCESS;
{ }
int i_group = (int)va_arg( args, int );
const vlc_meta_t *p_meta = va_arg( args, const vlc_meta_t * );
EsOutProgramMeta( out, i_group, p_meta ); case ES_OUT_SET_NEXT_DISPLAY_TIME:
return VLC_SUCCESS; {
} const int64_t i_date = (int64_t)va_arg( args, int64_t );
case ES_OUT_SET_GROUP_EPG:
{
int i_group = (int)va_arg( args, int );
const vlc_epg_t *p_epg = va_arg( args, const vlc_epg_t * );
EsOutProgramEpg( out, i_group, p_epg ); if( i_date < 0 )
return VLC_SUCCESS; return VLC_EGENERIC;
}
case ES_OUT_DEL_GROUP: p_sys->i_preroll_end = i_date;
{
int i_group = (int)va_arg( args, int );
return EsOutProgramDel( out, i_group ); return VLC_SUCCESS;
} }
case ES_OUT_SET_GROUP_META:
{
int i_group = (int)va_arg( args, int );
const vlc_meta_t *p_meta = va_arg( args, const vlc_meta_t * );
case ES_OUT_SET_META: EsOutProgramMeta( out, i_group, p_meta );
{ return VLC_SUCCESS;
const vlc_meta_t *p_meta = va_arg( args, const vlc_meta_t * ); }
case ES_OUT_SET_GROUP_EPG:
{
int i_group = (int)va_arg( args, int );
const vlc_epg_t *p_epg = va_arg( args, const vlc_epg_t * );
EsOutMeta( out, p_meta ); EsOutProgramEpg( out, i_group, p_epg );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
case ES_OUT_GET_WAKE_UP: case ES_OUT_DEL_GROUP:
{ {
mtime_t *pi_wakeup = (mtime_t*)va_arg( args, mtime_t* ); int i_group = (int)va_arg( args, int );
*pi_wakeup = EsOutGetWakeup( out );
return VLC_SUCCESS;
}
case ES_OUT_SET_ES_BY_ID: return EsOutProgramDel( out, i_group );
case ES_OUT_RESTART_ES_BY_ID: }
case ES_OUT_SET_ES_DEFAULT_BY_ID:
{
const int i_id = (int)va_arg( args, int );
es_out_id_t *p_es = EsOutGetFromID( out, i_id );
int i_new_query;
switch( i_query ) case ES_OUT_SET_META:
{ {
case ES_OUT_SET_ES_BY_ID: i_new_query = ES_OUT_SET_ES; break; const vlc_meta_t *p_meta = va_arg( args, const vlc_meta_t * );
case ES_OUT_RESTART_ES_BY_ID: i_new_query = ES_OUT_RESTART_ES; break;
case ES_OUT_SET_ES_DEFAULT_BY_ID: i_new_query = ES_OUT_SET_ES_DEFAULT; break;
default:
assert(0);
}
/* TODO if the lock is made non recursive it should be changed */
int i_ret = es_out_Control( out, i_new_query, p_es );
/* Clean up vout after user action (in active mode only). EsOutMeta( out, p_meta );
* FIXME it does not work well with multiple video windows */ return VLC_SUCCESS;
if( p_sys->b_active ) }
input_resource_TerminateVout( p_sys->p_input->p->p_resource );
return i_ret;
}
case ES_OUT_GET_ES_OBJECTS_BY_ID: case ES_OUT_GET_WAKE_UP:
{ {
const int i_id = va_arg( args, int ); mtime_t *pi_wakeup = (mtime_t*)va_arg( args, mtime_t* );
es_out_id_t *p_es = EsOutGetFromID( out, i_id ); *pi_wakeup = EsOutGetWakeup( out );
if( !p_es ) return VLC_SUCCESS;
return VLC_EGENERIC; }
vlc_object_t **pp_decoder = va_arg( args, vlc_object_t ** ); case ES_OUT_SET_ES_BY_ID:
vout_thread_t **pp_vout = va_arg( args, vout_thread_t ** ); case ES_OUT_RESTART_ES_BY_ID:
audio_output_t **pp_aout = va_arg( args, audio_output_t ** ); case ES_OUT_SET_ES_DEFAULT_BY_ID:
if( p_es->p_dec ) {
{ const int i_id = (int)va_arg( args, int );
if( pp_decoder ) es_out_id_t *p_es = EsOutGetFromID( out, i_id );
*pp_decoder = vlc_object_hold( p_es->p_dec ); int i_new_query;
input_DecoderGetObjects( p_es->p_dec, pp_vout, pp_aout );
}
else
{
if( pp_decoder )
*pp_decoder = NULL;
if( pp_vout )
*pp_vout = NULL;
if( pp_aout )
*pp_aout = NULL;
}
return VLC_SUCCESS;
}
case ES_OUT_GET_BUFFERING: switch( i_query )
{ {
bool *pb = va_arg( args, bool* ); case ES_OUT_SET_ES_BY_ID: i_new_query = ES_OUT_SET_ES; break;
*pb = p_sys->b_buffering; case ES_OUT_RESTART_ES_BY_ID: i_new_query = ES_OUT_RESTART_ES; break;
return VLC_SUCCESS; case ES_OUT_SET_ES_DEFAULT_BY_ID: i_new_query = ES_OUT_SET_ES_DEFAULT; break;
default:
assert(0);
} }
/* TODO if the lock is made non recursive it should be changed */
int i_ret = es_out_Control( out, i_new_query, p_es );
case ES_OUT_GET_EMPTY: /* Clean up vout after user action (in active mode only).
{ * FIXME it does not work well with multiple video windows */
bool *pb = va_arg( args, bool* ); if( p_sys->b_active )
*pb = EsOutDecodersIsEmpty( out ); input_resource_TerminateVout( p_sys->p_input->p->p_resource );
return VLC_SUCCESS; return i_ret;
} }
case ES_OUT_SET_DELAY: 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 ** );
audio_output_t **pp_aout = va_arg( args, audio_output_t ** );
if( p_es->p_dec )
{ {
const int i_cat = (int)va_arg( args, int ); if( pp_decoder )
const mtime_t i_delay = (mtime_t)va_arg( args, mtime_t ); *pp_decoder = vlc_object_hold( p_es->p_dec );
EsOutSetDelay( out, i_cat, i_delay ); input_DecoderGetObjects( p_es->p_dec, pp_vout, pp_aout );
return VLC_SUCCESS;
} }
else
case ES_OUT_SET_RECORD_STATE:
{ {
bool b = va_arg( args, int ); if( pp_decoder )
return EsOutSetRecord( out, b ); *pp_decoder = NULL;
if( pp_vout )
*pp_vout = NULL;
if( pp_aout )
*pp_aout = NULL;
} }
return VLC_SUCCESS;
}
case ES_OUT_SET_PAUSE_STATE: case ES_OUT_GET_BUFFERING:
{ {
const bool b_source_paused = (bool)va_arg( args, int ); bool *pb = va_arg( args, bool* );
const bool b_paused = (bool)va_arg( args, int ); *pb = p_sys->b_buffering;
const mtime_t i_date = (mtime_t) va_arg( args, mtime_t ); return VLC_SUCCESS;
}
assert( !b_source_paused == !b_paused ); case ES_OUT_GET_EMPTY:
EsOutChangePause( out, b_paused, i_date ); {
bool *pb = va_arg( args, bool* );
*pb = EsOutDecodersIsEmpty( out );
return VLC_SUCCESS;
}
return VLC_SUCCESS; case ES_OUT_SET_DELAY:
} {
const int i_cat = (int)va_arg( args, int );
const mtime_t i_delay = (mtime_t)va_arg( args, mtime_t );
EsOutSetDelay( out, i_cat, i_delay );
return VLC_SUCCESS;
}
case ES_OUT_SET_RATE: case ES_OUT_SET_RECORD_STATE:
{ {
const int i_src_rate = (int)va_arg( args, int ); bool b = va_arg( args, int );
const int i_rate = (int)va_arg( args, int ); return EsOutSetRecord( out, b );
}
assert( i_src_rate == i_rate ); case ES_OUT_SET_PAUSE_STATE:
EsOutChangeRate( out, i_rate ); {
const bool b_source_paused = (bool)va_arg( args, int );
const bool b_paused = (bool)va_arg( args, int );
const mtime_t i_date = (mtime_t) va_arg( args, mtime_t );
return VLC_SUCCESS; assert( !b_source_paused == !b_paused );
} EsOutChangePause( out, b_paused, i_date );
case ES_OUT_SET_TIME: return VLC_SUCCESS;
{ }
const mtime_t i_date = (mtime_t)va_arg( args, mtime_t );
assert( i_date == -1 ); case ES_OUT_SET_RATE:
EsOutChangePosition( out ); {
const int i_src_rate = (int)va_arg( args, int );
const int i_rate = (int)va_arg( args, int );
return VLC_SUCCESS; assert( i_src_rate == i_rate );
} EsOutChangeRate( out, i_rate );
case ES_OUT_SET_FRAME_NEXT: return VLC_SUCCESS;
EsOutFrameNext( out ); }
return VLC_SUCCESS;
case ES_OUT_SET_TIMES: case ES_OUT_SET_TIME:
{ {
double f_position = (double)va_arg( args, double ); const mtime_t i_date = (mtime_t)va_arg( args, mtime_t );
mtime_t i_time = (mtime_t)va_arg( args, mtime_t );
mtime_t i_length = (mtime_t)va_arg( args, mtime_t );
input_SendEventLength( p_sys->p_input, i_length ); assert( i_date == -1 );
EsOutChangePosition( out );
if( !p_sys->b_buffering ) return VLC_SUCCESS;
{ }
mtime_t i_delay;
/* Fix for buffering delay */ case ES_OUT_SET_FRAME_NEXT:
if( !p_sys->p_input->p->p_sout || EsOutFrameNext( out );
!p_sys->p_input->p->b_out_pace_control ) return VLC_SUCCESS;
i_delay = EsOutGetBuffering( out );
else
i_delay = 0;
i_time -= i_delay; case ES_OUT_SET_TIMES:
if( i_time < 0 ) {
i_time = 0; 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 );
if( i_length > 0 ) input_SendEventLength( p_sys->p_input, i_length );
f_position -= (double)i_delay / i_length;
if( f_position < 0 )
f_position = 0;
input_SendEventPosition( p_sys->p_input, f_position, i_time ); if( !p_sys->b_buffering )
}
return VLC_SUCCESS;
}
case ES_OUT_SET_JITTER:
{ {
mtime_t i_pts_delay = (mtime_t)va_arg( args, mtime_t ); mtime_t i_delay;
mtime_t i_pts_jitter = (mtime_t)va_arg( args, mtime_t );
int i_cr_average = (int)va_arg( args, int );
bool b_change_clock = /* Fix for buffering delay */
i_pts_delay + i_pts_jitter != p_sys->i_pts_delay || if( !p_sys->p_input->p->p_sout ||
i_cr_average != p_sys->i_cr_average; !p_sys->p_input->p->b_out_pace_control )
i_delay = EsOutGetBuffering( out );
else
i_delay = 0;
assert( i_pts_jitter >= 0 ); i_time -= i_delay;
p_sys->i_pts_delay = i_pts_delay + i_pts_jitter; if( i_time < 0 )
p_sys->i_pts_jitter = i_pts_jitter; i_time = 0;
p_sys->i_cr_average = i_cr_average;
for( int i = 0; i < p_sys->i_pgrm && b_change_clock; i++ ) if( i_length > 0 )
input_clock_SetJitter( p_sys->pgrm[i]->p_clock, f_position -= (double)i_delay / i_length;
i_pts_delay + i_pts_jitter, i_cr_average ); if( f_position < 0 )
return VLC_SUCCESS; f_position = 0;
input_SendEventPosition( p_sys->p_input, f_position, i_time );
} }
return VLC_SUCCESS;
}
case ES_OUT_SET_JITTER:
{
mtime_t i_pts_delay = (mtime_t)va_arg( args, mtime_t );
mtime_t i_pts_jitter = (mtime_t)va_arg( args, mtime_t );
int i_cr_average = (int)va_arg( args, int );
case ES_OUT_GET_PCR_SYSTEM: bool b_change_clock =
{ i_pts_delay + i_pts_jitter != p_sys->i_pts_delay ||
if( p_sys->b_buffering ) i_cr_average != p_sys->i_cr_average;
return VLC_EGENERIC;
es_out_pgrm_t *p_pgrm = p_sys->p_pgrm; assert( i_pts_jitter >= 0 );
if( !p_pgrm ) p_sys->i_pts_delay = i_pts_delay + i_pts_jitter;
return VLC_EGENERIC; p_sys->i_pts_jitter = i_pts_jitter;
p_sys->i_cr_average = i_cr_average;
mtime_t *pi_system = va_arg( args, mtime_t *); for( int i = 0; i < p_sys->i_pgrm && b_change_clock; i++ )
mtime_t *pi_delay = va_arg( args, mtime_t *); input_clock_SetJitter( p_sys->pgrm[i]->p_clock,
input_clock_GetSystemOrigin( p_pgrm->p_clock, pi_system, pi_delay ); i_pts_delay + i_pts_jitter, i_cr_average );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
case ES_OUT_MODIFY_PCR_SYSTEM: case ES_OUT_GET_PCR_SYSTEM:
{ {
if( p_sys->b_buffering ) if( p_sys->b_buffering )
return VLC_EGENERIC; return VLC_EGENERIC;
es_out_pgrm_t *p_pgrm = p_sys->p_pgrm; es_out_pgrm_t *p_pgrm = p_sys->p_pgrm;
if( !p_pgrm ) if( !p_pgrm )
return VLC_EGENERIC; return VLC_EGENERIC;
const bool b_absolute = va_arg( args, int ); mtime_t *pi_system = va_arg( args, mtime_t *);
const mtime_t i_system = va_arg( args, mtime_t ); mtime_t *pi_delay = va_arg( args, mtime_t *);
input_clock_ChangeSystemOrigin( p_pgrm->p_clock, b_absolute, i_system ); input_clock_GetSystemOrigin( p_pgrm->p_clock, pi_system, pi_delay );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
case ES_OUT_SET_EOS:
{
for (int i = 0; i < p_sys->i_es; i++) {
es_out_id_t *id = p_sys->es[i];
decoder_t *p_dec = id->p_dec;
if (!p_dec)
continue;
block_t *p_block = block_Alloc(0);
if( !p_block )
break;
p_block->i_flags |= BLOCK_FLAG_CORE_EOS; case ES_OUT_MODIFY_PCR_SYSTEM:
input_DecoderDecode(p_dec, p_block, false); {
} if( p_sys->b_buffering )
return VLC_SUCCESS; return VLC_EGENERIC;
}
default: es_out_pgrm_t *p_pgrm = p_sys->p_pgrm;
msg_Err( p_sys->p_input, "unknown query in es_out_Control" ); if( !p_pgrm )
return VLC_EGENERIC; 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;
}
case ES_OUT_SET_EOS:
{
for (int i = 0; i < p_sys->i_es; i++) {
es_out_id_t *id = p_sys->es[i];
decoder_t *p_dec = id->p_dec;
if (!p_dec)
continue;
block_t *p_block = block_Alloc(0);
if( !p_block )
break;
p_block->i_flags |= BLOCK_FLAG_CORE_EOS;
input_DecoderDecode(p_dec, p_block, false);
}
return VLC_SUCCESS;
}
default:
msg_Err( p_sys->p_input, "unknown query in es_out_Control" );
return VLC_EGENERIC;
} }
} }
static int EsOutControl( es_out_t *out, int i_query, va_list args ) static int EsOutControl( es_out_t *out, int i_query, va_list args )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment