* Preamble
*****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
+#include <ctype.h>
#include <vlc/vlc.h>
#include <vlc/input.h>
vlc_module_begin();
set_description( _("MPEG Transport Stream demuxer") );
- set_shortname ( _("MPEG-TS") );
+ set_shortname ( "MPEG-TS" );
set_category( CAT_INPUT );
set_subcategory( SUBCAT_INPUT_DEMUX );
} ts_prg_psi_t;
-typedef struct
-{
- demux_t *p_demux; /* Hack */
- int i_table_id;
- int i_version;
- int i_service_id;
-} ts_eit_psi_t;
-
typedef struct
{
/* for special PAT/SDT case */
int i_prg;
ts_prg_psi_t **prg;
- /* For EIT */
- int i_eit;
- ts_eit_psi_t **eit;
-
} ts_psi_t;
typedef struct
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 );
+ 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 );
+ 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,
if( pid->b_valid && pid->psi )
{
- int j;
switch( pid->i_pid )
{
case 0: /* PAT */
free( pid->psi );
break;
case 0x11: /* SDT */
- dvbpsi_DetachDemux( pid->psi->handle );
- free( pid->psi );
- break;
case 0x12: /* EIT */
dvbpsi_DetachDemux( pid->psi->handle );
- for( j = 0; j < pid->psi->i_eit; j++ )
- {
- free( pid->psi->eit[j] );
- }
- if( pid->psi->i_eit )
- free( pid->psi->eit );
free( pid->psi );
break;
default:
pid->psi->handle= NULL;
pid->psi->i_prg = 0;
pid->psi->prg = NULL;
- pid->psi->i_eit = 0;
- pid->psi->eit = NULL;
}
pid->psi->i_pat_version = -1;
pid->psi->i_sdt_version = -1;
{
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 )
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 );
+ 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 );
+ 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 )
{
char str1[257];
char str2[257];
- memcpy( str1, pD->i_service_provider_name, pD->i_service_provider_name_length );
+ 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';
}
}
#endif
-
-static void EITCallBack( ts_eit_psi_t *psi, dvbpsi_eit_t *p_eit )
+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 )
{
- demux_t *p_demux = psi->p_demux;
-
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( psi->i_version != -1 &&
- ( !p_eit->b_current_next || psi->i_version == p_eit->i_version ) )
+ 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 );
+ 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 )
{
- vlc_meta_t *p_meta = vlc_meta_New();
dvbpsi_descriptor_t *p_dr;
char *psz_cat = malloc( strlen("Event")+10 );
char psz_start[15];
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 );
}
memcpy( str1, pE->i_item_description[i],
pE->i_item_description_length[i] );
str1[pE->i_item_description_length[i]] = '\0';
+ EITEventFixString(str1);
- memcpy( str1, pE->i_item[i],
+ 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,
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 );
vlc_meta_Add( p_meta, psz_cat, psz_value );
free( psz_value );
- es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META,
- p_eit->i_service_id, p_meta );
- vlc_meta_Delete( p_meta );
+ 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 );
}
- psi->i_version = p_eit->i_version;
+
+ 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 );
}
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 );
+ dvbpsi_AttachSDT( h, i_table_id, i_extension,
+ (dvbpsi_sdt_callback)SDTCallBack, p_demux );
}
- else if( i_table_id == 0x4e || /* Current/Following */
+ else if( i_table_id == 0x4e || /* Current/Following */
( i_table_id >= 0x50 && i_table_id <= 0x5f ) ) /* Schedule */
{
- ts_eit_psi_t *psi = malloc( sizeof(ts_eit_psi_t) );
-
msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
i_table_id, i_table_id, i_extension, i_extension );
- psi->p_demux = p_demux;
- psi->i_table_id = i_table_id;
- psi->i_version = -1;
- psi->i_service_id = i_extension;
-
- dvbpsi_AttachEIT( h, i_table_id, i_extension, (dvbpsi_eit_callback)EITCallBack, psi );
+ dvbpsi_AttachEIT( h, i_table_id, i_extension,
+ (dvbpsi_eit_callback)EITCallBack, p_demux );
}
}
#endif
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 );
/* 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] );
}