Commit f81597cd authored by Jean-Paul Saman's avatar Jean-Paul Saman

Backport various fixes from trunk/modules/demux/ts.c this fixes playback of some mp4/h264 files.

parent c878ba6a
...@@ -67,7 +67,9 @@ ...@@ -67,7 +67,9 @@
# include "tables/eit.h" # include "tables/eit.h"
# endif # endif
#endif #endif
#ifdef HAVE_TIME_H
# include <time.h>
#endif
#undef TS_DEBUG #undef TS_DEBUG
/* TODO: /* TODO:
...@@ -135,13 +137,14 @@ vlc_module_begin(); ...@@ -135,13 +137,14 @@ vlc_module_begin();
add_string( "ts-extra-pmt", NULL, NULL, PMT_TEXT, PMT_LONGTEXT, VLC_TRUE ); add_string( "ts-extra-pmt", NULL, NULL, PMT_TEXT, PMT_LONGTEXT, VLC_TRUE );
add_bool( "ts-es-id-pid", 1, NULL, PID_TEXT, PID_LONGTEXT, VLC_TRUE ); add_bool( "ts-es-id-pid", 1, NULL, PID_TEXT, PID_LONGTEXT, VLC_TRUE );
add_string( "ts-out", NULL, NULL, TSOUT_TEXT, TSOUT_LONGTEXT, VLC_TRUE ); add_string( "ts-out", NULL, NULL, TSOUT_TEXT, TSOUT_LONGTEXT, VLC_TRUE );
add_integer( "ts-out-mtu", 1500, NULL, MTUOUT_TEXT, add_integer( "ts-out-mtu", 1400, NULL, MTUOUT_TEXT,
MTUOUT_LONGTEXT, VLC_TRUE ); MTUOUT_LONGTEXT, VLC_TRUE );
add_string( "ts-csa-ck", NULL, NULL, CSA_TEXT, CSA_LONGTEXT, VLC_TRUE ); add_string( "ts-csa-ck", NULL, NULL, CSA_TEXT, CSA_LONGTEXT, VLC_TRUE );
add_integer( "ts-csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, VLC_TRUE ); add_integer( "ts-csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, VLC_TRUE );
add_bool( "ts-silent", 0, NULL, SILENT_TEXT, SILENT_LONGTEXT, VLC_TRUE ); add_bool( "ts-silent", 0, NULL, SILENT_TEXT, SILENT_LONGTEXT, VLC_TRUE );
add_file( "ts-dump-file", NULL, NULL, TSDUMP_TEXT, TSDUMP_LONGTEXT, VLC_FALSE ); add_file( "ts-dump-file", NULL, NULL, TSDUMP_TEXT, TSDUMP_LONGTEXT, VLC_FALSE );
add_bool( "ts-dump-append", 0, NULL, APPEND_TEXT, APPEND_LONGTEXT, VLC_FALSE ); add_bool( "ts-dump-append", 0, NULL, APPEND_TEXT, APPEND_LONGTEXT, VLC_FALSE );
add_integer( "ts-dump-size", 16384, NULL, DUMPSIZE_TEXT, add_integer( "ts-dump-size", 16384, NULL, DUMPSIZE_TEXT,
DUMPSIZE_LONGTEXT, VLC_TRUE ); DUMPSIZE_LONGTEXT, VLC_TRUE );
...@@ -324,6 +327,8 @@ struct demux_sys_t ...@@ -324,6 +327,8 @@ struct demux_sys_t
vlc_bool_t b_dvb_control; vlc_bool_t b_dvb_control;
int i_dvb_program; int i_dvb_program;
int64_t i_dvb_start;
int64_t i_dvb_length;
vlc_list_t *p_programs_list; vlc_list_t *p_programs_list;
/* TS dump */ /* TS dump */
...@@ -377,12 +382,12 @@ static int Open( vlc_object_t *p_this ) ...@@ -377,12 +382,12 @@ static int Open( vlc_object_t *p_this )
demux_t *p_demux = (demux_t*)p_this; demux_t *p_demux = (demux_t*)p_this;
demux_sys_t *p_sys; demux_sys_t *p_sys;
uint8_t *p_peek; uint8_t *p_peek;
int i_sync, i_peek, i; int i_sync, i_peek, i;
int i_packet_size; int i_packet_size;
ts_pid_t *pat; ts_pid_t *pat;
char *psz_mode; const char *psz_mode;
vlc_bool_t b_append; vlc_bool_t b_append;
vlc_bool_t b_topfield = VLC_FALSE; vlc_bool_t b_topfield = VLC_FALSE;
...@@ -391,8 +396,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -391,8 +396,7 @@ static int Open( vlc_object_t *p_this )
if( stream_Peek( p_demux->s, &p_peek, TS_PACKET_SIZE_MAX ) < if( stream_Peek( p_demux->s, &p_peek, TS_PACKET_SIZE_MAX ) <
TS_PACKET_SIZE_MAX ) return VLC_EGENERIC; TS_PACKET_SIZE_MAX ) return VLC_EGENERIC;
if( p_peek[0] == 'T' && p_peek[1] == 'F' && if( memcmp( p_peek, "TFrc", 4 ) == 0 )
p_peek[2] == 'r' && p_peek[3] == 'c' )
{ {
b_topfield = VLC_TRUE; b_topfield = VLC_TRUE;
msg_Dbg( p_demux, "this is a topfield file" ); msg_Dbg( p_demux, "this is a topfield file" );
...@@ -405,7 +409,8 @@ static int Open( vlc_object_t *p_this ) ...@@ -405,7 +409,8 @@ static int Open( vlc_object_t *p_this )
} }
if( i_sync >= TS_PACKET_SIZE_MAX && !b_topfield ) if( i_sync >= TS_PACKET_SIZE_MAX && !b_topfield )
{ {
if( strcmp( p_demux->psz_demux, "ts" ) ) return VLC_EGENERIC; if( !p_demux->b_force )
return VLC_EGENERIC;
msg_Warn( p_demux, "this does not look like a TS stream, continuing" ); msg_Warn( p_demux, "this does not look like a TS stream, continuing" );
} }
...@@ -419,7 +424,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -419,7 +424,7 @@ static int Open( vlc_object_t *p_this )
/* Check next 3 sync bytes */ /* Check next 3 sync bytes */
i_peek = TS_PACKET_SIZE_MAX * 3 + i_sync + 1; i_peek = TS_PACKET_SIZE_MAX * 3 + i_sync + 1;
} }
if( ( stream_Peek( p_demux->s, &p_peek, i_peek ) ) < i_peek ) if( ( stream_Peek( p_demux->s, &p_peek, i_peek ) ) < i_peek )
{ {
msg_Err( p_demux, "cannot peek" ); msg_Err( p_demux, "cannot peek" );
...@@ -443,7 +448,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -443,7 +448,7 @@ static int Open( vlc_object_t *p_this )
{ {
i_packet_size = TS_PACKET_SIZE_204; i_packet_size = TS_PACKET_SIZE_204;
} }
else if( !strcmp( p_demux->psz_demux, "ts" ) ) else if( p_demux->b_force )
{ {
i_packet_size = TS_PACKET_SIZE_188; i_packet_size = TS_PACKET_SIZE_188;
} }
...@@ -451,7 +456,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -451,7 +456,7 @@ static int Open( vlc_object_t *p_this )
{ {
i_packet_size = TS_PACKET_SIZE_188; i_packet_size = TS_PACKET_SIZE_188;
#if 0 #if 0
/* I used the TF5000PVR 2004 Firmware .doc header documentation, /* I used the TF5000PVR 2004 Firmware .doc header documentation,
* http://www.i-topfield.com/data/product/firmware/Structure%20of%20Recorded%20File%20in%20TF5000PVR%20(Feb%2021%202004).doc * http://www.i-topfield.com/data/product/firmware/Structure%20of%20Recorded%20File%20in%20TF5000PVR%20(Feb%2021%202004).doc
* but after the filename the offsets seem to be incorrect. - DJ */ * but after the filename the offsets seem to be incorrect. - DJ */
int i_duration, i_name; int i_duration, i_name;
...@@ -482,7 +487,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -482,7 +487,7 @@ static int Open( vlc_object_t *p_this )
// 4 bytes of freq. Uimsbf (56,57,58,59) // 4 bytes of freq. Uimsbf (56,57,58,59)
// 2 bytes of symbol rate Uimsbf (60,61) // 2 bytes of symbol rate Uimsbf (60,61)
// 2 bytes of TS stream ID Uimsbf (62,63) // 2 bytes of TS stream ID Uimsbf (62,63)
// 4 bytes reserved // 4 bytes reserved
// 2 bytes reserved // 2 bytes reserved
// 2 bytes duration Uimsbf (70,71) // 2 bytes duration Uimsbf (70,71)
//i_duration = (int) (p_peek[70] << 8) | p_peek[71]; //i_duration = (int) (p_peek[70] << 8) | p_peek[71];
...@@ -521,6 +526,8 @@ static int Open( vlc_object_t *p_this ) ...@@ -521,6 +526,8 @@ static int Open( vlc_object_t *p_this )
} }
p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
if( !p_sys )
return VLC_ENOMEM;
memset( p_sys, 0, sizeof( demux_sys_t ) ); memset( p_sys, 0, sizeof( demux_sys_t ) );
p_sys->i_packet_size = i_packet_size; p_sys->i_packet_size = i_packet_size;
...@@ -583,6 +590,9 @@ static int Open( vlc_object_t *p_this ) ...@@ -583,6 +590,9 @@ static int Open( vlc_object_t *p_this )
p_sys->b_meta = VLC_TRUE; p_sys->b_meta = VLC_TRUE;
p_sys->b_dvb_control = VLC_TRUE; p_sys->b_dvb_control = VLC_TRUE;
p_sys->i_dvb_program = 0; p_sys->i_dvb_program = 0;
p_sys->i_dvb_start = 0;;
p_sys->i_dvb_length = 0;
for( i = 0; i < 8192; i++ ) for( i = 0; i < 8192; i++ )
{ {
ts_pid_t *pid = &p_sys->pid[i]; ts_pid_t *pid = &p_sys->pid[i];
...@@ -619,10 +629,11 @@ static int Open( vlc_object_t *p_this ) ...@@ -619,10 +629,11 @@ static int Open( vlc_object_t *p_this )
p_demux ); p_demux );
if( p_sys->b_dvb_control ) if( p_sys->b_dvb_control )
{ {
stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, if( stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
ACCESS_SET_PRIVATE_ID_STATE, 0x11, VLC_TRUE ); ACCESS_SET_PRIVATE_ID_STATE, 0x11, VLC_TRUE ) ||
stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
ACCESS_SET_PRIVATE_ID_STATE, 0x12, VLC_TRUE ); ACCESS_SET_PRIVATE_ID_STATE, 0x12, VLC_TRUE ) )
p_sys->b_dvb_control = VLC_FALSE;
} }
} }
#endif #endif
...@@ -654,7 +665,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -654,7 +665,7 @@ static int Open( vlc_object_t *p_this )
if( i_port <= 0 ) i_port = 1234; if( i_port <= 0 ) i_port = 1234;
msg_Dbg( p_demux, "resend ts to '%s:%d'", val.psz_string, i_port ); msg_Dbg( p_demux, "resend ts to '%s:%d'", val.psz_string, i_port );
p_sys->fd = net_ConnectUDP( p_demux, val.psz_string, i_port, 0 ); p_sys->fd = net_ConnectUDP( VLC_OBJECT(p_demux), val.psz_string, i_port, 0 );
if( p_sys->fd < 0 ) if( p_sys->fd < 0 )
{ {
msg_Err( p_demux, "failed to open udp socket, send disabled" ); msg_Err( p_demux, "failed to open udp socket, send disabled" );
...@@ -689,16 +700,26 @@ static int Open( vlc_object_t *p_this ) ...@@ -689,16 +700,26 @@ static int Open( vlc_object_t *p_this )
if( i_pid >= 2 && i_pid < 8192 ) if( i_pid >= 2 && i_pid < 8192 )
{ {
ts_pid_t *pmt = &p_sys->pid[i_pid]; ts_pid_t *pmt = &p_sys->pid[i_pid];
ts_prg_psi_t *prg;
msg_Dbg( p_demux, "extra pmt specified (pid=%d)", i_pid ); msg_Dbg( p_demux, "extra pmt specified (pid=%d)", i_pid );
PIDInit( pmt, VLC_TRUE, NULL ); PIDInit( pmt, VLC_TRUE, NULL );
pmt->psi->i_prg = 1;
pmt->psi->prg = malloc( sizeof(ts_prg_psi_t) ); /* Dummy PMT */
/* FIXME we should also ask for a number */ prg = malloc( sizeof( ts_prg_psi_t ) );
pmt->psi->prg[0]->handle = if( !prg )
dvbpsi_AttachPMT( 1, (dvbpsi_pmt_callback)PMTCallBack, {
p_demux ); msg_Err( p_demux, "out of memory" );
pmt->psi->prg[0]->i_number = 0; /* special one */ Close( VLC_OBJECT(p_demux) );
return VLC_ENOMEM;
}
memset( prg, 0, sizeof( ts_prg_psi_t ) );
prg->i_pid_pcr = -1;
prg->i_pid_pmt = -1;
prg->i_number = 0; /* special */
prg->handle = dvbpsi_AttachPMT( 1, (dvbpsi_pmt_callback)PMTCallBack, p_demux );
TAB_APPEND( pmt->psi->i_prg, pmt->psi->prg, prg );
psz = strchr( psz, '=' ) + 1; /* can't failed */ psz = strchr( psz, '=' ) + 1; /* can't failed */
while( psz && *psz ) while( psz && *psz )
...@@ -862,7 +883,9 @@ static void Close( vlc_object_t *p_this ) ...@@ -862,7 +883,9 @@ static void Close( vlc_object_t *p_this )
if( p_sys->b_dvb_control && pid->i_pid > 0 ) if( p_sys->b_dvb_control && pid->i_pid > 0 )
{ {
/* too much */ /* too much */
stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, ACCESS_SET_PRIVATE_ID_STATE, pid->i_pid, VLC_FALSE ); stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
ACCESS_SET_PRIVATE_ID_STATE, pid->i_pid,
VLC_FALSE );
} }
} }
...@@ -889,8 +912,8 @@ static void Close( vlc_object_t *p_this ) ...@@ -889,8 +912,8 @@ static void Close( vlc_object_t *p_this )
/* If in dump mode, then close the file */ /* If in dump mode, then close the file */
if( p_sys->b_file_out ) if( p_sys->b_file_out )
{ {
msg_Info( p_demux ,"closing %s ("I64Fd" Kbytes dumped)", p_sys->psz_file, msg_Info( p_demux ,"closing %s ("I64Fd" Kbytes dumped)",
p_sys->i_write / 1024 ); p_sys->psz_file, p_sys->i_write / 1024 );
if( p_sys->p_file != stdout ) if( p_sys->p_file != stdout )
{ {
...@@ -1152,6 +1175,32 @@ static int Demux( demux_t *p_demux ) ...@@ -1152,6 +1175,32 @@ static int Demux( demux_t *p_demux )
/***************************************************************************** /*****************************************************************************
* Control: * Control:
*****************************************************************************/ *****************************************************************************/
static int DVBEventInformation( demux_t *p_demux, int64_t *pi_time, int64_t *pi_length )
{
demux_sys_t *p_sys = p_demux->p_sys;
if( pi_length )
*pi_length = 0;
if( pi_time )
*pi_time = 0;
#ifdef HAVE_TIME_H
if( p_sys->b_dvb_control && 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 );
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 * I64C(1000000);
if( pi_time )
*pi_time = (t - p_sys->i_dvb_start) * I64C(1000000);
return VLC_SUCCESS;
}
}
#endif
return VLC_EGENERIC;
}
static int Control( demux_t *p_demux, int i_query, va_list args ) static int Control( demux_t *p_demux, int i_query, va_list args )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
...@@ -1174,7 +1223,11 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) ...@@ -1174,7 +1223,11 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
} }
else else
{ {
*pf = 0.0; int64_t i_time, i_length;
if( !DVBEventInformation( p_demux, &i_time, &i_length ) && i_length > 0 )
*pf = (double)i_time/(double)i_length;
else
*pf = 0.0;
} }
return VLC_SUCCESS; return VLC_SUCCESS;
case DEMUX_SET_POSITION: case DEMUX_SET_POSITION:
...@@ -1211,9 +1264,15 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) ...@@ -1211,9 +1264,15 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return VLC_EGENERIC; return VLC_EGENERIC;
#else #else
case DEMUX_GET_TIME: case DEMUX_GET_TIME:
pi64 = (int64_t*)va_arg( args, int64_t * );
if( DVBEventInformation( p_demux, pi64, NULL ) )
*pi64 = 0;
return VLC_SUCCESS;
case DEMUX_GET_LENGTH: case DEMUX_GET_LENGTH:
pi64 = (int64_t*)va_arg( args, int64_t * ); pi64 = (int64_t*)va_arg( args, int64_t * );
*pi64 = 0; if( DVBEventInformation( p_demux, NULL, pi64 ) )
*pi64 = 0;
return VLC_SUCCESS; return VLC_SUCCESS;
#endif #endif
case DEMUX_SET_GROUP: case DEMUX_SET_GROUP:
...@@ -1358,8 +1417,7 @@ static void PIDInit( ts_pid_t *pid, vlc_bool_t b_psi, ts_psi_t *p_owner ) ...@@ -1358,8 +1417,7 @@ static void PIDInit( ts_pid_t *pid, vlc_bool_t b_psi, ts_psi_t *p_owner )
pid->p_owner = p_owner; pid->p_owner = p_owner;
pid->i_owner_number = 0; pid->i_owner_number = 0;
pid->extra_es = NULL; TAB_INIT( pid->i_extra_es, pid->extra_es );
pid->i_extra_es = 0;
if( b_psi ) if( b_psi )
{ {
...@@ -1367,40 +1425,49 @@ static void PIDInit( ts_pid_t *pid, vlc_bool_t b_psi, ts_psi_t *p_owner ) ...@@ -1367,40 +1425,49 @@ static void PIDInit( ts_pid_t *pid, vlc_bool_t b_psi, ts_psi_t *p_owner )
if( !b_old_valid ) if( !b_old_valid )
{ {
free( pid->psi );
pid->psi = malloc( sizeof( ts_psi_t ) ); pid->psi = malloc( sizeof( ts_psi_t ) );
pid->psi->handle= NULL; if( pid->psi )
pid->psi->i_prg = 0; {
pid->psi->prg = NULL; pid->psi->handle= NULL;
pid->psi->i_prg = 0;
pid->psi->prg = NULL;
}
} }
pid->psi->i_pat_version = -1; pid->psi->i_pat_version = -1;
pid->psi->i_sdt_version = -1; pid->psi->i_sdt_version = -1;
if( p_owner ) if( p_owner )
{ {
ts_prg_psi_t *prg = malloc( sizeof( ts_prg_psi_t ) ); ts_prg_psi_t *prg = malloc( sizeof( ts_prg_psi_t ) );
/* PMT */ if( prg )
prg->i_version = -1; {
prg->i_number = -1; /* PMT */
prg->i_pid_pcr = -1; prg->i_version = -1;
prg->i_pid_pmt = -1; prg->i_number = -1;
prg->iod = NULL; prg->i_pid_pcr = -1;
prg->handle = NULL; prg->i_pid_pmt = -1;
prg->iod = NULL;
TAB_APPEND( pid->psi->i_prg, pid->psi->prg, prg ); prg->handle = NULL;
TAB_APPEND( pid->psi->i_prg, pid->psi->prg, prg );
}
} }
} }
else else
{ {
pid->psi = NULL; pid->psi = NULL;
pid->es = malloc( sizeof( ts_es_t ) ); pid->es = malloc( sizeof( ts_es_t ) );
if( pid->es )
es_format_Init( &pid->es->fmt, UNKNOWN_ES, 0 ); {
pid->es->id = NULL; es_format_Init( &pid->es->fmt, UNKNOWN_ES, 0 );
pid->es->p_pes = NULL; pid->es->id = NULL;
pid->es->i_pes_size= 0; pid->es->p_pes = NULL;
pid->es->i_pes_gathered= 0; pid->es->i_pes_size= 0;
pid->es->pp_last = &pid->es->p_pes; pid->es->i_pes_gathered= 0;
pid->es->p_mpeg4desc = NULL; pid->es->pp_last = &pid->es->p_pes;
pid->es->b_gather = VLC_FALSE; pid->es->p_mpeg4desc = NULL;
pid->es->b_gather = VLC_FALSE;
}
} }
} }
...@@ -1461,8 +1528,8 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) ...@@ -1461,8 +1528,8 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid )
{ {
block_t *p_pes = pid->es->p_pes; block_t *p_pes = pid->es->p_pes;
uint8_t header[30]; uint8_t header[30];
int i_pes_size = 0; uint32_t i_pes_size = 0;
int i_skip = 0; uint32_t i_skip = 0;
mtime_t i_dts = -1; mtime_t i_dts = -1;
mtime_t i_pts = -1; mtime_t i_pts = -1;
mtime_t i_length = 0; mtime_t i_length = 0;
...@@ -1593,14 +1660,14 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) ...@@ -1593,14 +1660,14 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid )
( dcd->p_decoder_specific_info[1]&0x10 ) ) ( dcd->p_decoder_specific_info[1]&0x10 ) )
{ {
/* display length */ /* display length */
if( p_pes->i_buffer + 2 <= i_skip ) if( (uint32_t)(p_pes->i_buffer + 2) <= i_skip )
{ {
i_length = GetWBE( &p_pes->p_buffer[i_skip] ); i_length = GetWBE( &p_pes->p_buffer[i_skip] );
} }
i_skip += 2; i_skip += 2;
} }
if( p_pes->i_buffer + 2 <= i_skip ) if( (uint32_t)(p_pes->i_buffer + 2) <= i_skip )
{ {
i_pes_size = GetWBE( &p_pes->p_buffer[i_skip] ); i_pes_size = GetWBE( &p_pes->p_buffer[i_skip] );
} }
...@@ -1611,7 +1678,7 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) ...@@ -1611,7 +1678,7 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid )
/* skip header */ /* skip header */
while( p_pes && i_skip > 0 ) while( p_pes && i_skip > 0 )
{ {
if( p_pes->i_buffer <= i_skip ) if( (uint32_t)p_pes->i_buffer <= i_skip )
{ {
block_t *p_next = p_pes->p_next; block_t *p_next = p_pes->p_next;
...@@ -1649,7 +1716,7 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) ...@@ -1649,7 +1716,7 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid )
p_block = block_ChainGather( p_pes ); 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_FOURCC( 's', 'u', 'b', 't' ) )
{ {
if( i_pes_size > 0 && p_block->i_buffer > i_pes_size ) if( (i_pes_size > 0) && ((uint32_t)p_block->i_buffer > (uint32_t)i_pes_size) )
{ {
p_block->i_buffer = i_pes_size; p_block->i_buffer = i_pes_size;
} }
...@@ -1714,7 +1781,7 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) ...@@ -1714,7 +1781,7 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
const vlc_bool_t b_adaptation = p[3]&0x20; const vlc_bool_t b_adaptation = p[3]&0x20;
const vlc_bool_t b_payload = p[3]&0x10; const vlc_bool_t b_payload = p[3]&0x10;
const int i_cc = p[3]&0x0f; /* continuity counter */ const int i_cc = p[3]&0x0f; /* continuity counter */
vlc_bool_t b_discontinuity = VLC_FALSE;/* discontinuity */ vlc_bool_t b_discontinuity = VLC_FALSE;/* discontinuity */
/* transport_scrambling_control is ignored */ /* transport_scrambling_control is ignored */
int i_skip = 0; int i_skip = 0;
...@@ -1927,6 +1994,7 @@ static int PIDFillFormat( ts_pid_t *pid, int i_stream_type ) ...@@ -1927,6 +1994,7 @@ static int PIDFillFormat( ts_pid_t *pid, int i_stream_type )
case 0x06: /* PES_PRIVATE (fixed later) */ case 0x06: /* PES_PRIVATE (fixed later) */
case 0x12: /* MPEG-4 generic (sub/scene/...) (fixed later) */ case 0x12: /* MPEG-4 generic (sub/scene/...) (fixed later) */
case 0xEA: /* Privately managed ES (VC-1) (fixed later */
default: default:
es_format_Init( fmt, UNKNOWN_ES, 0 ); es_format_Init( fmt, UNKNOWN_ES, 0 );
break; break;
...@@ -1956,6 +2024,7 @@ static int IODDescriptorLength( int *pi_data, uint8_t **pp_data ) ...@@ -1956,6 +2024,7 @@ static int IODDescriptorLength( int *pi_data, uint8_t **pp_data )
return( i_len ); return( i_len );
} }
static int IODGetByte( int *pi_data, uint8_t **pp_data ) static int IODGetByte( int *pi_data, uint8_t **pp_data )
{ {
if( *pi_data > 0 ) if( *pi_data > 0 )
...@@ -1967,12 +2036,14 @@ static int IODGetByte( int *pi_data, uint8_t **pp_data ) ...@@ -1967,12 +2036,14 @@ static int IODGetByte( int *pi_data, uint8_t **pp_data )
} }
return( 0 ); return( 0 );
} }
static int IODGetWord( int *pi_data, uint8_t **pp_data ) static int IODGetWord( int *pi_data, uint8_t **pp_data )
{ {
const int i1 = IODGetByte( pi_data, pp_data ); const int i1 = IODGetByte( pi_data, pp_data );
const int i2 = IODGetByte( pi_data, pp_data ); const int i2 = IODGetByte( pi_data, pp_data );
return( ( i1 << 8 ) | i2 ); return( ( i1 << 8 ) | i2 );
} }
static int IODGet3Bytes( int *pi_data, uint8_t **pp_data ) static int IODGet3Bytes( int *pi_data, uint8_t **pp_data )
{ {
const int i1 = IODGetByte( pi_data, pp_data ); const int i1 = IODGetByte( pi_data, pp_data );
...@@ -1996,6 +2067,7 @@ static char* IODGetURL( int *pi_data, uint8_t **pp_data ) ...@@ -1996,6 +2067,7 @@ static char* IODGetURL( int *pi_data, uint8_t **pp_data )
i_url_len = IODGetByte( pi_data, pp_data ); i_url_len = IODGetByte( pi_data, pp_data );
url = malloc( i_url_len + 1 ); url = malloc( i_url_len + 1 );
if( !url ) return NULL;
for( i = 0; i < i_url_len; i++ ) for( i = 0; i < i_url_len; i++ )
{ {
url[i] = IODGetByte( pi_data, pp_data ); url[i] = IODGetByte( pi_data, pp_data );
...@@ -2014,6 +2086,7 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data ) ...@@ -2014,6 +2086,7 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
int i_iod_length; int i_iod_length;
p_iod = malloc( sizeof( iod_descriptor_t ) ); p_iod = malloc( sizeof( iod_descriptor_t ) );
if( !p_iod ) return NULL;
memset( p_iod, 0, sizeof( iod_descriptor_t ) ); memset( p_iod, 0, sizeof( iod_descriptor_t ) );
#ifdef TS_DEBUG #ifdef TS_DEBUG
...@@ -2389,7 +2462,7 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) ...@@ -2389,7 +2462,7 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt )
for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next ) for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
{ {
vlc_meta_t *p_meta = vlc_meta_New(); vlc_meta_t *p_meta;
dvbpsi_descriptor_t *p_dr; dvbpsi_descriptor_t *p_dr;
msg_Dbg( p_demux, " * service id=%d eit schedule=%d present=%d " msg_Dbg( p_demux, " * service id=%d eit schedule=%d present=%d "
...@@ -2398,11 +2471,15 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) ...@@ -2398,11 +2471,15 @@ 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_eit_present, p_srv->i_running_status,
p_srv->b_free_ca ); p_srv->b_free_ca );
if( p_sys->i_dvb_program != -1 && p_sys->i_dvb_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 ) for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
{ {
if( p_dr->i_tag == 0x48 ) if( p_dr->i_tag == 0x48 )
{ {
static const char *psz_type[0x11] = { static const char *ppsz_type[17] = {
"Reserved", "Reserved",
"Digital television service", "Digital television service",
"Digital radio sound service", "Digital radio sound service",
...@@ -2432,12 +2509,12 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) ...@@ -2432,12 +2509,12 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt )
str2[pD->i_service_name_length] = '\0'; str2[pD->i_service_name_length] = '\0';
msg_Dbg( p_demux, " - type=%d provider=%s name=%s", msg_Dbg( p_demux, " - type=%d provider=%s name=%s",
pD->i_service_type, str1, str2 ); pD->i_service_type, str1, str2 );
vlc_meta_Add( p_meta, "Name", str2 ); vlc_meta_Add( p_meta, "Name", str2 );
vlc_meta_Add( p_meta, "Provider", str1 ); vlc_meta_Add( p_meta, "Provider", str1 );
if( pD->i_service_type >= 0x01 && pD->i_service_type <= 0x10 ) if( pD->i_service_type >= 0x01 && pD->i_service_type <= 0x10 )
vlc_meta_Add( p_meta, "Type", psz_type[pD->i_service_type] ); vlc_meta_Add( p_meta, "Type", ppsz_type[pD->i_service_type] );
} }
} }
...@@ -2452,7 +2529,6 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) ...@@ -2452,7 +2529,6 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt )
else else
vlc_meta_Add( p_meta, "Status", "Unknown" ); vlc_meta_Add( p_meta, "Status", "Unknown" );
es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META, es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META,
p_srv->i_service_id, p_meta ); p_srv->i_service_id, p_meta );
vlc_meta_Delete( p_meta ); vlc_meta_Delete( p_meta );
...@@ -2461,26 +2537,195 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) ...@@ -2461,26 +2537,195 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt )
sdt->psi->i_sdt_version = p_sdt->i_version; sdt->psi->i_sdt_version = p_sdt->i_version;
dvbpsi_DeleteSDT( p_sdt ); dvbpsi_DeleteSDT( p_sdt );
} }
#if 0
static void DecodeMjd( int i_mjd, int *p_y, int *p_m, int *p_d ) /* i_year: year - 1900 i_month: 0-11 i_mday: 1-31 i_hour: 0-23 i_minute: 0-59 i_second: 0-59 */
static int64_t vlc_timegm( int i_year, int i_month, int i_mday, int i_hour, int i_minute, int i_second )
{ {
int yp = (int)( ( (double)i_mjd - 15078.2)/365.25 ); static const int pn_day[12+1] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
int mp = (int)( ((double)i_mjd - 14956.1 - (int)(yp * 365.25)) / 30.6001 ); int64_t i_day;
int i;
if( i_year < 70 ||
i_month < 0 || i_month > 11 || i_mday < 1 || i_mday > 31 ||
i_hour < 0 || i_hour > 23 || i_minute < 0 || i_minute > 59 || i_second < 0 || i_second > 59 )
return -1;
/* Count the number of days */
i_day = 365 * (i_year-70) + pn_day[i_month] + i_mday - 1;
#define LEAP(y) ( ((y)%4) == 0 && (((y)%100) != 0 || ((y)%400) == 0) ? 1 : 0)
for( i = 70; i < i_year; i++ )
i_day += LEAP(1900+i);
if( i_month > 1 )
i_day += LEAP(1900+i_year);
#undef LEAP
/**/
return ((24*i_day + i_hour)*60 + i_minute)*60 + i_second;
}
static void EITDecodeMjd( int i_mjd, int *p_y, int *p_m, int *p_d )
{
const int yp = (int)( ( (double)i_mjd - 15078.2)/365.25 );
const int mp = (int)( ((double)i_mjd - 14956.1 - (int)(yp * 365.25)) / 30.6001 );
const int c = ( mp == 14 || mp == 15 ) ? 1 : 0;
*p_y = 1900 + yp + c*1;
*p_m = mp - 1 - c*12;
*p_d = i_mjd - 14956 - (int)(yp*365.25) - (int)(mp*30.6001); *p_d = i_mjd - 14956 - (int)(yp*365.25) - (int)(mp*30.6001);
}
#define CVT_FROM_BCD(v) ((((v) >> 4)&0xf)*10 + ((v)&0xf))
static int64_t EITConvertStartTime( uint64_t i_date )
{
const int i_mjd = i_date >> 24;
const int i_hour = CVT_FROM_BCD(i_date >> 16);
const int i_minute = CVT_FROM_BCD(i_date >> 8);
const int i_second = CVT_FROM_BCD(i_date );
int i_year;
int i_month;
int i_day;
/* if all 40 bits are 1, the start is unknown */
if( i_date == UINT64_C(0xffffffffff) )
return -1;
if( mp == 14 || mp == 15 ) EITDecodeMjd( i_mjd, &i_year, &i_month, &i_day );
{ return vlc_timegm( i_year - 1900, i_month - 1, i_day, i_hour, i_minute, i_second );
*p_y = yp + 1; }
*p_m = mp - 1 + 12; static int EITConvertDuration( uint32_t i_duration )
{
return CVT_FROM_BCD(i_duration >> 16) * 3600 +
CVT_FROM_BCD(i_duration >> 8 ) * 60 +
CVT_FROM_BCD(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 )
{
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 else
{ {
*p_y = yp; const char *psz_in = (const char *)&psz_instring[offset];
*p_m = mp - 1; 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';
} }
return psz_outstring;
} }
#endif
static void EITEventFixString( unsigned char *psz ) static void EITEventFixString( unsigned char *psz )
{ {
int i_len; int i_len;
...@@ -2491,14 +2736,16 @@ static void EITEventFixString( unsigned char *psz ) ...@@ -2491,14 +2736,16 @@ static void EITEventFixString( unsigned char *psz )
if( ( i_len = strlen( (char *) psz ) ) > 0 ) if( ( i_len = strlen( (char *) psz ) ) > 0 )
memmove( &psz[0], &psz[1], i_len ); /* Copy the \0 too */ memmove( &psz[0], &psz[1], i_len ); /* Copy the \0 too */
} }
static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit )
{ {
dvbpsi_eit_event_t *p_evt; demux_sys_t *p_sys = p_demux->p_sys;
vlc_meta_t *p_meta; vlc_meta_t *p_meta;
vlc_bool_t b_event_active = VLC_FALSE; vlc_bool_t b_event_active = VLC_FALSE;
dvbpsi_eit_event_t *p_evt;
msg_Dbg( p_demux, "EITCallBack called" ); msg_Dbg( p_demux, "EITCallBack called" );
if( !p_eit->b_current_next ) if( !p_eit->b_current_next || ( p_sys->i_dvb_program != -1 && p_sys->i_dvb_program != p_eit->i_service_id ) )
{ {
dvbpsi_DeleteEIT( p_eit ); dvbpsi_DeleteEIT( p_eit );
return; return;
...@@ -2516,32 +2763,20 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) ...@@ -2516,32 +2763,20 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit )
{ {
dvbpsi_descriptor_t *p_dr; dvbpsi_descriptor_t *p_dr;
char *psz_cat = malloc( strlen("Event")+10 ); char *psz_cat = malloc( strlen("Event")+10 );
char psz_start[15]; char *psz_name = NULL;
char psz_duration[15]; char *psz_text = NULL;
char psz_name[256];
char psz_text[256];
char *psz_extra = strdup(""); char *psz_extra = strdup("");
char *psz_value; char *psz_value;
int64_t i_start;
int i_duration;
sprintf( psz_cat, "Event %d", p_evt->i_event_id ); sprintf( psz_cat, "Event %d", p_evt->i_event_id );
sprintf( psz_start, "%d%d:%d%d:%d%d", i_start = EITConvertStartTime( p_evt->i_start_time );
(int)(p_evt->i_start_time >> 20)&0xf, i_duration = EITConvertDuration( p_evt->i_duration );
(int)(p_evt->i_start_time >> 16)&0xf,
(int)(p_evt->i_start_time >> 12)&0xf, msg_Dbg( p_demux, " * event id=%d start_time:%d duration=%d "
(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", "running=%d free_ca=%d",
p_evt->i_event_id, p_evt->i_event_id, (int)i_start, (int)i_duration,
(int)(p_evt->i_start_time >> 24),
psz_start, psz_duration,
p_evt->i_running_status, p_evt->b_free_ca ); 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 ) for( p_dr = p_evt->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
...@@ -2552,13 +2787,8 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) ...@@ -2552,13 +2787,8 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit )
if( pE ) if( pE )
{ {
memcpy( psz_name, pE->i_event_name, pE->i_event_name_length); psz_name = EITConvertToUTF8( pE->i_event_name, pE->i_event_name_length);
psz_name[pE->i_event_name_length] = '\0'; psz_text = EITConvertToUTF8( pE->i_text, pE->i_text_length );
memcpy( psz_text, pE->i_text, pE->i_text_length );
psz_text[pE->i_text_length] = '\0';
EITEventFixString((unsigned char *)&psz_name);
EITEventFixString((unsigned char *)&psz_text);
msg_Dbg( p_demux, " - short event lang=%3.3s '%s' : '%s'", msg_Dbg( p_demux, " - short event lang=%3.3s '%s' : '%s'",
pE->i_iso_639_code, psz_name, psz_text ); pE->i_iso_639_code, psz_name, psz_text );
} }
...@@ -2574,6 +2804,7 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) ...@@ -2574,6 +2804,7 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit )
int i; int i;
msg_Dbg( p_demux, " - extended event lang=%3.3s", msg_Dbg( p_demux, " - extended event lang=%3.3s",
pE->i_iso_639_code ); pE->i_iso_639_code );
for( i = 0; i < pE->i_entry_count; i++ ) for( i = 0; i < pE->i_entry_count; i++ )
{ {
memcpy( str1, pE->i_item_description[i], memcpy( str1, pE->i_item_description[i],
...@@ -2613,10 +2844,10 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit ) ...@@ -2613,10 +2844,10 @@ static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit )
} }
} }
asprintf( &psz_value, "%s: %s (+%s) %s (%s)", asprintf( &psz_value, ""I64Fd": %s (+%d) %s (%s)",
psz_start, i_start,
psz_name, psz_name,
psz_duration, i_duration,
psz_text, psz_extra ); psz_text, psz_extra );
vlc_meta_Add( p_meta, psz_cat, psz_value ); vlc_meta_Add( p_meta, psz_cat, psz_value );
free( psz_value ); free( psz_value );
...@@ -2647,10 +2878,7 @@ static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h, ...@@ -2647,10 +2878,7 @@ static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h,
msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)", msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
i_table_id, i_table_id, i_extension, i_extension ); i_table_id, i_table_id, i_extension, i_extension );
#endif #endif
if( p_demux->p_sys->pid[0].psi->i_pat_version == -1 ) if( p_demux->p_sys->pid[0].psi->i_pat_version != -1 && i_table_id == 0x42 )
return;
if( i_table_id == 0x42 )
{ {
msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)", msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
i_table_id, i_table_id, i_extension, i_extension ); i_table_id, i_table_id, i_extension, i_extension );
...@@ -2658,8 +2886,9 @@ static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h, ...@@ -2658,8 +2886,9 @@ static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h,
dvbpsi_AttachSDT( h, i_table_id, i_extension, dvbpsi_AttachSDT( h, i_table_id, i_extension,
(dvbpsi_sdt_callback)SDTCallBack, p_demux ); (dvbpsi_sdt_callback)SDTCallBack, p_demux );
} }
else if( i_table_id == 0x4e || /* Current/Following */ else if( p_demux->p_sys->pid[0x11].psi->i_sdt_version != -1 &&
( i_table_id >= 0x50 && i_table_id <= 0x5f ) ) /* Schedule */ ( 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)", msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
i_table_id, i_table_id, i_extension, i_extension ); i_table_id, i_table_id, i_extension, i_extension );
...@@ -2917,9 +3146,10 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -2917,9 +3146,10 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
if( pid->es->fmt.i_extra > 0 ) if( pid->es->fmt.i_extra > 0 )
{ {
pid->es->fmt.p_extra = malloc( pid->es->fmt.i_extra ); pid->es->fmt.p_extra = malloc( pid->es->fmt.i_extra );
memcpy( pid->es->fmt.p_extra, if( pid->es->fmt.p_extra )
dcd->p_decoder_specific_info, memcpy( pid->es->fmt.p_extra,
pid->es->fmt.i_extra ); dcd->p_decoder_specific_info,
pid->es->fmt.i_extra );
} }
} }
} }
...@@ -3004,18 +3234,23 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3004,18 +3234,23 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
msg_Dbg( p_demux, " * Stream Component Identifier: %d", si->i_component_tag ); msg_Dbg( p_demux, " * Stream Component Identifier: %d", si->i_component_tag );
} }
#endif #endif
else if( p_dr->i_tag == 0x56 ) else if( (p_dr->i_tag == 0x56) || (p_dr->i_tag == 0x46) )
{ {
msg_Dbg( p_demux, " * EBU Teletext descriptor" ); if( p_dr->i_tag == 0x46 )
msg_Dbg( p_demux, " * VBI Teletext descriptor" );
else
msg_Dbg( p_demux, " * EBU Teletext descriptor" );
pid->es->fmt.i_cat = SPU_ES; pid->es->fmt.i_cat = SPU_ES;
pid->es->fmt.i_codec = VLC_FOURCC( 't', 'e', 'l', 'x' ); pid->es->fmt.i_codec = VLC_FOURCC( 't', 'e', 'l', 'x' );
pid->es->fmt.i_extra = p_dr->i_length; pid->es->fmt.i_extra = p_dr->i_length;
pid->es->fmt.p_extra = malloc( p_dr->i_length ); pid->es->fmt.p_extra = malloc( p_dr->i_length );
memcpy( pid->es->fmt.p_extra, p_dr->p_data, if( pid->es->fmt.p_extra )
p_dr->i_length ); memcpy( pid->es->fmt.p_extra, p_dr->p_data,
p_dr->i_length );
#if defined _DVBPSI_DR_56_H_ && defined DVBPSI_VERSION \ #if defined(_DVBPSI_DR_56_H_) && defined(DVBPSI_VERSION) \
&& DVBPSI_VERSION_INT > ((0<<16)+(1<<8)+5) && (DVBPSI_VERSION_INT > ((0<<16)+(1<<8)+5))
pid->es->fmt.i_group = p_pmt->i_program_number; pid->es->fmt.i_group = p_pmt->i_program_number;
/* In stream output mode, only enable descriptor /* In stream output mode, only enable descriptor
...@@ -3033,8 +3268,8 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3033,8 +3268,8 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
for( n = 0; n < sub->i_pages_number; n++ ) for( n = 0; n < sub->i_pages_number; n++ )
{ {
dvbpsi_teletextpage_t *p_page = &sub->p_pages[n]; dvbpsi_teletextpage_t *p_page = &sub->p_pages[n];
if( p_page->i_teletext_type == 0x2 if( (p_page->i_teletext_type == 0x2)
|| p_page->i_teletext_type == 0x5 ) || (p_page->i_teletext_type == 0x5) )
{ {
ts_es_t *p_es; ts_es_t *p_es;
...@@ -3045,7 +3280,13 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3045,7 +3280,13 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
else else
{ {
p_es = malloc( sizeof( ts_es_t ) ); p_es = malloc( sizeof( ts_es_t ) );
p_es->fmt = pid->es->fmt; if( !p_es ) break;
es_format_Copy( &p_es->fmt, &pid->es->fmt );
free( p_es->fmt.psz_language );
free( p_es->fmt.psz_description );
p_es->fmt.psz_language = NULL;
p_es->fmt.psz_description = NULL;
p_es->id = NULL; p_es->id = NULL;
p_es->p_pes = NULL; p_es->p_pes = NULL;
p_es->i_pes_size = 0; p_es->i_pes_size = 0;
...@@ -3058,15 +3299,17 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3058,15 +3299,17 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
} }
p_es->fmt.psz_language = malloc( 4 ); p_es->fmt.psz_language = malloc( 4 );
memcpy( p_es->fmt.psz_language, if( p_es->fmt.psz_language )
p_page->i_iso6392_language_code, 3 ); {
p_es->fmt.psz_language[3] = 0; memcpy( p_es->fmt.psz_language,
p_page->i_iso6392_language_code, 3 );
p_es->fmt.psz_language[3] = 0;
}
switch( p_page->i_teletext_type ) switch( p_page->i_teletext_type )
{ {
case 0x2: case 0x2:
p_es->fmt.psz_description = p_es->fmt.psz_description =
strdup(_("subtitles")); strdup(_("Teletext subtitles"));
msg_Dbg( p_demux, msg_Dbg( p_demux,
" * sub lan=%s page=%d%x", " * sub lan=%s page=%d%x",
p_es->fmt.psz_language, p_es->fmt.psz_language,
...@@ -3076,7 +3319,7 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3076,7 +3319,7 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
case 0x5: case 0x5:
p_es->fmt.psz_description = p_es->fmt.psz_description =
strdup(_("hearing impaired")); strdup(_("Teletext hearing impaired subtitles"));
msg_Dbg( p_demux, msg_Dbg( p_demux,
" * hearing impaired lan=%s page=%d%x", " * hearing impaired lan=%s page=%d%x",
p_es->fmt.psz_language, p_es->fmt.psz_language,
...@@ -3114,8 +3357,9 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3114,8 +3357,9 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
pid->es->fmt.i_codec = VLC_FOURCC( 'd', 'v', 'b', 's' ); pid->es->fmt.i_codec = VLC_FOURCC( 'd', 'v', 'b', 's' );
pid->es->fmt.i_extra = p_dr->i_length; pid->es->fmt.i_extra = p_dr->i_length;
pid->es->fmt.p_extra = malloc( p_dr->i_length ); pid->es->fmt.p_extra = malloc( p_dr->i_length );
memcpy( pid->es->fmt.p_extra, p_dr->p_data, if( pid->es->fmt.p_extra )
p_dr->i_length ); memcpy( pid->es->fmt.p_extra, p_dr->p_data,
p_dr->i_length );
#ifdef _DVBPSI_DR_59_H_ #ifdef _DVBPSI_DR_59_H_
pid->es->fmt.i_group = p_pmt->i_program_number; pid->es->fmt.i_group = p_pmt->i_program_number;
...@@ -3142,7 +3386,11 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3142,7 +3386,11 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
else else
{ {
p_es = malloc( sizeof( ts_es_t ) ); p_es = malloc( sizeof( ts_es_t ) );
p_es->fmt = pid->es->fmt; if( !p_es ) break;
es_format_Copy( &p_es->fmt, &pid->es->fmt );
free( p_es->fmt.psz_language ); p_es->fmt.psz_language = NULL;
free( p_es->fmt.psz_description ); p_es->fmt.psz_description = NULL;
p_es->id = NULL; p_es->id = NULL;
p_es->p_pes = NULL; p_es->p_pes = NULL;
p_es->i_pes_size = 0; p_es->i_pes_size = 0;
...@@ -3155,9 +3403,12 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3155,9 +3403,12 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
} }
p_es->fmt.psz_language = malloc( 4 ); p_es->fmt.psz_language = malloc( 4 );
memcpy( p_es->fmt.psz_language, if( p_es->fmt.psz_language )
p_sub->i_iso6392_language_code, 3 ); {
p_es->fmt.psz_language[3] = 0; memcpy( p_es->fmt.psz_language,
p_sub->i_iso6392_language_code, 3 );
p_es->fmt.psz_language[3] = 0;
}
switch( p_sub->i_subtitling_type ) switch( p_sub->i_subtitling_type )
{ {
...@@ -3218,6 +3469,46 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3218,6 +3469,46 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
} }
} }
} }
else if( p_es->i_type == 0xEA )
{
dvbpsi_descriptor_t *p_dr;
for( p_dr = p_es->p_first_descriptor; p_dr != NULL;
p_dr = p_dr->p_next )
{
msg_Dbg( p_demux, " * es pid=%d type=%d dr->i_tag=0x%x",
p_es->i_pid, p_es->i_type, p_dr->i_tag );
if( p_dr->i_tag == 0x05 )
{
/* Registration Descriptor */
if( p_dr->i_length < 4 ) // XXX VC-1 has extended this descriptor with sub-descriptor
{
msg_Warn( p_demux, "invalid Registration Descriptor" );
}
else
{
if( !memcmp( p_dr->p_data, "VC-1", 4 ) )
{
/* registration descriptor for VC-1 (SMPTE rp227) */
pid->es->fmt.i_cat = VIDEO_ES;
pid->es->fmt.i_codec = VLC_FOURCC('W','V','C','1');
/* XXX With Simple and Main profile the SEQUENCE
* header is modified: video width and height are
* inserted just after the start code as 2 int16_t
* The packetizer will take care of that. */
}
else
{
msg_Warn( p_demux,
"unknown Registration Descriptor (%4.4s)",
p_dr->p_data );
}
}
}
}
}
else if( p_es->i_type == 0xa0 ) else if( p_es->i_type == 0xa0 )
{ {
/* MSCODEC sent by vlc */ /* MSCODEC sent by vlc */
...@@ -3235,14 +3526,15 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3235,14 +3526,15 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
( p_dr->p_data[4] << 8 ) | p_dr->p_data[5]; ( p_dr->p_data[4] << 8 ) | p_dr->p_data[5];
pid->es->fmt.video.i_height = pid->es->fmt.video.i_height =
( p_dr->p_data[6] << 8 ) | p_dr->p_data[7]; ( p_dr->p_data[6] << 8 ) | p_dr->p_data[7];
pid->es->fmt.i_extra = pid->es->fmt.i_extra =
(p_dr->p_data[8] << 8) | p_dr->p_data[9]; (p_dr->p_data[8] << 8) | p_dr->p_data[9];
if( pid->es->fmt.i_extra > 0 ) if( pid->es->fmt.i_extra > 0 )
{ {
pid->es->fmt.p_extra = malloc( pid->es->fmt.i_extra ); pid->es->fmt.p_extra = malloc( pid->es->fmt.i_extra );
memcpy( pid->es->fmt.p_extra, &p_dr->p_data[10], if( pid->es->fmt.p_extra )
pid->es->fmt.i_extra ); memcpy( pid->es->fmt.p_extra, &p_dr->p_data[10],
pid->es->fmt.i_extra );
} }
} }
else else
...@@ -3273,10 +3565,13 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3273,10 +3565,13 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
{ {
#if defined(DR_0A_API_VER) && (DR_0A_API_VER >= 2) #if defined(DR_0A_API_VER) && (DR_0A_API_VER >= 2)
pid->es->fmt.psz_language = malloc( 4 ); pid->es->fmt.psz_language = malloc( 4 );
memcpy( pid->es->fmt.psz_language, if( pid->es->fmt.psz_language )
p_decoded->code[0].iso_639_code, 3 ); {
pid->es->fmt.psz_language[3] = 0; memcpy( pid->es->fmt.psz_language,
msg_Dbg( p_demux, "found language: %s", pid->es->fmt.psz_language); p_decoded->code[0].iso_639_code, 3 );
pid->es->fmt.psz_language[3] = 0;
msg_Dbg( p_demux, "found language: %s", pid->es->fmt.psz_language);
}
switch( p_decoded->code[0].i_audio_type ) { switch( p_decoded->code[0].i_audio_type ) {
case 0: case 0:
pid->es->fmt.psz_description = NULL; pid->es->fmt.psz_description = NULL;
...@@ -3304,43 +3599,53 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt ) ...@@ -3304,43 +3599,53 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
pid->es->fmt.p_extra_languages = pid->es->fmt.p_extra_languages =
malloc( sizeof(*pid->es->fmt.p_extra_languages) * malloc( sizeof(*pid->es->fmt.p_extra_languages) *
pid->es->fmt.i_extra_languages ); pid->es->fmt.i_extra_languages );
for( i = 0; i < pid->es->fmt.i_extra_languages; i++ ) { if( pid->es->fmt.p_extra_languages )
msg_Dbg( p_demux, "bang" ); {
pid->es->fmt.p_extra_languages[i].psz_language = for( i = 0; i < pid->es->fmt.i_extra_languages; i++ )
malloc(4); {
memcpy(pid->es->fmt.p_extra_languages[i].psz_language, msg_Dbg( p_demux, "bang" );
p_decoded->code[i+1].iso_639_code, 3 ); pid->es->fmt.p_extra_languages[i].psz_language =
pid->es->fmt.p_extra_languages[i].psz_language[3] = '\0'; malloc(4);
switch( p_decoded->code[i].i_audio_type ) { if( pid->es->fmt.p_extra_languages[i].psz_language )
case 0: {
pid->es->fmt.p_extra_languages[i].psz_description = memcpy( pid->es->fmt.p_extra_languages[i].psz_language,
NULL; p_decoded->code[i+1].iso_639_code, 3 );
break; pid->es->fmt.p_extra_languages[i].psz_language[3] = '\0';
case 1: }
pid->es->fmt.p_extra_languages[i].psz_description = switch( p_decoded->code[i].i_audio_type ) {
strdup(_("clean effects")); case 0:
break; pid->es->fmt.p_extra_languages[i].psz_description =
case 2: NULL;
pid->es->fmt.p_extra_languages[i].psz_description = break;
strdup(_("hearing impaired")); case 1:
break; pid->es->fmt.p_extra_languages[i].psz_description =
case 3: strdup(_("clean effects"));
pid->es->fmt.p_extra_languages[i].psz_description = break;
strdup(_("visual impaired commentary")); case 2:
break; pid->es->fmt.p_extra_languages[i].psz_description =
default: strdup(_("hearing impaired"));
msg_Dbg( p_demux, "unknown audio type: %d", break;
p_decoded->code[i].i_audio_type); case 3:
pid->es->fmt.psz_description = NULL; pid->es->fmt.p_extra_languages[i].psz_description =
break; strdup(_("visual impaired commentary"));
} break;
default:
msg_Dbg( p_demux, "unknown audio type: %d",
p_decoded->code[i].i_audio_type);
pid->es->fmt.psz_description = NULL;
break;
}
}
} }
#else #else
pid->es->fmt.psz_language = malloc( 4 ); pid->es->fmt.psz_language = malloc( 4 );
memcpy( pid->es->fmt.psz_language, if( pid->es->fmt.psz_language )
p_decoded->i_iso_639_code, 3 ); {
pid->es->fmt.psz_language[3] = 0; memcpy( pid->es->fmt.psz_language,
p_decoded->i_iso_639_code, 3 );
pid->es->fmt.psz_language[3] = 0;
}
#endif #endif
} }
} }
...@@ -3629,4 +3934,3 @@ static void PATCallBack( demux_t *p_demux, dvbpsi_pat_t *p_pat ) ...@@ -3629,4 +3934,3 @@ static void PATCallBack( demux_t *p_demux, dvbpsi_pat_t *p_pat )
dvbpsi_DeletePAT( p_pat ); dvbpsi_DeletePAT( p_pat );
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment