From db7c88851fa45ecc3160a27f9a26e2f62b589baa Mon Sep 17 00:00:00 2001 From: Christophe Massiot Date: Fri, 19 Jan 2007 18:26:39 +0000 Subject: [PATCH] * modules/demux/ts.c: Parse the telx descriptor and create pseudo ES for different languages. Slightly changed the way the dvbsub parser works to allow correct streaming with --sout-all or --programs. * modules/mux/mpeg/ts.c: Changes to allow descriptor pass-through with telx and dvbsub. This is kind of kludgy. * module/codec/telx.c: Got rid of the ugly static variables and use info from the TS demux. --- modules/codec/telx.c | 105 +++++++++--------- modules/demux/ts.c | 242 +++++++++++++++++++++++++++++++++--------- modules/mux/mpeg/ts.c | 57 ++++++---- 3 files changed, 279 insertions(+), 125 deletions(-) diff --git a/modules/codec/telx.c b/modules/codec/telx.c index 13efdabb20..ac2b84345e 100644 --- a/modules/codec/telx.c +++ b/modules/codec/telx.c @@ -40,15 +40,6 @@ # define dbg( a ) #endif -/***************************************************************************** - * Local prototypes - *****************************************************************************/ -static int telx_conf_cb ( vlc_object_t *, /* variable's object */ - char const *, /* variable name */ - vlc_value_t, /* old value */ - vlc_value_t, /* new value */ - void * ); /* callback data */ - /***************************************************************************** * Module descriptor. *****************************************************************************/ @@ -56,12 +47,13 @@ static int Open ( vlc_object_t * ); static void Close( vlc_object_t * ); static subpicture_t *Decode( decoder_t *, block_t ** ); - -#define PAGE_TEXT N_("Teletext page") -#define PAGE_LONGTEXT N_("Set displayed teletext page for subtitles, 0 for all pages, 888 should be a standard value. Just leave it to zero if your stream has only one language for subtitles.") +#define OVERRIDE_PAGE_TEXT N_("Override page") +#define OVERRIDE_PAGE_LONGTEXT N_("Override the indicated page, try this if " \ + "your subtitles don't appear (0 = autodetect, usually 888 or 889).") #define IGNORE_SUB_FLAG_TEXT N_("Ignore subtitle flag") -#define IGNORE_SUB_FLAG_LONGTEXT N_("Ignore the subtitle flag, try this if your subtitles don't appear.") +#define IGNORE_SUB_FLAG_LONGTEXT N_("Ignore the subtitle flag, try this if " \ + "your subtitles don't appear.") vlc_module_begin(); set_description( _("Teletext subtitles decoder") ); @@ -71,9 +63,9 @@ vlc_module_begin(); set_subcategory( SUBCAT_INPUT_SCODEC ); set_callbacks( Open, Close ); - add_integer( "telx-page", 0, telx_conf_cb, PAGE_TEXT, PAGE_LONGTEXT, - VLC_FALSE ); - add_bool( "telx-ignore-subtitle-flag", 0, telx_conf_cb, + add_integer( "telx-override-page", -1, NULL, + OVERRIDE_PAGE_TEXT, OVERRIDE_PAGE_LONGTEXT, VLC_TRUE ); + add_bool( "telx-ignore-subtitle-flag", 0, NULL, IGNORE_SUB_FLAG_TEXT, IGNORE_SUB_FLAG_LONGTEXT, VLC_TRUE ); vlc_module_end(); @@ -92,15 +84,14 @@ struct decoder_sys_t int i_page[9]; vlc_bool_t b_erase[9]; uint16_t * pi_active_national_set[9]; + int i_wanted_page, i_wanted_magazine; + vlc_bool_t b_ignore_sub_flag; }; /**************************************************************************** * Local data ****************************************************************************/ -static int i_conf_wanted_page = 0; /* default 0 = all pages */ -static vlc_bool_t b_ignore_sub_flag = 0; - /* * My doc only mentions 13 national characters, but experiments show there * are more, in france for example I already found two more (0x9 and 0xb). @@ -188,14 +179,36 @@ static int Open( vlc_object_t *p_this ) for ( i = 0; i < 9; i++ ) p_sys->pi_active_national_set[i] = ppi_national_subsets[1]; - var_Create( p_dec, "telx-page", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Get( p_dec, "telx-page", &val ); - i_conf_wanted_page = val.i_int; + var_Create( p_dec, "telx-override-page", + VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); + var_Get( p_dec, "telx-override-page", &val ); + if( val.i_int == -1 ) + { + p_sys->i_wanted_magazine = p_dec->fmt_in.subs.dvb.i_id >> 16; + if( p_sys->i_wanted_magazine == 0 ) + p_sys->i_wanted_magazine = 8; + p_sys->i_wanted_page = p_dec->fmt_in.subs.dvb.i_id & 0xff; + } + else if( val.i_int == 0 ) + { + p_sys->i_wanted_magazine = -1; + p_sys->i_wanted_page = -1; + } + else + { + p_sys->i_wanted_magazine = val.i_int / 100; + p_sys->i_wanted_page = (((val.i_int % 100) / 10) << 4) + | ((val.i_int % 100) % 10); + } var_Create( p_dec, "telx-ignore-subtitle-flag", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_dec, "telx-ignore-subtitle-flag", &val ); - b_ignore_sub_flag = val.b_bool; + p_sys->b_ignore_sub_flag = val.b_bool; + + msg_Dbg( p_dec, "starting telx on magazine %d page %x flag %d", + p_sys->i_wanted_magazine, p_sys->i_wanted_page, + p_sys->b_ignore_sub_flag ); return VLC_SUCCESS; @@ -207,30 +220,6 @@ static int Open( vlc_object_t *p_this ) /* return VLC_EGENERIC; */ } -/***************************************************************************** - * Config callback - *****************************************************************************/ -static int telx_conf_cb ( vlc_object_t * obj, /* variable's object */ - char const * name, /* variable name */ - vlc_value_t oldv, /* old value */ - vlc_value_t newv, /* new value */ - void * data) /* callback data */ -{ - if ( !strcmp(name, "telx-page") ) - { - i_conf_wanted_page = newv.i_int; - dbg((obj, "display teletext page changed to %d\n", i_conf_wanted_page)); - } - else if ( !strcmp(name, "telx-ignore-subtitle-flag") ) - { - b_ignore_sub_flag = newv.b_bool; - dbg((obj, "ignore sub flag changed to %d\n", (int) b_ignore_sub_flag)); - } - - return 0; -} - - /***************************************************************************** * Close: *****************************************************************************/ @@ -430,9 +419,11 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) video_format_t fmt; /* int erase = 0; */ int len, offset; +#if 0 int i_wanted_magazine = i_conf_wanted_page / 100; int i_wanted_page = 0x10 * ((i_conf_wanted_page % 100) / 10) | (i_conf_wanted_page % 10); +#endif vlc_bool_t b_update = VLC_FALSE; char psz_text[512], *pt = psz_text; char psz_line[256]; @@ -472,7 +463,9 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) magazine = (7 & row) == 0 ? 8 : (7 & row); row >>= 3; - if ( i_conf_wanted_page && magazine != i_wanted_magazine ) continue; + if ( p_sys->i_wanted_page != -1 + && magazine != p_sys->i_wanted_magazine ) + continue; if ( row == 0 ) { @@ -486,7 +479,7 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) << (a * 4); } - /* if (!b_ignore_sub_flag && !(1 & flag>>15)) */ + /* if (!p_sys->b_ignore_sub_flag && !(1 & flag>>15)) */ /* continue; */ p_sys->i_page[magazine] = (0xF0 & bytereverse( hamming_8_4(packet[7]) )) | @@ -502,7 +495,7 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) p_sys->pi_active_national_set[magazine] = ppi_national_subsets[7 & (flag >> 21)]; - p_sys->b_is_subtitle[magazine] = b_ignore_sub_flag + p_sys->b_is_subtitle[magazine] = p_sys->b_ignore_sub_flag || ( (1 & (flag >> 15)) && (1 & (flag>>16)) ); @@ -516,7 +509,8 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) (1 & (flag>>19))? " inhibit" : "", (1 & (flag>>20)) )); - if ( (i_conf_wanted_page && p_sys->i_page[magazine] != i_wanted_page) + if ( (p_sys->i_wanted_page != -1 + && p_sys->i_page[magazine] != p_sys->i_wanted_page) || !p_sys->b_is_subtitle[magazine] ) continue; @@ -560,9 +554,11 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) int i; /* row 1-23 : normal lines */ - if ( (i_conf_wanted_page && p_sys->i_page[magazine] != i_wanted_page) + if ( (p_sys->i_wanted_page != -1 + && p_sys->i_page[magazine] != p_sys->i_wanted_page) || !p_sys->b_is_subtitle[magazine] - || (!i_conf_wanted_page && p_sys->i_page[magazine] > 0x99) ) + || (p_sys->i_wanted_page == -1 + && p_sys->i_page[magazine] > 0x99) ) continue; decode_string( psz_line, sizeof(psz_line), p_sys, magazine, @@ -615,7 +611,8 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) else if ( row == 25 ) { /* row 25 : alternate header line */ - if ( (i_conf_wanted_page && p_sys->i_page[magazine] != i_wanted_page) + if ( (p_sys->i_wanted_page != -1 + && p_sys->i_page[magazine] != p_sys->i_wanted_page) || !p_sys->b_is_subtitle[magazine] ) continue; diff --git a/modules/demux/ts.c b/modules/demux/ts.c index f3d768fca7..8cb2c82fc5 100644 --- a/modules/demux/ts.c +++ b/modules/demux/ts.c @@ -2655,7 +2655,7 @@ static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h, i_table_id, i_table_id, i_extension, i_extension ); #endif if( p_demux->p_sys->pid[0].psi->i_pat_version == -1 ) - return; + return; if( i_table_id == 0x42 ) { @@ -3016,69 +3016,210 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) msg_Dbg( p_demux, " * EBU Teletext descriptor" ); pid->es->fmt.i_cat = SPU_ES; pid->es->fmt.i_codec = VLC_FOURCC( 't', 'e', 'l', 'x' ); - pid->es->fmt.psz_description = strdup( "Teletext" ); pid->es->fmt.i_extra = p_dr->i_length; pid->es->fmt.p_extra = malloc( p_dr->i_length ); memcpy( pid->es->fmt.p_extra, p_dr->p_data, p_dr->i_length ); + +#ifdef _DVBPSI_DR_56_H_ + pid->es->fmt.i_group = p_pmt->i_program_number; + + /* If i_dvb_program == -1 it means the user specified + * --sout-all or --programs, so she want to stream, and + * she doesn't want to stream several identical ESes + * with different language descriptors. So for -1 we + * just enable descriptor pass-through. --Meuuh */ + if( p_sys->i_dvb_program != -1 ) + { + uint16_t n, i = 0; + dvbpsi_teletext_dr_t *sub; + + sub = dvbpsi_DecodeTeletextDr( p_dr ); + if( !sub ) continue; + + /* Each subtitle ES contains n languages, + * We are going to create n ES for the n tracks */ + for( n = 0; n < sub->i_pages_number; n++ ) + { + dvbpsi_teletextpage_t *p_page = &sub->p_pages[n]; + if( p_page->i_teletext_type == 0x2 + || p_page->i_teletext_type == 0x5 ) + { + ts_es_t *p_es; + + if( i == 0 ) + { + p_es = pid->es; + } + else + { + p_es = malloc( sizeof( ts_es_t ) ); + p_es->fmt = pid->es->fmt; + p_es->id = NULL; + p_es->p_pes = NULL; + p_es->i_pes_size = 0; + p_es->i_pes_gathered = 0; + p_es->pp_last = &p_es->p_pes; + p_es->p_mpeg4desc = NULL; + + TAB_APPEND( pid->i_extra_es, pid->extra_es, + p_es ); + } + + p_es->fmt.psz_language = malloc( 4 ); + memcpy( p_es->fmt.psz_language, + p_page->i_iso6392_language_code, 3 ); + p_es->fmt.psz_language[3] = 0; + + switch( p_page->i_teletext_type ) + { + case 0x2: + p_es->fmt.psz_description = + strdup(_("subtitles")); + msg_Dbg( p_demux, + " * sub lan=%s page=%d%x", + p_es->fmt.psz_language, + p_page->i_teletext_magazine_number, + p_page->i_teletext_page_number ); + break; + + case 0x5: + p_es->fmt.psz_description = + strdup(_("hearing impaired")); + msg_Dbg( p_demux, + " * hearing impaired lan=%s page=%d%x", + p_es->fmt.psz_language, + p_page->i_teletext_magazine_number, + p_page->i_teletext_page_number ); + break; + default: + break; + } + + p_es->fmt.subs.dvb.i_id = + p_page->i_teletext_page_number; + /* Hack, FIXME */ + p_es->fmt.subs.dvb.i_id |= + ((int)p_page->i_teletext_magazine_number << 16); + + i++; + } + } + + if( !i ) + pid->es->fmt.i_cat = UNKNOWN_ES; + } +#else + pid->es->fmt.psz_description = strdup( "Teletext" ); +#endif } -#ifdef _DVBPSI_DR_59_H_ else if( p_dr->i_tag == 0x59 ) { - uint16_t n; - dvbpsi_subtitling_dr_t *sub; - /* DVB subtitles */ pid->es->fmt.i_cat = SPU_ES; pid->es->fmt.i_codec = VLC_FOURCC( 'd', 'v', 'b', 's' ); - pid->es->fmt.i_group = p_pmt->i_program_number; + pid->es->fmt.i_extra = p_dr->i_length; + pid->es->fmt.p_extra = malloc( p_dr->i_length ); + memcpy( pid->es->fmt.p_extra, p_dr->p_data, + p_dr->i_length ); - sub = dvbpsi_DecodeSubtitlingDr( p_dr ); - if( !sub ) continue; +#ifdef _DVBPSI_DR_59_H_ + pid->es->fmt.i_group = p_pmt->i_program_number; - /* Each subtitle ES contains n languages, - * We are going to create n ES for the n tracks */ - if( sub->i_subtitles_number > 0 ) + /* If i_dvb_program == -1 it means the user specified + * --sout-all or --programs, so she want to stream, and + * she doesn't want to stream several identical ESes + * with different language descriptors. So for -1 we + * just enable descriptor pass-through. --Meuuh */ + if( p_sys->i_dvb_program != -1 ) { - pid->es->fmt.psz_language = malloc( 4 ); - memcpy( pid->es->fmt.psz_language, - sub->p_subtitle[0].i_iso6392_language_code, 3); - pid->es->fmt.psz_language[3] = 0; - - pid->es->fmt.subs.dvb.i_id = - sub->p_subtitle[0].i_composition_page_id; - /* Hack, FIXME */ - pid->es->fmt.subs.dvb.i_id |= - ((int)sub->p_subtitle[0].i_ancillary_page_id << 16); - } - else pid->es->fmt.i_cat = UNKNOWN_ES; + uint16_t n, i = 0; + dvbpsi_subtitling_dr_t *sub; - for( n = 1; n < sub->i_subtitles_number; n++ ) - { - ts_es_t *p_es = malloc( sizeof( ts_es_t ) ); - p_es->fmt = pid->es->fmt; - p_es->id = NULL; - p_es->p_pes = NULL; - p_es->i_pes_size = 0; - p_es->i_pes_gathered = 0; - p_es->pp_last = &p_es->p_pes; - p_es->p_mpeg4desc = NULL; - - p_es->fmt.psz_language = malloc( 4 ); - memcpy( p_es->fmt.psz_language, - sub->p_subtitle[n].i_iso6392_language_code, 3); - p_es->fmt.psz_language[3] = 0; - - p_es->fmt.subs.dvb.i_id = - sub->p_subtitle[n].i_composition_page_id; - /* Hack, FIXME */ - p_es->fmt.subs.dvb.i_id |= - ((int)sub->p_subtitle[n].i_ancillary_page_id << 16); - - TAB_APPEND( pid->i_extra_es, pid->extra_es, p_es ); + sub = dvbpsi_DecodeSubtitlingDr( p_dr ); + if( !sub ) continue; + + for( n = 0; n < sub->i_subtitles_number; n++ ) + { + dvbpsi_subtitle_t *p_sub = &sub->p_subtitle[n]; + ts_es_t *p_es; + + if( i == 0 ) + { + p_es = pid->es; + } + else + { + p_es = malloc( sizeof( ts_es_t ) ); + p_es->fmt = pid->es->fmt; + p_es->id = NULL; + p_es->p_pes = NULL; + p_es->i_pes_size = 0; + p_es->i_pes_gathered = 0; + p_es->pp_last = &p_es->p_pes; + p_es->p_mpeg4desc = NULL; + + TAB_APPEND( pid->i_extra_es, pid->extra_es, + p_es ); + } + + p_es->fmt.psz_language = malloc( 4 ); + memcpy( p_es->fmt.psz_language, + p_sub->i_iso6392_language_code, 3 ); + p_es->fmt.psz_language[3] = 0; + + switch( p_sub->i_subtitling_type ) + { + case 0x10: + p_es->fmt.psz_description = + strdup(_("subtitles")); + break; + case 0x11: + p_es->fmt.psz_description = + strdup(_("4:3 subtitles")); + break; + case 0x12: + p_es->fmt.psz_description = + strdup(_("16:9 subtitles")); + break; + case 0x13: + p_es->fmt.psz_description = + strdup(_("2.21:1 subtitles")); + break; + case 0x20: + p_es->fmt.psz_description = + strdup(_("hearing impaired")); + break; + case 0x21: + p_es->fmt.psz_description = + strdup(_("4:3 hearing impaired")); + break; + case 0x22: + p_es->fmt.psz_description = + strdup(_("16:9 hearing impaired")); + break; + case 0x23: + p_es->fmt.psz_description = + strdup(_("2.21:1 hearing impaired")); + break; + default: + break; + } + + p_es->fmt.subs.dvb.i_id = + p_sub->i_composition_page_id; + /* Hack, FIXME */ + p_es->fmt.subs.dvb.i_id |= + ((int)p_sub->i_ancillary_page_id << 16); + + i++; + } + + if( !i ) + pid->es->fmt.i_cat = UNKNOWN_ES; } - } #endif /* _DVBPSI_DR_59_H_ */ + } } } else if( p_es->i_type == 0xa0 ) @@ -3121,7 +3262,8 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) if( pid->es->fmt.i_cat == AUDIO_ES || ( pid->es->fmt.i_cat == SPU_ES && - pid->es->fmt.i_codec != VLC_FOURCC('d','v','b','s') ) ) + pid->es->fmt.i_codec != VLC_FOURCC('d','v','b','s') && + pid->es->fmt.i_codec != VLC_FOURCC('t','e','l','x') ) ) { /* get language descriptor */ dvbpsi_descriptor_t *p_dr = p_es->p_first_descriptor; @@ -3133,7 +3275,7 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) if( p_decoded ) { -#if DR_0A_API_VER >= 2 +#if defined(DR_0A_API_VER) && (DR_0A_API_VER >= 2) pid->es->fmt.psz_language = malloc( 4 ); memcpy( pid->es->fmt.psz_language, p_decoded->code[0].iso_639_code, 3 ); diff --git a/modules/mux/mpeg/ts.c b/modules/mux/mpeg/ts.c index 7ef7e0fa3f..4b118005ce 100644 --- a/modules/mux/mpeg/ts.c +++ b/modules/mux/mpeg/ts.c @@ -2497,33 +2497,48 @@ static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c ) } else if( p_stream->i_codec == VLC_FOURCC('t','e','l','x') ) { - dvbpsi_PMTESAddDescriptor( p_es, 0x56, - p_stream->i_decoder_specific_info, - p_stream->p_decoder_specific_info ); + if( p_stream->i_decoder_specific_info ) + { + dvbpsi_PMTESAddDescriptor( p_es, 0x56, + p_stream->i_decoder_specific_info, + p_stream->p_decoder_specific_info ); + } + continue; } -#ifdef _DVBPSI_DR_59_H_ else if( p_stream->i_codec == VLC_FOURCC('d','v','b','s') ) { /* DVB subtitles */ - dvbpsi_subtitling_dr_t descr; - dvbpsi_subtitle_t sub; - dvbpsi_descriptor_t *p_descr; - - memcpy( sub.i_iso6392_language_code, p_stream->lang, 3 ); - sub.i_subtitling_type = 0x10; /* no aspect-ratio criticality */ - sub.i_composition_page_id = p_stream->i_es_id & 0xFF; - sub.i_ancillary_page_id = p_stream->i_es_id >> 16; - - descr.i_subtitles_number = 1; - descr.p_subtitle[0] = sub; - - p_descr = dvbpsi_GenSubtitlingDr( &descr, 0 ); - /* Work around bug in old libdvbpsi */ p_descr->i_length = 8; - dvbpsi_PMTESAddDescriptor( p_es, p_descr->i_tag, - p_descr->i_length, p_descr->p_data ); + if( p_stream->i_decoder_specific_info ) + { + /* pass-through from the TS demux */ + dvbpsi_PMTESAddDescriptor( p_es, 0x59, + p_stream->i_decoder_specific_info, + p_stream->p_decoder_specific_info ); + } +#ifdef _DVBPSI_DR_59_H_ + else + { + /* from the dvbsub transcoder */ + dvbpsi_subtitling_dr_t descr; + dvbpsi_subtitle_t sub; + dvbpsi_descriptor_t *p_descr; + + memcpy( sub.i_iso6392_language_code, p_stream->lang, 3 ); + sub.i_subtitling_type = 0x10; /* no aspect-ratio criticality */ + sub.i_composition_page_id = p_stream->i_es_id & 0xFF; + sub.i_ancillary_page_id = p_stream->i_es_id >> 16; + + descr.i_subtitles_number = 1; + descr.p_subtitle[0] = sub; + + p_descr = dvbpsi_GenSubtitlingDr( &descr, 0 ); + /* Work around bug in old libdvbpsi */ p_descr->i_length = 8; + dvbpsi_PMTESAddDescriptor( p_es, p_descr->i_tag, + p_descr->i_length, p_descr->p_data ); + } +#endif /* _DVBPSI_DR_59_H_ */ continue; } -#endif /* _DVBPSI_DR_59_H_ */ if( p_stream->lang[0] != 0 ) {