|
|
|
@ -153,6 +153,7 @@ typedef struct attribute_packed |
|
|
|
{ |
|
|
|
ts_cmd_header_t header; |
|
|
|
int i_query; |
|
|
|
input_source_t *in; |
|
|
|
|
|
|
|
union |
|
|
|
{ |
|
|
|
@ -308,12 +309,13 @@ static int CmdInitAdd ( ts_cmd_add_t *, input_source_t *, es_out_id_t *, con |
|
|
|
static void CmdInitSend ( ts_cmd_send_t *, es_out_id_t *, block_t * ); |
|
|
|
static int CmdInitDel ( ts_cmd_del_t *, es_out_id_t * ); |
|
|
|
static int CmdInitControl( ts_cmd_control_t *, input_source_t *, int i_query, va_list, bool b_copy ); |
|
|
|
static int CmdInitPrivControl( ts_cmd_privcontrol_t *, int i_query, va_list, bool b_copy ); |
|
|
|
static int CmdInitPrivControl( ts_cmd_privcontrol_t *, input_source_t *, int i_query, va_list, bool b_copy ); |
|
|
|
|
|
|
|
/* */ |
|
|
|
static void CmdCleanAdd ( ts_cmd_add_t * ); |
|
|
|
static void CmdCleanSend ( ts_cmd_send_t * ); |
|
|
|
static void CmdCleanControl( ts_cmd_control_t * ); |
|
|
|
static void CmdCleanPrivControl( ts_cmd_privcontrol_t * ); |
|
|
|
|
|
|
|
/* */ |
|
|
|
static void CmdExecuteAdd ( es_out_t *, ts_cmd_add_t * ); |
|
|
|
@ -456,6 +458,24 @@ static inline int es_out_in_Control( es_out_t *p_out, input_source_t *in, |
|
|
|
return i_result; |
|
|
|
} |
|
|
|
|
|
|
|
static inline int es_out_in_vaPrivControl( es_out_t *p_out, input_source_t *in, |
|
|
|
int i_query, va_list args) |
|
|
|
{ |
|
|
|
return p_out->cbs->priv_control( p_out, in, i_query, args ); |
|
|
|
} |
|
|
|
|
|
|
|
static inline int es_out_in_PrivControl( es_out_t *p_out, input_source_t *in, |
|
|
|
int i_query, ... ) |
|
|
|
{ |
|
|
|
va_list args; |
|
|
|
int i_result; |
|
|
|
|
|
|
|
va_start( args, i_query ); |
|
|
|
i_result = es_out_in_vaPrivControl( p_out, in, i_query, args ); |
|
|
|
va_end( args ); |
|
|
|
return i_result; |
|
|
|
} |
|
|
|
|
|
|
|
static int ControlLockedGetEmpty( es_out_t *p_out, input_source_t *in, |
|
|
|
bool *pb_empty ) |
|
|
|
{ |
|
|
|
@ -471,7 +491,7 @@ static int ControlLockedGetEmpty( es_out_t *p_out, input_source_t *in, |
|
|
|
|
|
|
|
return VLC_SUCCESS; |
|
|
|
} |
|
|
|
static int ControlLockedGetWakeup( es_out_t *p_out, vlc_tick_t *pi_wakeup ) |
|
|
|
static int ControlLockedGetWakeup( es_out_t *p_out, input_source_t *in, vlc_tick_t *pi_wakeup ) |
|
|
|
{ |
|
|
|
es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out); |
|
|
|
|
|
|
|
@ -482,30 +502,37 @@ static int ControlLockedGetWakeup( es_out_t *p_out, vlc_tick_t *pi_wakeup ) |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
*pi_wakeup = es_out_GetWakeup( p_sys->p_out ); |
|
|
|
int ret = es_out_in_PrivControl( p_sys->p_out, in, ES_OUT_PRIV_GET_WAKE_UP, |
|
|
|
pi_wakeup ); |
|
|
|
assert( !ret ); |
|
|
|
} |
|
|
|
|
|
|
|
return VLC_SUCCESS; |
|
|
|
} |
|
|
|
static int ControlLockedGetBuffering( es_out_t *p_out, bool *pb_buffering ) |
|
|
|
static int ControlLockedGetBuffering( es_out_t *p_out, input_source_t *in, bool *pb_buffering ) |
|
|
|
{ |
|
|
|
es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out); |
|
|
|
|
|
|
|
if( p_sys->b_delayed ) |
|
|
|
*pb_buffering = true; |
|
|
|
else |
|
|
|
*pb_buffering = es_out_GetBuffering( p_sys->p_out ); |
|
|
|
{ |
|
|
|
int ret = es_out_in_PrivControl( p_sys->p_out, in, ES_OUT_PRIV_GET_BUFFERING, |
|
|
|
pb_buffering ); |
|
|
|
assert( !ret ); |
|
|
|
} |
|
|
|
|
|
|
|
return VLC_SUCCESS; |
|
|
|
} |
|
|
|
static int ControlLockedSetPauseState( es_out_t *p_out, bool b_source_paused, bool b_paused, vlc_tick_t i_date ) |
|
|
|
static int ControlLockedSetPauseState( es_out_t *p_out, input_source_t *in, bool b_source_paused, bool b_paused, vlc_tick_t i_date ) |
|
|
|
{ |
|
|
|
es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out); |
|
|
|
int i_ret; |
|
|
|
|
|
|
|
if( !p_sys->b_delayed && !b_source_paused == !b_paused ) |
|
|
|
{ |
|
|
|
i_ret = es_out_SetPauseState( p_sys->p_out, b_source_paused, b_paused, i_date ); |
|
|
|
i_ret = es_out_in_PrivControl( p_sys->p_out, in, ES_OUT_PRIV_SET_PAUSE_STATE, |
|
|
|
b_source_paused, b_paused, i_date ); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
@ -533,14 +560,15 @@ static int ControlLockedSetPauseState( es_out_t *p_out, bool b_source_paused, bo |
|
|
|
} |
|
|
|
return i_ret; |
|
|
|
} |
|
|
|
static int ControlLockedSetRate( es_out_t *p_out, float src_rate, float rate ) |
|
|
|
static int ControlLockedSetRate( es_out_t *p_out, input_source_t *in, float src_rate, float rate ) |
|
|
|
{ |
|
|
|
es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out); |
|
|
|
int i_ret; |
|
|
|
|
|
|
|
if( !p_sys->b_delayed && src_rate == rate ) |
|
|
|
{ |
|
|
|
i_ret = es_out_SetRate( p_sys->p_out, src_rate, rate ); |
|
|
|
i_ret = es_out_in_PrivControl( p_sys->p_out, in, ES_OUT_PRIV_SET_RATE, |
|
|
|
src_rate, rate ); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
@ -569,11 +597,11 @@ static int ControlLockedSetRate( es_out_t *p_out, float src_rate, float rate ) |
|
|
|
} |
|
|
|
return i_ret; |
|
|
|
} |
|
|
|
static int ControlLockedSetFrameNext( es_out_t *p_out ) |
|
|
|
static int ControlLockedSetFrameNext( es_out_t *p_out, input_source_t *in ) |
|
|
|
{ |
|
|
|
es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out); |
|
|
|
|
|
|
|
return es_out_SetFrameNext( p_sys->p_out ); |
|
|
|
return es_out_in_PrivControl( p_sys->p_out, in, ES_OUT_PRIV_SET_FRAME_NEXT ); |
|
|
|
} |
|
|
|
|
|
|
|
static int ControlLocked( es_out_t *p_out, input_source_t *in, int i_query, |
|
|
|
@ -707,7 +735,7 @@ static int Control( es_out_t *p_tsout, input_source_t *in, int i_query, va_list |
|
|
|
return i_ret; |
|
|
|
} |
|
|
|
|
|
|
|
static int PrivControlLocked( es_out_t *p_tsout, int i_query, va_list args ) |
|
|
|
static int PrivControlLocked( es_out_t *p_tsout, input_source_t *in, int i_query, va_list args ) |
|
|
|
{ |
|
|
|
es_out_sys_t *p_sys = container_of(p_tsout, es_out_sys_t, out); |
|
|
|
|
|
|
|
@ -720,7 +748,7 @@ static int PrivControlLocked( es_out_t *p_tsout, int i_query, va_list args ) |
|
|
|
case ES_OUT_PRIV_SET_EOS: |
|
|
|
{ |
|
|
|
ts_cmd_t cmd; |
|
|
|
if( CmdInitPrivControl( &cmd.privcontrol, i_query, args, p_sys->b_delayed ) ) |
|
|
|
if( CmdInitPrivControl( &cmd.privcontrol, in, i_query, args, p_sys->b_delayed ) ) |
|
|
|
return VLC_EGENERIC; |
|
|
|
if( p_sys->b_delayed ) |
|
|
|
{ |
|
|
|
@ -732,12 +760,12 @@ static int PrivControlLocked( es_out_t *p_tsout, int i_query, va_list args ) |
|
|
|
case ES_OUT_PRIV_GET_WAKE_UP: /* TODO ? */ |
|
|
|
{ |
|
|
|
vlc_tick_t *pi_wakeup = va_arg( args, vlc_tick_t* ); |
|
|
|
return ControlLockedGetWakeup( p_tsout, pi_wakeup ); |
|
|
|
return ControlLockedGetWakeup( p_tsout, in, pi_wakeup ); |
|
|
|
} |
|
|
|
case ES_OUT_PRIV_GET_BUFFERING: |
|
|
|
{ |
|
|
|
bool *pb_buffering = va_arg( args, bool* ); |
|
|
|
return ControlLockedGetBuffering( p_tsout, pb_buffering ); |
|
|
|
return ControlLockedGetBuffering( p_tsout, in, pb_buffering ); |
|
|
|
} |
|
|
|
case ES_OUT_PRIV_SET_PAUSE_STATE: |
|
|
|
{ |
|
|
|
@ -745,21 +773,21 @@ static int PrivControlLocked( es_out_t *p_tsout, int i_query, va_list args ) |
|
|
|
const bool b_paused = (bool)va_arg( args, int ); |
|
|
|
const vlc_tick_t i_date = va_arg( args, vlc_tick_t ); |
|
|
|
|
|
|
|
return ControlLockedSetPauseState( p_tsout, b_source_paused, b_paused, i_date ); |
|
|
|
return ControlLockedSetPauseState( p_tsout, in, b_source_paused, b_paused, i_date ); |
|
|
|
} |
|
|
|
case ES_OUT_PRIV_SET_RATE: |
|
|
|
{ |
|
|
|
const float src_rate = va_arg( args, double ); |
|
|
|
const float rate = va_arg( args, double ); |
|
|
|
|
|
|
|
return ControlLockedSetRate( p_tsout, src_rate, rate ); |
|
|
|
return ControlLockedSetRate( p_tsout, in, src_rate, rate ); |
|
|
|
} |
|
|
|
case ES_OUT_PRIV_SET_FRAME_NEXT: |
|
|
|
{ |
|
|
|
return ControlLockedSetFrameNext( p_tsout ); |
|
|
|
return ControlLockedSetFrameNext( p_tsout, in ); |
|
|
|
} |
|
|
|
case ES_OUT_PRIV_GET_GROUP_FORCED: |
|
|
|
return es_out_vaPrivControl( p_sys->p_out, i_query, args ); |
|
|
|
return es_out_in_vaPrivControl( p_sys->p_out, in, i_query, args ); |
|
|
|
/* Invalid queries for this es_out level */ |
|
|
|
case ES_OUT_PRIV_SET_ES: |
|
|
|
case ES_OUT_PRIV_UNSET_ES: |
|
|
|
@ -777,7 +805,7 @@ static int PrivControlLocked( es_out_t *p_tsout, int i_query, va_list args ) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static int PrivControl( es_out_t *p_tsout, int i_query, va_list args ) |
|
|
|
static int PrivControl( es_out_t *p_tsout, input_source_t *in, int i_query, va_list args ) |
|
|
|
{ |
|
|
|
es_out_sys_t *p_sys = container_of(p_tsout, es_out_sys_t, out); |
|
|
|
int i_ret; |
|
|
|
@ -786,7 +814,7 @@ static int PrivControl( es_out_t *p_tsout, int i_query, va_list args ) |
|
|
|
|
|
|
|
TsAutoStop( p_tsout ); |
|
|
|
|
|
|
|
i_ret = PrivControlLocked( p_tsout, i_query, args ); |
|
|
|
i_ret = PrivControlLocked( p_tsout, in, i_query, args ); |
|
|
|
|
|
|
|
vlc_mutex_unlock( &p_sys->lock ); |
|
|
|
|
|
|
|
@ -1206,6 +1234,7 @@ static void *TsRun( void *p_data ) |
|
|
|
break; |
|
|
|
case C_PRIVCONTROL: |
|
|
|
CmdExecutePrivControl( p_ts->p_tsout, &cmd.privcontrol ); |
|
|
|
CmdCleanPrivControl( &cmd.privcontrol ); |
|
|
|
break; |
|
|
|
case C_DEL: |
|
|
|
CmdExecuteDel( p_ts->p_tsout, &cmd.del ); |
|
|
|
@ -1443,6 +1472,7 @@ static void CmdClean( ts_cmd_t *p_cmd ) |
|
|
|
CmdCleanControl( &p_cmd->control ); |
|
|
|
break; |
|
|
|
case C_PRIVCONTROL: |
|
|
|
CmdCleanPrivControl( &p_cmd->privcontrol ); |
|
|
|
break; |
|
|
|
case C_DEL: |
|
|
|
break; |
|
|
|
@ -1776,13 +1806,17 @@ static void CmdCleanControl( ts_cmd_control_t *p_cmd ) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static int CmdInitPrivControl( ts_cmd_privcontrol_t *p_cmd, int i_query, va_list args, bool b_copy ) |
|
|
|
static int CmdInitPrivControl( ts_cmd_privcontrol_t *p_cmd, input_source_t *in, int i_query, va_list args, bool b_copy ) |
|
|
|
{ |
|
|
|
VLC_UNUSED( b_copy ); |
|
|
|
p_cmd->header.i_type = C_PRIVCONTROL; |
|
|
|
p_cmd->header.i_date = vlc_tick_now(); |
|
|
|
p_cmd->i_query = i_query; |
|
|
|
|
|
|
|
if( b_copy ) |
|
|
|
p_cmd->in = in ? input_source_Hold( in ) : NULL; |
|
|
|
else |
|
|
|
p_cmd->in = in; |
|
|
|
|
|
|
|
switch( i_query ) |
|
|
|
{ |
|
|
|
/* Pass-through control */ |
|
|
|
@ -1825,24 +1859,31 @@ static int CmdExecutePrivControl( es_out_t *p_tsout, ts_cmd_privcontrol_t *p_cmd |
|
|
|
{ |
|
|
|
es_out_sys_t *p_sys = container_of(p_tsout, es_out_sys_t, out); |
|
|
|
const int i_query = p_cmd->i_query; |
|
|
|
input_source_t *in = p_cmd->in; |
|
|
|
|
|
|
|
switch( i_query ) |
|
|
|
{ |
|
|
|
/* Pass-through control */ |
|
|
|
case ES_OUT_PRIV_SET_MODE: /* arg1= int */ |
|
|
|
return es_out_PrivControl( p_sys->p_out, i_query, p_cmd->u.i_int ); |
|
|
|
return es_out_in_PrivControl( p_sys->p_out, in, i_query, p_cmd->u.i_int ); |
|
|
|
case ES_OUT_PRIV_SET_JITTER: |
|
|
|
return es_out_PrivControl( p_sys->p_out, i_query, p_cmd->u.jitter.i_pts_delay, |
|
|
|
p_cmd->u.jitter.i_pts_jitter, |
|
|
|
p_cmd->u.jitter.i_cr_average ); |
|
|
|
return es_out_in_PrivControl( p_sys->p_out, in, i_query, p_cmd->u.jitter.i_pts_delay, |
|
|
|
p_cmd->u.jitter.i_pts_jitter, |
|
|
|
p_cmd->u.jitter.i_cr_average ); |
|
|
|
case ES_OUT_PRIV_SET_TIMES: |
|
|
|
return es_out_PrivControl( p_sys->p_out, i_query, |
|
|
|
p_cmd->u.times.f_position, |
|
|
|
p_cmd->u.times.i_time, |
|
|
|
p_cmd->u.times.i_normal_time, |
|
|
|
p_cmd->u.times.i_length ); |
|
|
|
return es_out_in_PrivControl( p_sys->p_out, in, i_query, |
|
|
|
p_cmd->u.times.f_position, |
|
|
|
p_cmd->u.times.i_time, |
|
|
|
p_cmd->u.times.i_normal_time, |
|
|
|
p_cmd->u.times.i_length ); |
|
|
|
case ES_OUT_PRIV_SET_EOS: /* no arg */ |
|
|
|
return es_out_PrivControl( p_sys->p_out, i_query ); |
|
|
|
return es_out_in_PrivControl( p_sys->p_out, in, i_query ); |
|
|
|
default: vlc_assert_unreachable(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void CmdCleanPrivControl( ts_cmd_privcontrol_t *p_cmd ) |
|
|
|
{ |
|
|
|
if( p_cmd->in ) |
|
|
|
input_source_Release( p_cmd->in ); |
|
|
|
} |
|
|
|
|