[vlc-commits] demux: ts: split PES processing

Francois Cartegnie git at videolan.org
Thu Jan 23 21:12:47 CET 2020


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Jan 17 17:17:55 2020 +0100| [7ed1257d9d917e486ad58eabb7cde2f46ea199fc] | committer: Francois Cartegnie

demux: ts: split PES processing

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7ed1257d9d917e486ad58eabb7cde2f46ea199fc
---

 modules/demux/Makefile.am   |   1 +
 modules/demux/mpeg/ts.c     | 273 +++--------------------------------------
 modules/demux/mpeg/ts_pes.c | 289 ++++++++++++++++++++++++++++++++++++++++++++
 modules/demux/mpeg/ts_pes.h |  40 ++++++
 4 files changed, 346 insertions(+), 257 deletions(-)

diff --git a/modules/demux/Makefile.am b/modules/demux/Makefile.am
index 59a80907fe..3aa42a2683 100644
--- a/modules/demux/Makefile.am
+++ b/modules/demux/Makefile.am
@@ -272,6 +272,7 @@ libts_plugin_la_SOURCES = demux/mpeg/ts.c demux/mpeg/ts.h \
         demux/mpeg/ts_metadata.c demux/mpeg/ts_metadata.h \
         demux/mpeg/ts_hotfixes.c demux/mpeg/ts_hotfixes.h \
         demux/mpeg/ts_strings.h demux/mpeg/ts_streams_private.h \
+        demux/mpeg/ts_pes.c demux/mpeg/ts_pes.h \
         demux/mpeg/pes.h \
         demux/mpeg/timestamps.h \
 	demux/mpeg/ts_descriptions.h \
diff --git a/modules/demux/mpeg/ts.c b/modules/demux/mpeg/ts.c
index dd7a87acc7..53b70aecf7 100644
--- a/modules/demux/mpeg/ts.c
+++ b/modules/demux/mpeg/ts.c
@@ -38,6 +38,7 @@
 #include "ts_pid.h"
 #include "ts_streams.h"
 #include "ts_streams_private.h"
+#include "ts_pes.h"
 #include "ts_psi.h"
 #include "ts_si.h"
 #include "ts_psip.h"
@@ -190,8 +191,8 @@ static inline int PIDGet( block_t *p )
 static stime_t GetPCR( const block_t * );
 
 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 bool GatherSectionsData( demux_t *p_demux, ts_pid_t *, block_t *, size_t );
+static bool GatherPESData( demux_t *p_demux, ts_pid_t *, block_t *, size_t );
 static void ProgramSetPCR( demux_t *p_demux, ts_pmt_t *p_prg, stime_t i_pcr );
 
 static block_t* ReadTSPacket( demux_t *p_demux );
@@ -209,8 +210,6 @@ static void PCRFixHandle( demux_t *, ts_pmt_t *, block_t * );
 #define PROBE_CHUNK_COUNT 500
 #define PROBE_MAX         (PROBE_CHUNK_COUNT * 10)
 
-#define BLOCK_FLAG_SOURCE_RANDOM_ACCESS (1 << BLOCK_FLAG_PRIVATE_SHIFT)
-
 static int DetectPacketSize( demux_t *p_demux, unsigned *pi_header_size, int i_offset )
 {
     const uint8_t *p_peek;
@@ -1758,45 +1757,9 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
     }
 }
 
-static bool PushPESBlock( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt, bool b_unit_start )
+static void PESDataChainHandle( vlc_object_t *p_obj, void *priv, block_t *p_data )
 {
-    bool b_ret = false;
-    ts_stream_t *p_pes = pid->u.p_stream;
-
-    if ( b_unit_start && p_pes->gather.p_data )
-    {
-        block_t *p_datachain = p_pes->gather.p_data;
-        /* Flush the pes from pid */
-        p_pes->gather.p_data = NULL;
-        p_pes->gather.i_data_size = 0;
-        p_pes->gather.i_gathered = 0;
-        p_pes->gather.pp_last = &p_pes->gather.p_data;
-        ParsePESDataChain( p_demux, pid, p_datachain );
-        b_ret = true;
-    }
-
-    if( p_pkt == NULL )
-        return b_ret;
-
-    if( !b_unit_start && p_pes->gather.p_data == NULL )
-    {
-        /* msg_Dbg( p_demux, "broken packet" ); */
-        block_Release( p_pkt );
-        return b_ret;
-    }
-
-    block_ChainLastAppend( &p_pes->gather.pp_last, p_pkt );
-    p_pes->gather.i_gathered += p_pkt->i_buffer;
-
-    if( p_pes->gather.i_data_size > 0 &&
-        p_pes->gather.i_gathered >= p_pes->gather.i_data_size )
-    {
-        /* re-enter in Flush above */
-        assert(p_pes->gather.p_data);
-        return PushPESBlock( p_demux, pid, NULL, true );
-    }
-
-    return b_ret;
+    ParsePESDataChain( (demux_t *)p_obj, (ts_pid_t *) priv, p_data );
 }
 
 static block_t* ReadTSPacket( demux_t *p_demux )
@@ -2384,7 +2347,10 @@ static void PCRCheckDTS( demux_t *p_demux, ts_pmt_t *p_pmt, stime_t i_pcr)
             {
                 msg_Warn( p_demux, "send queued data for pid %d: TS %"PRId64" <= PCR %"PRId64"\n",
                           p_pid->i_pid, i_dts != -1 ? i_dts : i_pts, i_pcr);
-                PushPESBlock( p_demux, p_pid, NULL, true ); /* Flush */
+                ts_pes_parse_callback cb = { .p_obj = VLC_OBJECT(p_demux),
+                                             .priv = p_pid,
+                                             .pf_parse = PESDataChainHandle };
+                ts_pes_Push( &cb, p_pes, NULL, true ); /* Flush */
             }
         }
     }
@@ -2650,225 +2616,18 @@ static block_t * ProcessTSPacket( demux_t *p_demux, ts_pid_t *pid, block_t *p_pk
     return p_pkt;
 }
 
-/* Avoids largest memcpy */
-static bool block_Split( block_t **pp_block, block_t **pp_remain, size_t i_offset )
-{
-    block_t *p_block = *pp_block;
-    block_t *p_split = NULL;
-    *pp_remain = NULL;
-
-    size_t i_tocopy = p_block->i_buffer - i_offset;
-    if( i_tocopy > i_offset ) /* make new block for head */
-    {
-        if( i_offset > 0 )
-        {
-            p_split = block_Alloc( i_offset );
-            if( p_split == NULL )
-                return false;
-            memcpy( p_split->p_buffer, p_block->p_buffer, i_offset );
-            p_block->p_buffer += i_offset;
-            p_block->i_buffer -= i_offset;
-        }
-        *pp_remain = p_block;
-        *pp_block = p_split;
-    }
-    else /* other gets the tail of our split */
-    {
-        if( i_tocopy > 0 )
-        {
-            p_split = block_Alloc( i_tocopy );
-            if( p_split == NULL )
-                return false;
-            memcpy( p_split->p_buffer, &p_block->p_buffer[i_offset], i_tocopy );
-            p_block->i_buffer -= i_tocopy;
-        }
-        *pp_remain = p_split;
-    }
-    return true;
-}
-
-static uint8_t *FindNextPESHeader( uint8_t *p_buf, size_t i_buffer )
-{
-    const uint8_t *p_end = &p_buf[i_buffer];
-    unsigned i_bitflow = 0;
-    for( ; p_buf != p_end; p_buf++ )
-    {
-        i_bitflow <<= 1;
-        if( !*p_buf )
-        {
-            i_bitflow |= 1;
-        }
-        else if( *p_buf == 0x01 && (i_bitflow & 0x06) == 0x06 ) /* >= two zero prefixed 1 */
-        {
-            return p_buf - 2;
-        }
-    }
-    return NULL;
-}
-
-static const uint8_t pes_sync[] = { 0, 0, 1 };
-
-static bool MayHaveStartCodeOnEnd( const uint8_t *p_buf, size_t i_buf )
-{
-    assert(i_buf > 2);
-    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 )
+static bool GatherPESData( demux_t *p_demux, ts_pid_t *p_pid, block_t *p_pkt, size_t i_skip )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
+    ts_pes_parse_callback cb = { .p_obj = VLC_OBJECT(p_demux),
+                                 .priv = p_pid,
+                                 .pf_parse = PESDataChainHandle };
     const bool b_unit_start = p_pkt->p_buffer[1]&0x40;
-    bool b_ret = false;
-    ts_stream_t *p_pes = pid->u.p_stream;
-
-    /* We have to gather it */
-    p_pkt->p_buffer += i_skip;
+    p_pkt->p_buffer += i_skip; /* point to PES */
     p_pkt->i_buffer -= i_skip;
-
-    bool b_single_payload = b_unit_start; /* Single payload in case of unit start */
-    bool b_aligned_ts_payload = true;
-
-    if( unlikely(p_pes->b_broken_PUSI_conformance) )
-    {
-        /* Stream does not conform to payload_unit_start flag
-         * applied to PES packets (AdTech private_stream_1) */
-        b_aligned_ts_payload = false;
-        b_single_payload = false;
-
-    }
-
-    /* We'll cannot parse any pes data */
-    if( (p_pkt->i_flags & BLOCK_FLAG_SCRAMBLED) && p_sys->b_valid_scrambling )
-    {
-        block_Release( p_pkt );
-        return PushPESBlock( p_demux, pid, NULL, true );
-    }
-
-    /* Seek discontinuity, we need to drop or output currently
-     * gathered data */
-    if( p_pkt->i_flags & BLOCK_FLAG_SOURCE_RANDOM_ACCESS )
-    {
-        p_pes->gather.i_saved = 0;
-        /* Flush/output current */
-        b_ret |= PushPESBlock( p_demux, pid, NULL, true );
-        /* Propagate to output block to notify packetizers/decoders */
-        if( p_pes->p_es )
-            p_pes->p_es->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
-    }
-    /* On dropped blocks discontinuity */
-    else if( p_pkt->i_flags & BLOCK_FLAG_DISCONTINUITY )
-    {
-        /* it can't match the target size and need to resync on sync code */
-        p_pes->gather.i_data_size = 0;
-        /* can't reuse prev bytes to lookup sync code */
-        p_pes->gather.i_saved = 0;
-        /* Propagate to output block to notify packetizers/decoders */
-        if( p_pes->p_es )
-            p_pes->p_es->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED;
-    }
-
-    if ( unlikely(p_pes->gather.i_saved > 0) )
-    {
-        /* Saved from previous packet end */
-        assert(p_pes->gather.i_saved < 6);
-        if( !b_aligned_ts_payload )
-        {
-            p_pkt = block_Realloc( p_pkt, p_pes->gather.i_saved, p_pkt->i_buffer );
-            if( p_pkt )
-                memcpy( p_pkt->p_buffer, p_pes->gather.saved, p_pes->gather.i_saved );
-        }
-        p_pes->gather.i_saved = 0;
-    }
-
-    for( bool b_first_sync_done = false; p_pkt; )
-    {
-        assert( p_pes->gather.i_saved == 0 );
-
-        if( p_pes->gather.p_data == NULL && !b_first_sync_done && p_pkt->i_buffer >= 6 )
-        {
-            if( likely(b_aligned_ts_payload) )
-            {
-                if( memcmp( p_pkt->p_buffer, pes_sync, 3 ) )
-                {
-                    block_Release( p_pkt );
-                    return b_ret;
-                }
-            }
-            else
-            {
-                /* Need to find sync code */
-                uint8_t *p_buf = FindNextPESHeader( p_pkt->p_buffer, p_pkt->i_buffer - 3 );
-                if( p_buf == NULL )
-                {
-                    /* no first sync code */
-                    if( MayHaveStartCodeOnEnd( p_pkt->p_buffer, p_pkt->i_buffer ) )
-                    {
-                        /* Drop everything except last bytes for next packet */
-                        p_pkt->p_buffer += p_pkt->i_buffer - 3;
-                        p_pes->gather.i_saved = p_pkt->i_buffer = 3;
-                        memcpy(p_pes->gather.saved, p_pkt->p_buffer, p_pkt->i_buffer);
-                    }
-                    block_Release( p_pkt );
-                    return b_ret;
-                }
-                p_pkt->i_buffer -= p_buf - p_pkt->p_buffer;
-                p_pkt->p_buffer = p_buf;
-            }
-            /* now points to PES header */
-            p_pes->gather.i_data_size = GetWBE(&p_pkt->p_buffer[4]);
-            if( p_pes->gather.i_data_size > 0 )
-                p_pes->gather.i_data_size += 6;
-            b_first_sync_done = true; /* Because if size is 0, we woud not look for second sync */
-        }
-        else
-        {
-            assert( p_pes->gather.i_data_size > p_pes->gather.i_gathered ||
-                    p_pes->gather.i_data_size == 0 );
-
-            /* If we started reading a fixed size */
-            if( p_pes->gather.i_data_size > p_pes->gather.i_gathered )
-            {
-                const size_t i_remain = p_pes->gather.i_data_size - p_pes->gather.i_gathered;
-                /* Append whole block */
-                if( likely(p_pkt->i_buffer <= i_remain || b_single_payload) )
-                {
-                    b_ret |= PushPESBlock( p_demux, pid, p_pkt, p_pes->gather.p_data == NULL );
-                    p_pkt = NULL;
-                }
-                else /* p_pkt->i_buffer > i_remain */
-                {
-                    block_t *p_split;
-                    if( !block_Split( &p_pkt, &p_split, i_remain ) )
-                    {
-                        block_Release( p_pkt );
-                        return false;
-                    }
-                    b_ret |= PushPESBlock( p_demux, pid, p_pkt, p_pes->gather.p_data == NULL );
-                    p_pkt = p_split;
-                    b_first_sync_done = false;
-                }
-            }
-            else /* if( p_pes->gather.i_data_size == 0 ) // see next packet */
-            {
-                /* Append or finish current/start new PES depending on unit_start */
-                b_ret |= PushPESBlock( p_demux, pid, p_pkt, b_unit_start );
-                p_pkt = NULL;
-            }
-        }
-
-        if( unlikely(p_pkt && p_pkt->i_buffer < 6) )
-        {
-            /* save and prepend to next packet */
-            assert(!b_single_payload);
-            assert(p_pes->gather.i_saved == 0);
-            p_pes->gather.i_saved = p_pkt->i_buffer;
-            memcpy(p_pes->gather.saved, p_pkt->p_buffer, p_pkt->i_buffer);
-            block_Release( p_pkt );
-            p_pkt = NULL;
-        }
-    }
-
-    return b_ret;
+    return ts_pes_Gather( &cb, p_pid->u.p_stream,
+                          p_pkt, b_unit_start,
+                          p_sys->b_valid_scrambling );
 }
 
 static bool GatherSectionsData( demux_t *p_demux, ts_pid_t *p_pid, block_t *p_pkt, size_t i_skip )
diff --git a/modules/demux/mpeg/ts_pes.c b/modules/demux/mpeg/ts_pes.c
new file mode 100644
index 0000000000..308ee5e61a
--- /dev/null
+++ b/modules/demux/mpeg/ts_pes.c
@@ -0,0 +1,289 @@
+/*****************************************************************************
+ * ts_pes.c: Transport Stream input module for VLC.
+ *****************************************************************************
+ * Copyright (C) 2004-2019 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_demux.h>
+
+#include "ts_streams.h"
+#include "ts_pid.h"
+#include "ts_streams_private.h"
+
+#include "ts_pes.h"
+
+#include <assert.h>
+
+/* Avoids largest memcpy */
+static bool block_Split( block_t **pp_block, block_t **pp_remain, size_t i_offset )
+{
+    block_t *p_block = *pp_block;
+    block_t *p_split = NULL;
+    *pp_remain = NULL;
+
+    size_t i_tocopy = p_block->i_buffer - i_offset;
+    if( i_tocopy > i_offset ) /* make new block for head */
+    {
+        if( i_offset > 0 )
+        {
+            p_split = block_Alloc( i_offset );
+            if( p_split == NULL )
+                return false;
+            memcpy( p_split->p_buffer, p_block->p_buffer, i_offset );
+            p_block->p_buffer += i_offset;
+            p_block->i_buffer -= i_offset;
+        }
+        *pp_remain = p_block;
+        *pp_block = p_split;
+    }
+    else /* other gets the tail of our split */
+    {
+        if( i_tocopy > 0 )
+        {
+            p_split = block_Alloc( i_tocopy );
+            if( p_split == NULL )
+                return false;
+            memcpy( p_split->p_buffer, &p_block->p_buffer[i_offset], i_tocopy );
+            p_block->i_buffer -= i_tocopy;
+        }
+        *pp_remain = p_split;
+    }
+    return true;
+}
+
+static const uint8_t pes_sync[] = { 0, 0, 1 };
+
+static bool MayHaveStartCodeOnEnd( const uint8_t *p_buf, size_t i_buf )
+{
+    assert(i_buf > 2);
+    return !( *(--p_buf) > 1 || *(--p_buf) > 0 || *(--p_buf) > 0 );
+}
+
+static uint8_t *FindNextPESHeader( uint8_t *p_buf, size_t i_buffer )
+{
+    const uint8_t *p_end = &p_buf[i_buffer];
+    unsigned i_bitflow = 0;
+    for( ; p_buf != p_end; p_buf++ )
+    {
+        i_bitflow <<= 1;
+        if( !*p_buf )
+        {
+            i_bitflow |= 1;
+        }
+        else if( *p_buf == 0x01 && (i_bitflow & 0x06) == 0x06 ) /* >= two zero prefixed 1 */
+        {
+            return p_buf - 2;
+        }
+    }
+    return NULL;
+}
+
+bool ts_pes_Push( ts_pes_parse_callback *cb,
+                  ts_stream_t *p_pes, block_t *p_pkt, bool b_unit_start )
+{
+    bool b_ret = false;
+
+    if ( b_unit_start && p_pes->gather.p_data )
+    {
+        block_t *p_datachain = p_pes->gather.p_data;
+        /* Flush the pes from pid */
+        p_pes->gather.p_data = NULL;
+        p_pes->gather.i_data_size = 0;
+        p_pes->gather.i_gathered = 0;
+        p_pes->gather.pp_last = &p_pes->gather.p_data;
+        cb->pf_parse( cb->p_obj, cb->priv, p_datachain );
+        b_ret = true;
+    }
+
+    if( p_pkt == NULL )
+        return b_ret;
+
+    if( !b_unit_start && p_pes->gather.p_data == NULL )
+    {
+        /* msg_Dbg( p_demux, "broken packet" ); */
+        block_Release( p_pkt );
+        return b_ret;
+    }
+
+    block_ChainLastAppend( &p_pes->gather.pp_last, p_pkt );
+    p_pes->gather.i_gathered += p_pkt->i_buffer;
+
+    if( p_pes->gather.i_data_size > 0 &&
+        p_pes->gather.i_gathered >= p_pes->gather.i_data_size )
+    {
+        /* re-enter in Flush above */
+        assert(p_pes->gather.p_data);
+        return ts_pes_Push( cb, p_pes, NULL, true );
+    }
+
+    return b_ret;
+}
+
+bool ts_pes_Gather( ts_pes_parse_callback *cb,
+                    ts_stream_t *p_pes, block_t *p_pkt,
+                    bool b_unit_start, bool b_valid_scrambling )
+{
+    bool b_ret = false;
+    bool b_single_payload = b_unit_start; /* Single payload in case of unit start */
+    bool b_aligned_ts_payload = true;
+
+    if( unlikely(p_pes->b_broken_PUSI_conformance) )
+    {
+        /* Stream does not conform to payload_unit_start flag
+         * applied to PES packets (AdTech private_stream_1) */
+        b_aligned_ts_payload = false;
+        b_single_payload = false;
+
+    }
+
+    /* We'll cannot parse any pes data */
+    if( (p_pkt->i_flags & BLOCK_FLAG_SCRAMBLED) && b_valid_scrambling )
+    {
+        block_Release( p_pkt );
+        return ts_pes_Push( cb, p_pes, NULL, true );
+    }
+
+    /* Seek discontinuity, we need to drop or output currently
+     * gathered data */
+    if( p_pkt->i_flags & BLOCK_FLAG_SOURCE_RANDOM_ACCESS )
+    {
+        p_pes->gather.i_saved = 0;
+        /* Flush/output current */
+        b_ret |= ts_pes_Push( cb, p_pes, NULL, true );
+        /* Propagate to output block to notify packetizers/decoders */
+        if( p_pes->p_es )
+            p_pes->p_es->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
+    }
+    /* On dropped blocks discontinuity */
+    else if( p_pkt->i_flags & BLOCK_FLAG_DISCONTINUITY )
+    {
+        /* it can't match the target size and need to resync on sync code */
+        p_pes->gather.i_data_size = 0;
+        /* can't reuse prev bytes to lookup sync code */
+        p_pes->gather.i_saved = 0;
+        /* Propagate to output block to notify packetizers/decoders */
+        if( p_pes->p_es )
+            p_pes->p_es->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED;
+    }
+
+    if ( unlikely(p_pes->gather.i_saved > 0) )
+    {
+        /* Saved from previous packet end */
+        assert(p_pes->gather.i_saved < 6);
+        if( !b_aligned_ts_payload )
+        {
+            p_pkt = block_Realloc( p_pkt, p_pes->gather.i_saved, p_pkt->i_buffer );
+            if( p_pkt )
+                memcpy( p_pkt->p_buffer, p_pes->gather.saved, p_pes->gather.i_saved );
+        }
+        p_pes->gather.i_saved = 0;
+    }
+
+    for( bool b_first_sync_done = false; p_pkt; )
+    {
+        assert( p_pes->gather.i_saved == 0 );
+
+        if( p_pes->gather.p_data == NULL && !b_first_sync_done && p_pkt->i_buffer >= 6 )
+        {
+            if( likely(b_aligned_ts_payload) )
+            {
+                if( memcmp( p_pkt->p_buffer, pes_sync, 3 ) )
+                {
+                    block_Release( p_pkt );
+                    return b_ret;
+                }
+            }
+            else
+            {
+                /* Need to find sync code */
+                uint8_t *p_buf = FindNextPESHeader( p_pkt->p_buffer, p_pkt->i_buffer - 3 );
+                if( p_buf == NULL )
+                {
+                    /* no first sync code */
+                    if( MayHaveStartCodeOnEnd( p_pkt->p_buffer, p_pkt->i_buffer ) )
+                    {
+                        /* Drop everything except last bytes for next packet */
+                        p_pkt->p_buffer += p_pkt->i_buffer - 3;
+                        p_pes->gather.i_saved = p_pkt->i_buffer = 3;
+                        memcpy(p_pes->gather.saved, p_pkt->p_buffer, p_pkt->i_buffer);
+                    }
+                    block_Release( p_pkt );
+                    return b_ret;
+                }
+                p_pkt->i_buffer -= p_buf - p_pkt->p_buffer;
+                p_pkt->p_buffer = p_buf;
+            }
+            /* now points to PES header */
+            p_pes->gather.i_data_size = GetWBE(&p_pkt->p_buffer[4]);
+            if( p_pes->gather.i_data_size > 0 )
+                p_pes->gather.i_data_size += 6;
+            b_first_sync_done = true; /* Because if size is 0, we woud not look for second sync */
+        }
+        else
+        {
+            assert( p_pes->gather.i_data_size > p_pes->gather.i_gathered ||
+                    p_pes->gather.i_data_size == 0 );
+
+            /* If we started reading a fixed size */
+            if( p_pes->gather.i_data_size > p_pes->gather.i_gathered )
+            {
+                const size_t i_remain = p_pes->gather.i_data_size - p_pes->gather.i_gathered;
+                /* Append whole block */
+                if( likely(p_pkt->i_buffer <= i_remain || b_single_payload) )
+                {
+                    b_ret |= ts_pes_Push( cb, p_pes, p_pkt, p_pes->gather.p_data == NULL );
+                    p_pkt = NULL;
+                }
+                else /* p_pkt->i_buffer > i_remain */
+                {
+                    block_t *p_split;
+                    if( !block_Split( &p_pkt, &p_split, i_remain ) )
+                    {
+                        block_Release( p_pkt );
+                        return false;
+                    }
+                    b_ret |= ts_pes_Push( cb, p_pes, p_pkt, p_pes->gather.p_data == NULL );
+                    p_pkt = p_split;
+                    b_first_sync_done = false;
+                }
+            }
+            else /* if( p_pes->gather.i_data_size == 0 ) // see next packet */
+            {
+                /* Append or finish current/start new PES depending on unit_start */
+                b_ret |= ts_pes_Push( cb, p_pes, p_pkt, b_unit_start );
+                p_pkt = NULL;
+            }
+        }
+
+        if( unlikely(p_pkt && p_pkt->i_buffer < 6) )
+        {
+            /* save and prepend to next packet */
+            assert(!b_single_payload);
+            assert(p_pes->gather.i_saved == 0);
+            p_pes->gather.i_saved = p_pkt->i_buffer;
+            memcpy(p_pes->gather.saved, p_pkt->p_buffer, p_pkt->i_buffer);
+            block_Release( p_pkt );
+            p_pkt = NULL;
+        }
+    }
+
+    return b_ret;
+}
diff --git a/modules/demux/mpeg/ts_pes.h b/modules/demux/mpeg/ts_pes.h
new file mode 100644
index 0000000000..57799b37bf
--- /dev/null
+++ b/modules/demux/mpeg/ts_pes.h
@@ -0,0 +1,40 @@
+/*****************************************************************************
+ * ts_pes.h: Transport Stream input module for VLC.
+ *****************************************************************************
+ * Copyright (C) 2004-2019 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifndef VLC_TS_PES_H
+#define VLC_TS_PES_H
+
+#define BLOCK_FLAG_SOURCE_RANDOM_ACCESS (1 << BLOCK_FLAG_PRIVATE_SHIFT)
+
+typedef struct
+{
+    vlc_object_t *p_obj;
+    void *priv;
+    void(*pf_parse)(vlc_object_t *, void *, block_t *);
+} ts_pes_parse_callback;
+
+bool ts_pes_Push( ts_pes_parse_callback *cb,
+                  ts_stream_t *p_pes, block_t *p_pkt, bool b_unit_start );
+
+bool ts_pes_Gather( ts_pes_parse_callback *cb,
+                    ts_stream_t *p_pes, block_t *p_pkt,
+                    bool b_unit_start, bool b_valid_scrambling );
+
+
+#endif



More information about the vlc-commits mailing list