[vlc-commits] Added support for SCTE-27 in TS demuxer.
Laurent Aimar
git at videolan.org
Wed Dec 12 21:44:12 CET 2012
vlc | branch: master | Laurent Aimar <fenrir at videolan.org> | Thu Dec 6 22:36:52 2012 +0100| [7e3dcdd09c2fac64f00acb360d30f24c74894609] | committer: Laurent Aimar
Added support for SCTE-27 in TS demuxer.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7e3dcdd09c2fac64f00acb360d30f24c74894609
---
modules/demux/ts.c | 140 ++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 120 insertions(+), 20 deletions(-)
diff --git a/modules/demux/ts.c b/modules/demux/ts.c
index 109ea90..87b8a00 100644
--- a/modules/demux/ts.c
+++ b/modules/demux/ts.c
@@ -235,10 +235,17 @@ typedef struct
} ts_psi_t;
+typedef enum
+{
+ TS_ES_DATA_PES,
+ TS_ES_DATA_TABLE_SECTION
+} ts_es_data_type_t;
+
typedef struct
{
es_format_t fmt;
es_out_id_t *id;
+ ts_es_data_type_t data_type;
int i_data_size;
int i_data_gathered;
block_t *p_data;
@@ -347,7 +354,7 @@ static inline int PIDGet( block_t *p )
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 mtime_t GetPCR( block_t *p_pkt );
@@ -865,7 +872,7 @@ static int Demux( demux_t *p_demux )
}
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
{
@@ -1327,6 +1334,7 @@ static void PIDInit( ts_pid_t *pid, bool b_psi, ts_psi_t *p_owner )
return;
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;
}
}
@@ -1391,9 +1399,8 @@ static void PIDClean( demux_t *p_demux, ts_pid_t *pid )
/****************************************************************************
* 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];
unsigned i_pes_size = 0;
unsigned i_skip = 0;
@@ -1401,12 +1408,6 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid )
mtime_t i_pts = -1;
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 */
/* 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 )
}
}
+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 )
{
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 )
}
}
-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 bool b_unit_start = p[1]&0x40;
@@ -2093,26 +2166,49 @@ static bool GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
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 )
{
- ParsePES( p_demux, pid );
+ ParseData( p_demux, pid );
i_ret = true;
}
block_ChainLastAppend( &pid->es->pp_last, p_bk );
- if( p_bk->i_buffer > 6 )
+ if( pid->es->data_type == TS_ES_DATA_PES )
{
- pid->es->i_data_size = GetWBE( &p_bk->p_buffer[4] );
- if( pid->es->i_data_size > 0 )
+ if( p_bk->i_buffer > 6 )
{
- pid->es->i_data_size += 6;
+ pid->es->i_data_size = GetWBE( &p_bk->p_buffer[4] );
+ if( pid->es->i_data_size > 0 )
+ {
+ 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;
if( pid->es->i_data_size > 0 &&
pid->es->i_data_gathered >= pid->es->i_data_size )
{
- ParsePES( p_demux, pid );
+ ParseData( p_demux, pid );
i_ret = true;
}
}
@@ -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 );
pid->es->i_data_gathered += p_bk->i_buffer;
+
if( pid->es->i_data_size > 0 &&
pid->es->i_data_gathered >= pid->es->i_data_size )
{
- ParsePES( p_demux, pid );
+ ParseData( p_demux, pid );
i_ret = true;
}
}
@@ -2171,8 +2268,9 @@ static void PIDFillFormat( ts_es_t *es, int i_stream_type )
case 0x81: /* A52 (audio) */
es_format_Init( fmt, AUDIO_ES, VLC_CODEC_A52 );
break;
- case 0x82: /* DVD_SPU (sub) */
- es_format_Init( fmt, SPU_ES, VLC_CODEC_SPU );
+ case 0x82: /* SCTE-27 (sub) */
+ es_format_Init( fmt, SPU_ES, VLC_CODEC_SCTE_27 );
+ es->data_type = TS_ES_DATA_TABLE_SECTION;
break;
case 0x83: /* LPCM (audio) */
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,
p_es->i_data_size = 0;
p_es->i_data_gathered = 0;
p_es->pp_last = &p_es->p_data;
+ p_es->data_type = TS_ES_DATA_PES;
p_es->p_mpeg4desc = NULL;
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,
p_es->i_data_size = 0;
p_es->i_data_gathered = 0;
p_es->pp_last = &p_es->p_data;
+ p_es->data_type = TS_ES_DATA_PES;
p_es->p_mpeg4desc = NULL;
TAB_APPEND( pid->i_extra_es, pid->extra_es, p_es );
More information about the vlc-commits
mailing list