[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