[vlc-devel] [PATCH] RFC: packetizer: API rework

Thomas Guillem thomas at gllm.fr
Sat Feb 29 15:25:33 CET 2020


As discussed during the sout workshop, the packetizer API need to be reworked
to allow to forward PCR. The first step is to rework the current API and use
the same API than decoder modules.

Here is the API change I propose with an example (a52).
---
 include/vlc_codec.h      | 48 ++++++++++++++++------------------------
 modules/packetizer/a52.c | 42 ++++++++++++++---------------------
 2 files changed, 36 insertions(+), 54 deletions(-)

diff --git a/include/vlc_codec.h b/include/vlc_codec.h
index ae647eab2e..ee73fc5866 100644
--- a/include/vlc_codec.h
+++ b/include/vlc_codec.h
@@ -85,6 +85,11 @@ struct decoder_owner_callbacks
             /* cf.decoder_QueueSub */
             void            (*queue)( decoder_t *, subpicture_t *);
         } spu;
+        struct
+        {
+            /* cf. packetizer_QueueBlock */
+            void (*queue)(decoder_t *, block_t *);
+        } pkt;
     };
 
     /* Input attachments
@@ -149,35 +154,6 @@ struct decoder_t
          *  next decoder module).
          */
         int             ( * pf_decode )   ( decoder_t *, block_t *p_block );
-
-        /* This function is called in a loop with the same pp_block argument until
-         * it returns NULL. This allows a module implementation to return more than
-         * one output blocks for one input block.
-         *
-         * pp_block or *pp_block can be NULL.
-         *
-         * If pp_block and *pp_block are not NULL, the module implementation will
-         * own the input block (*pp_block) and should process and release it. The
-         * module can also process a part of the block. In that case, it should
-         * modify (*pp_block)->p_buffer/i_buffer accordingly and return a valid
-         * output block. The module can also set *pp_block to NULL when the input
-         * block is consumed.
-         *
-         * If pp_block is not NULL but *pp_block is NULL, a previous call of the pf
-         * function has set the *pp_block to NULL. Here, the module can return new
-         * output block for the same, already processed, input block (the
-         * pf_packetize function will be called as long as the module return an
-         * output block).
-         *
-         * When the pf function returns NULL, the next call to this function will
-         * have a new a valid pp_block (if the packetizer is not drained).
-         *
-         * If pp_block is NULL, the packetizer asks the module to drain itself. In
-         * that case, the module has to return all output frames available (the
-         * pf_packetize function will be called as long as the module return an
-         * output block).
-         */
-        block_t *       ( * pf_packetize )( decoder_t *, block_t **pp_block );
     };
 
     /* */
@@ -544,6 +520,20 @@ static inline float decoder_GetDisplayRate( decoder_t *dec )
     return dec->cbs->video.get_display_rate( dec );
 }
 
+/**
+ * This function queues a single block to the packetizer owner
+ *
+ * \note
+ * The caller doesn't own the audio block anymore after this call (even in case
+ * of error).
+ */
+static inline void packetizer_QueueBlock( decoder_t *dec, block_t *p_block )
+{
+    vlc_assert( p_block->p_next == NULL );
+    vlc_assert( dec->cbs->pkt.queue != NULL );
+    dec->cbs->pkt.queue( dec, p_aout_buf );
+}
+
 /** @} */
 
 /**
diff --git a/modules/packetizer/a52.c b/modules/packetizer/a52.c
index 15890af14b..1a60ad5049 100644
--- a/modules/packetizer/a52.c
+++ b/modules/packetizer/a52.c
@@ -134,36 +134,34 @@ static block_t *GetOutBuffer( decoder_t *p_dec )
     return p_block;
 }
 
-static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
+static int PacketizeBlock( decoder_t *p_dec, block_t *p_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     uint8_t p_header[VLC_A52_MIN_HEADER_SIZE];
     block_t *p_out_buffer;
 
-    block_t *p_block = pp_block ? *pp_block : NULL;
-
     if( p_block )
     {
         if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
         {
             /* First always drain complete blocks before discontinuity */
-            block_t *p_drain = PacketizeBlock( p_dec, NULL );
-            if(p_drain)
-                return p_drain;
+            int ret = PacketizeBlock( p_dec, NULL );
+            if (ret != VLCDEC_SUCCESS)
+                return ret;
 
             PacketizeFlush( p_dec );
 
             if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
             {
                 block_Release( p_block );
-                return NULL;
+                return VLCDEC_SUCCESS;
             }
         }
 
         block_BytestreamPush( &p_sys->bytestream, p_block );
     }
 
-    while( 1 )
+    while( p_block )
     {
         switch( p_sys->i_state )
         {
@@ -183,7 +181,7 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
                 block_BytestreamFlush( &p_sys->bytestream );
 
                 /* Need more data */
-                return NULL;
+                return VLCDEC_SUCCESS;
             }
             /* fallthrough */
 
@@ -197,7 +195,7 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
                                  VLC_A52_MIN_HEADER_SIZE ) != VLC_SUCCESS )
             {
                 /* Need more data */
-                return NULL;
+                return VLCDEC_SUCCESS;
             }
 
             /* Check if frame is valid and get frame info */
@@ -216,7 +214,7 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
                 p_sys->i_state = STATE_NOSYNC;
                 if( block_SkipBytes( &p_sys->bytestream,
                                      p_sys->frame.i_size ) != VLC_SUCCESS )
-                    return NULL;
+                    return VLCDEC_SUCCESS;
                 break;
             }
 
@@ -236,7 +234,7 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
                     break;
                 }
                 /* Need more data */
-                return NULL;
+                return VLCDEC_SUCCESS;
             }
 
             if( p_header[0] == 0 || p_header[1] == 0 )
@@ -271,18 +269,13 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
             /* Make sure we have enough data. */
             if( block_WaitBytes( &p_sys->bytestream,
                                  p_sys->i_input_size ) != VLC_SUCCESS )
-            {
-                /* Need more data */
-                return NULL;
-            }
+                return VLCDEC_SUCCESS; /* Need more data */
             p_sys->i_state = STATE_SEND_DATA;
             /* fallthrough */
 
         case STATE_SEND_DATA:
             if( !(p_out_buffer = GetOutBuffer( p_dec )) )
-            {
-                return NULL;
-            }
+                return VLCDEC_ECRITICAL;
 
             /* Copy the whole frame into the buffer. When we reach this point
              * we already know we have enough data available. */
@@ -294,7 +287,7 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
             if( p_out_buffer->i_dts == VLC_TICK_INVALID )
             {
                 block_Release( p_out_buffer );
-                return NULL;
+                return VLCDEC_SUCCESS;
             }
 
             if( p_sys->b_discontuinity )
@@ -303,13 +296,12 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
                 p_sys->b_discontuinity = false;
             }
 
-            /* So p_block doesn't get re-added several times */
-            if( pp_block )
-                *pp_block = block_BytestreamPop( &p_sys->bytestream );
+            packetizer_QueueBlock( p_dec, p_out_buffer );
 
-            return p_out_buffer;
+            p_block = block_BytestreamPop( &p_sys->bytestream );
         }
     }
+    return VLCDEC_SUCCESS;
 }
 
 static void Close( vlc_object_t *p_this )
@@ -356,7 +348,7 @@ static int Open( vlc_object_t *p_this )
     p_dec->fmt_out.audio.i_rate = 0;
 
     /* Set callback */
-    p_dec->pf_packetize = PacketizeBlock;
+    p_dec->pf_decode    = PacketizeBlock;
     p_dec->pf_flush     = PacketizeFlush;
     p_dec->pf_get_cc    = NULL;
     return VLC_SUCCESS;
-- 
2.20.1



More information about the vlc-devel mailing list