X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fts.c;h=d3fcf37aa10a976fbafb66a016e15e21a49ad63e;hb=98ff57ae3a17d1a43cd4dc15f4d0c7da25648841;hp=5f4f8f7bf639155062619d0ceaa016c243f24bbb;hpb=26bc19853d930cea273eab07c87e06415f21f58e;p=vlc diff --git a/modules/demux/ts.c b/modules/demux/ts.c index 5f4f8f7bf6..d3fcf37aa1 100644 --- a/modules/demux/ts.c +++ b/modules/demux/ts.c @@ -33,7 +33,6 @@ #include #include -#include #include #include /* DVB-specific things */ @@ -77,7 +76,19 @@ # include "tables/eit.h" # endif #endif -#include + +/* TDT support */ +#ifdef _DVBPSI_DR_58_H_ +# define TS_USE_TDT 1 +# ifdef HAVE_DVBPSI_DR_H +# include +# else +# include "tables/tot.h" +# endif +#else +# include +#endif + #undef TS_DEBUG /***************************************************************************** @@ -150,17 +161,17 @@ vlc_module_begin () set_subcategory( SUBCAT_INPUT_DEMUX ) add_string( "ts-extra-pmt", NULL, NULL, PMT_TEXT, PMT_LONGTEXT, true ) - add_bool( "ts-es-id-pid", 1, NULL, PID_TEXT, PID_LONGTEXT, true ) + add_bool( "ts-es-id-pid", true, NULL, PID_TEXT, PID_LONGTEXT, true ) add_string( "ts-out", NULL, NULL, TSOUT_TEXT, TSOUT_LONGTEXT, true ) add_integer( "ts-out-mtu", 1400, NULL, MTUOUT_TEXT, MTUOUT_LONGTEXT, true ) add_string( "ts-csa-ck", NULL, NULL, CSA_TEXT, CSA_LONGTEXT, true ) add_string( "ts-csa2-ck", NULL, NULL, CSA_TEXT, CSA_LONGTEXT, true ) add_integer( "ts-csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, true ) - add_bool( "ts-silent", 0, NULL, SILENT_TEXT, SILENT_LONGTEXT, true ) + add_bool( "ts-silent", false, NULL, SILENT_TEXT, SILENT_LONGTEXT, true ) add_file( "ts-dump-file", NULL, NULL, TSDUMP_TEXT, TSDUMP_LONGTEXT, false ) - add_bool( "ts-dump-append", 0, NULL, APPEND_TEXT, APPEND_LONGTEXT, false ) + add_bool( "ts-dump-append", false, NULL, APPEND_TEXT, APPEND_LONGTEXT, false ) add_integer( "ts-dump-size", 16384, NULL, DUMPSIZE_TEXT, DUMPSIZE_LONGTEXT, true ) @@ -357,6 +368,7 @@ struct demux_sys_t /* */ bool b_dvb_meta; + int64_t i_tdt_delta; int64_t i_dvb_start; int64_t i_dvb_length; @@ -374,6 +386,8 @@ 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 ); @@ -603,7 +617,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 ); + 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 ); @@ -621,6 +635,7 @@ static int Open( vlc_object_t *p_this ) p_sys->b_dvb_meta = true; p_sys->b_access_control = true; p_sys->i_current_program = 0; + p_sys->i_tdt_delta = 0; p_sys->i_dvb_start = 0; p_sys->i_dvb_length = 0; @@ -660,10 +675,21 @@ static int Open( vlc_object_t *p_this ) eit->psi->handle = dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack, p_demux ); +#ifdef TS_USE_TDT + ts_pid_t *tdt = &p_sys->pid[0x14]; + PIDInit( tdt, true, NULL ); + tdt->psi->handle = + dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack, + p_demux ); +#endif if( p_sys->b_access_control ) { if( stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, ACCESS_SET_PRIVATE_ID_STATE, 0x11, true ) || +#ifdef TS_USE_TDT + stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, + ACCESS_SET_PRIVATE_ID_STATE, 0x14, true ) || +#endif stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, ACCESS_SET_PRIVATE_ID_STATE, 0x12, true ) ) p_sys->b_access_control = false; @@ -796,9 +822,9 @@ static void Close( vlc_object_t *p_this ) free( pid->psi ); break; default: - if( p_sys->b_dvb_meta && ( pid->i_pid == 0x11 || pid->i_pid == 0x12 ) ) + if( p_sys->b_dvb_meta && ( pid->i_pid == 0x11 || pid->i_pid == 0x12 || pid->i_pid == 0x14 ) ) { - /* SDT or EIT */ + /* SDT or EIT or TDT */ dvbpsi_DetachDemux( pid->psi->handle ); free( pid->psi ); } @@ -843,7 +869,7 @@ static void Close( vlc_object_t *p_this ) { vlc_value_t val; val.p_list = p_sys->p_programs_list; - var_Change( p_demux, "programs", VLC_VAR_FREELIST, &val, NULL ); + var_FreeList( &val, NULL ); } /* If in dump mode, then close the file */ @@ -1079,7 +1105,7 @@ static int Demux( demux_t *p_demux ) { if( p_pid->psi ) { - if( p_pid->i_pid == 0 || ( p_sys->b_dvb_meta && ( p_pid->i_pid == 0x11 || p_pid->i_pid == 0x12 ) ) ) + if( p_pid->i_pid == 0 || ( p_sys->b_dvb_meta && ( p_pid->i_pid == 0x11 || p_pid->i_pid == 0x12 || p_pid->i_pid == 0x14 ) ) ) { dvbpsi_PushPacket( p_pid->psi->handle, p_pkt->p_buffer ); } @@ -1140,16 +1166,20 @@ static int DVBEventInformation( demux_t *p_demux, int64_t *pi_time, int64_t *pi_ if( pi_time ) *pi_time = 0; - if( p_sys->b_access_control && p_sys->i_dvb_length > 0 ) + if( p_sys->i_dvb_length > 0 ) { - /* FIXME we should not use time() but read the date from the tdt */ - const time_t t = time( NULL ); +#ifdef TS_USE_TDT + const int64_t t = mdate() + p_sys->i_tdt_delta; +#else + const int64_t t = CLOCK_FREQ * time ( NULL ); +#endif + if( p_sys->i_dvb_start <= t && t < p_sys->i_dvb_start + p_sys->i_dvb_length ) { if( pi_length ) - *pi_length = p_sys->i_dvb_length * INT64_C(1000000); + *pi_length = p_sys->i_dvb_length; if( pi_time ) - *pi_time = (t - p_sys->i_dvb_start) * INT64_C(1000000); + *pi_time = t - p_sys->i_dvb_start; return VLC_SUCCESS; } } @@ -1175,7 +1205,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) i64 = stream_Size( p_demux->s ); if( i64 > 0 ) { - *pf = (double)stream_Tell( p_demux->s ) / (double)i64; + double f_current = stream_Tell( p_demux->s ); + *pf = f_current / (double)i64; } else { @@ -1516,7 +1547,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; @@ -1617,8 +1648,8 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) { block_t *p_pes = pid->es->p_pes; uint8_t header[34]; - int i_pes_size = 0; - int i_skip = 0; + unsigned i_pes_size = 0; + unsigned i_skip = 0; mtime_t i_dts = -1; mtime_t i_pts = -1; mtime_t i_length = 0; @@ -1630,8 +1661,8 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) pid->es->pp_last = &pid->es->p_pes; /* FIXME find real max size */ - const int i_max = block_ChainExtract( p_pes, header, 34 ); - + /* const int i_max = */ block_ChainExtract( p_pes, header, 34 ); + if( header[0] != 0 || header[1] != 0 || header[2] != 1 ) { if( !p_demux->p_sys->b_silent ) @@ -1737,7 +1768,7 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) { i_skip += 1; } - else if( pid->es->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) && + else if( pid->es->fmt.i_codec == VLC_CODEC_SUBT && pid->es->p_mpeg4desc ) { decoder_config_descriptor_t *dcd = &pid->es->p_mpeg4desc->dec_descr; @@ -1748,21 +1779,17 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) { /* display length */ if( p_pes->i_buffer + 2 <= i_skip ) - { i_length = GetWBE( &p_pes->p_buffer[i_skip] ); - } i_skip += 2; } if( p_pes->i_buffer + 2 <= i_skip ) - { i_pes_size = GetWBE( &p_pes->p_buffer[i_skip] ); - } /* */ i_skip += 2; } #ifdef ZVBI_COMPILED - else if( pid->es->fmt.i_codec == VLC_FOURCC( 't', 'e', 'l', 'x' ) ) + else if( pid->es->fmt.i_codec == VLC_CODEC_TELETEXT ) i_skip = 0; /*hack for zvbi support */ #endif /* skip header */ @@ -1794,17 +1821,15 @@ 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 ); - if( pid->es->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) ) + if( pid->es->fmt.i_codec == VLC_CODEC_SUBT ) { if( i_pes_size > 0 && p_block->i_buffer > i_pes_size ) { @@ -1854,7 +1879,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) ); } } } @@ -2048,38 +2073,41 @@ static int PIDFillFormat( ts_pid_t *pid, int i_stream_type ) case 0x01: /* MPEG-1 video */ case 0x02: /* MPEG-2 video */ case 0x80: /* MPEG-2 MOTO video */ - es_format_Init( fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', 'g', 'v' ) ); + es_format_Init( fmt, VIDEO_ES, VLC_CODEC_MPGV ); break; case 0x03: /* MPEG-1 audio */ case 0x04: /* MPEG-2 audio */ - es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'm', 'p', 'g', 'a' ) ); + 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_FOURCC( 'm', 'p', '4', 'a' ) ); + es_format_Init( fmt, AUDIO_ES, VLC_CODEC_MP4A ); break; case 0x10: /* MPEG4 (video) */ - es_format_Init( fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', '4', 'v' ) ); + es_format_Init( fmt, VIDEO_ES, VLC_CODEC_MP4V ); pid->es->b_gather = true; break; case 0x1B: /* H264 <- check transport syntax/needed descriptor */ - es_format_Init( fmt, VIDEO_ES, VLC_FOURCC( 'h', '2', '6', '4' ) ); + es_format_Init( fmt, VIDEO_ES, VLC_CODEC_H264 ); break; case 0x81: /* A52 (audio) */ - es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'a', '5', '2', ' ' ) ); + es_format_Init( fmt, AUDIO_ES, VLC_CODEC_A52 ); break; case 0x82: /* DVD_SPU (sub) */ - es_format_Init( fmt, SPU_ES, VLC_FOURCC( 's', 'p', 'u', ' ' ) ); + es_format_Init( fmt, SPU_ES, VLC_CODEC_SPU ); break; case 0x83: /* LPCM (audio) */ - es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'l', 'p', 'c', 'm' ) ); + es_format_Init( fmt, AUDIO_ES, VLC_CODEC_DVD_LPCM ); break; case 0x84: /* SDDS (audio) */ - es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 's', 'd', 'd', 's' ) ); + es_format_Init( fmt, AUDIO_ES, VLC_CODEC_SDDS ); break; case 0x85: /* DTS (audio) */ - es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'd', 't', 's', ' ' ) ); + es_format_Init( fmt, AUDIO_ES, VLC_CODEC_DTS ); + break; + case 0x87: /* E-AC3 */ + es_format_Init( fmt, AUDIO_ES, VLC_CODEC_EAC3 ); break; case 0x91: /* A52 vls (audio) */ @@ -2546,16 +2574,17 @@ static void ValidateDVBMeta( demux_t *p_demux, int i_pid ) { demux_sys_t *p_sys = p_demux->p_sys; - if( !p_sys->b_dvb_meta || ( i_pid != 0x11 && i_pid != 0x12 ) ) + if( !p_sys->b_dvb_meta || ( i_pid != 0x11 && i_pid != 0x12 && i_pid != 0x14 ) ) return; msg_Warn( p_demux, "Switching to non DVB mode" ); /* This doesn't look like a DVB stream so don't try - * parsing the SDT/EDT */ + * parsing the SDT/EDT/TDT */ - for( int i = 0x11; i <= 0x12; i++ ) + for( int i = 0x11; i <= 0x14; i++ ) { + if( i == 0x13 ) continue; ts_pid_t *p_pid = &p_sys->pid[i]; if( p_pid->psi ) { @@ -2574,6 +2603,155 @@ 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 ) +{ + const char *psz_encoding; + char *psz_outstring; + char psz_encbuf[sizeof( "ISO_8859-123" )]; + size_t i_in, i_out, offset = 1; + vlc_iconv_t iconv_handle; + + if( i_length < 1 ) return NULL; + if( psz_instring[0] >= 0x20 ) + { + /* According to ETSI EN 300 468 Annex A, this should be ISO6937, + * but some broadcasters use different charset... */ + if ( i_broken_epg == 1 ) + { + psz_encoding = "ISO_8859-1"; + } + else + { + psz_encoding = "ISO_6937"; + } + + offset = 0; + } + else switch( psz_instring[0] ) + { + case 0x01: + psz_encoding = "ISO_8859-5"; + break; + case 0x02: + psz_encoding = "ISO_8859-6"; + break; + case 0x03: + psz_encoding = "ISO_8859-7"; + break; + case 0x04: + psz_encoding = "ISO_8859-8"; + break; + case 0x05: + psz_encoding = "ISO_8859-9"; + break; + case 0x06: + psz_encoding = "ISO_8859-10"; + break; + case 0x07: + psz_encoding = "ISO_8859-11"; + break; + case 0x08: + psz_encoding = "ISO_8859-12"; + break; + case 0x09: + psz_encoding = "ISO_8859-13"; + break; + case 0x0a: + psz_encoding = "ISO_8859-14"; + break; + case 0x0b: + psz_encoding = "ISO_8859-15"; + break; + case 0x10: +#warning Is Latin-10 (psz_instring[2] == 16) really illegal? + if( i_length < 3 || psz_instring[1] != 0x00 || psz_instring[2] > 15 + || psz_instring[2] == 0 ) + { + psz_encoding = "UTF-8"; + offset = 0; + } + else + { + sprintf( psz_encbuf, "ISO_8859-%u", psz_instring[2] ); + psz_encoding = psz_encbuf; + offset = 3; + } + break; + case 0x11: +#warning Is there a BOM or do we use a fixed endianess? + psz_encoding = "UTF-16"; + break; + case 0x12: + psz_encoding = "KSC5601-1987"; + break; + case 0x13: + psz_encoding = "GB2312"; /* GB-2312-1980 */ + break; + case 0x14: + psz_encoding = "BIG-5"; + break; + case 0x15: + psz_encoding = "UTF-8"; + break; + default: + /* invalid */ + psz_encoding = "UTF-8"; + offset = 0; + } + + i_in = i_length - offset; + i_out = i_in * 6 + 1; + + psz_outstring = malloc( i_out ); + if( !psz_outstring ) + { + return NULL; + } + + iconv_handle = vlc_iconv_open( "UTF-8", psz_encoding ); + if( iconv_handle == (vlc_iconv_t)(-1) ) + { + /* Invalid character set (e.g. ISO_8859-12) */ + memcpy( psz_outstring, &psz_instring[offset], i_in ); + psz_outstring[i_in] = '\0'; + EnsureUTF8( psz_outstring ); + } + else + { + const char *psz_in = (const char *)&psz_instring[offset]; + char *psz_out = psz_outstring; + + while( vlc_iconv( iconv_handle, &psz_in, &i_in, + &psz_out, &i_out ) == (size_t)(-1) ) + { + /* skip naughty byte. This may fail terribly for multibyte stuff, + * but what can we do anyway? */ + psz_in++; + i_in--; + vlc_iconv( iconv_handle, NULL, NULL, NULL, NULL ); /* reset */ + } + vlc_iconv_close( iconv_handle ); + + *psz_out = '\0'; + + /* Convert EIT-coded CR/LFs */ + unsigned char *pbuf = (unsigned char *)psz_outstring; + for( ; pbuf < (unsigned char *)psz_out ; pbuf++) + { + if( pbuf[0] == 0xc2 && pbuf[1] == 0x8a ) + { + pbuf[0] = ' '; + pbuf[1] = '\n'; + } + } + + + } + return psz_outstring; +} + static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) { demux_sys_t *p_sys = p_demux->p_sys; @@ -2595,6 +2773,8 @@ 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; + for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next ) { vlc_meta_t *p_meta; @@ -2637,14 +2817,24 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) "DVB MHP service" }; dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr ); - char str1[257]; - char str2[257]; + char *str1 = NULL; + char *str2 = NULL; + + /* Workarounds for broadcasters with broken EPG */ - memcpy( str1, pD->i_service_provider_name, - pD->i_service_provider_name_length ); - str1[pD->i_service_provider_name_length] = '\0'; - memcpy( str2, pD->i_service_name, pD->i_service_name_length ); - str2[pD->i_service_name_length] = '\0'; + if ( p_sdt->i_network_id == 133 ) + i_broken_epg = 1; /* 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 */ + + /* FIXME: Digital+ ES also uses ISO8859-1 */ + + str1 = EITConvertToUTF8(pD->i_service_provider_name, + pD->i_service_provider_name_length); + str2 = EITConvertToUTF8(pD->i_service_name, + pD->i_service_name_length); msg_Dbg( p_demux, " - type=%d provider=%s name=%s", pD->i_service_type, str1, str2 ); @@ -2653,6 +2843,8 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) vlc_meta_SetPublisher( p_meta, str1 ); if( pD->i_service_type >= 0x01 && pD->i_service_type <= 0x10 ) psz_type = ppsz_type[pD->i_service_type]; + free( str1 ); + free( str2 ); } } @@ -2742,135 +2934,20 @@ static int EITConvertDuration( uint32_t i_duration ) } #undef CVT_FROM_BCD -/* FIXME same than dvbsi_to_utf8 from dvb access */ -static char *EITConvertToUTF8( const unsigned char *psz_instring, - size_t i_length ) +#ifdef TS_USE_TDT +static void TDTCallBack( demux_t *p_demux, dvbpsi_tot_t *p_tdt ) { - const char *psz_encoding; - char *psz_outstring; - char psz_encbuf[sizeof( "ISO_8859-123" )]; - size_t i_in, i_out, offset = 1; - vlc_iconv_t iconv_handle; - - if( i_length < 1 ) return NULL; - if( psz_instring[0] >= 0x20 ) - { - psz_encoding = "ISO_8859-1"; - /* According to the specification, this should be ISO6937, - * but it seems Latin-1 is used instead. */ - offset = 0; - } - else switch( psz_instring[0] ) - { - case 0x01: - psz_encoding = "ISO_8859-5"; - break; - case 0x02: - psz_encoding = "ISO_8859-6"; - break; - case 0x03: - psz_encoding = "ISO_8859-7"; - break; - case 0x04: - psz_encoding = "ISO_8859-8"; - break; - case 0x05: - psz_encoding = "ISO_8859-9"; - break; - case 0x06: - psz_encoding = "ISO_8859-10"; - break; - case 0x07: - psz_encoding = "ISO_8859-11"; - break; - case 0x08: - psz_encoding = "ISO_8859-12"; - break; - case 0x09: - psz_encoding = "ISO_8859-13"; - break; - case 0x0a: - psz_encoding = "ISO_8859-14"; - break; - case 0x0b: - psz_encoding = "ISO_8859-15"; - break; - case 0x10: -#warning Is Latin-10 (psz_instring[2] == 16) really illegal? - if( i_length < 3 || psz_instring[1] != 0x00 || psz_instring[2] > 15 - || psz_instring[2] == 0 ) - { - psz_encoding = "UTF-8"; - offset = 0; - } - else - { - sprintf( psz_encbuf, "ISO_8859-%u", psz_instring[2] ); - psz_encoding = psz_encbuf; - offset = 3; - } - break; - case 0x11: -#warning Is there a BOM or do we use a fixed endianess? - psz_encoding = "UTF-16"; - break; - case 0x12: - psz_encoding = "KSC5601-1987"; - break; - case 0x13: - psz_encoding = "GB2312"; /* GB-2312-1980 */ - break; - case 0x14: - psz_encoding = "BIG-5"; - break; - case 0x15: - psz_encoding = "UTF-8"; - break; - default: - /* invalid */ - psz_encoding = "UTF-8"; - offset = 0; - } - - i_in = i_length - offset; - i_out = i_in * 6 + 1; - - psz_outstring = malloc( i_out ); - if( !psz_outstring ) - { - return NULL; - } - - iconv_handle = vlc_iconv_open( "UTF-8", psz_encoding ); - if( iconv_handle == (vlc_iconv_t)(-1) ) - { - /* Invalid character set (e.g. ISO_8859-12) */ - memcpy( psz_outstring, &psz_instring[offset], i_in ); - psz_outstring[i_in] = '\0'; - EnsureUTF8( psz_outstring ); - } - else - { - const char *psz_in = (const char *)&psz_instring[offset]; - char *psz_out = psz_outstring; - - while( vlc_iconv( iconv_handle, &psz_in, &i_in, - &psz_out, &i_out ) == (size_t)(-1) ) - { - /* skip naughty byte. This may fail terribly for multibyte stuff, - * but what can we do anyway? */ - psz_in++; - i_in--; - vlc_iconv( iconv_handle, NULL, NULL, NULL, NULL ); /* reset */ - } - vlc_iconv_close( iconv_handle ); + demux_sys_t *p_sys = p_demux->p_sys; - *psz_out = '\0'; - } - return psz_outstring; + p_sys->i_tdt_delta = CLOCK_FREQ * EITConvertStartTime( p_tdt->i_utc_time ) + - mdate(); + dvbpsi_DeleteTOT(p_tdt); } +#endif -static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) + +static void EITCallBack( demux_t *p_demux, + dvbpsi_eit_t *p_eit, bool b_current_following ) { demux_sys_t *p_sys = p_demux->p_sys; dvbpsi_eit_event_t *p_evt; @@ -2938,7 +3015,8 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) { msg_Dbg( p_demux, " - text='%s'", psz_text ); - psz_extra = realloc( psz_extra, strlen(psz_extra) + strlen(psz_text) + 1 ); + psz_extra = xrealloc( psz_extra, + strlen(psz_extra) + strlen(psz_text) + 1 ); strcat( psz_extra, psz_text ); free( psz_text ); } @@ -2953,13 +3031,16 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) if( psz_dsc && psz_itm ) { msg_Dbg( p_demux, " - desc='%s' item='%s'", psz_dsc, psz_itm ); - - psz_extra = realloc( psz_extra, strlen(psz_extra) + strlen(psz_dsc) + strlen(psz_itm) + 3 + 1 ); +#if 0 + psz_extra = xrealloc( psz_extra, + strlen(psz_extra) + strlen(psz_dsc) + + strlen(psz_itm) + 3 + 1 ); strcat( psz_extra, "(" ); strcat( psz_extra, psz_dsc ); strcat( psz_extra, " " ); strcat( psz_extra, psz_itm ); strcat( psz_extra, ")" ); +#endif } free( psz_dsc ); free( psz_itm ); @@ -2974,7 +3055,8 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) /* */ if( i_start > 0 ) - vlc_epg_AddEvent( p_epg, i_start, i_duration, psz_name, psz_text, psz_extra ); + vlc_epg_AddEvent( p_epg, i_start, i_duration, psz_name, psz_text, + *psz_extra ? psz_extra : NULL ); /* Update "now playing" field */ if( p_evt->i_running_status == 0x04 && i_start > 0 ) @@ -2987,15 +3069,17 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) } if( p_epg->i_event > 0 ) { - if( p_eit->i_service_id == p_sys->i_current_program ) + if( b_current_following && + ( p_sys->i_current_program == -1 || + p_sys->i_current_program == p_eit->i_service_id ) ) { p_sys->i_dvb_length = 0; p_sys->i_dvb_start = 0; if( p_epg->p_current ) { - p_sys->i_dvb_start = p_epg->p_current->i_start; - p_sys->i_dvb_length = p_epg->p_current->i_duration; + p_sys->i_dvb_start = CLOCK_FREQ * p_epg->p_current->i_start; + p_sys->i_dvb_length = CLOCK_FREQ * p_epg->p_current->i_duration; } } es_out_Control( p_demux->out, ES_OUT_SET_GROUP_EPG, p_eit->i_service_id, p_epg ); @@ -3004,6 +3088,14 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) dvbpsi_DeleteEIT( p_eit ); } +static void EITCallBackCurrentFollowing( demux_t *p_demux, dvbpsi_eit_t *p_eit ) +{ + EITCallBack( p_demux, p_eit, true ); +} +static void EITCallBackSchedule( demux_t *p_demux, dvbpsi_eit_t *p_eit ) +{ + EITCallBack( p_demux, p_eit, false ); +} static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h, uint8_t i_table_id, uint16_t i_extension ) @@ -3027,9 +3119,22 @@ static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h, msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)", i_table_id, i_table_id, i_extension, i_extension ); - dvbpsi_AttachEIT( h, i_table_id, i_extension, - (dvbpsi_eit_callback)EITCallBack, p_demux ); + dvbpsi_eit_callback cb = i_table_id == 0x4e ? + (dvbpsi_eit_callback)EITCallBackCurrentFollowing : + (dvbpsi_eit_callback)EITCallBackSchedule; + dvbpsi_AttachEIT( h, i_table_id, i_extension, cb, p_demux ); + } +#ifdef TS_USE_TDT + else if( p_demux->p_sys->pid[0x11].psi->i_sdt_version != -1 && + i_table_id == 0x70 ) /* TDT */ + { + msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)", + i_table_id, i_table_id, i_extension, i_extension ); + dvbpsi_AttachTOT( h, i_table_id, i_extension, + (dvbpsi_tot_callback)TDTCallBack, p_demux); } +#endif + } #endif @@ -3103,14 +3208,14 @@ static void PMTSetupEsISO14496( demux_t *p_demux, ts_pid_t *pid, { case 0x0B: /* mpeg4 sub */ p_fmt->i_cat = SPU_ES; - p_fmt->i_codec = VLC_FOURCC('s','u','b','t'); + p_fmt->i_codec = VLC_CODEC_SUBT; break; case 0x20: /* mpeg4 */ - p_fmt->i_codec = VLC_FOURCC('m','p','4','v'); + p_fmt->i_codec = VLC_CODEC_MP4V; break; case 0x21: /* h264 */ - p_fmt->i_codec = VLC_FOURCC('h','2','6','4'); + p_fmt->i_codec = VLC_CODEC_H264; break; case 0x60: case 0x61: @@ -3118,13 +3223,13 @@ static void PMTSetupEsISO14496( demux_t *p_demux, ts_pid_t *pid, case 0x63: case 0x64: case 0x65: /* mpeg2 */ - p_fmt->i_codec = VLC_FOURCC( 'm','p','g','v' ); + p_fmt->i_codec = VLC_CODEC_MPGV; break; case 0x6a: /* mpeg1 */ - p_fmt->i_codec = VLC_FOURCC( 'm','p','g','v' ); + p_fmt->i_codec = VLC_CODEC_MPGV; break; case 0x6c: /* mpeg1 */ - p_fmt->i_codec = VLC_FOURCC( 'j','p','e','g' ); + p_fmt->i_codec = VLC_CODEC_JPEG; break; default: p_fmt->i_cat = UNKNOWN_ES; @@ -3137,18 +3242,18 @@ static void PMTSetupEsISO14496( demux_t *p_demux, ts_pid_t *pid, switch( dcd->i_objectTypeIndication ) { case 0x40: /* mpeg4 */ - p_fmt->i_codec = VLC_FOURCC('m','p','4','a'); + p_fmt->i_codec = VLC_CODEC_MP4A; break; case 0x66: case 0x67: case 0x68: /* mpeg2 aac */ - p_fmt->i_codec = VLC_FOURCC('m','p','4','a'); + p_fmt->i_codec = VLC_CODEC_MP4A; break; case 0x69: /* mpeg2 */ - p_fmt->i_codec = VLC_FOURCC('m','p','g','a'); + p_fmt->i_codec = VLC_CODEC_MPGA; break; case 0x6b: /* mpeg1 */ - p_fmt->i_codec = VLC_FOURCC('m','p','g','a'); + p_fmt->i_codec = VLC_CODEC_MPGA; break; default: p_fmt->i_cat = UNKNOWN_ES; @@ -3190,12 +3295,12 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, es_format_t *p_fmt = &pid->es->fmt; ts_teletext_page_t p_page[2 * 64 + 20]; - int i_page = 0; + unsigned i_page = 0; /* Gather pages informations */ #if defined _DVBPSI_DR_56_H_ && \ defined DVBPSI_VERSION && DVBPSI_VERSION_INT > ((0<<16)+(1<<8)+5) - for( int i_tag_idx = 0; i_tag_idx < 2; i_tag_idx++ ) + for( unsigned i_tag_idx = 0; i_tag_idx < 2; i_tag_idx++ ) { dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, i_tag_idx == 0 ? 0x46 : 0x56 ); if( !p_dr ) @@ -3209,7 +3314,7 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, { const dvbpsi_teletextpage_t *p_src = &p_sub->p_pages[i]; - if( p_src->i_teletext_type < 0 || p_src->i_teletext_type >= 0x06 ) + if( p_src->i_teletext_type >= 0x06 ) continue; assert( i_page < sizeof(p_page)/sizeof(*p_page) ); @@ -3217,7 +3322,8 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, ts_teletext_page_t *p_dst = &p_page[i_page++]; p_dst->i_type = p_src->i_teletext_type; - p_dst->i_magazine = p_src->i_teletext_magazine_number ? : 8; + p_dst->i_magazine = p_src->i_teletext_magazine_number + ? p_src->i_teletext_magazine_number : 8; p_dst->i_page = p_src->i_teletext_page_number; memcpy( p_dst->p_iso639, p_src->i_iso6392_language_code, 3 ); } @@ -3250,7 +3356,8 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, break; } /* FIXME check if it is the right split */ - p_dst->i_magazine = (p_src->i_composition_page_id >> 8) ? : 8; + p_dst->i_magazine = (p_src->i_composition_page_id >> 8) + ? (p_src->i_composition_page_id >> 8) : 8; p_dst->i_page = p_src->i_composition_page_id & 0xff; memcpy( p_dst->p_iso639, p_src->i_iso6392_language_code, 3 ); } @@ -3258,14 +3365,14 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, #endif /* */ - es_format_Init( p_fmt, SPU_ES, VLC_FOURCC( 't', 'e', 'l', 'x' ) ); + 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 ) { p_fmt->subs.teletext.i_magazine = -1; p_fmt->subs.teletext.i_page = 0; - p_fmt->psz_description = strdup( _(ppsz_teletext_type[1]) ); + p_fmt->psz_description = strdup( vlc_gettext(ppsz_teletext_type[1]) ); dvbpsi_descriptor_t *p_dr; p_dr = PMTEsFindDescriptor( p_es, 0x46 ); @@ -3285,7 +3392,7 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, } else { - for( int i = 0; i < i_page; i++ ) + for( unsigned i = 0; i < i_page; i++ ) { ts_es_t *p_es; @@ -3320,7 +3427,7 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, /* */ const ts_teletext_page_t *p = &p_page[i]; p_es->fmt.psz_language = strndup( p->p_iso639, 3 ); - p_es->fmt.psz_description = strdup(_(ppsz_teletext_type[p->i_type])); + p_es->fmt.psz_description = strdup(vlc_gettext(ppsz_teletext_type[p->i_type])); p_es->fmt.subs.teletext.i_magazine = p->i_magazine; p_es->fmt.subs.teletext.i_page = p->i_page; @@ -3337,7 +3444,7 @@ static void PMTSetupEsDvbSubtitle( demux_t *p_demux, ts_pid_t *pid, { es_format_t *p_fmt = &pid->es->fmt; - es_format_Init( p_fmt, SPU_ES, VLC_FOURCC( 'd', 'v', 'b', 's' ) ); + es_format_Init( p_fmt, SPU_ES, VLC_CODEC_DVBS ); dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0x59 ); int i_page = 0; @@ -3346,8 +3453,8 @@ static void PMTSetupEsDvbSubtitle( demux_t *p_demux, ts_pid_t *pid, for( int i = 0; p_sub && i < p_sub->i_subtitles_number; i++ ) { const int i_type = p_sub->p_subtitle[i].i_subtitling_type; - if( ( i_type >= 0x10 && i_type <= 0x13 ) || - ( i_type >= 0x20 && i_type <= 0x23 ) ) + if( ( i_type >= 0x10 && i_type <= 0x14 ) || + ( i_type >= 0x20 && i_type <= 0x24 ) ) i_page++; } #endif @@ -3413,12 +3520,14 @@ static void PMTSetupEsDvbSubtitle( demux_t *p_demux, ts_pid_t *pid, case 0x11: /* 4:3 */ case 0x12: /* 16:9 */ case 0x13: /* 2.21:1 */ + case 0x14: /* HD monitor */ p_es->fmt.psz_description = strdup( _("DVB subtitles") ); break; case 0x20: /* Hearing impaired unspec. */ case 0x21: /* h.i. 4:3 */ case 0x22: /* h.i. 16:9 */ case 0x23: /* h.i. 2.21:1 */ + case 0x24: /* h.i. HD monitor */ p_es->fmt.psz_description = strdup( _("DVB subtitles: hearing impaired") ); break; default: @@ -3442,13 +3551,13 @@ static void PMTSetupEs0x06( demux_t *p_demux, ts_pid_t *pid, PMTEsFindDescriptor( p_es, 0x81 ) ) { p_fmt->i_cat = AUDIO_ES; - p_fmt->i_codec = VLC_FOURCC('a','5','2',' '); + p_fmt->i_codec = VLC_CODEC_A52; } else if( PMTEsFindDescriptor( p_es, 0x7a ) ) { /* DVB with stream_type 0x06 (ETS EN 300 468) */ p_fmt->i_cat = AUDIO_ES; - p_fmt->i_codec = VLC_FOURCC( 'e', 'a', 'c', '3' ); + p_fmt->i_codec = VLC_CODEC_EAC3; } else if( PMTEsHasRegistration( p_demux, p_es, "DTS1" ) || PMTEsHasRegistration( p_demux, p_es, "DTS2" ) || @@ -3457,13 +3566,13 @@ static void PMTSetupEs0x06( demux_t *p_demux, ts_pid_t *pid, { /*registration descriptor(ETSI TS 101 154 Annex F)*/ p_fmt->i_cat = AUDIO_ES; - p_fmt->i_codec = VLC_FOURCC('d','t','s',' '); + p_fmt->i_codec = VLC_CODEC_DTS; } else if( PMTEsHasRegistration( p_demux, p_es, "BSSD" ) ) { p_fmt->i_cat = AUDIO_ES; p_fmt->b_packetized = true; - p_fmt->i_codec = VLC_FOURCC('a','e','s','3'); + p_fmt->i_codec = VLC_CODEC_302M; } else { @@ -3490,14 +3599,17 @@ static void PMTSetupEs0x06( demux_t *p_demux, ts_pid_t *pid, case 0x11: /* ... on 4:3 AR monitor */ case 0x12: /* ... on 16:9 AR monitor */ case 0x13: /* ... on 2.21:1 AR monitor */ + case 0x14: /* ... for display on a high definition monitor */ case 0x20: /* DVB Subtitle (impaired) with no monitor AR critical */ case 0x21: /* ... on 4:3 AR monitor */ case 0x22: /* ... on 16:9 AR monitor */ case 0x23: /* ... on 2.21:1 AR monitor */ + case 0x24: /* ... for display on a high definition monitor */ PMTSetupEsDvbSubtitle( p_demux, pid, p_es ); break; default: - msg_Err( p_demux, "Unrecognized DVB subtitle type" ); + msg_Err( p_demux, "Unrecognized DVB subtitle type (0x%x)", + p_sub->p_subtitle[i].i_subtitling_type ); break; } } @@ -3542,7 +3654,7 @@ static void PMTSetupEs0xEA( demux_t *p_demux, ts_pid_t *pid, /* registration descriptor for VC-1 (SMPTE rp227) */ p_fmt->i_cat = VIDEO_ES; - p_fmt->i_codec = VLC_FOURCC('W','V','C','1'); + p_fmt->i_codec = VLC_CODEC_VC1; /* XXX With Simple and Main profile the SEQUENCE * header is modified: video width and height are @@ -3565,7 +3677,7 @@ static void PMTSetupEs0xD1( demux_t *p_demux, ts_pid_t *pid, /* registration descriptor for Dirac * (backwards compatable with VC-2 (SMPTE Sxxxx:2008)) */ p_fmt->i_cat = VIDEO_ES; - p_fmt->i_codec = VLC_FOURCC('d','r','a','c'); + p_fmt->i_codec = VLC_CODEC_DIRAC; } static void PMTSetupEs0xA0( demux_t *p_demux, ts_pid_t *pid, @@ -3606,6 +3718,7 @@ static void PMTSetupEs0xA0( demux_t *p_demux, ts_pid_t *pid, static void PMTSetupEsHDMV( demux_t *p_demux, ts_pid_t *pid, const dvbpsi_pmt_es_t *p_es ) { + VLC_UNUSED(p_demux); es_format_t *p_fmt = &pid->es->fmt; /* Blu-Ray mapping */ @@ -3613,28 +3726,30 @@ static void PMTSetupEsHDMV( demux_t *p_demux, ts_pid_t *pid, { case 0x80: p_fmt->i_cat = AUDIO_ES; - p_fmt->i_codec = VLC_FOURCC( 'b', 'p', 'c', 'm' ); + p_fmt->i_codec = VLC_CODEC_BD_LPCM; break; case 0x82: case 0x85: /* DTS-HD High resolution audio */ case 0x86: /* DTS-HD Master audio */ case 0xA2: /* Secondary DTS audio */ p_fmt->i_cat = AUDIO_ES; - p_fmt->i_codec = VLC_FOURCC( 'd', 't', 's', ' ' ); + p_fmt->i_codec = VLC_CODEC_DTS; break; case 0x83: /* TrueHD AC3 */ p_fmt->i_cat = AUDIO_ES; - p_fmt->i_codec = VLC_FOURCC( 'm', 'l', 'p', ' ' ); + p_fmt->i_codec = VLC_CODEC_TRUEHD; break; case 0x84: /* E-AC3 */ - case 0x87: /* E-AC3 */ case 0xA1: /* Secondary E-AC3 */ p_fmt->i_cat = AUDIO_ES; - p_fmt->i_codec = VLC_FOURCC( 'e', 'a', 'c', '3' ); + p_fmt->i_codec = VLC_CODEC_EAC3; break; case 0x90: /* Presentation graphics */ + p_fmt->i_cat = SPU_ES; + p_fmt->i_codec = VLC_CODEC_BD_PG; + break; case 0x91: /* Interactive graphics */ case 0x92: /* Subtitle */ default: @@ -3847,21 +3962,18 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) } else if( p_dr->i_tag == 0x05 ) { - if( p_dr->i_tag == 0x05 ) + /* Registration Descriptor */ + if( p_dr->i_length != 4 ) { - /* Registration Descriptor */ - if( p_dr->i_length != 4 ) - { - msg_Warn( p_demux, "invalid Registration Descriptor" ); - } - else + msg_Warn( p_demux, "invalid Registration Descriptor" ); + } + else + { + msg_Dbg( p_demux, " * descriptor : registration %4.4s", p_dr->p_data ); + if( !memcmp( p_dr->p_data, "HDMV", 4 ) ) { - msg_Dbg( p_demux, " * descriptor : registration %4.4s", p_dr->p_data ); - if( !memcmp( p_dr->p_data, "HDMV", 4 ) ) - { - /* Blu-Ray */ - b_hdmv = true; - } + /* Blu-Ray */ + b_hdmv = true; } } } @@ -3934,8 +4046,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('t','e','l','x') ) ) + pid->es->fmt.i_codec != VLC_CODEC_DVBS && + pid->es->fmt.i_codec != VLC_CODEC_TELETEXT ) ) { PMTParseEsIso639( p_demux, pid, p_es ); } @@ -4021,16 +4133,11 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) } } - if( ProgramIsSelected( p_demux, prg->i_number ) ) - { - /* Set CAM descrambling */ - stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_CA, p_pmt ); - } - else - { + /* Set CAM descrambling */ + if( !ProgramIsSelected( p_demux, prg->i_number ) + || stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, + ACCESS_SET_PRIVATE_ID_CA, p_pmt ) != VLC_SUCCESS ) dvbpsi_DeletePMT( p_pmt ); - } for( int i = 0; i < i_clean; i++ ) {