[vlc-commits] codec: cc: rework old mpeg2 only reordering

Francois Cartegnie git at videolan.org
Thu May 18 12:34:45 CEST 2017


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed May 17 20:35:31 2017 +0200| [35d3aed9a9ffddadd3f8316d48f1c5187e77b618] | committer: Francois Cartegnie

codec: cc: rework old mpeg2 only reordering

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=35d3aed9a9ffddadd3f8316d48f1c5187e77b618
---

 modules/codec/cc.c | 146 ++++++++++++++++++++++++++++++++---------------------
 1 file changed, 89 insertions(+), 57 deletions(-)

diff --git a/modules/codec/cc.c b/modules/codec/cc.c
index b62adda31f..ce8600c5f8 100644
--- a/modules/codec/cc.c
+++ b/modules/codec/cc.c
@@ -212,14 +212,16 @@ static void         Eia608FillUpdaterRegions( subpicture_updater_sys_t *p_update
 #define CC_MAX_REORDER_SIZE (64)
 struct decoder_sys_t
 {
-    int     i_block;
-    block_t *pp_block[CC_MAX_REORDER_SIZE];
+    int      i_queue;
+    block_t *p_queue;
+
     block_t *p_block; /* currently processed block (if incomplely) */
 
     int i_field;
     int i_channel;
 
     mtime_t i_display_time;
+    int i_reorder_depth;
 
     eia608_t eia608;
     bool b_opaque;
@@ -274,6 +276,7 @@ static int Open( vlc_object_t *p_this )
 
     Eia608Init( &p_sys->eia608 );
     p_sys->b_opaque = var_InheritBool( p_dec, "cc-opaque" );
+    p_sys->i_reorder_depth = p_dec->fmt_in.subs.cc.i_reorder_depth;
 
     p_dec->fmt_out.i_cat = SPU_ES;
     p_dec->fmt_out.i_codec = VLC_CODEC_TEXT;
@@ -290,6 +293,15 @@ static void Flush( decoder_t *p_dec )
 
     Eia608Init( &p_sys->eia608 );
     p_sys->i_display_time = VLC_TS_INVALID;
+
+    block_ChainRelease( p_sys->p_queue );
+    p_sys->p_queue = NULL;
+    p_sys->i_queue = 0;
+    if( p_sys->p_block )
+    {
+        block_Release( p_sys->p_block );
+        p_sys->p_block = NULL;
+    }
 }
 
 /****************************************************************************
@@ -298,38 +310,63 @@ static void Flush( decoder_t *p_dec )
  *
  ****************************************************************************/
 static void     Push( decoder_t *, block_t * );
-static block_t *Pop( decoder_t * );
+static block_t *Pop( decoder_t *, bool );
 static subpicture_t *Convert( decoder_t *, block_t ** );
 
+static bool DoDecode( decoder_t *p_dec, bool b_drain )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    if( !p_sys->p_block )
+        p_sys->p_block = Pop( p_dec, b_drain );
+    if( !p_sys->p_block )
+        return false;
+
+    subpicture_t *p_spu = Convert( p_dec, &p_sys->p_block );
+    if( p_spu )
+        decoder_QueueSub( p_dec, p_spu );
+
+    return true;
+}
+
 static int Decode( decoder_t *p_dec, block_t *p_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
 
     if( p_block )
-        Push( p_dec, p_block );
-
-    for( ;; )
     {
-        if( !p_sys->p_block )
-            p_sys->p_block = Pop( p_dec );
-
         /* Reset decoder if needed */
-        if( p_sys->p_block &&
-           (p_sys->p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED)) )
+        if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
         {
-            Flush( p_dec );
-            /* clear flags, as we might process it more than once */
-            p_sys->p_block->i_flags &= ~(BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED);
-            continue;
+            /* Drain */
+            for( ; DoDecode( p_dec, true ) ; );
+            Eia608Init( &p_sys->eia608 );
+            p_sys->i_display_time = VLC_TS_INVALID;
+            if( (p_block->i_flags & BLOCK_FLAG_CORRUPTED) || p_block->i_buffer < 1 )
+            {
+                block_Release( p_block );
+                return VLCDEC_SUCCESS;
+            }
         }
 
-        if( !p_sys->p_block )
-            break;
+        /* XXX Cc captions data are OUT OF ORDER (because we receive them in the bitstream
+         * order (ie ordered by video picture dts) instead of the display order.
+         *  We will simulate a simple IPB buffer scheme
+         * and reorder with pts.
+         * XXX it won't work with H264 which use non out of order B picture or MMCO */
+        if( p_sys->i_reorder_depth == 0 )
+        {
+            /* Wait for a P and output all *previous* picture by pts order (for
+             * hierarchical B frames) */
+            if( (p_block->i_flags & BLOCK_FLAG_TYPE_B) == 0 )
+                for( ; DoDecode( p_dec, true ); );
+        }
 
-        subpicture_t *p_spu = Convert( p_dec, &p_sys->p_block );
-        if( p_spu )
-            decoder_QueueSub( p_dec, p_spu );
+        Push( p_dec, p_block );
     }
+
+    for( ; DoDecode( p_dec, (p_block == NULL) ); );
+
     return VLCDEC_SUCCESS;
 }
 
@@ -341,8 +378,7 @@ static void Close( vlc_object_t *p_this )
     decoder_t *p_dec = (decoder_t *)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    for( int i = 0; i < p_sys->i_block; i++ )
-        block_Release( p_sys->pp_block[i] );
+    block_ChainRelease( p_sys->p_queue );
     free( p_sys );
 }
 
@@ -353,51 +389,47 @@ static void Push( decoder_t *p_dec, block_t *p_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    if( p_sys->i_block >= CC_MAX_REORDER_SIZE )
+    if( p_sys->i_queue >= CC_MAX_REORDER_SIZE )
     {
+        block_t *p_block = Pop( p_dec, true );
+        block_Release( p_block );
         msg_Warn( p_dec, "Trashing a CC entry" );
-        memmove( &p_sys->pp_block[0], &p_sys->pp_block[1], sizeof(*p_sys->pp_block) * (CC_MAX_REORDER_SIZE-1) );
-        p_sys->i_block--;
     }
-    p_sys->pp_block[p_sys->i_block++] = p_block;
+
+    block_t **pp_block;
+    /* find insertion point */
+    for( pp_block = &p_sys->p_queue; *pp_block ; pp_block = &((*pp_block)->p_next) )
+    {
+        if( p_block->i_pts == VLC_TS_INVALID || (*pp_block)->i_pts == VLC_TS_INVALID )
+            continue;
+        if( p_block->i_pts < (*pp_block)->i_pts )
+            break;
+    }
+    /* Insert, keeping a pts and/or fifo ordered list */
+    p_block->p_next = *pp_block ? *pp_block : NULL;
+    *pp_block = p_block;
+    p_sys->i_queue++;
 }
-static block_t *Pop( decoder_t *p_dec )
+
+static block_t *Pop( decoder_t *p_dec, bool b_forced )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     block_t *p_block;
-    int i_index;
-    /* XXX Cc captions data are OUT OF ORDER (because we receive them in the bitstream
-     * order (ie ordered by video picture dts) instead of the display order.
-     *  We will simulate a simple IPB buffer scheme
-     * and reorder with pts.
-     * XXX it won't work with H264 which use non out of order B picture or MMCO
-     */
 
-    if( p_sys->i_block && (p_sys->pp_block[0]->i_flags & BLOCK_FLAG_PRIVATE_MASK) )
-    {
-        p_sys->i_block--;
-        return p_sys->pp_block[0];
-    }
+     if( p_sys->i_queue == 0 )
+         return NULL;
 
-    /* Wait for a P and output all *previous* picture by pts order (for
-     * hierarchical B frames) */
-    if( p_sys->i_block <= 1 ||
-        ( p_sys->pp_block[p_sys->i_block-1]->i_flags & BLOCK_FLAG_TYPE_B ) )
-        return NULL;
+     if( !b_forced && p_sys->i_queue < CC_MAX_REORDER_SIZE )
+     {
+        if( p_sys->i_queue < p_sys->i_reorder_depth || p_sys->i_reorder_depth == 0 )
+            return NULL;
+     }
 
-    p_block = p_sys->pp_block[i_index = 0];
-    if( p_block->i_pts > VLC_TS_INVALID )
-    {
-        for( int i = 1; i < p_sys->i_block-1; i++ )
-        {
-            if( p_sys->pp_block[i]->i_pts > VLC_TS_INVALID && p_block->i_pts > VLC_TS_INVALID &&
-                p_sys->pp_block[i]->i_pts < p_block->i_pts )
-                p_block = p_sys->pp_block[i_index = i];
-        }
-    }
-    assert( i_index+1 < p_sys->i_block );
-    memmove( &p_sys->pp_block[i_index], &p_sys->pp_block[i_index+1], sizeof(*p_sys->pp_block) * ( p_sys->i_block - i_index - 1 ) );
-    p_sys->i_block--;
+     /* dequeue head */
+     p_block = p_sys->p_queue;
+     p_sys->p_queue = p_block->p_next;
+     p_block->p_next = NULL;
+     p_sys->i_queue--;
 
     return p_block;
 }



More information about the vlc-commits mailing list