[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