[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