X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fts.c;h=bd13ff8fd688767989f842cc683af85620891cb1;hb=1d8fa38783a9e68ed9dfcc380eb63ac142d85907;hp=8e6fd9f1a77b0f8dbe55f755869e5d8d9a98881b;hpb=d06ef50813c0c809fec669e95b4391003e19b4df;p=vlc diff --git a/modules/demux/ts.c b/modules/demux/ts.c index 8e6fd9f1a7..bd13ff8fd6 100644 --- a/modules/demux/ts.c +++ b/modules/demux/ts.c @@ -25,6 +25,7 @@ * Preamble *****************************************************************************/ #include /* malloc(), free() */ +#include #include #include @@ -37,20 +38,34 @@ /* Include dvbpsi headers */ #ifdef HAVE_DVBPSI_DR_H # include +# include # include # include # include +# include # include # include #else # include "dvbpsi.h" +# include "demux.h" # include "descriptor.h" # include "tables/pat.h" # include "tables/pmt.h" +# include "tables/sdt.h" # include "descriptors/dr.h" # include "psi.h" #endif +/* EIT support */ +#ifdef _DVBPSI_DR_4D_H_ +# define TS_USE_DVB_SI 1 +# ifdef HAVE_DVBPSI_DR_H +# include +# else +# include "tables/eit.h" +# endif +#endif + /* TODO: * - XXX: do not mark options message to be translated, they are too osbcure for now ... * - test it @@ -87,8 +102,8 @@ static void Close ( vlc_object_t * ); #define CAPMT_SYSID_LONGTEXT N_("only forward descriptors from this SysID to the CAM") vlc_module_begin(); - set_description( _("ISO 13818-1 MPEG Transport Stream input - new" ) ); - set_shortname ( _("MPEG-TS") ); + set_description( _("MPEG Transport Stream demuxer") ); + set_shortname ( "MPEG-TS" ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_DEMUX ); @@ -99,8 +114,6 @@ vlc_module_begin(); MTUOUT_LONGTEXT, VLC_TRUE ); add_string( "ts-csa-ck", NULL, NULL, CSA_TEXT, CSA_LONGTEXT, VLC_TRUE ); add_bool( "ts-silent", 0, NULL, SILENT_TEXT, SILENT_LONGTEXT, VLC_TRUE ); - add_integer( "ts-capmt-sysid", 0, NULL, CAPMT_SYSID_TEXT, - CAPMT_SYSID_LONGTEXT, VLC_TRUE ); set_capability( "demux2", 10 ); set_callbacks( Open, Close ); @@ -175,7 +188,7 @@ typedef struct typedef struct { - uint8_t i_iod_label; + uint8_t i_iod_label, i_iod_label_scope; /* IOD */ uint16_t i_od_id; @@ -206,9 +219,10 @@ typedef struct typedef struct { - /* for special PAT case */ - dvbpsi_handle handle; + /* for special PAT/SDT case */ + dvbpsi_handle handle; /* PAT/SDT/EIT */ int i_pat_version; + int i_sdt_version; /* For PMT */ int i_prg; @@ -271,7 +285,6 @@ struct demux_sys_t vlc_bool_t b_es_id_pid; csa_t *csa; vlc_bool_t b_silent; - uint16_t i_capmt_sysid; vlc_bool_t b_udp_out; int fd; /* udp socket */ @@ -280,6 +293,9 @@ struct demux_sys_t vlc_bool_t b_dvb_control; int i_dvb_program; vlc_list_t *p_programs_list; + + /* */ + vlc_bool_t b_meta; }; static int Demux ( demux_t *p_demux ); @@ -292,6 +308,11 @@ static int PIDFillFormat( ts_pid_t *pid, int i_stream_type ); static void PATCallBack( demux_t *, dvbpsi_pat_t * ); static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ); +#ifdef TS_USE_DVB_SI +static void PSINewTableCallBack( demux_t *, dvbpsi_handle, + uint8_t i_table_id, uint16_t i_extension ); +#endif + static inline int PIDGet( block_t *p ) { @@ -327,11 +348,7 @@ static int Open( vlc_object_t *p_this ) vlc_value_t val; if( stream_Peek( p_demux->s, &p_peek, TS_PACKET_SIZE_MAX ) < - TS_PACKET_SIZE_MAX ) - { - msg_Err( p_demux, "cannot peek" ); - return VLC_EGENERIC; - } + TS_PACKET_SIZE_MAX ) return VLC_EGENERIC; /* Search first sync byte */ for( i_sync = 0; i_sync < TS_PACKET_SIZE_MAX; i_sync++ ) @@ -340,11 +357,7 @@ static int Open( vlc_object_t *p_this ) } if( i_sync >= TS_PACKET_SIZE_MAX ) { - if( strcmp( p_demux->psz_demux, "ts" ) ) - { - msg_Warn( p_demux, "TS module discarded" ); - return VLC_EGENERIC; - } + if( strcmp( p_demux->psz_demux, "ts" ) ) return VLC_EGENERIC; msg_Warn( p_demux, "this does not look like a TS stream, continuing" ); } @@ -390,6 +403,7 @@ static int Open( vlc_object_t *p_this ) memset( p_sys, 0, sizeof( demux_sys_t ) ); /* Init p_sys field */ + p_sys->b_meta = VLC_TRUE; p_sys->b_dvb_control = VLC_TRUE; p_sys->i_dvb_program = 0; for( i = 0; i < 8192; i++ ) @@ -410,6 +424,29 @@ static int Open( vlc_object_t *p_this ) PIDInit( pat, VLC_TRUE, NULL ); pat->psi->handle = dvbpsi_AttachPAT( (dvbpsi_pat_callback)PATCallBack, p_demux ); +#ifdef TS_USE_DVB_SI + if( p_sys->b_meta ) + { + ts_pid_t *sdt = &p_sys->pid[0x11]; + ts_pid_t *eit = &p_sys->pid[0x12]; + + PIDInit( sdt, VLC_TRUE, NULL ); + sdt->psi->handle = + dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack, + p_demux ); + PIDInit( eit, VLC_TRUE, NULL ); + eit->psi->handle = + dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack, + p_demux ); + if( p_sys->b_dvb_control ) + { + stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, + ACCESS_SET_PRIVATE_ID_STATE, 0x11, VLC_TRUE ); + stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, + ACCESS_SET_PRIVATE_ID_STATE, 0x12, VLC_TRUE ); + } + } +#endif /* Init PMT array */ p_sys->i_pmt = 0; @@ -418,7 +455,7 @@ static int Open( vlc_object_t *p_this ) /* Read config */ var_Create( p_demux, "ts-es-id-pid", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_demux, "ts-es-id-pid", &val ); - p_sys->b_es_id_pid = val.b_bool, + p_sys->b_es_id_pid = val.b_bool; var_Create( p_demux, "ts-out", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Get( p_demux, "ts-out", &val ); @@ -549,7 +586,11 @@ static int Open( vlc_object_t *p_this ) } else { +#ifndef UNDER_CE uint64_t i_ck = strtoull( psz, NULL, 16 ); +#else + uint64_t i_ck = strtoll( psz, NULL, 16 ); +#endif uint8_t ck[8]; int i; for( i = 0; i < 8; i++ ) @@ -574,10 +615,6 @@ static int Open( vlc_object_t *p_this ) var_Get( p_demux, "ts-silent", &val ); p_sys->b_silent = val.b_bool; - var_Create( p_demux, "ts-capmt-sysid", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Get( p_demux, "ts-capmt-sysid", &val ); - p_sys->i_capmt_sysid = val.i_int; - return VLC_SUCCESS; } @@ -607,6 +644,11 @@ static void Close( vlc_object_t *p_this ) case 1: /* CAT */ free( pid->psi ); break; + case 0x11: /* SDT */ + case 0x12: /* EIT */ + dvbpsi_DetachDemux( pid->psi->handle ); + free( pid->psi ); + break; default: PIDClean( p_demux->out, pid ); break; @@ -732,7 +774,7 @@ static int Demux( demux_t *p_demux ) { if( p_pid->psi ) { - if( p_pid->i_pid == 0 ) + if( p_pid->i_pid == 0 || p_pid->i_pid == 0x11 || p_pid->i_pid == 0x12 ) { dvbpsi_PushPacket( p_pid->psi->handle, p_pkt->p_buffer ); } @@ -994,11 +1036,12 @@ static void PIDInit( ts_pid_t *pid, vlc_bool_t b_psi, ts_psi_t *p_owner ) if( !b_old_valid ) { pid->psi = malloc( sizeof( ts_psi_t ) ); + pid->psi->handle= NULL; pid->psi->i_prg = 0; pid->psi->prg = NULL; - pid->psi->handle= NULL; } pid->psi->i_pat_version = -1; + pid->psi->i_sdt_version = -1; if( p_owner ) { ts_prg_psi_t *prg = malloc( sizeof( ts_prg_psi_t ) ); @@ -1252,6 +1295,10 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) } } + /* ISO/IEC 13818-1 2.7.5: if no pts and no dts, then dts == pts */ + if( i_pts >= 0 && i_dts < 0 ) + i_dts = i_pts; + if( p_pes ) { block_t *p_block; @@ -1356,6 +1403,8 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) { msg_Dbg( p_demux, "transport_error_indicator set (pid=%d)", pid->i_pid ); + if( pid->es->p_pes ) //&& pid->es->fmt.i_cat == VIDEO_ES ) + pid->es->p_pes->i_flags |= BLOCK_FLAG_CORRUPTED; } if( p_demux->p_sys->csa ) @@ -1407,8 +1456,8 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) else if( i_diff != 0 ) { /* FIXME what to do when discontinuity_indicator is set ? */ - msg_Warn( p_demux, "discontinuity received 0x%x instead of 0x%x", - i_cc, ( pid->i_cc + 1 )&0x0f ); + msg_Warn( p_demux, "discontinuity received 0x%x instead of 0x%x (pid=%d)", + i_cc, ( pid->i_cc + 1 )&0x0f, pid->i_pid ); pid->i_cc = i_cc; @@ -1416,7 +1465,7 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) { /* Small video artifacts are usually better then * dropping full frames */ - pid->es->p_pes->i_flags |= BLOCK_FLAG_DISCONTINUITY; + pid->es->p_pes->i_flags |= BLOCK_FLAG_CORRUPTED; } } } @@ -1626,7 +1675,7 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data ) iod_descriptor_t *p_iod; int i; int i_es_index; - uint8_t i_flags; + uint8_t i_flags, i_iod_tag, byte1, byte2, byte3; vlc_bool_t b_url; int i_iod_length; @@ -1645,14 +1694,28 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data ) return p_iod; } - p_iod->i_iod_label = IODGetByte( &i_data, &p_data ); + byte1 = IODGetByte( &i_data, &p_data ); + byte2 = IODGetByte( &i_data, &p_data ); + byte3 = IODGetByte( &i_data, &p_data ); + if( byte2 == 0x02 ) //old vlc's buggy implementation of the IOD_descriptor + { + p_iod->i_iod_label_scope = 0x11; + p_iod->i_iod_label = byte1; + i_iod_tag = byte2; + } + else //correct implementation of the IOD_descriptor + { + p_iod->i_iod_label_scope = byte1; + p_iod->i_iod_label = byte2; + i_iod_tag = byte3; + } fprintf( stderr, "\n* iod_label:%d", p_iod->i_iod_label ); fprintf( stderr, "\n* ===========" ); - fprintf( stderr, "\n* tag:0x%x", p_data[0] ); + fprintf( stderr, "\n* tag:0x%x", i_iod_tag ); - if( IODGetByte( &i_data, &p_data ) != 0x02 ) + if( i_iod_tag != 0x02 ) { - fprintf( stderr, "\n ERR: tag != 0x02" ); + fprintf( stderr, "\n ERR: tag %02x != 0x02", i_iod_tag ); return p_iod; } @@ -1935,6 +1998,309 @@ static vlc_bool_t DVBProgramIsSelected( demux_t *p_demux, uint16_t i_pgrm ) return VLC_FALSE; } +#ifdef TS_USE_DVB_SI +static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) +{ + demux_sys_t *p_sys = p_demux->p_sys; + ts_pid_t *sdt = &p_sys->pid[0x11]; + dvbpsi_sdt_service_t *p_srv; + + msg_Dbg( p_demux, "SDTCallBack called" ); + + if( sdt->psi->i_sdt_version != -1 && + ( !p_sdt->b_current_next || + p_sdt->i_version == sdt->psi->i_sdt_version ) ) + { + dvbpsi_DeleteSDT( p_sdt ); + return; + } + + msg_Dbg( p_demux, "new SDT ts_id=%d version=%d current_next=%d " + "network_id=%d", + p_sdt->i_ts_id, p_sdt->i_version, p_sdt->b_current_next, + p_sdt->i_network_id ); + + for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next ) + { + vlc_meta_t *p_meta = vlc_meta_New(); + dvbpsi_descriptor_t *p_dr; + + msg_Dbg( p_demux, " * service id=%d eit schedule=%d present=%d " + "runing=%d free_ca=%d", + p_srv->i_service_id, p_srv->b_eit_schedule, + p_srv->b_eit_present, p_srv->i_running_status, + p_srv->b_free_ca ); + + for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next ) + { + if( p_dr->i_tag == 0x48 ) + { + static const char *psz_type[0x11] = { + "Reserved", + "Digital television service", + "Digital radio sound service", + "Teletext service", + "NVOD reference service", + "NVOD time-shifted service", + "Mosaic service", + "PAL coded signal", + "SECAM coded signal", + "D/D2-MAC", + "FM Radio", + "NTSC coded signal", + "Data broadcast service", + "Reserved for Common Interface Usage", + "RCS Map (see EN 301 790 [35])", + "RCS FLS (see EN 301 790 [35])", + "DVB MHP service" + }; + dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr ); + char str1[257]; + char str2[257]; + + 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'; + + msg_Dbg( p_demux, " - type=%d provider=%s name=%s", + pD->i_service_type, str1, str2 ); + + vlc_meta_Add( p_meta, "Name", str2 ); + vlc_meta_Add( p_meta, "Provider", str1 ); + if( pD->i_service_type >= 0x01 && pD->i_service_type <= 0x10 ) + vlc_meta_Add( p_meta, "Type", psz_type[pD->i_service_type] ); + } + } + + if( p_srv->i_running_status == 0x01 ) + vlc_meta_Add( p_meta, "Status", "Not running" ); + else if( p_srv->i_running_status == 0x02 ) + vlc_meta_Add( p_meta, "Status", "Starts in a few seconds" ); + else if( p_srv->i_running_status == 0x03 ) + vlc_meta_Add( p_meta, "Status", "Pausing" ); + else if( p_srv->i_running_status == 0x04 ) + vlc_meta_Add( p_meta, "Status", "Running" ); + else + vlc_meta_Add( p_meta, "Status", "Unknown" ); + + + es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META, + p_srv->i_service_id, p_meta ); + vlc_meta_Delete( p_meta ); + } + + sdt->psi->i_sdt_version = p_sdt->i_version; + dvbpsi_DeleteSDT( p_sdt ); +} +#if 0 +static void DecodeMjd( int i_mjd, int *p_y, int *p_m, int *p_d ) +{ + int yp = (int)( ( (double)i_mjd - 15078.2)/365.25 ); + int mp = (int)( ((double)i_mjd - 14956.1 - (int)(yp * 365.25)) / 30.6001 ); + + *p_d = i_mjd - 14956 - (int)(yp*365.25) - (int)(mp*30.6001); + + if( mp == 14 || mp == 15 ) + { + *p_y = yp + 1; + *p_m = mp - 1 + 12; + } + else + { + *p_y = yp; + *p_m = mp - 1; + } +} +#endif +static void EITEventFixString( unsigned char *psz ) +{ + int i_len; + /* Sometimes the first char isn't a normal char but designed + * caracters encoding, for now lets skip it */ + if( psz[0] >= 0x20 ) + return; + if( ( i_len = strlen( psz ) ) > 0 ) + memmove( &psz[0], &psz[1], i_len ); /* Copy the \0 too */ +} +static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) +{ + dvbpsi_eit_event_t *p_evt; + vlc_meta_t *p_meta; + vlc_bool_t b_event_active = VLC_FALSE; + + msg_Dbg( p_demux, "EITCallBack called" ); + if( !p_eit->b_current_next ) + { + dvbpsi_DeleteEIT( p_eit ); + return; + } + + msg_Dbg( p_demux, "new EIT service_id=%d version=%d current_next=%d " + "ts_id=%d network_id=%d segment_last_section_number=%d " + "last_table_id=%d", + p_eit->i_service_id, p_eit->i_version, p_eit->b_current_next, + p_eit->i_ts_id, p_eit->i_network_id, + p_eit->i_segment_last_section_number, p_eit->i_last_table_id ); + + p_meta = vlc_meta_New(); + for( p_evt = p_eit->p_first_event; p_evt; p_evt = p_evt->p_next ) + { + dvbpsi_descriptor_t *p_dr; + char *psz_cat = malloc( strlen("Event")+10 ); + char psz_start[15]; + char psz_duration[15]; + char psz_name[256]; + char psz_text[256]; + char *psz_extra = strdup(""); + char *psz_value; + + sprintf( psz_cat, "Event %d", p_evt->i_event_id ); + sprintf( psz_start, "%d%d:%d%d:%d%d", + (int)(p_evt->i_start_time >> 20)&0xf, + (int)(p_evt->i_start_time >> 16)&0xf, + (int)(p_evt->i_start_time >> 12)&0xf, + (int)(p_evt->i_start_time >> 8)&0xf, + (int)(p_evt->i_start_time >> 4)&0xf, + (int)(p_evt->i_start_time )&0xf ); + sprintf( psz_duration, "%d%d:%d%d:%d%d", + (p_evt->i_duration >> 20)&0xf, (p_evt->i_duration >> 16)&0xf, + (p_evt->i_duration >> 12)&0xf, (p_evt->i_duration >> 8)&0xf, + (p_evt->i_duration >> 4)&0xf, (p_evt->i_duration )&0xf ); + psz_name[0] = psz_text[0] = '\0'; + + msg_Dbg( p_demux, " * event id=%d start_time:mjd=%d %s duration=%s " + "running=%d free_ca=%d", + p_evt->i_event_id, + (int)(p_evt->i_start_time >> 24), + psz_start, psz_duration, + p_evt->i_running_status, p_evt->b_free_ca ); + + for( p_dr = p_evt->p_first_descriptor; p_dr; p_dr = p_dr->p_next ) + { + if( p_dr->i_tag == 0x4d ) + { + dvbpsi_short_event_dr_t *pE = dvbpsi_DecodeShortEventDr( p_dr ); + + if( pE ) + { + memcpy( psz_name, pE->i_event_name, pE->i_event_name_length); + psz_name[pE->i_event_name_length] = '\0'; + memcpy( psz_text, pE->i_text, pE->i_text_length ); + psz_text[pE->i_text_length] = '\0'; + + EITEventFixString(psz_name); + EITEventFixString(psz_text); + msg_Dbg( p_demux, " - short event lang=%3.3s '%s' : '%s'", + pE->i_iso_639_code, psz_name, psz_text ); + } + } + else if( p_dr->i_tag == 0x4e ) + { + dvbpsi_extended_event_dr_t *pE = dvbpsi_DecodeExtendedEventDr( p_dr ); + char str1[257]; + char str2[257]; + + if( pE ) + { + int i; + msg_Dbg( p_demux, " - extended event lang=%3.3s", + pE->i_iso_639_code ); + for( i = 0; i < pE->i_entry_count; i++ ) + { + memcpy( str1, pE->i_item_description[i], + pE->i_item_description_length[i] ); + str1[pE->i_item_description_length[i]] = '\0'; + EITEventFixString(str1); + + memcpy( str2, pE->i_item[i], + pE->i_item_length[i] ); + str2[pE->i_item_length[i]] = '\0'; + EITEventFixString(str2); + + msg_Dbg( p_demux, " - desc='%s' item='%s'", str1, str2 ); + psz_extra = realloc( psz_extra, + strlen(psz_extra) + + strlen(str1) +strlen(str2) + 1 + 3 ); + strcat( psz_extra, str1 ); + strcat( psz_extra, "(" ); + strcat( psz_extra, str2 ); + strcat( psz_extra, ") " ); + } + + memcpy( str1, pE->i_text, pE->i_text_length ); + str1[pE->i_text_length] = '\0'; + EITEventFixString(str1); + + msg_Dbg( p_demux, " - text='%s'", str1 ); + psz_extra = realloc( psz_extra, + strlen(psz_extra) + strlen(str1) + 2 ); + strcat( psz_extra, str1 ); + strcat( psz_extra, " " ); + } + } + else + { + msg_Dbg( p_demux, " - tag=0x%x(%d)", p_dr->i_tag, p_dr->i_tag ); + } + } + + asprintf( &psz_value, "%s: %s (+%s) %s (%s)", + psz_start, + psz_name, + psz_duration, + psz_text, psz_extra ); + vlc_meta_Add( p_meta, psz_cat, psz_value ); + free( psz_value ); + + if( p_evt->i_running_status == 0x04 ) + { + vlc_meta_Add( p_meta, VLC_META_NOW_PLAYING, psz_name ); + b_event_active = VLC_TRUE; + } + + free( psz_cat ); + free( psz_extra ); + } + + if( !b_event_active ) + vlc_meta_Add( p_meta, VLC_META_NOW_PLAYING, "" ); + es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META, + p_eit->i_service_id, p_meta ); + vlc_meta_Delete( p_meta ); + + dvbpsi_DeleteEIT( p_eit ); +} + +static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h, + uint8_t i_table_id, uint16_t i_extension ) +{ +#if 0 + msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)", + i_table_id, i_table_id, i_extension, i_extension ); +#endif + + if( i_table_id == 0x42 ) + { + msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)", + i_table_id, i_table_id, i_extension, i_extension ); + + dvbpsi_AttachSDT( h, i_table_id, i_extension, + (dvbpsi_sdt_callback)SDTCallBack, p_demux ); + } + else if( i_table_id == 0x4e || /* Current/Following */ + ( i_table_id >= 0x50 && i_table_id <= 0x5f ) ) /* Schedule */ + { + 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 ); + } +} +#endif + static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) { demux_sys_t *p_sys = p_demux->p_sys; @@ -2054,9 +2420,22 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) if( !old_pid && p_sys->pid[p_es->i_pid].b_valid ) { - msg_Warn( p_demux, "pmt error: pid=%d already defined", - p_es->i_pid ); - continue; + ts_pid_t *pid = &p_sys->pid[p_es->i_pid]; + if( ( pid->i_pid == 0x11 /* SDT */ || + pid->i_pid == 0x12 /* EDT */ ) && pid->psi ) + { + /* This doesn't look like a DVB stream so don't try + * parsing the SDT/EDT */ + dvbpsi_DetachDemux( pid->psi->handle ); + free( pid->psi ); + pid->psi = 0; + } + else + { + msg_Warn( p_demux, "pmt error: pid=%d already defined", + p_es->i_pid ); + continue; + } } PIDInit( pid, VLC_FALSE, pmt->psi ); @@ -2112,6 +2491,9 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) case 0x20: /* mpeg4 */ pid->es->fmt.i_codec = VLC_FOURCC('m','p','4','v'); break; + case 0x21: /* h264 */ + pid->es->fmt.i_codec = VLC_FOURCC('h','2','6','4'); + break; case 0x60: case 0x61: case 0x62: @@ -2237,24 +2619,12 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) else if( p_dr->i_tag == 0x45 ) { msg_Dbg( p_demux, " * VBI Data descriptor" ); - pid->es->fmt.i_cat = SPU_ES; - pid->es->fmt.i_codec = VLC_FOURCC( 'v', 'b', 'i', 'd' ); - pid->es->fmt.psz_description = strdup( "VBI Data" ); - 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 ); + /* FIXME : store the information somewhere */ } else if( p_dr->i_tag == 0x46 ) { msg_Dbg( p_demux, " * VBI Teletext descriptor" ); - pid->es->fmt.i_cat = SPU_ES; - pid->es->fmt.i_codec = VLC_FOURCC( 'v', 'b', 'i', 't' ); - pid->es->fmt.psz_description = strdup( "VBI 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 ); + /* FIXME : store the information somewhere */ } else if( p_dr->i_tag == 0x56 ) { @@ -2584,6 +2954,7 @@ static void PATCallBack( demux_t *p_demux, dvbpsi_pat_t *p_pat ) /* Delete PMT pid */ for( i = 0; i < i_pmt_rm; i++ ) { + int i_prg; if( p_sys->b_dvb_control ) { if( stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, @@ -2592,6 +2963,13 @@ static void PATCallBack( demux_t *p_demux, dvbpsi_pat_t *p_pat ) p_sys->b_dvb_control = VLC_FALSE; } + for( i_prg = 0; i_prg < pmt_rm[i]->psi->i_prg; i_prg++ ) + { + const int i_number = pmt_rm[i]->psi->prg[i_prg]->i_number; + if( i_number != 0 ) + es_out_Control( p_demux->out, ES_OUT_DEL_GROUP, i_number ); + } + PIDClean( p_demux->out, &p_sys->pid[pmt_rm[i]->i_pid] ); TAB_REMOVE( p_sys->i_pmt, p_sys->pmt, pmt_rm[i] ); }