]> git.sesse.net Git - vlc/commitdiff
input core: add status field per elementary stream
authorJean-Paul Saman <jean-paul.saman@m2x.nl>
Sat, 15 Feb 2014 14:02:42 +0000 (15:02 +0100)
committerJean-Paul Saman <jean-paul.saman@m2x.nl>
Sat, 15 Feb 2014 21:45:25 +0000 (22:45 +0100)
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.

14 files changed:
include/vlc_codec.h
include/vlc_es_out.h
include/vlc_input.h
modules/codec/a52.c
modules/codec/avcodec/video.c
modules/codec/dts.c
modules/codec/mpeg_audio.c
modules/codec/quicktime.c
modules/packetizer/mpeg4audio.c
src/input/control.c
src/input/decoder.c
src/input/es_out.c
src/input/es_out.h
src/input/es_out_timeshift.c

index 1e7c8a6f160cd27fc3123abf64c62a52b62f5111..17f8d5d7d22bf85098b184020419cf8c86e15176 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef VLC_CODEC_H
 #define VLC_CODEC_H 1
 
+#include <vlc_atomic.h>
 #include <vlc_block.h>
 #include <vlc_es.h>
 #include <vlc_picture.h>
@@ -131,7 +132,7 @@ struct decoder_t
     /* Private structure for the owner of the decoder */
     decoder_owner_sys_t *p_owner;
 
-    bool                b_error;
+    atomic_bool       b_error;
 };
 
 /**
index cf1abcec08467eb495ad62474e055c1500f358b6..c08741c3b51dee44a5502b46717bc87c821b43d1 100644 (file)
@@ -45,7 +45,9 @@ enum es_out_query_e
 
     /* force selection/unselection of the ES (bypass current mode) */
     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                            */
index 4098e6b6559c0ddbbd565ca441dc3d0b29592a66..61258ca9697b1f1e756b9693bf9d4b824a14b35a 100644 (file)
@@ -297,6 +297,14 @@ typedef enum input_state_e
     ERROR_S,
 } 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.
  *
@@ -480,6 +488,9 @@ enum input_query_e
     /* External clock managments */
     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 */
+
+    /* 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
 {
     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
  */
index 4fec50c7c073dbb5d2228062cd957be81f2dee40..4efa6082de83bc7b9377e0dbed91a9ac0459cef2 100644 (file)
@@ -294,7 +294,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
         case STATE_SEND_DATA:
             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
             {
-                //p_dec->b_error = true;
+                //atomic_store( &p_dec->b_error, true );
                 return NULL;
             }
 
index b62ea938c206f0f18d5d6482ccb6726fbb34a75f..429de09d68aff7daf2edb96982b1c0fe86f74d28 100644 (file)
@@ -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 );
         msg_Err( p_dec, "Unsupported decoded output format %d (%s)",
                  p_sys->p_context->pix_fmt, name ? name : "unknown" );
-        p_dec->b_error = 1;
+        atomic_store( &p_dec->b_error, true );
     }
 }
 
index 09ebc0d75727cb402aa26df3cefc97a58785d9bb..6289d6edd50b2afbe72053d2cb8f5969bd00ed38 100644 (file)
@@ -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 )) )
             {
-                //p_dec->b_error = true;
+                //atomic_store( &p_dec->b_error, true );
                 return NULL;
             }
 
index e67abeba49e0d0a6e606fd60dba42c2a490c68f9..d0e7d0f272a6e282eda8e6774fb9eb6e892833ba 100644 (file)
@@ -440,7 +440,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
         case STATE_SEND_DATA:
             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
             {
-                //p_dec->b_error = true;
+                //atomic_store( &p_dec->b_error, true );
                 return NULL;
             }
 
index 885c758e7ca6c220cd7265c3196bfb91216e1929..e671b519a616a4953fa94e3f6ab539df92b20480 100644 (file)
@@ -538,7 +538,7 @@ static block_t *DecodeAudio( decoder_t *p_dec, block_t **pp_block )
         if( OpenAudio( p_dec ) )
         {
             /* Fatal */
-            p_dec->b_error = true;
+            atomic_store( &p_dec->b_error, true );
             return NULL;
         }
 
@@ -883,7 +883,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
         if( OpenVideo( p_dec ) )
         {
             /* Fatal */
-            p_dec->b_error = true;
+            atomic_store( &p_dec->b_error, true );
             return NULL;
         }
         p_sys = p_dec->p_sys;
index e17cac11e4640c5c964175dbd1238cc627275356..cfd87aa63972d10bb52e0573bd94215f3a3b7e10 100644 (file)
@@ -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);
         if (!p_out_buffer) {
-            //p_dec->b_error = true;
+            //atomic_store( &p_dec->b_error, true );
             return NULL;
         }
         p_buf = p_out_buffer->p_buffer;
index a4b2842cf369c6c08c181d9179050c092002e0cd..4003a3f66330af16f040243384a0cee25d2953a9 100644 (file)
@@ -36,6 +36,7 @@
 #include "resource.h"
 #include "es_out.h"
 
+typedef enum input_es_state_e input_es_state_e;
 
 static void UpdateBookmarksOption( input_thread_t * );
 
@@ -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 );
         }
 
+        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:
             msg_Err( p_input, "unknown query in input_vaControl" );
             return VLC_EGENERIC;
@@ -554,4 +573,3 @@ static void UpdateBookmarksOption( input_thread_t *p_input )
 
     input_SendEventBookmark( p_input );
 }
-
index 46129fc9c2071ce1b847f9c825abe6f134f05429..1a776908c9a1c5edf4907446750be30f16ba316c 100644 (file)
@@ -729,6 +729,8 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     p_dec->pf_get_cc = NULL;
     p_dec->pf_packetize = NULL;
 
+    atomic_init( &p_dec->b_error, false );
+
     /* Initialize the decoder */
     p_dec->p_module = NULL;
 
@@ -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)",
                          (char *)&p_owner->sout.i_codec );
-                p_dec->b_error = true;
+                atomic_store( &p_dec->b_error, true );
 
                 block_ChainRelease(p_sout_block);
                 break;
@@ -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;
     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 )
             block_Release( p_block );
@@ -1810,7 +1812,7 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
         else
         {
             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 )
         if( p_aout == NULL )
         {
             msg_Err( p_dec, "failed to create audio output" );
-            p_dec->b_error = true;
+            atomic_store( &p_dec->b_error, true );
             return -1;
         }
 
@@ -2155,7 +2157,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
         if( p_vout == NULL )
         {
             msg_Err( p_dec, "failed to create video output" );
-            p_dec->b_error = true;
+            atomic_store( &p_dec->b_error, true );
             return NULL;
         }
     }
@@ -2164,7 +2166,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
      */
     for( ;; )
     {
-        if( DecoderIsExitRequested( p_dec ) || p_dec->b_error )
+        if( DecoderIsExitRequested( p_dec ) || atomic_load( &p_dec->b_error ) )
             return NULL;
 
         picture_t *p_picture = vout_GetPicture( p_owner->p_vout );
@@ -2210,7 +2212,7 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
 
     while( i_attempts-- )
     {
-        if( DecoderIsExitRequested( p_dec ) || p_dec->b_error )
+        if( DecoderIsExitRequested( p_dec ) || atomic_load( &p_dec->b_error ) )
             break;
 
         p_vout = input_resource_HoldVout( p_owner->p_resource );
index b41460f79c0b75b3e0910d6a2160379cfbd5640e..bbba71f9214b2ea8252247ac4a21eb2ac61ededb 100644 (file)
@@ -247,7 +247,6 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
     p_sys->b_active = false;
     p_sys->i_mode   = ES_OUT_MODE_NONE;
 
-
     TAB_INIT( p_sys->i_pgrm, p_sys->pgrm );
 
     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 )
     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 )
     p_sys->i_preroll_end = -1;
 }
 
-
-
 static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
 {
     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 )
 
     EsOutDecoderChangeDelay( out, p_es );
 }
+
 static void EsDestroyDecoder( es_out_t *out, es_out_id_t *p_es )
 {
     VLC_UNUSED(out);
@@ -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 * );
         bool *pb = va_arg( args, bool * );
+        bool *pb_error = va_arg( args, bool *);
 
         *pb = EsIsSelected( es );
+        *pb_error = (es->p_dec ? atomic_load( &es->p_dec->b_error ) : false);
         return VLC_SUCCESS;
     }
 
@@ -2696,6 +2723,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
         return VLC_EGENERIC;
     }
 }
+
 static int EsOutControl( es_out_t *out, int i_query, va_list args )
 {
     es_out_sys_t *p_sys = out->p_sys;
index 56cefed7c99acf5898d9a7064b1ee3dac50f5449..b817adaa15bf9ab81f7f7d98858b01741912d94a 100644 (file)
@@ -168,6 +168,8 @@ static inline void es_out_Eos( es_out_t *p_out )
     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 );
 
 #endif
index c12d73ad496dd7e8313fa4c7809ace09a64c02c2..92b9d904eec161e444f5d48cf1df664160ddf728 100644 (file)
@@ -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 * );
         bool *pb_enabled = (bool*)va_arg( args, bool* );
+        bool *pb_error = (bool*)va_arg( args, bool* );
 
         if( p_sys->b_delayed )
         {
             *pb_enabled = true;
             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 */
     case ES_OUT_GET_EMPTY: