[vlc-devel] [PATCH 3/4] decoder: add decoder_QueueAudio

Thomas Guillem thomas at gllm.fr
Fri Dec 4 14:35:15 CET 2015


This function allow asynchronous decoders to queue an audio block to the audio
output. Decoders that use this function should return NULL in pf_decode_audio
callback.
---
 include/vlc_codec.h | 21 ++++++++++++
 src/input/decoder.c | 93 +++++++++++++++++++++++++++++++++++------------------
 2 files changed, 83 insertions(+), 31 deletions(-)

diff --git a/include/vlc_codec.h b/include/vlc_codec.h
index d55e966..8abe904 100644
--- a/include/vlc_codec.h
+++ b/include/vlc_codec.h
@@ -123,6 +123,8 @@ struct decoder_t
 
     /* XXX use decoder_QueueVideo */
     int             (*pf_queue_video)( decoder_t *, picture_t * );
+    /* XXX use decoder_QueueAudio */
+    int             (*pf_queue_audio)( decoder_t *, block_t * );
 
     /* Private structure for the owner of the decoder */
     decoder_owner_sys_t *p_owner;
@@ -262,6 +264,25 @@ static inline int decoder_QueueVideo( decoder_t *dec, picture_t *p_pic )
 }
 
 /**
+ * This function queues an audio block to the audio output.
+ *
+ * \note
+ * The caller doesn't own the audio block anymore after this call (even in case
+ * of error).
+ *
+ * \return 0 if the block is queued, -1 on error
+ */
+static inline int decoder_QueueAudio( decoder_t *dec, block_t *p_aout_buf )
+{
+    if( !dec->pf_queue_audio )
+    {
+        block_Release( p_aout_buf );
+        return -1;
+    }
+    return dec->pf_queue_audio( dec, p_aout_buf );
+}
+
+/**
  * This function notifies the audio output pipeline of a new audio output
  * format (fmt_out.audio). If there is currently no audio output or if the
  * audio output format has changed, a new audio output will be set up.
diff --git a/src/input/decoder.c b/src/input/decoder.c
index a793add..c794223 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -1072,46 +1072,41 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
     *pi_lost_sum += aout_DecGetResetLost( p_aout );
 }
 
-static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
+static int DecoderPreparePlayAudio( decoder_t *p_dec, block_t *p_aout_buf )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
-    block_t *p_aout_buf;
-    int i_decoded = 0;
-    int i_lost = 0;
-    int i_played = 0;
 
-    while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
+    vlc_mutex_lock( &p_owner->lock );
+    if( p_owner->i_preroll_end > VLC_TS_INVALID &&
+        p_aout_buf->i_pts < p_owner->i_preroll_end )
     {
-        i_decoded++;
-
-        vlc_mutex_lock( &p_owner->lock );
-        if( p_owner->i_preroll_end > VLC_TS_INVALID &&
-            p_aout_buf->i_pts < p_owner->i_preroll_end )
-        {
-            vlc_mutex_unlock( &p_owner->lock );
-            block_Release( p_aout_buf );
-            continue;
-        }
+        vlc_mutex_unlock( &p_owner->lock );
+        block_Release( p_aout_buf );
+        return -1;
+    }
 
-        if( p_owner->i_preroll_end > VLC_TS_INVALID )
-        {
-            msg_Dbg( p_dec, "End of audio preroll" );
-            p_owner->i_preroll_end = VLC_TS_INVALID;
-            vlc_mutex_unlock( &p_owner->lock );
-            /* */
-            if( p_owner->p_aout )
-                aout_DecFlush( p_owner->p_aout, false );
-        }
-        else
-            vlc_mutex_unlock( &p_owner->lock );
+    if( p_owner->i_preroll_end > VLC_TS_INVALID )
+    {
+        msg_Dbg( p_dec, "End of audio preroll" );
+        p_owner->i_preroll_end = VLC_TS_INVALID;
+        vlc_mutex_unlock( &p_owner->lock );
+        /* */
+        if( p_owner->p_aout )
+            aout_DecFlush( p_owner->p_aout, false );
+    }
+    else
+        vlc_mutex_unlock( &p_owner->lock );
 
+    return 0;
+}
 
-        DecoderPlayAudio( p_dec, p_aout_buf, &i_played, &i_lost );
-    }
+static void DecoderUpdateStatAudio( decoder_t *p_dec, int i_decoded,
+                                    int i_lost, int i_played )
+{
+    decoder_owner_sys_t *p_owner = p_dec->p_owner;
+    input_thread_t *p_input = p_owner->p_input;
 
     /* Update ugly stat */
-    input_thread_t  *p_input = p_owner->p_input;
-
     if( p_input != NULL && (i_decoded > 0 || i_lost > 0 || i_played > 0) )
     {
         vlc_mutex_lock( &p_input->p->counters.counters_lock);
@@ -1122,6 +1117,41 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
     }
 }
 
+static int DecoderQueueAudio( decoder_t *p_dec, block_t *p_aout_buf )
+{
+    assert( p_aout_buf );
+    int i_lost = 0;
+    int i_played = 0;
+    int i_ret;
+
+    if( ( i_ret = DecoderPreparePlayAudio( p_dec, p_aout_buf ) ) == 0 )
+        DecoderPlayAudio( p_dec, p_aout_buf, &i_played, &i_lost );
+
+    DecoderUpdateStatAudio( p_dec, 1, i_lost, i_played );
+
+    return i_ret;
+}
+
+static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
+{
+    block_t *p_aout_buf;
+    int i_decoded = 0;
+    int i_lost = 0;
+    int i_played = 0;
+
+    while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
+    {
+        i_decoded++;
+
+        if( DecoderPreparePlayAudio( p_dec, p_aout_buf ) != 0 )
+            continue;
+
+        DecoderPlayAudio( p_dec, p_aout_buf, &i_played, &i_lost );
+    }
+
+    DecoderUpdateStatAudio( p_dec, i_decoded, i_lost, i_played );
+}
+
 /* This function process a audio block
  */
 static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block )
@@ -1562,6 +1592,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     p_dec->pf_get_display_date = DecoderGetDisplayDate;
     p_dec->pf_get_display_rate = DecoderGetDisplayRate;
     p_dec->pf_queue_video = DecoderQueueVideo;
+    p_dec->pf_queue_audio = DecoderQueueAudio;
 
     /* Load a packetizer module if the input is not already packetized */
     if( p_sout == NULL && !fmt->b_packetized )
-- 
2.1.4



More information about the vlc-devel mailing list