[vlc-commits] [Git][videolan/vlc][master] 11 commits: demux: ps: refactor dts as condition branch
Felix Paul Kühne (@fkuehne)
gitlab at videolan.org
Sat Jul 5 12:24:50 UTC 2025
Felix Paul Kühne pushed to branch master at VideoLAN / VLC
Commits:
fd7157d0 by François Cartegnie at 2025-07-05T12:09:25+00:00
demux: ps: refactor dts as condition branch
- - - - -
1125e0a1 by François Cartegnie at 2025-07-05T12:09:25+00:00
demux: ts: simplify signature and code for ParsePESHeader
- - - - -
92469e17 by François Cartegnie at 2025-07-05T12:09:25+00:00
demux: ts: move getters and defines to ts_packet.h
- - - - -
581d8653 by François Cartegnie at 2025-07-05T12:09:25+00:00
demux: ts: refactor skipping AF header
- - - - -
630578f9 by François Cartegnie at 2025-07-05T12:09:25+00:00
demux: ts: refactor PES using helpers
- - - - -
461968f9 by François Cartegnie at 2025-07-05T12:09:25+00:00
demux: ts: add define for stream_id
- - - - -
bd77a06e by François Cartegnie at 2025-07-05T12:09:25+00:00
demux: ps: use stream id defines
- - - - -
ab0b0969 by François Cartegnie at 2025-07-05T12:09:25+00:00
demux: ts: move PES check into header parsing
- - - - -
93b69419 by François Cartegnie at 2025-07-05T12:09:25+00:00
demux: ts: simplify ProbePES using ts_packet.h
- - - - -
dd60043f by François Cartegnie at 2025-07-05T12:09:25+00:00
demux: ps: update comments
- - - - -
fe2328a4 by François Cartegnie at 2025-07-05T12:09:25+00:00
demux: ps: use single scale conversion
- - - - -
8 changed files:
- modules/demux/Makefile.am
- modules/demux/mpeg/pes.h
- modules/demux/mpeg/ps.c
- modules/demux/mpeg/ps.h
- modules/demux/mpeg/ts.c
- modules/demux/mpeg/ts_hotfixes.c
- modules/demux/mpeg/ts_hotfixes.h
- + modules/demux/mpeg/ts_packet.h
Changes:
=====================================
modules/demux/Makefile.am
=====================================
@@ -280,6 +280,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_packet.h \
demux/mpeg/ts_pes.c demux/mpeg/ts_pes.h \
demux/mpeg/ts_streamwrapper.h \
demux/mpeg/pes.h \
=====================================
modules/demux/mpeg/pes.h
=====================================
@@ -22,8 +22,24 @@
#include "timestamps.h"
+#define STREAM_ID_PROGRAM_STREAM_MAP 0xBC
+#define STREAM_ID_PRIVATE_STREAM_1 0xBD
+#define STREAM_ID_PADDING 0xBE
+#define STREAM_ID_PRIVATE_STREAM_2 0xBF
+#define STREAM_ID_AUDIO_STREAM_0 0xC0
+#define STREAM_ID_VIDEO_STREAM_0 0xE0
+#define STREAM_ID_ECM 0xF0
+#define STREAM_ID_EMM 0xF1
+#define STREAM_ID_DSM_CC 0xF2
+#define STREAM_ID_H222_1_TYPE_E 0xF8
+#define STREAM_ID_METADATA_STREAM 0xFC
+#define STREAM_ID_EXTENDED_STREAM_ID 0xFD
+#define STREAM_ID_PROGRAM_STREAM_DIRECTORY 0xFF
+
+/* MPEG-2 PTS/DTS */
static inline ts_90khz_t GetPESTimestamp( const uint8_t *p_data )
{
+ /* prefixed by 4 bits 0010 or 0011 */
return ((ts_90khz_t)(p_data[ 0]&0x0e ) << 29)|
(ts_90khz_t)(p_data[1] << 22)|
((ts_90khz_t)(p_data[2]&0xfe) << 14)|
@@ -50,6 +66,7 @@ static inline bool ExtractPESTimestamp( const uint8_t *p_data, uint8_t i_flags,
/* PS SCR timestamp as defined in H222 2.5.3.2 */
static inline ts_90khz_t ExtractPackHeaderTimestamp( const uint8_t *p_data )
{
+ /* prefixed by 2 bits 01 */
return ((ts_90khz_t)(p_data[0]&0x38 ) << 27)|
((ts_90khz_t)(p_data[0]&0x03 ) << 28)|
(ts_90khz_t)(p_data[1] << 20)|
@@ -59,31 +76,50 @@ static inline ts_90khz_t ExtractPackHeaderTimestamp( const uint8_t *p_data )
(ts_90khz_t)(p_data[4] >> 3);
}
+typedef struct
+{
+ ts_90khz_t i_dts;
+ ts_90khz_t i_pts;
+ uint8_t i_stream_id;
+ bool b_scrambling;
+ unsigned i_size;
+} ts_pes_header_t;
+
+static inline void ts_pes_header_init(ts_pes_header_t *h)
+{
+ h->i_dts = TS_90KHZ_INVALID;
+ h->i_pts = TS_90KHZ_INVALID;
+ h->i_stream_id = 0;
+ h->b_scrambling = false;
+ h->i_size = 0;
+}
+
inline
-static int ParsePESHeader( vlc_object_t *p_object, const uint8_t *p_header, size_t i_header,
- unsigned *pi_skip, ts_90khz_t *pi_dts, ts_90khz_t *pi_pts,
- uint8_t *pi_stream_id, bool *pb_pes_scambling )
+static int ParsePESHeader( struct vlc_logger *p_logger, const uint8_t *p_header, size_t i_header,
+ ts_pes_header_t *h )
{
unsigned i_skip;
if ( i_header < 9 )
return VLC_EGENERIC;
- *pi_stream_id = p_header[3];
+ if( p_header[0] != 0 || p_header[1] != 0 || p_header[2] != 1 )
+ return VLC_EGENERIC;
+
+ h->i_stream_id = p_header[3];
switch( p_header[3] )
{
- case 0xBC: /* Program stream map */
- case 0xBE: /* Padding */
- case 0xBF: /* Private stream 2 */
- case 0xF0: /* ECM */
- case 0xF1: /* EMM */
- case 0xFF: /* Program stream directory */
- case 0xF2: /* DSMCC stream */
- case 0xF8: /* ITU-T H.222.1 type E stream */
+ case STREAM_ID_PROGRAM_STREAM_MAP:
+ case STREAM_ID_PADDING:
+ case STREAM_ID_PRIVATE_STREAM_2:
+ case STREAM_ID_ECM:
+ case STREAM_ID_EMM:
+ case STREAM_ID_PROGRAM_STREAM_DIRECTORY:
+ case STREAM_ID_DSM_CC:
+ case STREAM_ID_H222_1_TYPE_E:
i_skip = 6;
- if( pb_pes_scambling )
- *pb_pes_scambling = false;
+ h->b_scrambling = false;
break;
default:
if( ( p_header[6]&0xC0 ) == 0x80 )
@@ -91,17 +127,16 @@ static int ParsePESHeader( vlc_object_t *p_object, const uint8_t *p_header, size
/* mpeg2 PES */
i_skip = p_header[8] + 9;
- if( pb_pes_scambling )
- *pb_pes_scambling = p_header[6]&0x30;
+ h->b_scrambling = p_header[6]&0x30;
if( p_header[7]&0x80 ) /* has pts */
{
if( i_header >= 9 + 5 )
- (void) ExtractPESTimestamp( &p_header[9], p_header[7] >> 6, pi_pts );
+ (void) ExtractPESTimestamp( &p_header[9], p_header[7] >> 6, &h->i_pts );
if( ( p_header[7]&0x40 ) && /* has dts */
i_header >= 14 + 5 )
- (void) ExtractPESTimestamp( &p_header[14], 0x01, pi_dts );
+ (void) ExtractPESTimestamp( &p_header[14], 0x01, &h->i_dts );
}
}
else
@@ -112,8 +147,7 @@ static int ParsePESHeader( vlc_object_t *p_object, const uint8_t *p_header, size
Non spec reference for packet format on http://andrewduncan.net/mpeg/mpeg-1.html */
i_skip = 6;
- if( pb_pes_scambling )
- *pb_pes_scambling = false;
+ h->b_scrambling = false;
while( i_skip < 23 && p_header[i_skip] == 0xff )
{
@@ -123,7 +157,7 @@ static int ParsePESHeader( vlc_object_t *p_object, const uint8_t *p_header, size
}
if( i_skip == 23 )
{
- msg_Err( p_object, "too much MPEG-1 stuffing" );
+ vlc_error( p_logger, "too much MPEG-1 stuffing" );
return VLC_EGENERIC;
}
/* Skip STD buffer size */
@@ -138,12 +172,12 @@ static int ParsePESHeader( vlc_object_t *p_object, const uint8_t *p_header, size
if( p_header[i_skip]&0x20 )
{
if( i_header >= i_skip + 5 )
- (void) ExtractPESTimestamp( &p_header[i_skip], p_header[i_skip] >> 4, pi_pts );
+ (void) ExtractPESTimestamp( &p_header[i_skip], p_header[i_skip] >> 4, &h->i_pts );
if( ( p_header[i_skip]&0x10 ) && /* has dts */
i_header >= i_skip + 10 )
{
- (void) ExtractPESTimestamp( &p_header[i_skip+5], 0x01, pi_dts );
+ (void) ExtractPESTimestamp( &p_header[i_skip+5], 0x01, &h->i_dts );
i_skip += 10;
}
else
@@ -161,7 +195,7 @@ static int ParsePESHeader( vlc_object_t *p_object, const uint8_t *p_header, size
break;
}
- *pi_skip = i_skip;
+ h->i_size = i_skip;
return VLC_SUCCESS;
}
=====================================
modules/demux/mpeg/ps.c
=====================================
@@ -210,8 +210,8 @@ static int OpenCommon( vlc_object_t *p_this, bool b_force )
if( memcmp( p_header, startcode, 3 ) ||
( (p_header[3] & 0xB0) != 0xB0 &&
!(p_header[3] >= 0xC0 && p_header[3] <= 0xEF) &&
- p_header[3] != PS_STREAM_ID_EXTENDED &&
- p_header[3] != PS_STREAM_ID_DIRECTORY ) )
+ p_header[3] != STREAM_ID_EXTENDED_STREAM_ID &&
+ p_header[3] != STREAM_ID_PROGRAM_STREAM_DIRECTORY ) )
return VLC_EGENERIC;
ssize_t i_pessize = ps_pkt_size( p_header, 16 );
@@ -480,7 +480,7 @@ static int Demux( demux_t *p_demux )
switch( i_stream_id )
{
case PS_STREAM_ID_END_STREAM:
- case PS_STREAM_ID_PADDING:
+ case STREAM_ID_PADDING:
block_Release( p_pkt );
break;
@@ -507,7 +507,7 @@ static int Demux( demux_t *p_demux )
block_Release( p_pkt );
break;
- case PS_STREAM_ID_MAP:
+ case STREAM_ID_PROGRAM_STREAM_MAP:
if( p_sys->psm.i_version == 0xFF )
msg_Dbg( p_demux, "contains a PSM");
@@ -525,8 +525,8 @@ static int Demux( demux_t *p_demux )
break;
}
/* fallthrough */
- case PS_STREAM_ID_PRIVATE_STREAM1:
- case PS_STREAM_ID_EXTENDED:
+ case STREAM_ID_PRIVATE_STREAM_1:
+ case STREAM_ID_EXTENDED_STREAM_ID:
{
int i_id = ps_pkt_id( p_pkt->p_buffer, p_pkt->i_buffer );
/* Small heuristic to improve MLP detection from AOB */
=====================================
modules/demux/mpeg/ps.h
=====================================
@@ -27,11 +27,6 @@
#define PS_STREAM_ID_END_STREAM 0xB9
#define PS_STREAM_ID_PACK_HEADER 0xBA
#define PS_STREAM_ID_SYSTEM_HEADER 0xBB
-#define PS_STREAM_ID_MAP 0xBC
-#define PS_STREAM_ID_PRIVATE_STREAM1 0xBD
-#define PS_STREAM_ID_PADDING 0xBE
-#define PS_STREAM_ID_EXTENDED 0xFD
-#define PS_STREAM_ID_DIRECTORY 0xFF
/* 256-0xC0 for normal stream, 256 for 0xbd stream, 256 for 0xfd stream, 8 for 0xa0 AOB stream */
#define PS_TK_COUNT (256+256+256+8 - 0xc0)
@@ -435,8 +430,8 @@ static inline int ps_pkt_size( const uint8_t *p, int i_peek )
break;
case PS_STREAM_ID_SYSTEM_HEADER:
- case PS_STREAM_ID_MAP:
- case PS_STREAM_ID_DIRECTORY:
+ case STREAM_ID_PROGRAM_STREAM_MAP:
+ case STREAM_ID_PROGRAM_STREAM_DIRECTORY:
default:
if( i_peek >= 6 )
return 6 + ((p[4]<<8) | p[5] );
@@ -449,23 +444,23 @@ static inline int ps_pkt_parse_pack( const uint8_t *p_pkt, size_t i_pkt,
vlc_tick_t *pi_scr, int *pi_mux_rate )
{
const uint8_t *p = p_pkt;
- if( i_pkt >= 14 && (p[4] >> 6) == 0x01 )
+ ts_90khz_t i_scr;
+ if( i_pkt >= 14 && (p[4] >> 6) == 0x01 ) /* 0b01 H.222 MPEG-2 Pack Header */
{
- *pi_scr = FROM_SCALE( ExtractPackHeaderTimestamp( &p[4] ) );
+ i_scr = ExtractPackHeaderTimestamp( &p[4] );
*pi_mux_rate = ( p[10] << 14 )|( p[11] << 6 )|( p[12] >> 2);
}
- else if( i_pkt >= 12 && (p[4] >> 4) == 0x02 ) /* MPEG-1 Pack SCR, same bits as PES/PTS */
+ else if( i_pkt >= 12 && (p[4] >> 4) == 0x02 ) /* 0b0010 ISO 11172-1 MPEG-1 Pack Header */
{
- ts_90khz_t i_scr;
- if(!ExtractPESTimestamp( &p[4], 0x02, &i_scr ))
+ if(!ExtractPESTimestamp( &p[4], 0x02, &i_scr )) /* same bits as PES/PTS */
return VLC_EGENERIC;
- *pi_scr = FROM_SCALE( i_scr );
*pi_mux_rate = ( ( p[9]&0x7f )<< 15 )|( p[10] << 7 )|( p[11] >> 1);
}
else
{
return VLC_EGENERIC;
}
+ *pi_scr = FROM_SCALE( i_scr );
return VLC_SUCCESS;
}
@@ -487,7 +482,7 @@ static inline int ps_pkt_parse_system( const uint8_t *p_pkt, size_t i_pkt,
case 0xB7:
if( p_pktend - p < 6 )
return VLC_EGENERIC;
- i_id = ((int)PS_STREAM_ID_EXTENDED << 8) | (p[2] & 0x7F);
+ i_id = ((int)STREAM_ID_EXTENDED_STREAM_ID << 8) | (p[2] & 0x7F);
p += 6;
break;
default:
@@ -510,17 +505,16 @@ static inline int ps_pkt_parse_system( const uint8_t *p_pkt, size_t i_pkt,
/* Parse a PES (and skip i_skip_extra in the payload) */
static inline int ps_pkt_parse_pes( vlc_object_t *p_object, block_t *p_pes, int i_skip_extra )
{
- unsigned int i_skip = 0;
- ts_90khz_t i_pts = TS_90KHZ_INVALID;
- ts_90khz_t i_dts = TS_90KHZ_INVALID;
- uint8_t i_stream_id = 0;
- bool b_pes_scrambling = false;
-
- if( ParsePESHeader( p_object, p_pes->p_buffer, p_pes->i_buffer,
- &i_skip, &i_dts, &i_pts, &i_stream_id, &b_pes_scrambling ) != VLC_SUCCESS )
+ unsigned int i_skip;
+ ts_pes_header_t pesh;
+ ts_pes_header_init( &pesh );
+
+ if( ParsePESHeader( p_object->logger, p_pes->p_buffer, p_pes->i_buffer, &pesh ) != VLC_SUCCESS )
return VLC_EGENERIC;
- if( b_pes_scrambling )
+ i_skip = pesh.i_size;
+
+ if( pesh.b_scrambling )
p_pes->i_flags |= BLOCK_FLAG_SCRAMBLED;
if( i_skip_extra >= 0 )
@@ -538,14 +532,14 @@ static inline int ps_pkt_parse_pes( vlc_object_t *p_object, block_t *p_pes, int
p_pes->p_buffer += i_skip;
p_pes->i_buffer -= i_skip;
- /* ISO/IEC 13818-1 2.7.5: if no pts and no dts, then dts == pts */
- if( i_pts != TS_90KHZ_INVALID && i_dts == TS_90KHZ_INVALID )
- i_dts = i_pts;
-
- if( i_dts != TS_90KHZ_INVALID )
- p_pes->i_dts = FROM_SCALE( i_dts );
- if( i_pts != TS_90KHZ_INVALID )
- p_pes->i_pts = FROM_SCALE( i_pts );
+ if( pesh.i_pts != TS_90KHZ_INVALID )
+ {
+ p_pes->i_pts = FROM_SCALE( pesh.i_pts );
+ if( pesh.i_dts != TS_90KHZ_INVALID )
+ p_pes->i_dts = FROM_SCALE( pesh.i_dts );
+ else /* ISO/IEC 13818-1 2.7.5: if pts and no dts, then dts == pts */
+ p_pes->i_dts = p_pes->i_pts;
+ }
return VLC_SUCCESS;
}
@@ -644,7 +638,7 @@ static inline int ps_psm_fill( ps_psm_t *p_psm,
// Demux() checks that we have at least 4 bytes, but we need
// at least 10 to read up to the info_length field
assert(i_pkt >= 4);
- if( !p_psm || i_pkt < 10 || p_buffer[3] != PS_STREAM_ID_MAP)
+ if( !p_psm || i_pkt < 10 || p_buffer[3] != STREAM_ID_PROGRAM_STREAM_MAP)
return VLC_EGENERIC;
i_length = GetWBE(&p_buffer[4]) + 6;
@@ -690,7 +684,7 @@ static inline int ps_psm_fill( ps_psm_t *p_psm,
* descriptor 0x5 with format_identifier == 0x56432D31 (VC-1)
* (I need a sample that use PSM with VC-1) */
- if( p_es->i_id == PS_STREAM_ID_EXTENDED && b_single_extension == 0 )
+ if( p_es->i_id == STREAM_ID_EXTENDED_STREAM_ID && b_single_extension == 0 )
{
if( i_info_length < 3 )
break;
=====================================
modules/demux/mpeg/ts.c
=====================================
@@ -38,6 +38,7 @@
#include "ts_pid.h"
#include "ts_streams.h"
#include "ts_streams_private.h"
+#include "ts_packet.h"
#include "ts_pes.h"
#include "ts_psi.h"
#include "ts_si.h"
@@ -182,11 +183,6 @@ static bool PIDReferencedByProgram( const ts_pmt_t *, uint16_t );
void UpdatePESFilters( demux_t *p_demux, bool b_all );
static inline void FlushESBuffer( ts_stream_t *p_pes );
static void UpdatePIDScrambledState( demux_t *p_demux, ts_pid_t *p_pid, bool );
-static inline int PIDGet( block_t *p )
-{
- return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2];
-}
-static ts_90khz_t GetPCR( const block_t * );
static block_t * ProcessTSPacket( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt, int * );
static bool GatherSectionsData( demux_t *p_demux, ts_pid_t *, block_t *, size_t );
@@ -199,12 +195,6 @@ static void ReadyQueuesPostSeek( demux_t *p_demux );
static void PCRHandle( demux_t *p_demux, ts_pid_t *, ts_90khz_t );
static void PCRFixHandle( demux_t *, ts_pmt_t *, block_t * );
-#define TS_PACKET_SIZE_188 188
-#define TS_PACKET_SIZE_192 192
-#define TS_PACKET_SIZE_204 204
-#define TS_PACKET_SIZE_MAX 204
-#define TS_HEADER_SIZE 4
-
#define PROBE_CHUNK_COUNT 500
#define PROBE_MAX (PROBE_CHUNK_COUNT * 10)
@@ -707,8 +697,7 @@ static int Demux( demux_t *p_demux )
(p_pkt->p_buffer[1] & 0xC0) == 0x40 && /* Payload start but not corrupt */
(p_pkt->p_buffer[3] & 0xD0) == 0x10 ) /* Has payload but is not encrypted */
{
- ProbePES( p_demux, p_pid, p_pkt->p_buffer + TS_HEADER_SIZE,
- p_pkt->i_buffer - TS_HEADER_SIZE, p_pkt->p_buffer[3] & 0x20 /* Adaptation field */);
+ ProbePES( p_demux, p_pid, p_pkt );
}
switch( p_pid->type )
@@ -1551,13 +1540,9 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
uint8_t header[34];
unsigned i_pes_size = 0;
unsigned i_skip = 0;
- ts_90khz_t i_pktdts = TS_90KHZ_INVALID;
- ts_90khz_t i_pktpts = TS_90KHZ_INVALID;
ts_90khz_t i_length = 0;
vlc_tick_t i_dts = VLC_TICK_INVALID;
vlc_tick_t i_pts = VLC_TICK_INVALID;
- uint8_t i_stream_id;
- bool b_pes_scrambling = false;
const es_mpeg4_descriptor_t *p_mpeg4desc = NULL;
demux_sys_t *p_sys = p_demux->p_sys;
@@ -1586,20 +1571,23 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
ts_es_t *p_es = pid->u.p_stream->p_es;
- if( ParsePESHeader( VLC_OBJECT(p_demux), (uint8_t*)&header, i_max, &i_skip,
- &i_pktdts, &i_pktpts, &i_stream_id, &b_pes_scrambling ) == VLC_EGENERIC )
+ ts_pes_header_t pesh;
+ ts_pes_header_init( &pesh );
+
+ if( ParsePESHeader( p_demux->obj.logger, (uint8_t*)&header, i_max, &pesh ) == VLC_EGENERIC )
{
block_ChainRelease( p_pes );
return;
}
else
{
- if( i_pktpts != TS_90KHZ_INVALID && p_es->p_program )
- i_pts = TimeStampWrapAround( p_es->p_program->pcr.i_first, FROM_SCALE(i_pktpts) );
- if( i_pktdts != TS_90KHZ_INVALID && p_es->p_program )
- i_dts = TimeStampWrapAround( p_es->p_program->pcr.i_first, FROM_SCALE(i_pktdts) );
- if( b_pes_scrambling )
+ if( pesh.i_pts != TS_90KHZ_INVALID && p_es->p_program )
+ i_pts = TimeStampWrapAround( p_es->p_program->pcr.i_first, FROM_SCALE(pesh.i_pts) );
+ if( pesh.i_dts != TS_90KHZ_INVALID && p_es->p_program )
+ i_dts = TimeStampWrapAround( p_es->p_program->pcr.i_first, FROM_SCALE(pesh.i_dts) );
+ if( pesh.b_scrambling )
p_pes->i_flags |= BLOCK_FLAG_SCRAMBLED;
+ i_skip = pesh.i_size;
}
if( p_es->i_sl_es_id )
@@ -1749,12 +1737,12 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
{
if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
ts_stream_processor_Reset( pid->u.p_stream->p_proc );
- p_block = ts_stream_processor_Push( pid->u.p_stream->p_proc, i_stream_id, p_block );
+ p_block = ts_stream_processor_Push( pid->u.p_stream->p_proc, pesh.i_stream_id, p_block );
}
else
/* Some codecs might need xform or AU splitting */
{
- p_block = ConvertPESBlock( p_demux, p_es, i_pes_size, i_stream_id, p_block );
+ p_block = ConvertPESBlock( p_demux, p_es, i_pes_size, pesh.i_stream_id, p_block );
}
SendDataChain( p_demux, p_es, p_block );
@@ -1768,7 +1756,7 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
{
if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
ts_stream_processor_Reset( pid->u.p_stream->p_proc );
- p_block = ts_stream_processor_Push( pid->u.p_stream->p_proc, i_stream_id, p_block );
+ p_block = ts_stream_processor_Push( pid->u.p_stream->p_proc, pesh.i_stream_id, p_block );
}
if( p_block )
@@ -1874,32 +1862,6 @@ static block_t* ReadTSPacket( demux_t *p_demux )
return p_pkt;
}
-static ts_90khz_t GetPCR( const block_t *p_pkt )
-{
- const uint8_t *p = p_pkt->p_buffer;
-
- ts_90khz_t i_pcr = TS_90KHZ_INVALID;
-
- if(unlikely(p_pkt->i_buffer < 12))
- return i_pcr;
-
- const uint8_t i_adaption = p[3] & 0x30;
-
- if( ( ( i_adaption == 0x30 && p[4] <= 182 ) || /* adaptation 0b11 */
- ( i_adaption == 0x20 && p[4] == 183 ) ) && /* adaptation 0b10 */
- ( p[4] >= 7 ) &&
- ( p[5] & 0x10 ) ) /* PCR carry flag */
- {
- /* PCR is 33 bits */
- i_pcr = ( (ts_90khz_t)p[6] << 25 ) |
- ( (ts_90khz_t)p[7] << 17 ) |
- ( (ts_90khz_t)p[8] << 9 ) |
- ( (ts_90khz_t)p[9] << 1 ) |
- ( (ts_90khz_t)p[10] >> 7 );
- }
- return i_pcr;
-}
-
static inline void UpdateESScrambledState( es_out_t *out, const ts_es_t *p_es, bool b_scrambled )
{
for( ; p_es; p_es = p_es->p_next )
@@ -2044,32 +2006,23 @@ static int SeekToTime( demux_t *p_demux, const ts_pmt_t *p_pmt, vlc_tick_t i_see
ts_pid_t *p_pid = GetPID(p_sys, i_pid);
if( i_pid != 0x1FFF )
{
- unsigned i_skip = 4;
- if ( p_pkt->p_buffer[3] & 0x20 ) // adaptation field
- {
- if( p_pkt->i_buffer >= 4 + 2 + 5 )
- {
- if( p_pmt->i_pid_pcr == i_pid )
- i_pktpcr = GetPCR( p_pkt );
- i_skip += 1 + __MIN(p_pkt->p_buffer[4], 182);
- }
- }
+ if( p_pmt->i_pid_pcr == i_pid )
+ i_pktpcr = GetPCR( p_pkt );
+ unsigned i_skip = PKTHeaderAndAFSize( p_pkt );
if( i_pktpcr == TS_90KHZ_INVALID && p_pid->type == TYPE_STREAM &&
ts_stream_Find_es( p_pid->u.p_stream, p_pmt ) &&
(p_pkt->p_buffer[1] & 0xC0) == 0x40 && /* Payload start but not corrupt */
(p_pkt->p_buffer[3] & 0xD0) == 0x10 /* Has payload but is not encrypted */
)
{
- ts_90khz_t i_pktdts = TS_90KHZ_INVALID;
- ts_90khz_t i_pktpts = TS_90KHZ_INVALID;
- uint8_t i_stream_id;
- if ( VLC_SUCCESS == ParsePESHeader( VLC_OBJECT(p_demux), &p_pkt->p_buffer[i_skip],
- p_pkt->i_buffer - i_skip, &i_skip,
- &i_pktdts, &i_pktpts, &i_stream_id, NULL ) )
+ ts_pes_header_t pesh;
+ ts_pes_header_init( &pesh );
+ if ( VLC_SUCCESS == ParsePESHeader( NULL, &p_pkt->p_buffer[i_skip],
+ p_pkt->i_buffer - i_skip, &pesh ) )
{
- if( i_pktdts != TS_90KHZ_INVALID )
- i_pktpcr = i_pktdts;
+ if( pesh.i_dts != TS_90KHZ_INVALID )
+ i_pktpcr = pesh.i_dts;
}
}
}
@@ -2132,10 +2085,7 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, bool *pb_fou
if( i_pid != 0x1FFF && (p_pkt->p_buffer[1] & 0x80) == 0 ) /* not corrupt */
{
bool b_pcrresult = true;
- bool b_adaptfield = p_pkt->p_buffer[3] & 0x20;
-
- if( b_adaptfield && p_pkt->i_buffer >= 4 + 2 + 5 )
- i_pcr = GetPCR( p_pkt );
+ i_pcr = GetPCR( p_pkt );
/* Designated PCR pid will be valid, don't repick (on the fly probing) */
if( i_pcr != TS_90KHZ_INVALID && !p_pid->probed.i_pcr_count )
@@ -2149,21 +2099,16 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, bool *pb_fou
)
{
b_pcrresult = false;
- ts_90khz_t i_dts = TS_90KHZ_INVALID;
- ts_90khz_t i_pts = TS_90KHZ_INVALID;
- uint8_t i_stream_id;
- unsigned i_skip = 4;
- if ( b_adaptfield ) // adaptation field
- i_skip += 1 + __MIN(p_pkt->p_buffer[4], 182);
-
- if ( VLC_SUCCESS == ParsePESHeader( VLC_OBJECT(p_demux), &p_pkt->p_buffer[i_skip],
- p_pkt->i_buffer - i_skip, &i_skip,
- &i_dts, &i_pts, &i_stream_id, NULL ) )
+ unsigned i_skip = PKTHeaderAndAFSize( p_pkt );
+ ts_pes_header_t pesh;
+ ts_pes_header_init( &pesh );
+ if ( VLC_SUCCESS == ParsePESHeader( NULL, &p_pkt->p_buffer[i_skip],
+ p_pkt->i_buffer - i_skip, &pesh ) )
{
- if( i_dts != TS_90KHZ_INVALID )
- i_pcr = i_dts;
- else if( i_pts != TS_90KHZ_INVALID )
- i_pcr = i_pts;
+ if( pesh.i_dts != TS_90KHZ_INVALID )
+ i_pcr = pesh.i_dts;
+ else if( pesh.i_pts != TS_90KHZ_INVALID )
+ i_pcr = pesh.i_pts;
}
}
@@ -2383,24 +2328,19 @@ static void PCRCheckDTS( demux_t *p_demux, ts_pmt_t *p_pmt, vlc_tick_t i_pcr)
uint8_t header[34];
const int i_max = block_ChainExtract( p_pes->gather.p_data, header, 34 );
- if( i_max < 6 || header[0] != 0 || header[1] != 0 || header[2] != 1 )
+ ts_pes_header_t pesh;
+ ts_pes_header_init( &pesh );
+
+ if( ParsePESHeader( NULL, (uint8_t*)&header, i_max, &pesh ) == VLC_EGENERIC )
continue;
- unsigned i_skip = 0;
- ts_90khz_t i_pktdts = TS_90KHZ_INVALID;
- ts_90khz_t i_pktpts = TS_90KHZ_INVALID;
vlc_tick_t i_dts = VLC_TICK_INVALID;
vlc_tick_t i_pts = VLC_TICK_INVALID;
- uint8_t i_stream_id;
-
- if( ParsePESHeader( VLC_OBJECT(p_demux), (uint8_t*)&header, i_max, &i_skip,
- &i_pktdts, &i_pktpts, &i_stream_id, NULL ) == VLC_EGENERIC )
- continue;
- if( i_pktdts != TS_90KHZ_INVALID )
- i_dts = TimeStampWrapAround( i_pcr, FROM_SCALE(i_pktdts) );
- if( i_pktpts != TS_90KHZ_INVALID )
- i_pts = TimeStampWrapAround( i_pcr, FROM_SCALE(i_pktpts) );
+ if( pesh.i_dts != TS_90KHZ_INVALID )
+ i_dts = TimeStampWrapAround( i_pcr, FROM_SCALE(pesh.i_dts) );
+ if( pesh.i_pts != TS_90KHZ_INVALID )
+ i_pts = TimeStampWrapAround( i_pcr, FROM_SCALE(pesh.i_pts) );
if (p_pmt->pcr.i_pcroffset > 0) {
if( i_dts != VLC_TICK_INVALID )
=====================================
modules/demux/mpeg/ts_hotfixes.c
=====================================
@@ -44,113 +44,38 @@
#include "ts_streams_private.h"
#include "ts.h"
#include "ts_hotfixes.h"
+#include "ts_packet.h"
#include <assert.h>
-void ProbePES( demux_t *p_demux, ts_pid_t *pid, const uint8_t *p_pesstart, size_t i_data, bool b_adaptfield )
+void ProbePES( demux_t *p_demux, ts_pid_t *pid, const block_t *p_pkt )
{
demux_sys_t *p_sys = p_demux->p_sys;
- const uint8_t *p_pes = p_pesstart;
- if( b_adaptfield )
- {
- if ( i_data < 2 )
- return;
-
- uint8_t len = *p_pes;
- p_pes++; i_data--;
+ unsigned i_skip = PKTHeaderAndAFSize( p_pkt );
+ ts_90khz_t pktpcr = GetPCR( p_pkt );
- if(len == 0)
- {
- p_pes++; i_data--;/* stuffing */
- }
- else
- {
- if( i_data < len )
- return;
- if( len >= 7 && (p_pes[0] & 0x10) )
- pid->probed.i_pcr_count++;
- p_pes += len;
- i_data -= len;
- }
- }
+ if( pktpcr != TS_90KHZ_INVALID )
+ pid->probed.i_pcr_count++;
- if( i_data < 9 )
- return;
+ size_t i_data = p_pkt->i_buffer - i_skip;
+ const uint8_t *p_pes = &p_pkt->p_buffer[i_skip];
- if( p_pes[0] != 0 || p_pes[1] != 0 || p_pes[2] != 1 )
+ ts_pes_header_t pesh;
+ ts_pes_header_init( &pesh );
+ if( ParsePESHeader( NULL, p_pes, i_data, &pesh ) != VLC_SUCCESS )
return;
- size_t i_pesextoffset = 8;
- ts_90khz_t i_dts = TS_90KHZ_INVALID;
- if( p_pes[7] & 0x80 ) // PTS
- {
- i_pesextoffset += 5;
- if ( i_data < i_pesextoffset ||
- !ExtractPESTimestamp( &p_pes[9], p_pes[7] >> 6, &i_dts ) )
- return;
+ if( pesh.i_dts != TS_90KHZ_INVALID )
pid->probed.i_dts_count++;
- }
- if( p_pes[7] & 0x40 ) // DTS
- {
- i_pesextoffset += 5;
- if ( i_data < i_pesextoffset ||
- !ExtractPESTimestamp( &p_pes[14], 0x01, &i_dts ) )
- return;
- }
- if( p_pes[7] & 0x20 ) // ESCR
- i_pesextoffset += 6;
- if( p_pes[7] & 0x10 ) // ESrate
- i_pesextoffset += 3;
- if( p_pes[7] & 0x08 ) // DSM
- i_pesextoffset += 1;
- if( p_pes[7] & 0x04 ) // CopyInfo
- i_pesextoffset += 1;
- if( p_pes[7] & 0x02 ) // PESCRC
- i_pesextoffset += 2;
if( pid->probed.i_fourcc != 0 )
goto codecprobingend;
- if ( i_data < i_pesextoffset )
- return;
-
- /* HeaderdataLength */
- const size_t i_payloadoffset = 8 + 1 + p_pes[8];
- i_pesextoffset += 1;
-
- if ( i_data < i_pesextoffset || i_data < i_payloadoffset )
- return;
-
- i_data -= 8 + 1 + p_pes[8];
-
- if( p_pes[7] & 0x01 ) // PESExt
- {
- size_t i_extension2_offset = 1;
- if ( p_pes[i_pesextoffset] & 0x80 ) // private data
- i_extension2_offset += 16;
- if ( p_pes[i_pesextoffset] & 0x40 ) // pack
- i_extension2_offset += 1;
- if ( p_pes[i_pesextoffset] & 0x20 ) // seq
- i_extension2_offset += 2;
- if ( p_pes[i_pesextoffset] & 0x10 ) // P-STD
- i_extension2_offset += 2;
- if ( p_pes[i_pesextoffset] & 0x01 ) // Extension 2
- {
- uint8_t i_len = p_pes[i_pesextoffset + i_extension2_offset] & 0x7F;
- i_extension2_offset += i_len;
- }
- if( i_data < i_extension2_offset )
- return;
-
- i_data -= i_extension2_offset;
- }
- /* (i_payloadoffset - i_pesextoffset) 0xFF stuffing */
-
- if ( i_data < 4 )
+ if( i_data < pesh.i_size + 4 )
return;
- const uint8_t *p_data = &p_pes[i_payloadoffset];
+ const uint8_t *p_data = &p_pes[pesh.i_size];
const uint8_t i_stream_id = pid->probed.i_stream_id = p_pes[3];
/* NON MPEG audio & subpictures STREAM */
if(i_stream_id == 0xBD)
@@ -197,15 +122,15 @@ void ProbePES( demux_t *p_demux, ts_pid_t *pid, const uint8_t *p_pesstart, size_
codecprobingend:
/* Track timestamps and flag missing PAT */
- if( !p_sys->patfix.i_timesourcepid && i_dts != TS_90KHZ_INVALID )
+ if( !p_sys->patfix.i_timesourcepid && pesh.i_dts != TS_90KHZ_INVALID )
{
- p_sys->patfix.i_first_dts = FROM_SCALE(i_dts);
+ p_sys->patfix.i_first_dts = FROM_SCALE(pesh.i_dts);
p_sys->patfix.i_timesourcepid = pid->i_pid;
}
- else if( p_sys->patfix.i_timesourcepid == pid->i_pid && i_dts != TS_90KHZ_INVALID &&
+ else if( p_sys->patfix.i_timesourcepid == pid->i_pid && pesh.i_dts != TS_90KHZ_INVALID &&
p_sys->patfix.status == PAT_WAITING )
{
- if( FROM_SCALE(i_dts) - p_sys->patfix.i_first_dts > MIN_PAT_INTERVAL )
+ if( FROM_SCALE(pesh.i_dts) - p_sys->patfix.i_first_dts > MIN_PAT_INTERVAL )
p_sys->patfix.status = PAT_MISSING;
}
=====================================
modules/demux/mpeg/ts_hotfixes.h
=====================================
@@ -21,7 +21,7 @@
#define MIN_PAT_INTERVAL VLC_TICK_FROM_SEC(1) // DVB is 500ms
-void ProbePES( demux_t *p_demux, ts_pid_t *pid, const uint8_t *p_pesstart, size_t i_data, bool b_adaptfield );
+void ProbePES(demux_t *p_demux, ts_pid_t *pid, const block_t * );
void MissingPATPMTFixup( demux_t *p_demux );
#endif
=====================================
modules/demux/mpeg/ts_packet.h
=====================================
@@ -0,0 +1,72 @@
+/*****************************************************************************
+ * ts_packet.h : MPEG-TS packet headers
+ *****************************************************************************
+ * Copyright (C) 2025 - VideoLabs, VideoLAN and VLC authors
+ *
+ * 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *****************************************************************************/
+#ifndef VLC_TS_PACKET_H
+#define VLC_TS_PACKET_H
+
+#include "timestamps.h"
+
+#define TS_PACKET_SIZE_188 188
+#define TS_PACKET_SIZE_192 192
+#define TS_PACKET_SIZE_204 204
+#define TS_PACKET_SIZE_MAX 204
+#define TS_HEADER_SIZE 4
+
+#define AS_BUF(pkt) pkt->p_buffer,pkt->i_buffer
+
+static inline unsigned PKTHeaderAndAFSize( const block_t *p_pkt )
+{
+ const uint8_t *p = p_pkt->p_buffer;
+ unsigned i_size = 4;
+ if ( p[3] & 0x30 ) // adaptation field
+ i_size += 1 + __MIN(p[4], 182);
+ return i_size;
+}
+
+static inline int PIDGet( const block_t *p )
+{
+ return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2];
+}
+
+static inline ts_90khz_t GetPCR( const block_t *p_pkt )
+{
+ const uint8_t *p = p_pkt->p_buffer;
+
+ ts_90khz_t i_pcr = TS_90KHZ_INVALID;
+
+ if(unlikely(p_pkt->i_buffer < 12))
+ return i_pcr;
+
+ const uint8_t i_adaption = p[3] & 0x30;
+
+ if( ( ( i_adaption == 0x30 && p[4] <= 182 ) || /* adaptation 0b11 */
+ ( i_adaption == 0x20 && p[4] == 183 ) ) && /* adaptation 0b10 */
+ ( p[4] >= 7 ) &&
+ ( p[5] & 0x10 ) ) /* PCR carry flag */
+ {
+ /* PCR is 33 bits */
+ i_pcr = ( (ts_90khz_t)p[6] << 25 ) |
+ ( (ts_90khz_t)p[7] << 17 ) |
+ ( (ts_90khz_t)p[8] << 9 ) |
+ ( (ts_90khz_t)p[9] << 1 ) |
+ ( (ts_90khz_t)p[10] >> 7 );
+ }
+ return i_pcr;
+}
+
+#endif
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/6950a5cd1f326709d6967ba79aba858658921125...fe2328a408cec775a9fc2bc7fcbfd1f1d50c083f
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/6950a5cd1f326709d6967ba79aba858658921125...fe2328a408cec775a9fc2bc7fcbfd1f1d50c083f
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list