vlc | branch: master | Francois Cartegnie <fcvlc...@free.fr> | Mon Sep 25 16:50:16 2017 +0200| [5ac1ca3f168833760f2b9fb134938cc55fa4316a] | committer: Francois Cartegnie
codec/esout: use bitmap for cc channels and refactor channel creation > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=5ac1ca3f168833760f2b9fb134938cc55fa4316a --- include/vlc_codec.h | 25 ++++--- modules/codec/avcodec/video.c | 5 +- modules/codec/cc.h | 10 +-- modules/codec/libmpeg2.c | 5 +- modules/demux/ty.c | 8 ++- modules/packetizer/h264.c | 6 +- modules/packetizer/hevc.c | 6 +- modules/packetizer/hxxx_common.c | 16 ++--- modules/packetizer/hxxx_common.h | 3 +- modules/packetizer/mpegvideo.c | 12 ++-- modules/packetizer/vc1.c | 11 ++-- src/input/decoder.c | 110 ++++++++++++++++++------------- src/input/decoder.h | 9 ++- src/input/es_out.c | 138 +++++++++++++++++++++++++-------------- 14 files changed, 211 insertions(+), 153 deletions(-) diff --git a/include/vlc_codec.h b/include/vlc_codec.h index c62ccd0e94..cbb689ece1 100644 --- a/include/vlc_codec.h +++ b/include/vlc_codec.h @@ -45,6 +45,8 @@ typedef struct decoder_owner_sys_t decoder_owner_sys_t; +typedef struct decoder_cc_desc_t decoder_cc_desc_t; + /* * BIG FAT WARNING : the code relies in the first 4 members of filter_t * and decoder_t to be the same, so if you have anything to add, do it @@ -127,10 +129,10 @@ struct decoder_t /* Closed Caption (CEA 608/708) extraction. * If set, it *may* be called after pf_packetize returned data. It should * return CC for the pictures returned by the last pf_packetize call only, - * pb_present will be used to known which cc channel are present (but + * channel bitmaps will be used to known which cc channel are present (but * globaly, not necessary for the current packet. Video decoders should use * the decoder_QueueCc() function to pass closed captions. */ - block_t * ( * pf_get_cc ) ( decoder_t *, bool pb_present[4], int * ); + block_t * ( * pf_get_cc ) ( decoder_t *, decoder_cc_desc_t * ); /* Meta data at codec level * The decoder owner set it back to NULL once it has retreived what it needs. @@ -178,7 +180,7 @@ struct decoder_t /* XXX use decoder_QueueAudio */ int (*pf_queue_audio)( decoder_t *, block_t * ); /* XXX use decoder_QueueCC */ - int (*pf_queue_cc)( decoder_t *, block_t *, bool p_cc_present[4], int ); + int (*pf_queue_cc)( decoder_t *, block_t *, const decoder_cc_desc_t * ); /* XXX use decoder_QueueSub */ int (*pf_queue_sub)( decoder_t *, subpicture_t *); void *p_queue_ctx; @@ -187,6 +189,14 @@ struct decoder_t decoder_owner_sys_t *p_owner; }; +/* struct for packetizer get_cc polling/decoder queue_cc + * until we have a proper metadata way */ +struct decoder_cc_desc_t +{ + uint8_t i_608_channels; /* 608 channels bitmap */ + int i_reorder_depth; /* reorder depth, -1 for no reorder, 0 for old P/B flag based */ +}; + /** * @} */ @@ -311,21 +321,18 @@ static inline int decoder_QueueVideo( decoder_t *dec, picture_t *p_pic ) * * \param dec the decoder object * \param p_cc the closed-caption to queue - * \param p_cc_present array-of-bool where each entry indicates whether the - * given channel is present or not - * \param i_depth the closed-caption to queue reorder depth, or simply 0 - * if using the old mpgv block flag tagging + * \param p_desc decoder_cc_desc_t description structure * \return 0 if queued, -1 on error */ static inline int decoder_QueueCc( decoder_t *dec, block_t *p_cc, - bool p_cc_present[4], int i_depth ) + const decoder_cc_desc_t *p_desc ) { if( dec->pf_queue_cc == NULL ) { block_Release( p_cc ); return -1; } - return dec->pf_queue_cc( dec, p_cc, p_cc_present, i_depth ); + return dec->pf_queue_cc( dec, p_cc, p_desc ); } /** diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c index e1457154b9..9f53f0c17a 100644 --- a/modules/codec/avcodec/video.c +++ b/modules/codec/avcodec/video.c @@ -864,7 +864,10 @@ static void DecodeSidedata( decoder_t *p_dec, const AVFrame *frame, picture_t *p p_cc->i_dts = p_cc->i_pts = p_pic->date; else p_cc->i_pts = p_cc->i_dts; - decoder_QueueCc( p_dec, p_cc, p_sys->cc.pb_present, 4 ); + decoder_cc_desc_t desc; + desc.i_608_channels = p_sys->cc.i_608channels; + desc.i_reorder_depth = 4; + decoder_QueueCc( p_dec, p_cc, &desc ); } cc_Flush( &p_sys->cc ); } diff --git a/modules/codec/cc.h b/modules/codec/cc.h index 2caea83218..f5d902a8a4 100644 --- a/modules/codec/cc.h +++ b/modules/codec/cc.h @@ -42,7 +42,7 @@ enum cc_payload_type_e typedef struct { /* Which channel are present */ - bool pb_present[4]; + uint8_t i_608channels; /* */ bool b_reorder; @@ -62,8 +62,7 @@ typedef struct static inline void cc_Init( cc_data_t *c ) { - for( int i = 0; i < 4; i++ ) - c->pb_present[i] = false; + c->i_608channels = 0; c->i_data = 0; c->b_reorder = false; c->i_payload_type = CC_PAYLOAD_NONE; @@ -83,10 +82,7 @@ static inline void cc_AppendData( cc_data_t *c, uint8_t cc_preamble, const uint8 { uint8_t i_field = cc_preamble & 0x03; if( i_field == 0 || i_field == 1 ) - { - c->pb_present[2*i_field+0] = - c->pb_present[2*i_field+1] = true; - } + c->i_608channels |= (3 << (2 * i_field)); c->p_data[c->i_data++] = cc_preamble; c->p_data[c->i_data++] = cc[0]; diff --git a/modules/codec/libmpeg2.c b/modules/codec/libmpeg2.c index 2cbc96cf08..2abd8e9cdf 100644 --- a/modules/codec/libmpeg2.c +++ b/modules/codec/libmpeg2.c @@ -717,7 +717,10 @@ static void SendCc( decoder_t *p_dec ) p_cc->i_dts = p_cc->i_pts = p_sys->cc.b_reorder ? p_sys->i_cc_pts : p_sys->i_cc_dts; p_cc->i_flags = p_sys->i_cc_flags & BLOCK_FLAG_TYPE_MASK; - decoder_QueueCc( p_dec, p_cc, p_sys->cc.pb_present, p_sys->cc.b_reorder ? 0 : -1 ); + decoder_cc_desc_t desc; + desc.i_608_channels = p_sys->cc.i_608channels; + desc.i_reorder_depth = p_sys->cc.b_reorder ? 0 : -1; + decoder_QueueCc( p_dec, p_cc, &desc ); } cc_Flush( &p_sys->cc ); return; diff --git a/modules/demux/ty.c b/modules/demux/ty.c index 67f7aca70b..d96ea139bf 100644 --- a/modules/demux/ty.c +++ b/modules/demux/ty.c @@ -759,8 +759,12 @@ static int DemuxRecVideo( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_bl } /* Register the CC decoders when needed */ - for( i = 0; i < 4; i++ ) + uint64_t i_chans = p_sys->cc.i_608channels; + for( i = 0; i_chans > 0; i++, i_chans >>= 1 ) { + if( (i_chans & 1) == 0 || p_sys->p_cc[i] ) + continue; + static const char *ppsz_description[4] = { N_("Closed captions 1"), N_("Closed captions 2"), @@ -770,8 +774,6 @@ static int DemuxRecVideo( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_bl es_format_t fmt; - if( !p_sys->cc.pb_present[i] || p_sys->p_cc[i] ) - continue; es_format_Init( &fmt, SPU_ES, VLC_CODEC_CEA608 ); fmt.subs.cc.i_channel = i; diff --git a/modules/packetizer/h264.c b/modules/packetizer/h264.c index f209ed455a..cdb0d4c326 100644 --- a/modules/packetizer/h264.c +++ b/modules/packetizer/h264.c @@ -135,7 +135,7 @@ struct decoder_sys_t static block_t *Packetize( decoder_t *, block_t ** ); static block_t *PacketizeAVC1( decoder_t *, block_t ** ); -static block_t *GetCc( decoder_t *p_dec, bool pb_present[4], int * ); +static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t * ); static void PacketizeFlush( decoder_t * ); static void PacketizeReset( void *p_private, bool b_broken ); @@ -486,9 +486,9 @@ static block_t *PacketizeAVC1( decoder_t *p_dec, block_t **pp_block ) /***************************************************************************** * GetCc: *****************************************************************************/ -static block_t *GetCc( decoder_t *p_dec, bool pb_present[4], int *pi_reorder_depth ) +static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t *p_desc ) { - return cc_storage_get_current( p_dec->p_sys->p_ccs, pb_present, pi_reorder_depth ); + return cc_storage_get_current( p_dec->p_sys->p_ccs, p_desc ); } /**************************************************************************** diff --git a/modules/packetizer/hevc.c b/modules/packetizer/hevc.c index 3262b602ca..b58aa615a9 100644 --- a/modules/packetizer/hevc.c +++ b/modules/packetizer/hevc.c @@ -71,7 +71,7 @@ static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *); static block_t *ParseNALBlock(decoder_t *, bool *pb_ts_used, block_t *); static int PacketizeValidate(void *p_private, block_t *); static bool ParseSEICallback( const hxxx_sei_data_t *, void * ); -static block_t *GetCc( decoder_t *, bool pb_present[4], int * ); +static block_t *GetCc( decoder_t *, decoder_cc_desc_t * ); struct decoder_sys_t { @@ -304,9 +304,9 @@ static void PacketizeFlush( decoder_t *p_dec ) /***************************************************************************** * GetCc: *****************************************************************************/ -static block_t *GetCc( decoder_t *p_dec, bool pb_present[4], int *pi_reorder_depth ) +static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t *p_desc ) { - return cc_storage_get_current( p_dec->p_sys->p_ccs, pb_present, pi_reorder_depth ); + return cc_storage_get_current( p_dec->p_sys->p_ccs, p_desc ); } /**************************************************************************** diff --git a/modules/packetizer/hxxx_common.c b/modules/packetizer/hxxx_common.c index 0eecf9aff2..bcfeae15dc 100644 --- a/modules/packetizer/hxxx_common.c +++ b/modules/packetizer/hxxx_common.c @@ -21,10 +21,11 @@ # include "config.h" #endif -#include "hxxx_common.h" - +#include <vlc_common.h> #include <vlc_block.h> #include <vlc_codec.h> + +#include "hxxx_common.h" #include "../codec/cc.h" /**************************************************************************** @@ -80,16 +81,10 @@ void cc_storage_commit( cc_storage_t *p_ccs, block_t *p_pic ) cc_Flush( &p_ccs->next ); } -block_t * cc_storage_get_current( cc_storage_t *p_ccs, bool pb_present[4], - int *pi_reorder_depth ) +block_t * cc_storage_get_current( cc_storage_t *p_ccs, decoder_cc_desc_t *p_desc ) { block_t *p_block; - *pi_reorder_depth = p_ccs->current.b_reorder ? 4 : -1; - - for( int i = 0; i < 4; i++ ) - pb_present[i] = p_ccs->current.pb_present[i]; - if( !p_ccs->current.b_reorder && p_ccs->current.i_data <= 0 ) return NULL; @@ -100,6 +95,9 @@ block_t * cc_storage_get_current( cc_storage_t *p_ccs, bool pb_present[4], p_block->i_dts = p_block->i_pts = p_ccs->current.b_reorder ? p_ccs->i_pts : p_ccs->i_dts; p_block->i_flags = p_ccs->i_flags & BLOCK_FLAG_TYPE_MASK; + + p_desc->i_608_channels = p_ccs->current.i_608channels; + p_desc->i_reorder_depth = p_ccs->current.b_reorder ? 4 : -1; } cc_Flush( &p_ccs->current ); diff --git a/modules/packetizer/hxxx_common.h b/modules/packetizer/hxxx_common.h index 6e7cd0964f..eff2f0b3c2 100644 --- a/modules/packetizer/hxxx_common.h +++ b/modules/packetizer/hxxx_common.h @@ -33,8 +33,7 @@ void cc_storage_append( cc_storage_t *p_ccs, bool b_top_field_first, const uint8_t *p_buf, size_t i_buf ); void cc_storage_commit( cc_storage_t *p_ccs, block_t *p_pic ); -block_t * cc_storage_get_current( cc_storage_t *p_ccs, bool pb_present[4], - int *pi_reorder_depth ); +block_t * cc_storage_get_current( cc_storage_t *p_ccs, decoder_cc_desc_t * ); /* */ diff --git a/modules/packetizer/mpegvideo.c b/modules/packetizer/mpegvideo.c index 71126d8979..0f1af4d225 100644 --- a/modules/packetizer/mpegvideo.c +++ b/modules/packetizer/mpegvideo.c @@ -177,7 +177,7 @@ struct decoder_sys_t static block_t *Packetize( decoder_t *, block_t ** ); static void PacketizeFlush( decoder_t * ); -static block_t *GetCc( decoder_t *p_dec, bool pb_present[4], int * ); +static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t * ); static void PacketizeReset( void *p_private, bool b_broken ); static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t * ); @@ -312,15 +312,10 @@ static void PacketizeFlush( decoder_t *p_dec ) /***************************************************************************** * GetCc: *****************************************************************************/ -static block_t *GetCc( decoder_t *p_dec, bool pb_present[4], int *pi_reorder_depth ) +static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t *p_desc ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_cc; - int i; - *pi_reorder_depth = p_sys->cc.b_reorder ? 0 : -1; - - for( i = 0; i < 4; i++ ) - pb_present[i] = p_sys->cc.pb_present[i]; if( !p_sys->cc.b_reorder && p_sys->cc.i_data <= 0 ) return NULL; @@ -332,6 +327,9 @@ static block_t *GetCc( decoder_t *p_dec, bool pb_present[4], int *pi_reorder_dep p_cc->i_dts = p_cc->i_pts = p_sys->cc.b_reorder ? p_sys->i_cc_pts : p_sys->i_cc_dts; p_cc->i_flags = p_sys->i_cc_flags & BLOCK_FLAG_TYPE_MASK; + + p_desc->i_608_channels = p_sys->cc.i_608channels; + p_desc->i_reorder_depth = p_sys->cc.b_reorder ? 0 : -1; } cc_Flush( &p_sys->cc ); return p_cc; diff --git a/modules/packetizer/vc1.c b/modules/packetizer/vc1.c index b075299980..a3b9dddfe7 100644 --- a/modules/packetizer/vc1.c +++ b/modules/packetizer/vc1.c @@ -129,7 +129,7 @@ static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t * ); static int PacketizeValidate( void *p_private, block_t * ); static block_t *ParseIDU( decoder_t *p_dec, bool *pb_ts_used, block_t *p_frag ); -static block_t *GetCc( decoder_t *p_dec, bool pb_present[4], int * ); +static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t * ); static const uint8_t p_vc1_startcode[3] = { 0x00, 0x00, 0x01 }; /***************************************************************************** @@ -762,14 +762,10 @@ static block_t *ParseIDU( decoder_t *p_dec, bool *pb_ts_used, block_t *p_frag ) /***************************************************************************** * GetCc: *****************************************************************************/ -static block_t *GetCc( decoder_t *p_dec, bool pb_present[4], int *pi_reorder_depth ) +static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t *p_desc ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_cc; - *pi_reorder_depth = p_sys->cc.b_reorder ? 4 : -1; - - for( int i = 0; i < 4; i++ ) - pb_present[i] = p_sys->cc.pb_present[i]; p_cc = block_Alloc( p_sys->cc.i_data); if( p_cc ) @@ -778,6 +774,9 @@ static block_t *GetCc( decoder_t *p_dec, bool pb_present[4], int *pi_reorder_dep p_cc->i_dts = p_cc->i_pts = p_sys->cc.b_reorder ? p_sys->i_cc_pts : p_sys->i_cc_dts; p_cc->i_flags = p_sys->i_cc_flags & BLOCK_FLAG_TYPE_MASK; + + p_desc->i_608_channels = p_sys->cc.i_608channels; + p_desc->i_reorder_depth = p_sys->cc.b_reorder ? 4 : -1; } cc_Flush( &p_sys->cc ); return p_cc; diff --git a/src/input/decoder.c b/src/input/decoder.c index 78c96986e4..1818224ff8 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -131,12 +131,12 @@ struct decoder_owner_sys_t bool b_idle; /* CC */ +#define MAX_CC_DECODERS 4 /* The es_out only creates one type of es */ struct { bool b_supported; - bool pb_present[4]; - uint8_t i_reorder_depth; - decoder_t *pp_decoder[4]; + decoder_cc_desc_t desc; + decoder_t *pp_decoder[MAX_CC_DECODERS]; } cc; /* Delay */ @@ -907,35 +907,37 @@ static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block ) #endif static void DecoderPlayCc( decoder_t *p_dec, block_t *p_cc, - bool pb_present[4], int i_reorder_depth ) + const decoder_cc_desc_t *p_desc ) { decoder_owner_sys_t *p_owner = p_dec->p_owner; - bool b_processed = false; - int i_cc_decoder = 0; vlc_mutex_lock( &p_owner->lock ); - for( int i = 0; i < 4; i++ ) - { - p_owner->cc.pb_present[i] |= pb_present[i]; - if( p_owner->cc.pp_decoder[i] ) - i_cc_decoder++; - } - p_owner->cc.i_reorder_depth = i_reorder_depth; - for( int i = 0; i < 4; i++ ) + p_owner->cc.desc = *p_desc; + + /* Fanout data to all decoders. */ + uint64_t i_bitmap = p_owner->cc.desc.i_608_channels; + + for( int i=0; i_bitmap > 0; i_bitmap >>= 1, i++ ) { - if( !p_owner->cc.pp_decoder[i] ) + decoder_t *p_ccdec = p_owner->cc.pp_decoder[i]; + if( !p_ccdec ) continue; - block_FifoPut( p_owner->cc.pp_decoder[i]->p_owner->p_fifo, - (i_cc_decoder > 1) ? block_Duplicate(p_cc) : p_cc); - - i_cc_decoder--; - b_processed = true; + if( i_bitmap > 1 ) + { + block_FifoPut( p_ccdec->p_owner->p_fifo, block_Duplicate(p_cc) ); + } + else + { + block_FifoPut( p_ccdec->p_owner->p_fifo, p_cc ); + p_cc = NULL; /* was last dec */ + } } + vlc_mutex_unlock( &p_owner->lock ); - if( !b_processed ) + if( p_cc ) /* can have bitmap set but no created decs */ block_Release( p_cc ); } @@ -943,7 +945,7 @@ static void PacketizerGetCc( decoder_t *p_dec, decoder_t *p_dec_cc ) { decoder_owner_sys_t *p_owner = p_dec->p_owner; block_t *p_cc; - bool pb_present[4]; + decoder_cc_desc_t desc; /* Do not try retreiving CC if not wanted (sout) or cannot be retreived */ if( !p_owner->cc.b_supported ) @@ -951,15 +953,14 @@ static void PacketizerGetCc( decoder_t *p_dec, decoder_t *p_dec_cc ) assert( p_dec_cc->pf_get_cc != NULL ); - int i_reorder_depth; - p_cc = p_dec_cc->pf_get_cc( p_dec_cc, pb_present, &i_reorder_depth ); + p_cc = p_dec_cc->pf_get_cc( p_dec_cc, &desc ); if( !p_cc ) return; - DecoderPlayCc( p_dec, p_cc, pb_present, i_reorder_depth ); + DecoderPlayCc( p_dec, p_cc, &desc ); } static int DecoderQueueCc( decoder_t *p_videodec, block_t *p_cc, - bool p_cc_present[4], int i_reorder_depth ) + const decoder_cc_desc_t *p_desc ) { decoder_owner_sys_t *p_owner = p_videodec->p_owner; @@ -967,7 +968,7 @@ static int DecoderQueueCc( decoder_t *p_videodec, block_t *p_cc, { if( p_owner->cc.b_supported && ( !p_owner->p_packetizer || !p_owner->p_packetizer->pf_get_cc ) ) - DecoderPlayCc( p_videodec, p_cc, p_cc_present, i_reorder_depth ); + DecoderPlayCc( p_videodec, p_cc, p_desc ); else block_Release( p_cc ); } @@ -1467,7 +1468,7 @@ static void DecoderProcessFlush( decoder_t *p_dec ) /* flush CC sub decoders */ if( p_owner->cc.b_supported ) { - for( int i=0; i<4; i++ ) + for( int i=0; i<MAX_CC_DECODERS; i++ ) { decoder_t *p_subdec = p_owner->cc.pp_decoder[i]; if( p_subdec && p_subdec->pf_flush ) @@ -1775,12 +1776,9 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent, /* */ p_owner->cc.b_supported = ( p_sout == NULL ); - for( unsigned i = 0; i < 4; i++ ) - { - p_owner->cc.pb_present[i] = false; + p_owner->cc.desc.i_608_channels = 0; + for( unsigned i = 0; i < MAX_CC_DECODERS; i++ ) p_owner->cc.pp_decoder[i] = NULL; - } - p_owner->cc.i_reorder_depth = 0; p_owner->i_ts_delay = 0; return p_dec; } @@ -1996,8 +1994,8 @@ void input_DecoderDelete( decoder_t *p_dec ) /* */ if( p_dec->p_owner->cc.b_supported ) { - for( int i = 0; i < 4; i++ ) - input_DecoderSetCcState( p_dec, false, i ); + for( int i = 0; i < MAX_CC_DECODERS; i++ ) + input_DecoderSetCcState( p_dec, VLC_CODEC_CEA608, i, false ); } /* Delete decoder */ @@ -2123,23 +2121,41 @@ void input_DecoderFlush( decoder_t *p_dec ) vlc_fifo_Unlock( p_owner->p_fifo ); } -void input_DecoderIsCcPresent( decoder_t *p_dec, bool pb_present[4] ) +void input_DecoderGetCcDesc( decoder_t *p_dec, decoder_cc_desc_t *p_desc ) { decoder_owner_sys_t *p_owner = p_dec->p_owner; vlc_mutex_lock( &p_owner->lock ); - for( int i = 0; i < 4; i++ ) - pb_present[i] = p_owner->cc.pb_present[i]; + *p_desc = p_owner->cc.desc; vlc_mutex_unlock( &p_owner->lock ); } -int input_DecoderSetCcState( decoder_t *p_dec, bool b_decode, int i_channel ) +static bool input_DecoderHasCCChanFlag( decoder_t *p_dec, + vlc_fourcc_t codec, int i_channel ) { decoder_owner_sys_t *p_owner = p_dec->p_owner; - //msg_Warn( p_dec, "input_DecoderSetCcState: %d @%d", b_decode, i_channel ); + int i_max_channels; + uint64_t i_bitmap; + if( codec == VLC_CODEC_CEA608 ) + { + i_max_channels = 4; + i_bitmap = p_owner->cc.desc.i_608_channels; + } + else return false; + + return ( i_channel >= 0 && i_channel < i_max_channels && + ( i_bitmap & ((uint64_t)1 << i_channel) ) ); +} - if( i_channel < 0 || i_channel >= 4 || !p_owner->cc.pb_present[i_channel] ) +int input_DecoderSetCcState( decoder_t *p_dec, vlc_fourcc_t codec, + int i_channel, bool b_decode ) +{ + decoder_owner_sys_t *p_owner = p_dec->p_owner; + + //msg_Warn( p_dec, "input_DecoderSetCcState: %d @%x", b_decode, i_channel ); + + if( !input_DecoderHasCCChanFlag( p_dec, codec, i_channel ) ) return VLC_EGENERIC; if( b_decode ) @@ -2147,9 +2163,9 @@ int input_DecoderSetCcState( decoder_t *p_dec, bool b_decode, int i_channel ) decoder_t *p_cc; es_format_t fmt; - es_format_Init( &fmt, SPU_ES, VLC_CODEC_CEA608 ); + es_format_Init( &fmt, SPU_ES, codec ); fmt.subs.cc.i_channel = i_channel; - fmt.subs.cc.i_reorder_depth = p_owner->cc.i_reorder_depth; + fmt.subs.cc.i_reorder_depth = p_owner->cc.desc.i_reorder_depth; p_cc = input_DecoderNew( p_owner->p_input, &fmt, p_dec->p_owner->p_clock, p_owner->p_sout ); if( !p_cc ) @@ -2187,18 +2203,18 @@ int input_DecoderSetCcState( decoder_t *p_dec, bool b_decode, int i_channel ) return VLC_SUCCESS; } -int input_DecoderGetCcState( decoder_t *p_dec, bool *pb_decode, int i_channel ) +int input_DecoderGetCcState( decoder_t *p_dec, vlc_fourcc_t codec, + int i_channel, bool *pb_decode ) { decoder_owner_sys_t *p_owner = p_dec->p_owner; - *pb_decode = false; - if( i_channel < 0 || i_channel >= 4 || !p_owner->cc.pb_present[i_channel] ) + if( !input_DecoderHasCCChanFlag( p_dec, codec, i_channel ) ) return VLC_EGENERIC; vlc_mutex_lock( &p_owner->lock ); *pb_decode = p_owner->cc.pp_decoder[i_channel] != NULL; vlc_mutex_unlock( &p_owner->lock ); - return VLC_EGENERIC; + return VLC_SUCCESS; } void input_DecoderChangePause( decoder_t *p_dec, bool b_paused, mtime_t i_date ) diff --git a/src/input/decoder.h b/src/input/decoder.h index 226ecde862..ccfe8ecd05 100644 --- a/src/input/decoder.h +++ b/src/input/decoder.h @@ -66,19 +66,18 @@ bool input_DecoderIsEmpty( decoder_t * ); /** * This function activates the request closed caption channel. */ -int input_DecoderSetCcState( decoder_t *, bool b_decode, int i_channel ); +int input_DecoderSetCcState( decoder_t *, vlc_fourcc_t, int i_channel, bool b_decode ); /** * This function returns an error if the requested channel does not exist and * set pb_decode to the channel status(active or not) otherwise. */ -int input_DecoderGetCcState( decoder_t *, bool *pb_decode, int i_channel ); +int input_DecoderGetCcState( decoder_t *, vlc_fourcc_t, int i_channel, bool *pb_decode ); /** - * This function set each pb_present entry to true if the corresponding channel - * exists or false otherwise. + * This function get cc channels descriptions */ -void input_DecoderIsCcPresent( decoder_t *, bool pb_present[4] ); +void input_DecoderGetCcDesc( decoder_t *, decoder_cc_desc_t * ); /** * This function force the display of the next picture and fills the stream diff --git a/src/input/es_out.c b/src/input/es_out.c index 9d406d9ef7..40456d1059 100644 --- a/src/input/es_out.c +++ b/src/input/es_out.c @@ -93,8 +93,12 @@ struct es_out_id_t decoder_t *p_dec_record; /* Fields for Video with CC */ - bool pb_cc_present[4]; - es_out_id_t *pp_cc_es[4]; + struct + { + vlc_fourcc_t type; + uint64_t i_bitmap; /* channels bitmap */ + es_out_id_t *pp_es[64]; /* a max of 64 chans for CEA708 */ + } cc; /* Field for CC track from a master video */ es_out_id_t *p_master; @@ -1624,8 +1628,8 @@ static es_out_id_t *EsOutAddSlave( es_out_t *out, const es_format_t *fmt, es_out es->psz_language_code = LanguageGetCode( es->fmt.psz_language ); es->p_dec = NULL; es->p_dec_record = NULL; - for( i = 0; i < 4; i++ ) - es->pb_cc_present[i] = false; + es->cc.type = 0; + es->cc.i_bitmap = 0; es->p_master = p_master; TAB_APPEND( p_sys->i_es, p_sys->es, es ); @@ -1660,8 +1664,8 @@ static bool EsIsSelected( es_out_id_t *es ) if( es->p_master->p_dec ) { int i_channel = EsOutGetClosedCaptionsChannel( &es->fmt ); - if( i_channel != -1 ) - input_DecoderGetCcState( es->p_master->p_dec, &b_decode, i_channel ); + input_DecoderGetCcState( es->p_master->p_dec, es->fmt.i_codec, + i_channel, &b_decode ); } return b_decode; } @@ -1727,7 +1731,9 @@ static void EsSelect( es_out_t *out, es_out_id_t *es ) i_channel = EsOutGetClosedCaptionsChannel( &es->fmt ); - if( i_channel == -1 || input_DecoderSetCcState( es->p_master->p_dec, true, i_channel ) ) + if( i_channel == -1 || + input_DecoderSetCcState( es->p_master->p_dec, es->fmt.i_codec, + i_channel, true ) ) return; } else @@ -1772,6 +1778,34 @@ static void EsSelect( es_out_t *out, es_out_id_t *es ) input_SendEventTeletextSelect( p_input, EsFmtIsTeletext( &es->fmt ) ? es->i_id : -1 ); } +static void EsDeleteCCChannels( es_out_t *out, es_out_id_t *parent ) +{ + es_out_sys_t *p_sys = out->p_sys; + input_thread_t *p_input = p_sys->p_input; + + if( parent->cc.type == 0 ) + return; + + const int i_spu_id = var_GetInteger( p_input, "spu-es"); + + uint64_t i_bitmap = parent->cc.i_bitmap; + for( int i = 0; i_bitmap > 0; i++, i_bitmap >>= 1 ) + { + if( (i_bitmap & 1) == 0 || !parent->cc.pp_es[i] ) + continue; + + if( i_spu_id == parent->cc.pp_es[i]->i_id ) + { + /* Force unselection of the CC */ + input_SendEventEsSelect( p_input, SPU_ES, -1 ); + } + EsOutDel( out, parent->cc.pp_es[i] ); + } + + parent->cc.i_bitmap = 0; + parent->cc.type = 0; +} + static void EsUnselect( es_out_t *out, es_out_id_t *es, bool b_update ) { es_out_sys_t *p_sys = out->p_sys; @@ -1789,27 +1823,13 @@ static void EsUnselect( es_out_t *out, es_out_id_t *es, bool b_update ) { int i_channel = EsOutGetClosedCaptionsChannel( &es->fmt ); if( i_channel != -1 ) - input_DecoderSetCcState( es->p_master->p_dec, false, i_channel ); + input_DecoderSetCcState( es->p_master->p_dec, es->fmt.i_codec, + i_channel, false ); } } else { - const int i_spu_id = var_GetInteger( p_input, "spu-es"); - int i; - for( i = 0; i < 4; i++ ) - { - if( !es->pb_cc_present[i] || !es->pp_cc_es[i] ) - continue; - - if( i_spu_id == es->pp_cc_es[i]->i_id ) - { - /* Force unselection of the CC */ - input_SendEventEsSelect( p_input, SPU_ES, -1 ); - } - EsOutDel( out, es->pp_cc_es[i] ); - - es->pb_cc_present[i] = false; - } + EsDeleteCCChannels( out, es ); EsDestroyDecoder( out, es ); } @@ -1965,6 +1985,46 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force ) } } +static void EsOutCreateCCChannels( es_out_t *out, vlc_fourcc_t codec, uint64_t i_bitmap, + const char *psz_descfmt, es_out_id_t *parent ) +{ + es_out_sys_t *p_sys = out->p_sys; + input_thread_t *p_input = p_sys->p_input; + + /* Only one type of captions is allowed ! */ + if( parent->cc.type && parent->cc.type != codec ) + return; + + uint64_t i_existingbitmap = parent->cc.i_bitmap; + for( int i = 0; i_bitmap > 0; i++, i_bitmap >>= 1, i_existingbitmap >>= 1 ) + { + es_format_t fmt; + + if( (i_bitmap & 1) == 0 || (i_existingbitmap & 1) ) + continue; + + msg_Dbg( p_input, "Adding CC track %d for es[%d]", 1+i, parent->i_id ); + + es_format_Init( &fmt, SPU_ES, codec ); + fmt.subs.cc.i_channel = i; + fmt.i_group = parent->fmt.i_group; + if( asprintf( &fmt.psz_description, psz_descfmt, 1 + i ) == -1 ) + fmt.psz_description = NULL; + + es_out_id_t **pp_es = &parent->cc.pp_es[i]; + *pp_es = EsOutAddSlave( out, &fmt, parent ); + es_format_Clean( &fmt ); + + /* */ + parent->cc.i_bitmap |= (1ULL << i); + parent->cc.type = codec; + + /* Enable if user specified on command line */ + if (p_sys->sub.i_channel == i) + EsOutSelect(out, *pp_es, true); + } +} + /** * Send a block for the given es_out * @@ -2060,33 +2120,11 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block ) } /* Check CC status */ - bool pb_cc[4]; - - input_DecoderIsCcPresent( es->p_dec, pb_cc ); - for( int i = 0; i < 4; i++ ) - { - es_format_t fmt; + decoder_cc_desc_t desc; - if( es->pb_cc_present[i] || !pb_cc[i] ) - continue; - msg_Dbg( p_input, "Adding CC track %d for es[%d]", 1+i, es->i_id ); - - es_format_Init( &fmt, SPU_ES, VLC_CODEC_CEA608 ); - fmt.subs.cc.i_channel = i; - fmt.i_group = es->fmt.i_group; - if( asprintf( &fmt.psz_description, - _("Closed captions %u"), 1 + i ) == -1 ) - fmt.psz_description = NULL; - es->pp_cc_es[i] = EsOutAddSlave( out, &fmt, es ); - es_format_Clean( &fmt ); - - /* */ - es->pb_cc_present[i] = true; - - /* Enable if user specified on command line */ - if (p_sys->sub.i_channel == i) - EsOutSelect(out, es->pp_cc_es[i], true); - } + input_DecoderGetCcDesc( es->p_dec, &desc ); + EsOutCreateCCChannels( out, VLC_CODEC_CEA608, desc.i_608_channels, + _("Closed captions %u"), es ); vlc_mutex_unlock( &p_sys->lock ); _______________________________________________ vlc-commits mailing list vlc-commits@videolan.org https://mailman.videolan.org/listinfo/vlc-commits