vlc | branch: master | Francois Cartegnie <[email protected]> | 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; } _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
