Commit 7e3dcdd0 authored by Laurent Aimar's avatar Laurent Aimar

Added support for SCTE-27 in TS demuxer.

parent 6ce3ecfc
...@@ -235,10 +235,17 @@ typedef struct ...@@ -235,10 +235,17 @@ typedef struct
} ts_psi_t; } ts_psi_t;
typedef enum
{
TS_ES_DATA_PES,
TS_ES_DATA_TABLE_SECTION
} ts_es_data_type_t;
typedef struct typedef struct
{ {
es_format_t fmt; es_format_t fmt;
es_out_id_t *id; es_out_id_t *id;
ts_es_data_type_t data_type;
int i_data_size; int i_data_size;
int i_data_gathered; int i_data_gathered;
block_t *p_data; block_t *p_data;
...@@ -347,7 +354,7 @@ static inline int PIDGet( block_t *p ) ...@@ -347,7 +354,7 @@ static inline int PIDGet( block_t *p )
return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2]; return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2];
} }
static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ); static bool GatherData( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk );
static block_t* ReadTSPacket( demux_t *p_demux ); static block_t* ReadTSPacket( demux_t *p_demux );
static mtime_t GetPCR( block_t *p_pkt ); static mtime_t GetPCR( block_t *p_pkt );
...@@ -865,7 +872,7 @@ static int Demux( demux_t *p_demux ) ...@@ -865,7 +872,7 @@ static int Demux( demux_t *p_demux )
} }
else if( !p_sys->b_udp_out ) else if( !p_sys->b_udp_out )
{ {
b_frame = GatherPES( p_demux, p_pid, p_pkt ); b_frame = GatherData( p_demux, p_pid, p_pkt );
} }
else else
{ {
...@@ -1327,6 +1334,7 @@ static void PIDInit( ts_pid_t *pid, bool b_psi, ts_psi_t *p_owner ) ...@@ -1327,6 +1334,7 @@ static void PIDInit( ts_pid_t *pid, bool b_psi, ts_psi_t *p_owner )
return; return;
es_format_Init( &pid->es->fmt, UNKNOWN_ES, 0 ); es_format_Init( &pid->es->fmt, UNKNOWN_ES, 0 );
pid->es->data_type = TS_ES_DATA_PES;
pid->es->pp_last = &pid->es->p_data; pid->es->pp_last = &pid->es->p_data;
} }
} }
...@@ -1391,9 +1399,8 @@ static void PIDClean( demux_t *p_demux, ts_pid_t *pid ) ...@@ -1391,9 +1399,8 @@ static void PIDClean( demux_t *p_demux, ts_pid_t *pid )
/**************************************************************************** /****************************************************************************
* gathering stuff * gathering stuff
****************************************************************************/ ****************************************************************************/
static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
{ {
block_t *p_pes = pid->es->p_data;
uint8_t header[34]; uint8_t header[34];
unsigned i_pes_size = 0; unsigned i_pes_size = 0;
unsigned i_skip = 0; unsigned i_skip = 0;
...@@ -1401,12 +1408,6 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) ...@@ -1401,12 +1408,6 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid )
mtime_t i_pts = -1; mtime_t i_pts = -1;
mtime_t i_length = 0; mtime_t i_length = 0;
/* remove the pes from pid */
pid->es->p_data = NULL;
pid->es->i_data_size= 0;
pid->es->i_data_gathered= 0;
pid->es->pp_last = &pid->es->p_data;
/* FIXME find real max size */ /* FIXME find real max size */
/* const int i_max = */ block_ChainExtract( p_pes, header, 34 ); /* const int i_max = */ block_ChainExtract( p_pes, header, 34 );
...@@ -1617,6 +1618,78 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid ) ...@@ -1617,6 +1618,78 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid )
} }
} }
static void ParseTableSection( demux_t *p_demux, ts_pid_t *pid, block_t *p_data )
{
block_t *p_content = block_ChainGather( p_data );
mtime_t i_date = -1;
for( int i = 0; pid->p_owner && i < pid->p_owner->i_prg; i++ )
{
if( pid->i_owner_number == pid->p_owner->prg[i]->i_number )
{
i_date = pid->p_owner->prg[i]->i_pcr_value;
if( i_date >= 0 )
break;
}
}
if( i_date >= 0 )
{
if( pid->es->fmt.i_codec == VLC_CODEC_SCTE_27 )
{
/* We need to extract the truncated pts stored inside the payload */
if( p_content->i_buffer > 9 && p_content->p_buffer[0] == 0xc6 )
{
int i_index = 0;
int i_offset = 4;
if( p_content->p_buffer[3] & 0x40 )
{
i_index = ((p_content->p_buffer[7] & 0x0f) << 8) |
p_content->p_buffer[8];
i_offset = 9;
}
if( i_index == 0 && p_content->i_buffer > i_offset + 8 )
{
bool is_immediate = p_content->p_buffer[i_offset + 3] & 0x40;
if( !is_immediate )
{
mtime_t i_display_in = GetDWBE( &p_content->p_buffer[i_offset + 4] );
if( i_display_in < i_date )
i_date = i_display_in + (1ll << 32);
else
i_date = i_display_in;
}
}
}
}
p_content->i_dts =
p_content->i_pts = VLC_TS_0 + i_date * 100 / 9;
}
es_out_Send( p_demux->out, pid->es->id, p_content );
}
static void ParseData( demux_t *p_demux, ts_pid_t *pid )
{
block_t *p_data = pid->es->p_data;
/* remove the pes from pid */
pid->es->p_data = NULL;
pid->es->i_data_size = 0;
pid->es->i_data_gathered = 0;
pid->es->pp_last = &pid->es->p_data;
if( pid->es->data_type == TS_ES_DATA_PES )
{
ParsePES( p_demux, pid, p_data );
}
else if( pid->es->data_type == TS_ES_DATA_TABLE_SECTION )
{
ParseTableSection( p_demux, pid, p_data );
}
else
{
block_ChainRelease( p_data );
}
}
static block_t* ReadTSPacket( demux_t *p_demux ) static block_t* ReadTSPacket( demux_t *p_demux )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
...@@ -1961,7 +2034,7 @@ static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) ...@@ -1961,7 +2034,7 @@ static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
} }
} }
static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) static bool GatherData( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
{ {
const uint8_t *p = p_bk->p_buffer; const uint8_t *p = p_bk->p_buffer;
const bool b_unit_start = p[1]&0x40; const bool b_unit_start = p[1]&0x40;
...@@ -2093,13 +2166,28 @@ static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) ...@@ -2093,13 +2166,28 @@ static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
if( b_unit_start ) if( b_unit_start )
{ {
if( pid->es->data_type == TS_ES_DATA_TABLE_SECTION && p_bk->i_buffer > 0 )
{
int i_pointer_field = __MIN( p_bk->p_buffer[0], p_bk->i_buffer - 1 );
block_t *p = block_Duplicate( p_bk );
if( p )
{
p->i_buffer = i_pointer_field;
p->p_buffer++;
block_ChainLastAppend( &pid->es->pp_last, p );
}
p_bk->i_buffer -= 1 + i_pointer_field;
p_bk->p_buffer += 1 + i_pointer_field;
}
if( pid->es->p_data ) if( pid->es->p_data )
{ {
ParsePES( p_demux, pid ); ParseData( p_demux, pid );
i_ret = true; i_ret = true;
} }
block_ChainLastAppend( &pid->es->pp_last, p_bk ); block_ChainLastAppend( &pid->es->pp_last, p_bk );
if( pid->es->data_type == TS_ES_DATA_PES )
{
if( p_bk->i_buffer > 6 ) if( p_bk->i_buffer > 6 )
{ {
pid->es->i_data_size = GetWBE( &p_bk->p_buffer[4] ); pid->es->i_data_size = GetWBE( &p_bk->p_buffer[4] );
...@@ -2108,11 +2196,19 @@ static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) ...@@ -2108,11 +2196,19 @@ static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
pid->es->i_data_size += 6; pid->es->i_data_size += 6;
} }
} }
}
else if( pid->es->data_type == TS_ES_DATA_TABLE_SECTION )
{
if( p_bk->i_buffer > 3 && p_bk->p_buffer[0] != 0xff )
{
pid->es->i_data_size = 3 + (((p_bk->p_buffer[1] & 0xf) << 8) | p_bk->p_buffer[2]);
}
}
pid->es->i_data_gathered += p_bk->i_buffer; pid->es->i_data_gathered += p_bk->i_buffer;
if( pid->es->i_data_size > 0 && if( pid->es->i_data_size > 0 &&
pid->es->i_data_gathered >= pid->es->i_data_size ) pid->es->i_data_gathered >= pid->es->i_data_size )
{ {
ParsePES( p_demux, pid ); ParseData( p_demux, pid );
i_ret = true; i_ret = true;
} }
} }
...@@ -2127,10 +2223,11 @@ static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) ...@@ -2127,10 +2223,11 @@ static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
{ {
block_ChainLastAppend( &pid->es->pp_last, p_bk ); block_ChainLastAppend( &pid->es->pp_last, p_bk );
pid->es->i_data_gathered += p_bk->i_buffer; pid->es->i_data_gathered += p_bk->i_buffer;
if( pid->es->i_data_size > 0 && if( pid->es->i_data_size > 0 &&
pid->es->i_data_gathered >= pid->es->i_data_size ) pid->es->i_data_gathered >= pid->es->i_data_size )
{ {
ParsePES( p_demux, pid ); ParseData( p_demux, pid );
i_ret = true; i_ret = true;
} }
} }
...@@ -2171,8 +2268,9 @@ static void PIDFillFormat( ts_es_t *es, int i_stream_type ) ...@@ -2171,8 +2268,9 @@ static void PIDFillFormat( ts_es_t *es, int i_stream_type )
case 0x81: /* A52 (audio) */ case 0x81: /* A52 (audio) */
es_format_Init( fmt, AUDIO_ES, VLC_CODEC_A52 ); es_format_Init( fmt, AUDIO_ES, VLC_CODEC_A52 );
break; break;
case 0x82: /* DVD_SPU (sub) */ case 0x82: /* SCTE-27 (sub) */
es_format_Init( fmt, SPU_ES, VLC_CODEC_SPU ); es_format_Init( fmt, SPU_ES, VLC_CODEC_SCTE_27 );
es->data_type = TS_ES_DATA_TABLE_SECTION;
break; break;
case 0x83: /* LPCM (audio) */ case 0x83: /* LPCM (audio) */
es_format_Init( fmt, AUDIO_ES, VLC_CODEC_DVD_LPCM ); es_format_Init( fmt, AUDIO_ES, VLC_CODEC_DVD_LPCM );
...@@ -3178,6 +3276,7 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid, ...@@ -3178,6 +3276,7 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid,
p_es->i_data_size = 0; p_es->i_data_size = 0;
p_es->i_data_gathered = 0; p_es->i_data_gathered = 0;
p_es->pp_last = &p_es->p_data; p_es->pp_last = &p_es->p_data;
p_es->data_type = TS_ES_DATA_PES;
p_es->p_mpeg4desc = NULL; p_es->p_mpeg4desc = NULL;
TAB_APPEND( pid->i_extra_es, pid->extra_es, p_es ); TAB_APPEND( pid->i_extra_es, pid->extra_es, p_es );
...@@ -3261,6 +3360,7 @@ static void PMTSetupEsDvbSubtitle( demux_t *p_demux, ts_pid_t *pid, ...@@ -3261,6 +3360,7 @@ static void PMTSetupEsDvbSubtitle( demux_t *p_demux, ts_pid_t *pid,
p_es->i_data_size = 0; p_es->i_data_size = 0;
p_es->i_data_gathered = 0; p_es->i_data_gathered = 0;
p_es->pp_last = &p_es->p_data; p_es->pp_last = &p_es->p_data;
p_es->data_type = TS_ES_DATA_PES;
p_es->p_mpeg4desc = NULL; p_es->p_mpeg4desc = NULL;
TAB_APPEND( pid->i_extra_es, pid->extra_es, p_es ); TAB_APPEND( pid->i_extra_es, pid->extra_es, p_es );
......
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