X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fts.c;h=86c94781193e4bbba6deb49439724cf76de5100a;hb=4d85871d1b29265a6cc5744677f0f0bb9bfac20f;hp=81fc879587fdf44cc1a251e9266abdc5839f708c;hpb=3147cc20d467e776b8996268e04352729c26a66d;p=vlc diff --git a/modules/demux/ts.c b/modules/demux/ts.c index 81fc879587..86c9478119 100644 --- a/modules/demux/ts.c +++ b/modules/demux/ts.c @@ -33,7 +33,6 @@ #include #include -#include #include #include /* DVB-specific things */ @@ -44,6 +43,7 @@ #include #include #include +#include #include "../mux/mpeg/csa.h" @@ -77,7 +77,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 /***************************************************************************** @@ -143,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 independent ES. " \ + "It can be useful to turn off this option when using stream output." ) + vlc_module_begin () set_description( N_("MPEG Transport Stream demuxer") ) set_shortname ( "MPEG-TS" ) @@ -163,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 ) @@ -341,12 +359,14 @@ struct demux_sys_t bool b_user_pmt; int i_pmt; ts_pid_t **pmt; + int i_pmt_es; /* */ bool b_es_id_pid; csa_t *csa; int i_csa_pkt_size; bool b_silent; + bool b_split_es; bool b_udp_out; int fd; /* udp socket */ @@ -357,12 +377,14 @@ struct demux_sys_t /* */ bool b_dvb_meta; + 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; - vlc_list_t *p_programs_list; + vlc_list_t programs_list; /* TS dump */ char *psz_file; /* file to dump data in */ @@ -379,7 +401,7 @@ static int DemuxFile( demux_t *p_demux ); static int Control( demux_t *p_demux, int i_query, va_list args ); static void PIDInit ( ts_pid_t *pid, bool b_psi, ts_psi_t *p_owner ); -static void PIDClean( es_out_t *out, ts_pid_t *pid ); +static void PIDClean( demux_t *, ts_pid_t *pid ); static int PIDFillFormat( ts_pid_t *pid, int i_stream_type ); static void PATCallBack( demux_t *, dvbpsi_pat_t * ); @@ -405,6 +427,9 @@ static void IODFree( iod_descriptor_t * ); #define TS_USER_PMT_NUMBER (0) static int UserPmt( demux_t *p_demux, const char * ); +static int SetPIDFilter( demux_t *, int i_pid, bool b_selected ); +static void SetPrgFilter( demux_t *, int i_prg, bool b_selected ); + #define TS_PACKET_SIZE_188 188 #define TS_PACKET_SIZE_192 192 #define TS_PACKET_SIZE_204 204 @@ -588,7 +613,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; @@ -603,7 +628,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,9 +646,14 @@ 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->programs_list.i_count = 0; + p_sys->programs_list.p_values = NULL; + p_sys->i_tdt_delta = 0; 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]; @@ -660,12 +690,20 @@ 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 ) || - stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, 0x12, true ) ) + if( SetPIDFilter( p_demux, 0x11, true ) || +#ifdef TS_USE_TDT + SetPIDFilter( p_demux, 0x14, true ) || +#endif + SetPIDFilter( p_demux, 0x12, true ) ) p_sys->b_access_control = false; } } @@ -673,6 +711,7 @@ static int Open( vlc_object_t *p_this ) /* Init PMT array */ TAB_INIT( p_sys->i_pmt, p_sys->pmt ); + p_sys->i_pmt_es = 0; /* Read config */ p_sys->b_es_id_pid = var_CreateGetBool( p_demux, "ts-es-id-pid" ); @@ -767,6 +806,15 @@ 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" ); + + while( !p_sys->b_file_out && p_sys->i_pmt_es <= 0 && + vlc_object_alive( p_demux ) ) + { + if( p_demux->pf_demux( p_demux ) != 1 ) + break; + } + return VLC_SUCCESS; } @@ -796,22 +844,22 @@ 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 ); } else { - PIDClean( p_demux->out, pid ); + PIDClean( p_demux, pid ); } break; } } else if( pid->b_valid && pid->es ) { - PIDClean( p_demux->out, pid ); + PIDClean( p_demux, pid ); } if( pid->b_seen ) @@ -819,13 +867,9 @@ static void Close( vlc_object_t *p_this ) msg_Dbg( p_demux, " - pid[%d] seen", pid->i_pid ); } - if( p_sys->b_access_control && pid->i_pid > 0 ) - { - /* too much */ - stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, pid->i_pid, - false ); - } + /* too much */ + if( pid->i_pid > 0 ) + SetPIDFilter( p_demux, pid->i_pid, false ); } vlc_mutex_lock( &p_sys->csa_lock ); @@ -839,17 +883,12 @@ static void Close( vlc_object_t *p_this ) TAB_CLEAN( p_sys->i_pmt, p_sys->pmt ); - if( p_sys->p_programs_list ) - { - vlc_value_t val; - val.p_list = p_sys->p_programs_list; - var_FreeList( &val, NULL ); - } + free( p_sys->programs_list.p_values ); /* 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 ) @@ -1000,6 +1039,7 @@ static int DemuxFile( demux_t *p_demux ) static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; + bool b_wait_es = p_sys->i_pmt_es <= 0; /* We read at most 100 TS packet or until a frame is completed */ for( int i_pkt = 0; i_pkt < p_sys->i_ts_read; i_pkt++ ) @@ -1079,7 +1119,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 ); } @@ -1115,7 +1155,7 @@ static int Demux( demux_t *p_demux ) } p_pid->b_seen = true; - if( b_frame ) + if( b_frame || ( b_wait_es && p_sys->i_pmt_es > 0 ) ) break; } @@ -1140,16 +1180,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; } } @@ -1232,125 +1276,53 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) #endif case DEMUX_SET_GROUP: { - uint16_t i_vpid = 0, i_apid1 = 0, i_apid2 = 0, i_apid3 = 0; - ts_prg_psi_t *p_prg = NULL; vlc_list_t *p_list; i_int = (int)va_arg( args, int ); p_list = (vlc_list_t *)va_arg( args, vlc_list_t * ); msg_Dbg( p_demux, "DEMUX_SET_GROUP %d %p", i_int, p_list ); - if( p_sys->b_access_control && i_int > 0 && i_int != p_sys->i_current_program ) - { - int i_pmt_pid = -1; + if( i_int == 0 && p_sys->i_current_program > 0 ) + i_int = p_sys->i_current_program; - /* Search pmt to be unselected */ - for( int i = 0; i < p_sys->i_pmt; i++ ) - { - ts_pid_t *pmt = p_sys->pmt[i]; - - for( int i_prg = 0; i_prg < pmt->psi->i_prg; i_prg++ ) - { - if( pmt->psi->prg[i_prg]->i_number == p_sys->i_current_program ) - { - i_pmt_pid = p_sys->pmt[i]->i_pid; - break; - } - } - if( i_pmt_pid > 0 ) break; - } - - if( i_pmt_pid > 0 ) - { - stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, i_pmt_pid, - false ); - /* All ES */ - for( int i = 2; i < 8192; i++ ) - { - ts_pid_t *pid = &p_sys->pid[i]; - - if( !pid->b_valid || pid->psi ) - continue; - - for( int i_prg = 0; i_prg < pid->p_owner->i_prg; i_prg++ ) - { - if( pid->p_owner->prg[i_prg]->i_pid_pmt == i_pmt_pid && pid->es->id ) - { - /* We only remove es that aren't defined by extra pmt */ - stream_Control( p_demux->s, - STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, - i, false ); - break; - } - } - } - } + if( p_sys->i_current_program > 0 ) + { + if( p_sys->i_current_program != i_int ) + SetPrgFilter( p_demux, p_sys->i_current_program, false ); + } + else if( p_sys->i_current_program < 0 ) + { + for( int i = 0; i < p_sys->programs_list.i_count; i++ ) + SetPrgFilter( p_demux, p_sys->programs_list.p_values[i].i_int, false ); + } - /* select new program */ + if( i_int > 0 ) + { p_sys->i_current_program = i_int; - i_pmt_pid = -1; - for( int i = 0; i < p_sys->i_pmt; i++ ) + SetPrgFilter( p_demux, p_sys->i_current_program, true ); + } + else if( i_int < 0 ) + { + p_sys->i_current_program = -1; + p_sys->programs_list.i_count = 0; + if( p_list ) { - ts_pid_t *pmt = p_sys->pmt[i]; + vlc_list_t *p_dst = &p_sys->programs_list; + free( p_dst->p_values ); - for( int i_prg = 0; i_prg < pmt->psi->i_prg; i_prg++ ) - { - if( pmt->psi->prg[i_prg]->i_number == i_int ) - { - i_pmt_pid = p_sys->pmt[i]->i_pid; - p_prg = p_sys->pmt[i]->psi->prg[i_prg]; - break; - } - } - if( i_pmt_pid > 0 ) - break; - } - if( i_pmt_pid > 0 ) - { - stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, i_pmt_pid, - true ); - stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, p_prg->i_pid_pcr, - true ); - - for( int i = 2; i < 8192; i++ ) + p_dst->p_values = calloc( p_list->i_count, + sizeof(*p_dst->p_values) ); + if( p_dst->p_values ) { - ts_pid_t *pid = &p_sys->pid[i]; - - if( !pid->b_valid || pid->psi ) - continue; - - for( int i_prg = 0; i_prg < pid->p_owner->i_prg; i_prg++ ) + p_dst->i_count = p_list->i_count; + for( int i = 0; i < p_list->i_count; i++ ) { - if( pid->p_owner->prg[i_prg]->i_pid_pmt == i_pmt_pid && pid->es->id ) - { - if ( pid->es->fmt.i_cat == VIDEO_ES && !i_vpid ) - i_vpid = i; - if ( pid->es->fmt.i_cat == AUDIO_ES && !i_apid1 ) - i_apid1 = i; - else if ( pid->es->fmt.i_cat == AUDIO_ES && !i_apid2 ) - i_apid2 = i; - else if ( pid->es->fmt.i_cat == AUDIO_ES && !i_apid3 ) - i_apid3 = i; - - stream_Control( p_demux->s, - STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, - i, true ); - break; - } + p_dst->p_values[i] = p_list->p_values[i]; + SetPrgFilter( p_demux, p_dst->p_values[i].i_int, true ); } } } } - else - { - p_sys->i_current_program = -1; - p_sys->p_programs_list = p_list; - } return VLC_SUCCESS; } @@ -1482,6 +1454,7 @@ static int UserPmt( demux_t *p_demux, const char *psz_fmt ) (char*)&pid->es->fmt.i_codec ); pid->es->id = es_out_Add( p_demux->out, &pid->es->fmt ); + p_sys->i_pmt_es++; } } @@ -1499,6 +1472,68 @@ error: return VLC_EGENERIC; } +static int SetPIDFilter( demux_t *p_demux, int i_pid, bool b_selected ) +{ + demux_sys_t *p_sys = p_demux->p_sys; + + if( !p_sys->b_access_control ) + return VLC_EGENERIC; + + return stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, + ACCESS_SET_PRIVATE_ID_STATE, i_pid, b_selected ); +} + +static void SetPrgFilter( demux_t *p_demux, int i_prg_id, bool b_selected ) +{ + demux_sys_t *p_sys = p_demux->p_sys; + ts_prg_psi_t *p_prg = NULL; + int i_pmt_pid = -1; + + /* Search pmt to be unselected */ + for( int i = 0; i < p_sys->i_pmt; i++ ) + { + ts_pid_t *pmt = p_sys->pmt[i]; + + for( int i_prg = 0; i_prg < pmt->psi->i_prg; i_prg++ ) + { + if( pmt->psi->prg[i_prg]->i_number == i_prg_id ) + { + i_pmt_pid = p_sys->pmt[i]->i_pid; + p_prg = p_sys->pmt[i]->psi->prg[i_prg]; + break; + } + } + if( i_pmt_pid > 0 ) + break; + } + if( i_pmt_pid <= 0 ) + return; + assert( p_prg ); + + SetPIDFilter( p_demux, i_pmt_pid, b_selected ); + if( p_prg->i_pid_pcr > 0 ) + SetPIDFilter( p_demux, p_prg->i_pid_pcr, b_selected ); + + /* All ES */ + for( int i = 2; i < 8192; i++ ) + { + ts_pid_t *pid = &p_sys->pid[i]; + + if( !pid->b_valid || pid->psi ) + continue; + + for( int i_prg = 0; i_prg < pid->p_owner->i_prg; i_prg++ ) + { + if( pid->p_owner->prg[i_prg]->i_pid_pmt == i_pmt_pid && pid->es->id ) + { + /* We only remove/select es that aren't defined by extra pmt */ + SetPIDFilter( p_demux, i, b_selected ); + break; + } + } + } +} + static void PIDInit( ts_pid_t *pid, bool b_psi, ts_psi_t *p_owner ) { bool b_old_valid = pid->b_valid; @@ -1517,7 +1552,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; @@ -1563,8 +1598,11 @@ static void PIDInit( ts_pid_t *pid, bool b_psi, ts_psi_t *p_owner ) } } -static void PIDClean( es_out_t *out, ts_pid_t *pid ) +static void PIDClean( demux_t *p_demux, ts_pid_t *pid ) { + demux_sys_t *p_sys = p_demux->p_sys; + es_out_t *out = p_demux->out; + if( pid->psi ) { if( pid->psi->handle ) @@ -1583,7 +1621,10 @@ static void PIDClean( es_out_t *out, ts_pid_t *pid ) else { if( pid->es->id ) + { es_out_Del( out, pid->es->id ); + p_sys->i_pmt_es--; + } if( pid->es->p_pes ) block_ChainRelease( pid->es->p_pes ); @@ -1595,7 +1636,10 @@ static void PIDClean( es_out_t *out, ts_pid_t *pid ) for( int i = 0; i < pid->i_extra_es; i++ ) { if( pid->extra_es[i]->id ) + { es_out_Del( out, pid->extra_es[i]->id ); + p_sys->i_pmt_es--; + } if( pid->extra_es[i]->p_pes ) block_ChainRelease( pid->extra_es[i]->p_pes ); @@ -1791,13 +1835,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 ); @@ -1831,6 +1873,9 @@ static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) demux_sys_t *p_sys = p_demux->p_sys; const uint8_t *p = p_bk->p_buffer; + if( p_sys->i_pmt_es <= 0 ) + return; + if( ( p[3]&0x20 ) && /* adaptation */ ( p[5]&0x10 ) && ( p[4] >= 7 ) ) @@ -1851,7 +1896,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) ); } } } @@ -1952,7 +1997,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; } @@ -2051,7 +2096,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; @@ -2078,6 +2123,9 @@ static int PIDFillFormat( ts_pid_t *pid, int i_stream_type ) case 0x85: /* DTS (audio) */ 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) */ es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'a', '5', '2', 'b' ) ); @@ -2520,19 +2568,17 @@ static bool ProgramIsSelected( demux_t *p_demux, uint16_t i_pgrm ) { demux_sys_t *p_sys = p_demux->p_sys; - if( !p_sys->b_access_control ) - return false; - if( ( p_sys->i_current_program == -1 && p_sys->p_programs_list == NULL ) || + if( ( p_sys->i_current_program == -1 && p_sys->programs_list.i_count == 0 ) || p_sys->i_current_program == 0 ) return true; if( p_sys->i_current_program == i_pgrm ) return true; - if( p_sys->p_programs_list != NULL ) + if( p_sys->programs_list.i_count != 0 ) { - for( int i = 0; i < p_sys->p_programs_list->i_count; i++ ) + for( int i = 0; i < p_sys->programs_list.i_count; i++ ) { - if( i_pgrm == p_sys->p_programs_list->p_values[i].i_int ) + if( i_pgrm == p_sys->programs_list.p_values[i].i_int ) return true; } } @@ -2543,16 +2589,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 ) { @@ -2561,16 +2608,159 @@ static void ValidateDVBMeta( demux_t *p_demux, int i_pid ) p_pid->psi = NULL; p_pid->b_valid = false; } - if( p_sys->b_access_control ) - stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, i, false ); - + SetPIDFilter( p_demux, i, false ); } p_sys->b_dvb_meta = false; } #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, + bool b_broken ) +{ + 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( b_broken ) + 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; @@ -2592,6 +2782,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 ); + p_sys->b_broken_charset = false; + for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next ) { vlc_meta_t *p_meta; @@ -2606,9 +2798,6 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) p_srv->b_eit_present, p_srv->i_running_status, p_srv->b_free_ca ); - if( p_sys->i_current_program != -1 && p_sys->i_current_program != p_srv->i_service_id ) - continue; - p_meta = vlc_meta_New(); for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next ) { @@ -2634,14 +2823,38 @@ 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 */ + + if( p_sdt->i_network_id == 133 ) + p_sys->b_broken_charset = true; /* SKY DE & BetaDigital use 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; + } - 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'; + /* FIXME: Digital+ ES also uses ISO8859-1 */ + + str1 = EITConvertToUTF8(pD->i_service_provider_name, + pD->i_service_provider_name_length, + p_sys->b_broken_charset ); + str2 = EITConvertToUTF8(pD->i_service_name, + 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 ); @@ -2650,6 +2863,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 ); } } @@ -2739,133 +2954,17 @@ 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, bool b_current_following ) @@ -2875,7 +2974,7 @@ static void EITCallBack( demux_t *p_demux, vlc_epg_t *p_epg; msg_Dbg( p_demux, "EITCallBack called" ); - if( !p_eit->b_current_next || ( p_sys->i_current_program != -1 && p_sys->i_current_program != p_eit->i_service_id ) ) + if( !p_eit->b_current_next ) { dvbpsi_DeleteEIT( p_eit ); return; @@ -2912,10 +3011,14 @@ static void EITCallBack( demux_t *p_demux, { dvbpsi_short_event_dr_t *pE = dvbpsi_DecodeShortEventDr( p_dr ); - if( pE ) + /* Only take first description, as we don't handle language-info + for epg atm*/ + if( pE && psz_name == NULL) { - 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 ); } @@ -2931,12 +3034,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( 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 ); } @@ -2945,19 +3050,24 @@ 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 ); - - 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 ); @@ -2972,7 +3082,8 @@ static void EITCallBack( demux_t *p_demux, /* */ 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 ) @@ -2985,15 +3096,17 @@ static void EITCallBack( demux_t *p_demux, } if( p_epg->i_event > 0 ) { - if( p_eit->i_service_id == p_sys->i_current_program && b_current_following ) + 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 ); @@ -3038,6 +3151,17 @@ static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h, (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 @@ -3200,7 +3324,7 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, ts_teletext_page_t p_page[2 * 64 + 20]; unsigned i_page = 0; - /* Gather pages informations */ + /* Gather pages information */ #if defined _DVBPSI_DR_56_H_ && \ defined DVBPSI_VERSION && DVBPSI_VERSION_INT > ((0<<16)+(1<<8)+5) for( unsigned i_tag_idx = 0; i_tag_idx < 2; i_tag_idx++ ) @@ -3270,8 +3394,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; @@ -3282,9 +3405,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 ) { @@ -3329,6 +3452,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; @@ -3356,21 +3480,20 @@ 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 - /* 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 ) { @@ -3423,12 +3546,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: @@ -3530,7 +3655,7 @@ static void PMTSetupEs0x06( demux_t *p_demux, ts_pid_t *pid, } #ifdef _DVBPSI_DR_52_H_ - /* FIXME is it usefull ? */ + /* FIXME is it useful ? */ if( PMTEsFindDescriptor( p_es, 0x52 ) ) { dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0x52 ); @@ -3643,7 +3768,6 @@ static void PMTSetupEsHDMV( demux_t *p_demux, ts_pid_t *pid, 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_CODEC_EAC3; @@ -3658,6 +3782,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 ) { @@ -3835,15 +3991,7 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) if( ProgramIsSelected( p_demux, prg->i_number ) ) { /* Set demux filter */ - stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, prg->i_pid_pcr, - true ); - } - else if ( p_sys->b_access_control ) - { - msg_Warn( p_demux, "skipping program (not selected)" ); - dvbpsi_DeletePMT(p_pmt); - return; + SetPIDFilter( p_demux, prg->i_pid_pcr, true ); } /* Parse descriptor */ @@ -3945,6 +4093,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 && @@ -3995,7 +4147,7 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) { if( old_pid ) { - PIDClean( p_demux->out, old_pid ); + PIDClean( p_demux, old_pid ); TAB_REMOVE( i_clean, pp_clean, old_pid ); old_pid = 0; } @@ -4006,13 +4158,14 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) pid->extra_es[i]->id = es_out_Add( p_demux->out, &pid->extra_es[i]->fmt ); } + p_sys->i_pmt_es += 1 + pid->i_extra_es; } } /* Add ES to the list */ if( old_pid ) { - PIDClean( p_demux->out, old_pid ); + PIDClean( p_demux, old_pid ); TAB_REMOVE( i_clean, pp_clean, old_pid ); } p_sys->pid[p_es->i_pid] = *pid; @@ -4029,33 +4182,24 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ( pid->es->id != NULL || p_sys->b_udp_out ) ) { /* Set demux filter */ - stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, p_es->i_pid, - true ); + SetPIDFilter( p_demux, p_es->i_pid, true ); } } - 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++ ) { if( ProgramIsSelected( p_demux, prg->i_number ) ) { - stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, pp_clean[i]->i_pid, - false ); + SetPIDFilter( p_demux, pp_clean[i]->i_pid, false ); } - PIDClean( p_demux->out, pp_clean[i] ); + PIDClean( p_demux, pp_clean[i] ); } if( i_clean ) free( pp_clean ); @@ -4134,15 +4278,10 @@ static void PATCallBack( demux_t *p_demux, dvbpsi_pat_t *p_pat ) if( pid->p_owner->prg[i_prg]->i_pid_pmt != pmt_rm[j]->i_pid ) continue; - if( p_sys->b_access_control && pid->es->id ) - { - if( stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, i, - false ) ) - p_sys->b_access_control = false; - } + if( pid->es->id ) + SetPIDFilter( p_demux, i, false ); - PIDClean( p_demux->out, pid ); + PIDClean( p_demux, pid ); break; } } @@ -4151,13 +4290,7 @@ static void PATCallBack( demux_t *p_demux, dvbpsi_pat_t *p_pat ) /* Delete PMT pid */ for( int i = 0; i < i_pmt_rm; i++ ) { - if( p_sys->b_access_control ) - { - if( stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, - pmt_rm[i]->i_pid, false ) ) - p_sys->b_access_control = false; - } + SetPIDFilter( p_demux, pmt_rm[i]->i_pid, false ); for( int i_prg = 0; i_prg < pmt_rm[i]->psi->i_prg; i_prg++ ) { @@ -4165,7 +4298,7 @@ static void PATCallBack( demux_t *p_demux, dvbpsi_pat_t *p_pat ) es_out_Control( p_demux->out, ES_OUT_DEL_GROUP, i_number ); } - PIDClean( p_demux->out, &p_sys->pid[pmt_rm[i]->i_pid] ); + PIDClean( p_demux, &p_sys->pid[pmt_rm[i]->i_pid] ); TAB_REMOVE( p_sys->i_pmt, p_sys->pmt, pmt_rm[i] ); } @@ -4215,18 +4348,13 @@ static void PATCallBack( demux_t *p_demux, dvbpsi_pat_t *p_pat ) p_program->i_pid; /* Now select PID at access level */ - if( p_sys->b_access_control ) + if( ProgramIsSelected( p_demux, p_program->i_number ) ) { - if( ProgramIsSelected( p_demux, p_program->i_number ) ) - { - if( p_sys->i_current_program == 0 ) - p_sys->i_current_program = p_program->i_number; + if( p_sys->i_current_program == 0 ) + p_sys->i_current_program = p_program->i_number; - if( stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, - ACCESS_SET_PRIVATE_ID_STATE, - p_program->i_pid, true ) ) - p_sys->b_access_control = false; - } + if( SetPIDFilter( p_demux, p_program->i_pid, true ) ) + p_sys->b_access_control = false; } } }