From 248519b2c01ce933ccdb0de9f1da1f4cfbd5b893 Mon Sep 17 00:00:00 2001 From: Naohiro KORIYAMA Date: Sat, 2 Aug 2014 10:31:18 +0900 Subject: [PATCH] demux: ts: add ARIB support Signed-off-by: Francois Cartegnie Fixed-by: Francois Cartegnie --- modules/demux/ts.c | 147 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 138 insertions(+), 9 deletions(-) diff --git a/modules/demux/ts.c b/modules/demux/ts.c index 05d764a911..14ea4f709d 100644 --- a/modules/demux/ts.c +++ b/modules/demux/ts.c @@ -74,6 +74,13 @@ VLC_FORMAT(1, 2) static void ts_debug(const char *format, ...) #endif } +typedef enum arib_modes_e +{ + ARIBMODE_AUTO = -1, + ARIBMODE_DISABLED = 0, + ARIBMODE_ENABLED = 1 +} arib_modes_e; + /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -126,6 +133,16 @@ static void Close ( vlc_object_t * ); #define PCR_TEXT N_("Trust in-stream PCR") #define PCR_LONGTEXT N_("Use the stream PCR as a reference.") +static const int const arib_mode_list[] = + { ARIBMODE_AUTO, ARIBMODE_ENABLED, ARIBMODE_DISABLED }; +static const char *const arib_mode_list_text[] = + { N_("Auto"), N_("Enabled"), N_("Disabled") }; + +#define SUPPORT_ARIB_TEXT N_("ARIB STD-B24 mode") +#define SUPPORT_ARIB_LONGTEXT N_( \ + "Forces ARIB STD-B24 mode for decoding characters." \ + "This feature affects EPG information and subtitles." ) + vlc_module_begin () set_description( N_("MPEG Transport Stream demuxer") ) set_shortname ( "MPEG-TS" ) @@ -149,6 +166,9 @@ vlc_module_begin () add_bool( "ts-split-es", true, SPLIT_ES_TEXT, SPLIT_ES_LONGTEXT, false ) add_bool( "ts-seek-percent", false, SEEK_PERCENT_TEXT, SEEK_PERCENT_LONGTEXT, true ) + add_integer( "ts-arib", ARIBMODE_AUTO, SUPPORT_ARIB_TEXT, SUPPORT_ARIB_LONGTEXT, false ) + change_integer_list( arib_mode_list, arib_mode_list_text ) + add_obsolete_bool( "ts-silent" ); set_capability( "demux", 10 ) @@ -297,6 +317,11 @@ struct demux_sys_t mtime_t *p_pcrs; int64_t *p_pos; + struct + { + arib_modes_e e_mode; + } arib; + /* All pid */ ts_pid_t pid[8192]; @@ -759,6 +784,8 @@ static int Open( vlc_object_t *p_this ) p_sys->p_pcrs = (mtime_t *)calloc( p_sys->i_pcrs_num, sizeof( mtime_t ) ); p_sys->p_pos = (int64_t *)calloc( p_sys->i_pcrs_num, sizeof( int64_t ) ); + p_sys->arib.e_mode = var_InheritInteger( p_demux, "ts-arib" ); + if( !p_sys->p_pcrs || !p_sys->p_pos ) { Close( p_this ); @@ -1717,6 +1744,22 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes ) } } } + else if( pid->es->fmt.i_codec == VLC_CODEC_ARIB_A || + pid->es->fmt.i_codec == VLC_CODEC_ARIB_C ) + { + if( p_block->i_pts <= VLC_TS_INVALID ) + { + if( i_pes_size > 0 && p_block->i_buffer > i_pes_size ) + { + p_block->i_buffer = i_pes_size; + } + /* Append a \0 */ + p_block = block_Realloc( p_block, 0, p_block->i_buffer + 1 ); + if( !p_block ) + return; + p_block->p_buffer[p_block->i_buffer -1] = '\0'; + } + } for( int i = 0; i < pid->i_extra_es; i++ ) { @@ -2752,10 +2795,13 @@ static void ValidateDVBMeta( demux_t *p_demux, int i_pid ) #include "dvb-text.h" -static char *EITConvertToUTF8( const unsigned char *psz_instring, +static char *EITConvertToUTF8( demux_t *p_demux, + const unsigned char *psz_instring, size_t i_length, bool b_broken ) { + demux_sys_t *p_sys = p_demux->p_sys; + VLC_UNUSED(p_sys); /* Deal with no longer broken providers (no switch byte but sending ISO_8859-1 instead of ISO_6937) without removing them from the broken providers table @@ -2861,10 +2907,12 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) /* FIXME: Digital+ ES also uses ISO8859-1 */ - str1 = EITConvertToUTF8(pD->i_service_provider_name, + str1 = EITConvertToUTF8(p_demux, + pD->i_service_provider_name, pD->i_service_provider_name_length, p_sys->b_broken_charset ); - str2 = EITConvertToUTF8(pD->i_service_name, + str2 = EITConvertToUTF8(p_demux, + pD->i_service_name, pD->i_service_name_length, p_sys->b_broken_charset ); @@ -3032,9 +3080,11 @@ static void EITCallBack( demux_t *p_demux, for epg atm*/ if( pE && psz_name == NULL) { - psz_name = EITConvertToUTF8( pE->i_event_name, pE->i_event_name_length, + psz_name = EITConvertToUTF8( p_demux, + pE->i_event_name, pE->i_event_name_length, p_sys->b_broken_charset ); - psz_text = EITConvertToUTF8( pE->i_text, pE->i_text_length, + psz_text = EITConvertToUTF8( p_demux, + pE->i_text, pE->i_text_length, p_sys->b_broken_charset ); msg_Dbg( p_demux, " - short event lang=%3.3s '%s' : '%s'", pE->i_iso_639_code, psz_name, psz_text ); @@ -3053,7 +3103,8 @@ static void EITCallBack( demux_t *p_demux, if( pE->i_text_length > 0 ) { - char *psz_text = EITConvertToUTF8( pE->i_text, pE->i_text_length, + char *psz_text = EITConvertToUTF8( p_demux, + pE->i_text, pE->i_text_length, p_sys->b_broken_charset ); if( psz_text ) { @@ -3068,10 +3119,12 @@ static void EITCallBack( demux_t *p_demux, for( int i = 0; i < pE->i_entry_count; i++ ) { - char *psz_dsc = EITConvertToUTF8( pE->i_item_description[i], + char *psz_dsc = EITConvertToUTF8( p_demux, + pE->i_item_description[i], pE->i_item_description_length[i], p_sys->b_broken_charset ); - char *psz_itm = EITConvertToUTF8( pE->i_item[i], pE->i_item_length[i], + char *psz_itm = EITConvertToUTF8( p_demux, + pE->i_item[i], pE->i_item_length[i], p_sys->b_broken_charset ); if( psz_dsc && psz_itm ) @@ -3262,6 +3315,20 @@ static bool PMTEsHasRegistration( demux_t *p_demux, assert( strlen(psz_tag) == 4 ); return !memcmp( p_dr->p_data, psz_tag, 4 ); } + +static bool PMTEsHasComponentTag( const dvbpsi_pmt_es_t *p_es, + int i_component_tag ) +{ + dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0x52 ); + if( !p_dr ) + return false; + dvbpsi_stream_identifier_dr_t *p_si = dvbpsi_DecodeStreamIdentifierDr( p_dr ); + if( !p_si ) + return false; + + return p_si->i_component_tag == i_component_tag; +} + static void PMTSetupEsISO14496( demux_t *p_demux, ts_pid_t *pid, const ts_prg_psi_t *prg, const dvbpsi_pmt_es_t *p_es ) { @@ -3683,6 +3750,37 @@ static void PMTSetupEs0x06( demux_t *p_demux, ts_pid_t *pid, p_fmt->i_cat = VIDEO_ES; p_fmt->i_codec = VLC_CODEC_HEVC; } + else if ( p_demux->p_sys->arib.e_mode == ARIBMODE_ENABLED ) + { + /* Lookup our data component descriptor first ARIB STD B10 6.4 */ + dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0xFD ); + /* and check that it maps to something ARIB STD B14 Table 5.1/5.2 */ + if ( p_dr && p_dr->i_length >= 2 ) + { + if( !memcmp( p_dr->p_data, "\x00\x08", 2 ) && ( + PMTEsHasComponentTag( p_es, 0x30 ) || + PMTEsHasComponentTag( p_es, 0x31 ) || + PMTEsHasComponentTag( p_es, 0x32 ) || + PMTEsHasComponentTag( p_es, 0x33 ) || + PMTEsHasComponentTag( p_es, 0x34 ) || + PMTEsHasComponentTag( p_es, 0x35 ) || + PMTEsHasComponentTag( p_es, 0x36 ) || + PMTEsHasComponentTag( p_es, 0x37 ) ) ) + { + es_format_Init( &pid->es->fmt, SPU_ES, VLC_CODEC_ARIB_A ); + p_fmt->psz_language = strndup ( "jpn", 3 ); + p_fmt->psz_description = strdup( _("ARIB subtitles") ); + } + else if( !memcmp( p_dr->p_data, "\x00\x12", 2 ) && ( + PMTEsHasComponentTag( p_es, 0x87 ) || + PMTEsHasComponentTag( p_es, 0x88 ) ) ) + { + es_format_Init( &pid->es->fmt, SPU_ES, VLC_CODEC_ARIB_C ); + p_fmt->psz_language = strndup ( "jpn", 3 ); + p_fmt->psz_description = strdup( _("ARIB subtitles") ); + } + } + } else { /* Subtitle/Teletext/VBI fallbacks */ @@ -4056,7 +4154,38 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_pmt ) /* Parse PMT descriptors */ ts_pmt_registration_type_t registration_type = TS_PMT_REGISTRATION_NONE; dvbpsi_descriptor_t *p_dr; + + /* First pass for standard detection */ + if ( p_sys->arib.e_mode == ARIBMODE_AUTO ) + { + int i_arib_flags = 0; /* Descriptors can be repeated */ + for( p_dr = p_pmt->p_first_descriptor; p_dr != NULL; p_dr = p_dr->p_next ) + { + switch(p_dr->i_tag) + { + case 0x09: + { + dvbpsi_ca_dr_t *p_cadr = dvbpsi_DecodeCADr( p_dr ); + i_arib_flags |= (p_cadr->i_ca_system_id == 0x05); + } + break; + case 0xF6: + i_arib_flags |= 1 << 1; + break; + case 0xC1: + i_arib_flags |= 1 << 2; + break; + default: + break; + } + } + if ( i_arib_flags == 0b111 ) + p_sys->arib.e_mode = ARIBMODE_ENABLED; + } + for( p_dr = p_pmt->p_first_descriptor; p_dr != NULL; p_dr = p_dr->p_next ) + { + /* special descriptors handling */ switch(p_dr->i_tag) { case 0x1d: /* We have found an IOD descriptor */ @@ -4098,7 +4227,7 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_pmt ) default: msg_Dbg( p_demux, " * PMT descriptor : unknown (0x%x)", p_dr->i_tag ); } - + } dvbpsi_pmt_es_t *p_es; for( p_es = p_pmt->p_first_es; p_es != NULL; p_es = p_es->p_next ) { -- 2.39.2