Commit d8199d8c authored by Jean-Paul Saman's avatar Jean-Paul Saman

input core: add status field per elementary stream

VLC has status reporting on the input state, but not on the output state.
This makes it impossible to know if playback actually started completely from
checking stream status states.

For instance a failed audio output cannot be determined programatically. This
patch adds an extra field per ES (in src/input/es_out.c) to determine the state
of that ES (DISABLE, ENABLED, ERROR).

If CreateDecoder() cannot instantiate an output, then it set p_dec->b_error = true.
This is used to determine what the return value for es_out_GetEsState() should be.
If p_dec->b_error is true, then it returns an ES_OUT_STATE_ES_ERROR to the caller.
Else it returns ES_OUT_STATE_ES_ENABLED or ES_OUT_STATE_ES_DISABLED.

A function 'es_out_GetEsState()' is available to query an input for the state of
the primary audio, video and SPU elementary streams.
parent 2bc56d7d
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#ifndef VLC_CODEC_H #ifndef VLC_CODEC_H
#define VLC_CODEC_H 1 #define VLC_CODEC_H 1
#include <vlc_atomic.h>
#include <vlc_block.h> #include <vlc_block.h>
#include <vlc_es.h> #include <vlc_es.h>
#include <vlc_picture.h> #include <vlc_picture.h>
...@@ -131,7 +132,7 @@ struct decoder_t ...@@ -131,7 +132,7 @@ struct decoder_t
/* Private structure for the owner of the decoder */ /* Private structure for the owner of the decoder */
decoder_owner_sys_t *p_owner; decoder_owner_sys_t *p_owner;
bool b_error; atomic_bool b_error;
}; };
/** /**
......
...@@ -45,7 +45,9 @@ enum es_out_query_e ...@@ -45,7 +45,9 @@ enum es_out_query_e
/* force selection/unselection of the ES (bypass current mode) */ /* force selection/unselection of the ES (bypass current mode) */
ES_OUT_SET_ES_STATE,/* arg1= es_out_id_t* arg2=bool */ ES_OUT_SET_ES_STATE,/* arg1= es_out_id_t* arg2=bool */
ES_OUT_GET_ES_STATE,/* arg1= es_out_id_t* arg2=bool* */ ES_OUT_GET_ES_STATE,/* arg1= es_out_id_t* arg2=bool* arg3=bool* res=can fail
* arg2 is true if es has been selected, false otherwise,
* arg3 is true if es has an error, false otherwise */
/* */ /* */
ES_OUT_SET_GROUP, /* arg1= int */ ES_OUT_SET_GROUP, /* arg1= int */
......
...@@ -297,6 +297,14 @@ typedef enum input_state_e ...@@ -297,6 +297,14 @@ typedef enum input_state_e
ERROR_S, ERROR_S,
} input_state_e; } input_state_e;
/* same order as es_out_state_es_e enum in vlc_es_out.h */
typedef enum input_es_state_e
{
INPUT_ES_STATE_DISABLED = 0,
INPUT_ES_STATE_ENABLED,
INPUT_ES_STATE_ERROR,
} input_es_state_e;
/** /**
* Input rate. * Input rate.
* *
...@@ -480,6 +488,9 @@ enum input_query_e ...@@ -480,6 +488,9 @@ enum input_query_e
/* External clock managments */ /* External clock managments */
INPUT_GET_PCR_SYSTEM, /* arg1=mtime_t *, arg2=mtime_t * res=can fail */ INPUT_GET_PCR_SYSTEM, /* arg1=mtime_t *, arg2=mtime_t * res=can fail */
INPUT_MODIFY_PCR_SYSTEM,/* arg1=int absolute, arg2=mtime_t res=can fail */ INPUT_MODIFY_PCR_SYSTEM,/* arg1=int absolute, arg2=mtime_t res=can fail */
/* Ask status of main ES objects */
INPUT_GET_ES_STATE, /* arg1=int (AUDIO/VIDEO/SPU_ES), arg2=es_out state * res=can fail */
}; };
/** @}*/ /** @}*/
...@@ -606,6 +617,17 @@ static inline int input_GetPcrSystem( input_thread_t *p_input, mtime_t *pi_syste ...@@ -606,6 +617,17 @@ static inline int input_GetPcrSystem( input_thread_t *p_input, mtime_t *pi_syste
{ {
return input_Control( p_input, INPUT_GET_PCR_SYSTEM, pi_system, pi_delay ); return input_Control( p_input, INPUT_GET_PCR_SYSTEM, pi_system, pi_delay );
} }
/**
* It will return the state of the current selected elementary streams for this input.
*/
static inline input_es_state_e input_GetEsState( input_thread_t *p_input, const int i_cat )
{
input_es_state_e state = INPUT_ES_STATE_DISABLED;
input_Control( p_input, INPUT_GET_ES_STATE, i_cat, &state );
return state;
}
/** /**
* \see input_clock_ChangeSystemOrigin * \see input_clock_ChangeSystemOrigin
*/ */
......
...@@ -294,7 +294,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -294,7 +294,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
case STATE_SEND_DATA: case STATE_SEND_DATA:
if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) ) if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
{ {
//p_dec->b_error = true; //atomic_store( &p_dec->b_error, true );
return NULL; return NULL;
} }
......
...@@ -921,7 +921,7 @@ static void ffmpeg_CopyPicture( decoder_t *p_dec, ...@@ -921,7 +921,7 @@ static void ffmpeg_CopyPicture( decoder_t *p_dec,
const char *name = av_get_pix_fmt_name( p_sys->p_context->pix_fmt ); const char *name = av_get_pix_fmt_name( p_sys->p_context->pix_fmt );
msg_Err( p_dec, "Unsupported decoded output format %d (%s)", msg_Err( p_dec, "Unsupported decoded output format %d (%s)",
p_sys->p_context->pix_fmt, name ? name : "unknown" ); p_sys->p_context->pix_fmt, name ? name : "unknown" );
p_dec->b_error = 1; atomic_store( &p_dec->b_error, true );
} }
} }
......
...@@ -310,7 +310,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -310,7 +310,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) ) if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
{ {
//p_dec->b_error = true; //atomic_store( &p_dec->b_error, true );
return NULL; return NULL;
} }
......
...@@ -440,7 +440,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -440,7 +440,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
case STATE_SEND_DATA: case STATE_SEND_DATA:
if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) ) if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
{ {
//p_dec->b_error = true; //atomic_store( &p_dec->b_error, true );
return NULL; return NULL;
} }
......
...@@ -538,7 +538,7 @@ static block_t *DecodeAudio( decoder_t *p_dec, block_t **pp_block ) ...@@ -538,7 +538,7 @@ static block_t *DecodeAudio( decoder_t *p_dec, block_t **pp_block )
if( OpenAudio( p_dec ) ) if( OpenAudio( p_dec ) )
{ {
/* Fatal */ /* Fatal */
p_dec->b_error = true; atomic_store( &p_dec->b_error, true );
return NULL; return NULL;
} }
...@@ -883,7 +883,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -883,7 +883,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
if( OpenVideo( p_dec ) ) if( OpenVideo( p_dec ) )
{ {
/* Fatal */ /* Fatal */
p_dec->b_error = true; atomic_store( &p_dec->b_error, true );
return NULL; return NULL;
} }
p_sys = p_dec->p_sys; p_sys = p_dec->p_sys;
......
...@@ -1057,7 +1057,7 @@ static block_t *PacketizeStreamBlock(decoder_t *p_dec, block_t **pp_block) ...@@ -1057,7 +1057,7 @@ static block_t *PacketizeStreamBlock(decoder_t *p_dec, block_t **pp_block)
p_out_buffer = block_Alloc(p_sys->i_frame_size); p_out_buffer = block_Alloc(p_sys->i_frame_size);
if (!p_out_buffer) { if (!p_out_buffer) {
//p_dec->b_error = true; //atomic_store( &p_dec->b_error, true );
return NULL; return NULL;
} }
p_buf = p_out_buffer->p_buffer; p_buf = p_out_buffer->p_buffer;
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "resource.h" #include "resource.h"
#include "es_out.h" #include "es_out.h"
typedef enum input_es_state_e input_es_state_e;
static void UpdateBookmarksOption( input_thread_t * ); static void UpdateBookmarksOption( input_thread_t * );
...@@ -494,6 +495,24 @@ int input_vaControl( input_thread_t *p_input, int i_query, va_list args ) ...@@ -494,6 +495,24 @@ int input_vaControl( input_thread_t *p_input, int i_query, va_list args )
return es_out_ControlModifyPcrSystem( p_input->p->p_es_out_display, b_absolute, i_system ); return es_out_ControlModifyPcrSystem( p_input->p->p_es_out_display, b_absolute, i_system );
} }
case INPUT_GET_ES_STATE:
{
int i_cat = (int)va_arg( args, int );
input_es_state_e *pi_state = (input_es_state_e *)va_arg( args, input_es_state_e* );
bool b_selected = false, b_error = false;
int ret = es_out_GetEsState( p_input->p->p_es_out_display, i_cat, &b_selected, &b_error);
if (ret != VLC_SUCCESS)
{
*pi_state = INPUT_ES_STATE_DISABLED;
return VLC_EGENERIC;
}
*pi_state = b_error ? INPUT_ES_STATE_ERROR :
( b_selected ? INPUT_ES_STATE_ENABLED : INPUT_ES_STATE_DISABLED );
return ret;
}
default: default:
msg_Err( p_input, "unknown query in input_vaControl" ); msg_Err( p_input, "unknown query in input_vaControl" );
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -554,4 +573,3 @@ static void UpdateBookmarksOption( input_thread_t *p_input ) ...@@ -554,4 +573,3 @@ static void UpdateBookmarksOption( input_thread_t *p_input )
input_SendEventBookmark( p_input ); input_SendEventBookmark( p_input );
} }
...@@ -729,6 +729,8 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent, ...@@ -729,6 +729,8 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
p_dec->pf_get_cc = NULL; p_dec->pf_get_cc = NULL;
p_dec->pf_packetize = NULL; p_dec->pf_packetize = NULL;
atomic_init( &p_dec->b_error, false );
/* Initialize the decoder */ /* Initialize the decoder */
p_dec->p_module = NULL; p_dec->p_module = NULL;
...@@ -1534,7 +1536,7 @@ static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block ) ...@@ -1534,7 +1536,7 @@ static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
{ {
msg_Err( p_dec, "cannot create packetizer output (%4.4s)", msg_Err( p_dec, "cannot create packetizer output (%4.4s)",
(char *)&p_owner->sout.i_codec ); (char *)&p_owner->sout.i_codec );
p_dec->b_error = true; atomic_store( &p_dec->b_error, true );
block_ChainRelease(p_sout_block); block_ChainRelease(p_sout_block);
break; break;
...@@ -1758,7 +1760,7 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block ) ...@@ -1758,7 +1760,7 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner; decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
const bool b_flush_request = p_block && (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH); const bool b_flush_request = p_block && (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH);
if( p_dec->b_error ) if( atomic_load( &p_dec->b_error ) )
{ {
if( p_block ) if( p_block )
block_Release( p_block ); block_Release( p_block );
...@@ -1810,7 +1812,7 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block ) ...@@ -1810,7 +1812,7 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
else else
{ {
msg_Err( p_dec, "unknown ES format" ); msg_Err( p_dec, "unknown ES format" );
p_dec->b_error = true; atomic_store( &p_dec->b_error, true );
} }
} }
...@@ -2022,7 +2024,7 @@ static int aout_update_format( decoder_t *p_dec ) ...@@ -2022,7 +2024,7 @@ static int aout_update_format( decoder_t *p_dec )
if( p_aout == NULL ) if( p_aout == NULL )
{ {
msg_Err( p_dec, "failed to create audio output" ); msg_Err( p_dec, "failed to create audio output" );
p_dec->b_error = true; atomic_store( &p_dec->b_error, true );
return -1; return -1;
} }
...@@ -2155,7 +2157,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) ...@@ -2155,7 +2157,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
if( p_vout == NULL ) if( p_vout == NULL )
{ {
msg_Err( p_dec, "failed to create video output" ); msg_Err( p_dec, "failed to create video output" );
p_dec->b_error = true; atomic_store( &p_dec->b_error, true );
return NULL; return NULL;
} }
} }
...@@ -2164,7 +2166,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) ...@@ -2164,7 +2166,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
*/ */
for( ;; ) for( ;; )
{ {
if( DecoderIsExitRequested( p_dec ) || p_dec->b_error ) if( DecoderIsExitRequested( p_dec ) || atomic_load( &p_dec->b_error ) )
return NULL; return NULL;
picture_t *p_picture = vout_GetPicture( p_owner->p_vout ); picture_t *p_picture = vout_GetPicture( p_owner->p_vout );
...@@ -2210,7 +2212,7 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec, ...@@ -2210,7 +2212,7 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
while( i_attempts-- ) while( i_attempts-- )
{ {
if( DecoderIsExitRequested( p_dec ) || p_dec->b_error ) if( DecoderIsExitRequested( p_dec ) || atomic_load( &p_dec->b_error ) )
break; break;
p_vout = input_resource_HoldVout( p_owner->p_resource ); p_vout = input_resource_HoldVout( p_owner->p_resource );
......
...@@ -247,7 +247,6 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate ) ...@@ -247,7 +247,6 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
p_sys->b_active = false; p_sys->b_active = false;
p_sys->i_mode = ES_OUT_MODE_NONE; p_sys->i_mode = ES_OUT_MODE_NONE;
TAB_INIT( p_sys->i_pgrm, p_sys->pgrm ); TAB_INIT( p_sys->i_pgrm, p_sys->pgrm );
TAB_INIT( p_sys->i_es, p_sys->es ); TAB_INIT( p_sys->i_es, p_sys->es );
...@@ -298,6 +297,33 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate ) ...@@ -298,6 +297,33 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
return out; return out;
} }
int es_out_GetEsState( es_out_t *out, const int i_cat, bool *b_selected, bool *b_error)
{
if( !out && !out->p_sys )
return VLC_EGENERIC;
es_out_id_t *p_es;
switch( i_cat )
{
case VIDEO_ES:
p_es = out->p_sys->p_es_video;
break;
case AUDIO_ES:
p_es = out->p_sys->p_es_audio;
break;
case SPU_ES:
p_es = out->p_sys->p_es_sub;
break;
default:
p_es = NULL;
return VLC_EGENERIC;
}
if( !p_es )
return VLC_EGENERIC;
return es_out_Control( out, ES_OUT_GET_ES_STATE, p_es, b_selected, b_error );
}
/***************************************************************************** /*****************************************************************************
* *
*****************************************************************************/ *****************************************************************************/
...@@ -592,8 +618,6 @@ static void EsOutChangePosition( es_out_t *out ) ...@@ -592,8 +618,6 @@ static void EsOutChangePosition( es_out_t *out )
p_sys->i_preroll_end = -1; p_sys->i_preroll_end = -1;
} }
static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced ) static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
{ {
es_out_sys_t *p_sys = out->p_sys; es_out_sys_t *p_sys = out->p_sys;
...@@ -1570,6 +1594,7 @@ static void EsCreateDecoder( es_out_t *out, es_out_id_t *p_es ) ...@@ -1570,6 +1594,7 @@ static void EsCreateDecoder( es_out_t *out, es_out_id_t *p_es )
EsOutDecoderChangeDelay( out, p_es ); EsOutDecoderChangeDelay( out, p_es );
} }
static void EsDestroyDecoder( es_out_t *out, es_out_id_t *p_es ) static void EsDestroyDecoder( es_out_t *out, es_out_id_t *p_es )
{ {
VLC_UNUSED(out); VLC_UNUSED(out);
...@@ -2132,8 +2157,10 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) ...@@ -2132,8 +2157,10 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
{ {
es_out_id_t *es = va_arg( args, es_out_id_t * ); es_out_id_t *es = va_arg( args, es_out_id_t * );
bool *pb = va_arg( args, bool * ); bool *pb = va_arg( args, bool * );
bool *pb_error = va_arg( args, bool *);
*pb = EsIsSelected( es ); *pb = EsIsSelected( es );
*pb_error = (es->p_dec ? atomic_load( &es->p_dec->b_error ) : false);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -2696,6 +2723,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) ...@@ -2696,6 +2723,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
return VLC_EGENERIC; 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 )
{ {
es_out_sys_t *p_sys = out->p_sys; es_out_sys_t *p_sys = out->p_sys;
......
...@@ -168,6 +168,8 @@ static inline void es_out_Eos( es_out_t *p_out ) ...@@ -168,6 +168,8 @@ static inline void es_out_Eos( es_out_t *p_out )
assert( !i_ret ); assert( !i_ret );
} }
int es_out_GetEsState( es_out_t *p_out, const int i_cat, bool *b_selected, bool *b_error);
es_out_t *input_EsOutNew( input_thread_t *, int i_rate ); es_out_t *input_EsOutNew( input_thread_t *, int i_rate );
#endif #endif
...@@ -623,13 +623,15 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args ) ...@@ -623,13 +623,15 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
{ {
es_out_id_t *p_es = (es_out_id_t*)va_arg( args, es_out_id_t * ); es_out_id_t *p_es = (es_out_id_t*)va_arg( args, es_out_id_t * );
bool *pb_enabled = (bool*)va_arg( args, bool* ); bool *pb_enabled = (bool*)va_arg( args, bool* );
bool *pb_error = (bool*)va_arg( args, bool* );
if( p_sys->b_delayed ) if( p_sys->b_delayed )
{ {
*pb_enabled = true; *pb_enabled = true;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
return es_out_Control( p_sys->p_out, ES_OUT_GET_ES_STATE, p_es->p_es, pb_enabled ); return es_out_Control( p_sys->p_out, ES_OUT_GET_ES_STATE, p_es->p_es,
pb_enabled, pb_error );
} }
/* Special internal input control */ /* Special internal input control */
case ES_OUT_GET_EMPTY: case ES_OUT_GET_EMPTY:
......
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