X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fts.c;h=78332fe745924335711fa1914d43f535b9115b22;hb=e2eccee759772d903d7fb1fed398fb354d45b676;hp=7745445179a973b776abd2e9b5b942617e9b6b2e;hpb=15643af12d9eb61eff8a8e89d8170f3d2b73d7e1;p=vlc diff --git a/modules/demux/ts.c b/modules/demux/ts.c index 7745445179..78332fe745 100644 --- a/modules/demux/ts.c +++ b/modules/demux/ts.c @@ -32,9 +32,7 @@ #include #include -#include -#include #include #include /* DVB-specific things */ @@ -45,6 +43,7 @@ #include #include #include +#include #include "../mux/mpeg/csa.h" @@ -156,6 +155,11 @@ static void Close ( vlc_object_t * ); "Tweak the buffer size for reading and writing an integer number of packets." \ "Specify the size of the buffer here and not the number of packets." ) +#define SPLIT_ES_TEXT N_("Separate sub-streams") +#define SPLIT_ES_LONGTEXT N_( \ + "Separate teletex/dvbs pages into independant ES. " \ + "It can be usefull to turn off this option when using stream output." ) + vlc_module_begin () set_description( N_("MPEG Transport Stream demuxer") ) set_shortname ( "MPEG-TS" ) @@ -176,6 +180,7 @@ vlc_module_begin () add_bool( "ts-dump-append", false, NULL, APPEND_TEXT, APPEND_LONGTEXT, false ) add_integer( "ts-dump-size", 16384, NULL, DUMPSIZE_TEXT, DUMPSIZE_LONGTEXT, true ) + add_bool( "ts-split-es", true, NULL, SPLIT_ES_TEXT, SPLIT_ES_LONGTEXT, false ) set_capability( "demux", 10 ) set_callbacks( Open, Close ) @@ -360,6 +365,7 @@ struct demux_sys_t csa_t *csa; int i_csa_pkt_size; bool b_silent; + bool b_split_es; bool b_udp_out; int fd; /* udp socket */ @@ -373,6 +379,7 @@ struct demux_sys_t int64_t i_tdt_delta; int64_t i_dvb_start; int64_t i_dvb_length; + bool b_broken_charset; /* True if broken encoding is used in EPG/SDT */ /* */ int i_current_program; @@ -388,8 +395,6 @@ struct demux_sys_t bool b_start_record; }; -static int i_broken_epg; - static int Demux ( demux_t *p_demux ); static int DemuxFile( demux_t *p_demux ); static int Control( demux_t *p_demux, int i_query, va_list args ); @@ -516,10 +521,6 @@ static int Open( vlc_object_t *p_this ) char *psz_event_text = malloc(130); char *psz_ext_text = malloc(1025); - assert( psz_name ); - assert( psz_event_text ); - assert( psz_ext_text ); - // 2 bytes version Uimsbf (4,5) // 2 bytes reserved (6,7) // 2 bytes duration in minutes Uimsbf (8,9( @@ -608,7 +609,7 @@ static int Open( vlc_object_t *p_this ) msg_Info( p_demux, "dumping raw stream to standard output" ); p_sys->p_file = stdout; } - else if( ( p_sys->p_file = utf8_fopen( p_sys->psz_file, psz_mode ) ) == NULL ) + else if( ( p_sys->p_file = vlc_fopen( p_sys->psz_file, psz_mode ) ) == NULL ) { msg_Err( p_demux, "cannot create `%s' for writing", p_sys->psz_file ); p_sys->b_file_out = false; @@ -623,8 +624,7 @@ static int Open( vlc_object_t *p_this ) { p_sys->i_ts_read = 1500 / p_sys->i_packet_size; } - p_sys->buffer = malloc( p_sys->i_packet_size * p_sys->i_ts_read ); - assert( p_sys->buffer ); + p_sys->buffer = xmalloc( p_sys->i_packet_size * p_sys->i_ts_read ); msg_Info( p_demux, "%s raw stream to file `%s' reading packets %d", b_append ? "appending" : "dumping", p_sys->psz_file, p_sys->i_ts_read ); @@ -646,6 +646,8 @@ static int Open( vlc_object_t *p_this ) p_sys->i_dvb_start = 0; p_sys->i_dvb_length = 0; + p_sys->b_broken_charset = false; + for( i = 0; i < 8192; i++ ) { ts_pid_t *pid = &p_sys->pid[i]; @@ -800,6 +802,7 @@ static int Open( vlc_object_t *p_this ) free( psz_string ); p_sys->b_silent = var_CreateGetBool( p_demux, "ts-silent" ); + p_sys->b_split_es = var_InheritBool( p_demux, "ts-split-es" ); return VLC_SUCCESS; } @@ -882,7 +885,7 @@ static void Close( vlc_object_t *p_this ) /* If in dump mode, then close the file */ if( p_sys->b_file_out ) { - msg_Info( p_demux ,"closing %s (%"PRId64" Kbytes dumped)", + msg_Info( p_demux ,"closing %s (%"PRId64" KiB dumped)", p_sys->psz_file, p_sys->i_write / 1024 ); if( p_sys->p_file != stdout ) @@ -1554,7 +1557,7 @@ static void PIDInit( ts_pid_t *pid, bool b_psi, ts_psi_t *p_owner ) if( !b_old_valid ) { - pid->psi = malloc( sizeof( ts_psi_t ) ); + pid->psi = xmalloc( sizeof( ts_psi_t ) ); if( pid->psi ) { pid->psi->handle = NULL; @@ -1828,13 +1831,11 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) int i; if( i_dts >= 0 ) - { - p_pes->i_dts = i_dts * 100 / 9; - } + p_pes->i_dts = VLC_TS_0 + i_dts * 100 / 9; + if( i_pts >= 0 ) - { - p_pes->i_pts = i_pts * 100 / 9; - } + p_pes->i_pts = VLC_TS_0 + i_pts * 100 / 9; + p_pes->i_length = i_length * 100 / 9; p_block = block_ChainGather( p_pes ); @@ -1888,7 +1889,7 @@ static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) { es_out_Control( p_demux->out, ES_OUT_SET_GROUP_PCR, (int)p_sys->pmt[i]->psi->prg[i_prg]->i_number, - (int64_t)(i_pcr * 100 / 9) ); + (int64_t)(VLC_TS_0 + i_pcr * 100 / 9) ); } } } @@ -1989,7 +1990,7 @@ static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) pid->i_cc = i_cc; if( pid->es->p_pes && pid->es->fmt.i_cat != VIDEO_ES ) { - /* Small video artifacts are usually better then + /* Small video artifacts are usually better than * dropping full frames */ pid->es->p_pes->i_flags |= BLOCK_FLAG_CORRUPTED; } @@ -2088,7 +2089,7 @@ static int PIDFillFormat( ts_pid_t *pid, int i_stream_type ) case 0x04: /* MPEG-2 audio */ es_format_Init( fmt, AUDIO_ES, VLC_CODEC_MPGA ); break; - case 0x11: /* MPEG4 (audio) */ + case 0x11: /* MPEG4 (audio) LATM */ case 0x0f: /* ISO/IEC 13818-7 Audio with ADTS transport syntax */ es_format_Init( fmt, AUDIO_ES, VLC_CODEC_MP4A ); break; @@ -2614,7 +2615,8 @@ static void ValidateDVBMeta( demux_t *p_demux, int i_pid ) #ifdef TS_USE_DVB_SI /* FIXME same than dvbsi_to_utf8 from dvb access */ static char *EITConvertToUTF8( const unsigned char *psz_instring, - size_t i_length ) + size_t i_length, + bool b_broken ) { const char *psz_encoding; char *psz_outstring; @@ -2627,14 +2629,10 @@ static char *EITConvertToUTF8( const unsigned char *psz_instring, { /* According to ETSI EN 300 468 Annex A, this should be ISO6937, * but some broadcasters use different charset... */ - if ( i_broken_epg == 1 ) - { + if( b_broken ) psz_encoding = "ISO_8859-1"; - } else - { psz_encoding = "ISO_6937"; - } offset = 0; } @@ -2782,7 +2780,7 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) p_sdt->i_ts_id, p_sdt->i_version, p_sdt->b_current_next, p_sdt->i_network_id ); - i_broken_epg = 0; + p_sys->b_broken_charset = false; for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next ) { @@ -2831,19 +2829,33 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) /* Workarounds for broadcasters with broken EPG */ - if ( p_sdt->i_network_id == 133 ) - i_broken_epg = 1; /* SKY DE & BetaDigital use ISO8859-1 */ + if( p_sdt->i_network_id == 133 ) + p_sys->b_broken_charset = true; /* SKY DE & BetaDigital use ISO8859-1 */ - if ( (pD->i_service_provider_name_length == 4) && - !strncmp(pD->i_service_provider_name, "CSAT", 4) ) - i_broken_epg = 1; /* CanalSat FR uses ISO8859-1 */ + /* List of providers using ISO8859-1 */ + static const char ppsz_broken_providers[][8] = { + "CSAT", /* CanalSat FR */ + "GR1", /* France televisions */ + "MULTI4", /* NT1 */ + "MR5", /* France 2/M6 HD */ + "" + }; + for( int i = 0; *ppsz_broken_providers[i]; i++ ) + { + const size_t i_length = strlen(ppsz_broken_providers[i]); + if( pD->i_service_provider_name_length == i_length && + !strncmp( pD->i_service_provider_name, ppsz_broken_providers[i], i_length ) ) + p_sys->b_broken_charset = true; + } /* FIXME: Digital+ ES also uses ISO8859-1 */ str1 = EITConvertToUTF8(pD->i_service_provider_name, - pD->i_service_provider_name_length); + pD->i_service_provider_name_length, + p_sys->b_broken_charset ); str2 = EITConvertToUTF8(pD->i_service_name, - pD->i_service_name_length); + pD->i_service_name_length, + p_sys->b_broken_charset ); msg_Dbg( p_demux, " - type=%d provider=%s name=%s", pD->i_service_type, str1, str2 ); @@ -3002,8 +3014,10 @@ static void EITCallBack( demux_t *p_demux, if( pE ) { - psz_name = EITConvertToUTF8( pE->i_event_name, pE->i_event_name_length); - psz_text = EITConvertToUTF8( pE->i_text, pE->i_text_length ); + psz_name = EITConvertToUTF8( pE->i_event_name, pE->i_event_name_length, + p_sys->b_broken_charset ); + psz_text = EITConvertToUTF8( 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 ); } @@ -3019,14 +3033,14 @@ 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( pE->i_text, pE->i_text_length, + p_sys->b_broken_charset ); if( psz_text ) { msg_Dbg( p_demux, " - text='%s'", psz_text ); - psz_extra = realloc_or_free( psz_extra, + psz_extra = xrealloc( psz_extra, strlen(psz_extra) + strlen(psz_text) + 1 ); - assert( psz_extra ); strcat( psz_extra, psz_text ); free( psz_text ); } @@ -3035,17 +3049,18 @@ 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], - pE->i_item_description_length[i] ); - char *psz_itm = EITConvertToUTF8( pE->i_item[i], pE->i_item_length[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], + p_sys->b_broken_charset ); if( psz_dsc && psz_itm ) { msg_Dbg( p_demux, " - desc='%s' item='%s'", psz_dsc, psz_itm ); #if 0 - psz_extra = realloc_or_free( psz_extra, + psz_extra = xrealloc( psz_extra, strlen(psz_extra) + strlen(psz_dsc) + strlen(psz_itm) + 3 + 1 ); - assert( psz_extra ); strcat( psz_extra, "(" ); strcat( psz_extra, psz_dsc ); strcat( psz_extra, " " ); @@ -3378,8 +3393,7 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, /* */ es_format_Init( p_fmt, SPU_ES, VLC_CODEC_TELETEXT ); - /* In stream output mode, do not separate the stream by page */ - if( p_demux->out->b_sout || i_page <= 0 ) + if( !p_demux->p_sys->b_split_es || i_page <= 0 ) { p_fmt->subs.teletext.i_magazine = -1; p_fmt->subs.teletext.i_page = 0; @@ -3390,9 +3404,9 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, if( !p_dr ) p_dr = PMTEsFindDescriptor( p_es, 0x56 ); - if( p_demux->out->b_sout && p_dr && p_dr->i_length > 0 ) + if( !p_demux->p_sys->b_split_es && p_dr && p_dr->i_length > 0 ) { - /* Descriptor pass-through for sout */ + /* Descriptor pass-through */ p_fmt->p_extra = malloc( p_dr->i_length ); if( p_fmt->p_extra ) { @@ -3437,6 +3451,7 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, /* */ const ts_teletext_page_t *p = &p_page[i]; + p_es->fmt.i_priority = (p->i_type == 0x02 || p->i_type == 0x05) ? 0 : -1; p_es->fmt.psz_language = strndup( p->p_iso639, 3 ); p_es->fmt.psz_description = strdup(vlc_gettext(ppsz_teletext_type[p->i_type])); p_es->fmt.subs.teletext.i_magazine = p->i_magazine; @@ -3470,15 +3485,14 @@ static void PMTSetupEsDvbSubtitle( demux_t *p_demux, ts_pid_t *pid, } #endif - /* In stream output mode, do not separate the stream by page */ - if( p_demux->out->b_sout || i_page <= 0 ) + if( !p_demux->p_sys->b_split_es || i_page <= 0 ) { p_fmt->subs.dvb.i_id = -1; p_fmt->psz_description = strdup( _("DVB subtitles") ); - if( p_demux->out->b_sout && p_dr && p_dr->i_length > 0 ) + if( !p_demux->p_sys->b_split_es && p_dr && p_dr->i_length > 0 ) { - /* Descriptor pass-through for sout */ + /* Descriptor pass-through */ p_fmt->p_extra = malloc( p_dr->i_length ); if( p_fmt->p_extra ) { @@ -3767,6 +3781,38 @@ static void PMTSetupEsHDMV( demux_t *p_demux, ts_pid_t *pid, break; } } + +static void PMTSetupEsRegistration( demux_t *p_demux, ts_pid_t *pid, + const dvbpsi_pmt_es_t *p_es ) +{ + static const struct + { + char psz_tag[5]; + int i_cat; + vlc_fourcc_t i_codec; + } p_regs[] = { + { "AC-3", AUDIO_ES, VLC_CODEC_A52 }, + { "DTS1", AUDIO_ES, VLC_CODEC_DTS }, + { "DTS2", AUDIO_ES, VLC_CODEC_DTS }, + { "DTS3", AUDIO_ES, VLC_CODEC_DTS }, + { "BSSD", AUDIO_ES, VLC_CODEC_302M }, + { "VC-1", VIDEO_ES, VLC_CODEC_VC1 }, + { "drac", VIDEO_ES, VLC_CODEC_DIRAC }, + { "", UNKNOWN_ES, 0 } + }; + es_format_t *p_fmt = &pid->es->fmt; + + for( int i = 0; p_regs[i].i_cat != UNKNOWN_ES; i++ ) + { + if( PMTEsHasRegistration( p_demux, p_es, p_regs[i].psz_tag ) ) + { + p_fmt->i_cat = p_regs[i].i_cat; + p_fmt->i_codec = p_regs[i].i_codec; + break; + } + } +} + static void PMTParseEsIso639( demux_t *p_demux, ts_pid_t *pid, const dvbpsi_pmt_es_t *p_es ) { @@ -4054,6 +4100,10 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) { PMTSetupEsHDMV( p_demux, pid, p_es ); } + else if( p_es->i_type >= 0x80 ) + { + PMTSetupEsRegistration( p_demux, pid, p_es ); + } if( pid->es->fmt.i_cat == AUDIO_ES || ( pid->es->fmt.i_cat == SPU_ES &&