[vlc-commits] demux: ts: rework the corrupted/discontinuity/duplicate handling
Francois Cartegnie
git at videolan.org
Thu Dec 22 19:45:55 CET 2016
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Dec 21 18:13:27 2016 +0100| [05413606fabf70214e9fa19e8636dc755531b51c] | committer: Francois Cartegnie
demux: ts: rework the corrupted/discontinuity/duplicate handling
So we stop parsing known corrupted headers for timestamps
and drop duplicates for psi sections
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=05413606fabf70214e9fa19e8636dc755531b51c
---
modules/demux/mpeg/ts.c | 107 ++++++++++++++++++++++++++----------------------
1 file changed, 58 insertions(+), 49 deletions(-)
diff --git a/modules/demux/mpeg/ts.c b/modules/demux/mpeg/ts.c
index 4bcc00c..e4eefe4 100644
--- a/modules/demux/mpeg/ts.c
+++ b/modules/demux/mpeg/ts.c
@@ -174,8 +174,8 @@ static inline int PIDGet( block_t *p )
}
static mtime_t GetPCR( const block_t * );
-static bool ProcessTSPacket( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt );
-static bool GatherPESData( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk, size_t, bool );
+static block_t * ProcessTSPacket( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt, int * );
+static bool GatherPESData( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk, size_t );
static void ProgramSetPCR( demux_t *p_demux, ts_pmt_t *p_prg, mtime_t i_pcr );
static block_t* ReadTSPacket( demux_t *p_demux );
@@ -602,6 +602,7 @@ static int Demux( demux_t *p_demux )
for( unsigned i_pkt = 0; i_pkt < p_sys->i_ts_read; i_pkt++ )
{
bool b_frame = false;
+ int i_header = 0;
block_t *p_pkt;
if( !(p_pkt = ReadTSPacket( p_demux )) )
{
@@ -650,6 +651,11 @@ static int Demux( demux_t *p_demux )
p_sys->b_valid_scrambling = true;
}
+ /* Drop duplicates and invalid (DOES NOT drop corrupted) */
+ p_pkt = ProcessTSPacket( p_demux, p_pid, p_pkt, &i_header );
+ if( !p_pkt )
+ continue;
+
/* Adaptation field cannot be scrambled */
mtime_t i_pcr = GetPCR( p_pkt );
if( i_pcr > VLC_TS_INVALID )
@@ -696,7 +702,21 @@ static int Demux( demux_t *p_demux )
continue;
}
- b_frame = ProcessTSPacket( p_demux, p_pid, p_pkt );
+ if( p_pid->u.p_pes->transport == TS_TRANSPORT_PES )
+ {
+ b_frame = GatherPESData( p_demux, p_pid, p_pkt, i_header );
+ }
+ else if( p_pid->u.p_pes->transport == TS_TRANSPORT_SECTIONS &&
+ !(p_pkt->i_flags & BLOCK_FLAG_SCRAMBLED) )
+ {
+ ts_sections_processor_Push( p_pid->u.p_pes->p_sections_proc, p_pkt );
+ b_frame = true;
+ }
+ else // pid->u.p_pes->transport == TS_TRANSPORT_IGNORE
+ {
+ block_Release( p_pkt );
+ }
+
break;
case TYPE_SI:
@@ -2335,21 +2355,16 @@ static void PCRFixHandle( demux_t *p_demux, ts_pmt_t *p_pmt, block_t *p_block )
}
}
-static bool ProcessTSPacket( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt )
+static block_t * ProcessTSPacket( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt, int *pi_skip )
{
const uint8_t *p = p_pkt->p_buffer;
- const bool b_unit_start = p[1]&0x40;
const bool b_adaptation = p[3]&0x20;
const bool b_payload = p[3]&0x10;
const int i_cc = p[3]&0x0f; /* continuity counter */
bool b_discontinuity = false; /* discontinuity */
/* transport_scrambling_control is ignored */
- int i_skip = 0;
- bool b_ret = false;
-
- assert(pid->type == TYPE_PES);
- ts_pes_t *p_pes = pid->u.p_pes;
+ *pi_skip = 4;
#if 0
msg_Dbg( p_demux, "pid=%d unit_start=%d adaptation=%d payload=%d "
@@ -2375,21 +2390,23 @@ static bool ProcessTSPacket( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt )
}
}
- if( !b_adaptation )
- {
- /* We don't have any adaptation_field, so payload starts
- * immediately after the 4 byte TS header */
- i_skip = 4;
- }
- else
+ /* We don't have any adaptation_field, so payload starts
+ * immediately after the 4 byte TS header */
+ if( b_adaptation )
{
/* p[4] is adaptation_field_length minus one */
- i_skip = 5 + p[4];
- if( p[4] > 0 )
+ *pi_skip += 1 + p[4];
+ if( p[4] + 5 > 188 /* adaptation field only == 188 */ )
+ {
+ /* Broken is broken */
+ block_Release( p_pkt );
+ return NULL;
+ }
+ else if( p[4] > 0 )
{
/* discontinuity indicator found in stream */
b_discontinuity = (p[5]&0x80) ? true : false;
- if( b_discontinuity && p_pes->gather.p_data )
+ if( b_discontinuity )
{
msg_Warn( p_demux, "discontinuity indicator (pid=%d) ",
pid->i_pid );
@@ -2426,8 +2443,9 @@ static bool ProcessTSPacket( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt )
else if( i_diff == 0 && pid->i_dup == 0 && b_payload )
{
/* Discard duplicated payload 2.4.3.3 */
- i_skip = 188;
pid->i_dup++;
+ block_Release( p_pkt );
+ return NULL;
}
else if( i_diff != 0 && !b_discontinuity )
{
@@ -2436,39 +2454,17 @@ static bool ProcessTSPacket( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt )
pid->i_cc = i_cc;
pid->i_dup = 0;
- if( p_pes->gather.p_data &&
- p_pes->p_es->fmt.i_cat != VIDEO_ES &&
- p_pes->p_es->fmt.i_cat != AUDIO_ES )
- {
- /* Small audio/video artifacts are usually better than
- * dropping full frames */
- p_pes->gather.p_data->i_flags |= BLOCK_FLAG_CORRUPTED;
- }
+ p_pkt->i_flags |= BLOCK_FLAG_DISCONTINUITY;
}
}
- if( i_skip >= 188 ||
- unlikely(!(b_payload || b_adaptation)) ) /* Invalid */
+ if( unlikely(!(b_payload || b_adaptation)) ) /* Invalid, ignore */
{
block_Release( p_pkt );
- return b_ret;
+ return NULL;
}
- if( pid->u.p_pes->transport == TS_TRANSPORT_PES )
- {
- return GatherPESData( p_demux, pid, p_pkt, i_skip, b_unit_start );
- }
- else if( pid->u.p_pes->transport == TS_TRANSPORT_SECTIONS &&
- !(p_pkt->i_flags & BLOCK_FLAG_SCRAMBLED) )
- {
- ts_sections_processor_Push( pid->u.p_pes->p_sections_proc, p_pkt );
- return true;
- }
- else // pid->u.p_pes->transport == TS_TRANSPORT_IGNORE
- {
- block_Release( p_pkt );
- return true;
- }
+ return p_pkt;
}
/* Avoids largest memcpy */
@@ -2535,9 +2531,9 @@ static bool MayHaveStartCodeOnEnd( const uint8_t *p_buf, size_t i_buf )
return !( *(--p_buf) > 1 || *(--p_buf) > 0 || *(--p_buf) > 0 );
}
-static bool GatherPESData( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt,
- size_t i_skip, bool b_unit_start )
+static bool GatherPESData( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt, size_t i_skip )
{
+ const bool b_unit_start = p_pkt->p_buffer[1]&0x40;
bool b_ret = false;
ts_pes_t *p_pes = pid->u.p_pes;
@@ -2557,6 +2553,19 @@ static bool GatherPESData( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt,
}
+ /* Data discontinuity, we need to drop or output currently
+ * gathered data as it can't match the target size or can
+ * have dropped next sync code */
+ if( p_pkt->i_flags & BLOCK_FLAG_DISCONTINUITY )
+ {
+ p_pes->gather.i_saved = 0;
+ /* Propagate to output block to notify packetizers/decoders */
+ if( p_pes->gather.p_data )
+ p_pes->gather.p_data->i_flags |= BLOCK_FLAG_DISCONTINUITY;
+ /* Flush/output current */
+ b_ret |= PushPESBlock( p_demux, pid, NULL, true );
+ }
+
if ( unlikely(p_pes->gather.i_saved > 0) )
{
/* Saved from previous packet end */
More information about the vlc-commits
mailing list