* Preamble
*****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
+#include <ctype.h>
#include <vlc/vlc.h>
#include <vlc/input.h>
/* Include dvbpsi headers */
#ifdef HAVE_DVBPSI_DR_H
# include <dvbpsi/dvbpsi.h>
+# include <dvbpsi/demux.h>
# include <dvbpsi/descriptor.h>
# include <dvbpsi/pat.h>
# include <dvbpsi/pmt.h>
+# include <dvbpsi/sdt.h>
# include <dvbpsi/dr.h>
# include <dvbpsi/psi.h>
#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 <dvbpsi/eit.h>
+# 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
#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 );
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 );
typedef struct
{
- uint8_t i_iod_label;
+ uint8_t i_iod_label, i_iod_label_scope;
/* IOD */
uint16_t i_od_id;
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;
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 */
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 );
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 )
{
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++ )
}
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" );
}
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++ )
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;
/* 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 );
}
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++ )
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;
}
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;
{
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 );
}
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 ) );
}
}
+ /* 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;
{
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 )
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;
{
/* 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;
}
}
}
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;
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;
}
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;
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 );
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:
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 )
{
/* 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,
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] );
}