[vlc-commits] [Git][videolan/vlc][master] 9 commits: demux: ts: change stime_t for ts_90khz_t
Steve Lhomme (@robUx4)
gitlab at videolan.org
Tue Apr 29 08:44:07 UTC 2025
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
0a5bd92c by François Cartegnie at 2025-04-29T08:29:05+00:00
demux: ts: change stime_t for ts_90khz_t
- - - - -
cf2f062f by François Cartegnie at 2025-04-29T08:29:05+00:00
demux: ts: add TS_90KHZ_INVALID
- - - - -
2f5f0422 by François Cartegnie at 2025-04-29T08:29:05+00:00
demux: ts: remove SETANDVALID macro
- - - - -
fe9457b2 by François Cartegnie at 2025-04-29T08:29:05+00:00
demux: ts: remove usage of TS_UNKNOWN, simplifying comparisons
- - - - -
01aa9fee by François Cartegnie at 2025-04-29T08:29:05+00:00
codec: textst: use ts_90khz_t
- - - - -
e9e99b04 by François Cartegnie at 2025-04-29T08:29:05+00:00
demux: pva: use ts_90khz_t
- - - - -
af38707d by François Cartegnie at 2025-04-29T08:29:05+00:00
demux: ts: revert native scale changes to fix wrapping
Can never work with timestamp value 0
- - - - -
56b19564 by François Cartegnie at 2025-04-29T08:29:05+00:00
tests: add timestamps wrapping check
- - - - -
caf3ea13 by François Cartegnie at 2025-04-29T08:29:05+00:00
demux: ts: fix multiple wrapping
refs streams/ts/1fps93hours.ts
- - - - -
19 changed files:
- modules/codec/textst.c
- modules/demux/mpeg/pes.h
- modules/demux/mpeg/ps.h
- modules/demux/mpeg/timestamps.h
- modules/demux/mpeg/ts.c
- modules/demux/mpeg/ts.h
- modules/demux/mpeg/ts_hotfixes.c
- modules/demux/mpeg/ts_pes.c
- modules/demux/mpeg/ts_pes.h
- modules/demux/mpeg/ts_psi.c
- modules/demux/mpeg/ts_scte.c
- modules/demux/mpeg/ts_streams.c
- modules/demux/mpeg/ts_streams_private.h
- modules/demux/pva.c
- modules/demux/ty.c
- test/Makefile.am
- + test/modules/demux/timestamps.c
- test/modules/demux/ts_pes.c
- test/modules/meson.build
Changes:
=====================================
modules/codec/textst.c
=====================================
@@ -237,8 +237,8 @@ static int Decode(decoder_t *p_dec, block_t *p_block)
(p_block->i_flags & BLOCK_FLAG_CORRUPTED) == 0 &&
(p_sub = decoder_NewSubpictureText(p_dec)))
{
- p_sub->i_start = FROM_SCALE(((int64_t)(p_block->p_buffer[3] & 0x01) << 32) | GetDWBE(&p_block->p_buffer[4]));
- p_sub->i_stop = FROM_SCALE(((int64_t)(p_block->p_buffer[8] & 0x01) << 32) | GetDWBE(&p_block->p_buffer[9]));
+ p_sub->i_start = FROM_SCALE(((ts_90khz_t)(p_block->p_buffer[3] & 0x01) << 32) | GetDWBE(&p_block->p_buffer[4]));
+ p_sub->i_stop = FROM_SCALE(((ts_90khz_t)(p_block->p_buffer[8] & 0x01) << 32) | GetDWBE(&p_block->p_buffer[9]));
if (p_sub->i_start < p_block->i_dts)
{
p_sub->i_stop += p_block->i_dts - p_sub->i_start;
=====================================
modules/demux/mpeg/pes.h
=====================================
@@ -22,16 +22,16 @@
#include "timestamps.h"
-static inline stime_t GetPESTimestamp( const uint8_t *p_data )
+static inline ts_90khz_t GetPESTimestamp( const uint8_t *p_data )
{
- return ((int64_t)(p_data[ 0]&0x0e ) << 29)|
- (int64_t)(p_data[1] << 22)|
- ((int64_t)(p_data[2]&0xfe) << 14)|
- (int64_t)(p_data[3] << 7)|
- (int64_t)(p_data[4] >> 1);
+ return ((ts_90khz_t)(p_data[ 0]&0x0e ) << 29)|
+ (ts_90khz_t)(p_data[1] << 22)|
+ ((ts_90khz_t)(p_data[2]&0xfe) << 14)|
+ (ts_90khz_t)(p_data[3] << 7)|
+ (ts_90khz_t)(p_data[4] >> 1);
}
-static inline bool ExtractPESTimestamp( const uint8_t *p_data, uint8_t i_flags, stime_t *ret )
+static inline bool ExtractPESTimestamp( const uint8_t *p_data, uint8_t i_flags, ts_90khz_t *ret )
{
/* !warn broken muxers set incorrect flags. see #17773 and #19140 */
/* check marker bits, and i_flags = b 0010, 0011 or 0001 */
@@ -48,20 +48,20 @@ 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 stime_t ExtractPackHeaderTimestamp( const uint8_t *p_data )
+static inline ts_90khz_t ExtractPackHeaderTimestamp( const uint8_t *p_data )
{
- return ((int64_t)(p_data[ 0]&0x38 ) << 27)|
- ((int64_t)(p_data[0]&0x03 ) << 28)|
- (int64_t)(p_data[1] << 20)|
- ((int64_t)(p_data[2]&0xf8 ) << 12)|
- ((int64_t)(p_data[2]&0x03 ) << 13)|
- (int64_t)(p_data[3] << 5) |
- (int64_t)(p_data[4] >> 3);
+ return ((ts_90khz_t)(p_data[0]&0x38 ) << 27)|
+ ((ts_90khz_t)(p_data[0]&0x03 ) << 28)|
+ (ts_90khz_t)(p_data[1] << 20)|
+ ((ts_90khz_t)(p_data[2]&0xf8 ) << 12)|
+ ((ts_90khz_t)(p_data[2]&0x03 ) << 13)|
+ (ts_90khz_t)(p_data[3] << 5) |
+ (ts_90khz_t)(p_data[4] >> 3);
}
inline
static int ParsePESHeader( vlc_object_t *p_object, const uint8_t *p_header, size_t i_header,
- unsigned *pi_skip, stime_t *pi_dts, stime_t *pi_pts,
+ unsigned *pi_skip, ts_90khz_t *pi_dts, ts_90khz_t *pi_pts,
uint8_t *pi_stream_id, bool *pb_pes_scambling )
{
unsigned i_skip;
=====================================
modules/demux/mpeg/ps.h
=====================================
@@ -456,7 +456,7 @@ static inline int ps_pkt_parse_pack( const uint8_t *p_pkt, size_t i_pkt,
}
else if( i_pkt >= 12 && (p[4] >> 4) == 0x02 ) /* MPEG-1 Pack SCR, same bits as PES/PTS */
{
- stime_t i_scr;
+ ts_90khz_t i_scr;
if(!ExtractPESTimestamp( &p[4], 0x02, &i_scr ))
return VLC_EGENERIC;
*pi_scr = FROM_SCALE( i_scr );
@@ -511,8 +511,8 @@ static inline int ps_pkt_parse_system( const uint8_t *p_pkt, size_t i_pkt,
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;
- stime_t i_pts = -1;
- stime_t i_dts = -1;
+ 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;
@@ -539,12 +539,12 @@ static inline int ps_pkt_parse_pes( vlc_object_t *p_object, block_t *p_pes, int
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 >= 0 && i_dts < 0 )
+ if( i_pts != TS_90KHZ_INVALID && i_dts == TS_90KHZ_INVALID )
i_dts = i_pts;
- if( i_dts >= 0 )
+ if( i_dts != TS_90KHZ_INVALID )
p_pes->i_dts = FROM_SCALE( i_dts );
- if( i_pts >= 0 )
+ if( i_pts != TS_90KHZ_INVALID )
p_pes->i_pts = FROM_SCALE( i_pts );
return VLC_SUCCESS;
=====================================
modules/demux/mpeg/timestamps.h
=====================================
@@ -25,15 +25,25 @@
#define FROM_SCALE(x) (VLC_TICK_0 + FROM_SCALE_NZ(x))
#define TO_SCALE(x) TO_SCALE_NZ((x) - VLC_TICK_0)
-typedef int64_t stime_t;
+typedef int64_t ts_90khz_t;
+#define TS_90KHZ_INVALID -1
-static inline stime_t TimeStampWrapAround( stime_t i_first_pcr, stime_t i_time )
+#define TS_33BITS_ROLL_NZ FROM_SCALE_NZ(0x1FFFFFFFF)
+#define TS_33BITS_HALF_ROLL_NZ FROM_SCALE_NZ(0x0FFFFFFFF)
+
+static inline vlc_tick_t TimeStampWrapAround( vlc_tick_t i_past_pcr, vlc_tick_t i_time )
{
- stime_t i_adjust = 0;
- if( i_first_pcr > 0x0FFFFFFFF && i_time < 0x0FFFFFFFF )
- i_adjust = 0x1FFFFFFFF;
+ if( i_past_pcr == VLC_TICK_INVALID || i_time >= i_past_pcr )
+ return i_time;
+
+ vlc_tick_t delta = i_past_pcr - i_time;
+ if( delta >= TS_33BITS_HALF_ROLL_NZ )
+ {
+ vlc_tick_t rolls = (delta + TS_33BITS_ROLL_NZ - 1) / TS_33BITS_ROLL_NZ;
+ i_time += rolls * TS_33BITS_ROLL_NZ;
+ }
- return i_time + i_adjust;
+ return i_time;
}
#endif
=====================================
modules/demux/mpeg/ts.c
=====================================
@@ -186,17 +186,17 @@ static inline int PIDGet( block_t *p )
{
return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2];
}
-static stime_t GetPCR( const block_t * );
+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 );
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 void ProgramSetPCR( demux_t *p_demux, ts_pmt_t *p_prg, vlc_tick_t i_pcr );
static block_t* ReadTSPacket( demux_t *p_demux );
-static int SeekToTime( demux_t *p_demux, const ts_pmt_t *, stime_t time );
+static int SeekToTime( demux_t *p_demux, const ts_pmt_t *, vlc_tick_t time );
static void ReadyQueuesPostSeek( demux_t *p_demux );
-static void PCRHandle( demux_t *p_demux, ts_pid_t *, stime_t );
+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
@@ -411,7 +411,7 @@ static int Open( vlc_object_t *p_this )
vlc_dictionary_init( &p_sys->attachments, 0 );
- p_sys->patfix.i_first_dts = -1;
+ p_sys->patfix.i_first_dts = VLC_TICK_INVALID;
p_sys->patfix.i_timesourcepid = 0;
p_sys->patfix.b_pcrhasnopcrfield = false;
p_sys->patfix.status = var_CreateGetBool( p_demux, "ts-patfix" ) ? PAT_WAITING : PAT_FIXTRIED;
@@ -698,8 +698,8 @@ static int Demux( demux_t *p_demux )
}
/* Adaptation field cannot be scrambled */
- stime_t i_pcr = GetPCR( p_pkt );
- if( i_pcr >= 0 )
+ ts_90khz_t i_pcr = GetPCR( p_pkt );
+ if( i_pcr != TS_90KHZ_INVALID )
PCRHandle( p_demux, p_pid, i_pcr );
/* Probe streams to build PAT/PMT after MIN_PAT_INTERVAL in case we don't see any PAT */
@@ -949,14 +949,13 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
if( !p_sys->b_ignore_time_for_positions &&
p_pmt &&
- p_pmt->pcr.i_first > -1 && SETANDVALID(p_pmt->i_last_dts) &&
- p_pmt->pcr.i_current > -1 )
+ p_pmt->pcr.i_first != VLC_TICK_INVALID &&
+ p_pmt->i_last_dts != VLC_TICK_INVALID &&
+ p_pmt->pcr.i_current != VLC_TICK_INVALID )
{
- double i_length = TimeStampWrapAround( p_pmt->pcr.i_first,
- p_pmt->i_last_dts ) - p_pmt->pcr.i_first;
+ double i_length = p_pmt->i_last_dts - p_pmt->pcr.i_first;
i_length += p_pmt->pcr.i_pcroffset;
- double i_pos = TimeStampWrapAround( p_pmt->pcr.i_first,
- p_pmt->pcr.i_current ) - p_pmt->pcr.i_first;
+ double i_pos = p_pmt->pcr.i_current - p_pmt->pcr.i_first;
if( i_length > 0 )
{
*pf = i_pos / i_length;
@@ -982,30 +981,30 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
if( p_sys->b_access_control &&
!p_sys->b_ignore_time_for_positions && b_bool && p_pmt )
{
- time_t i_time, i_length;
+ time_t i_time, i_length = 0;
+ vlc_tick_t i_seektime = VLC_TICK_0 + vlc_tick_from_sec( i_length * f );
if( !EITCurrentEventTime( p_pmt, p_sys, &i_time, &i_length ) &&
- i_length > 0 && !SeekToTime( p_demux, p_pmt, (int64_t)(TO_SCALE( vlc_tick_from_sec( i_length * f ))) ) )
+ i_length > 0 && !SeekToTime( p_demux, p_pmt, i_seektime ) )
{
ReadyQueuesPostSeek( p_demux );
- es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
- vlc_tick_from_sec( i_length * f ) );
+ es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_seektime );
return VLC_SUCCESS;
}
}
if( !p_sys->b_ignore_time_for_positions && b_bool && p_pmt &&
- p_pmt->pcr.i_first > -1 && SETANDVALID(p_pmt->i_last_dts) &&
- p_pmt->pcr.i_current > -1 )
+ p_pmt->pcr.i_first != VLC_TICK_INVALID &&
+ p_pmt->i_last_dts != VLC_TICK_INVALID &&
+ p_pmt->pcr.i_current != VLC_TICK_INVALID )
{
- stime_t i_length = TimeStampWrapAround( p_pmt->pcr.i_first,
- p_pmt->i_last_dts ) - p_pmt->pcr.i_first;
- i64 = p_pmt->pcr.i_first + (int64_t)(i_length * f);
+ vlc_tick_t i_length = p_pmt->i_last_dts - p_pmt->pcr.i_first;
+ i64 = p_pmt->pcr.i_first + i_length * f;
if( i64 <= p_pmt->i_last_dts )
{
if( !SeekToTime( p_demux, p_pmt, i64 ) )
{
ReadyQueuesPostSeek( p_demux );
- es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, FROM_SCALE(i64) );
+ es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, i64 );
return VLC_SUCCESS;
}
}
@@ -1024,12 +1023,12 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
{
vlc_tick_t i_time = va_arg( args, vlc_tick_t );
- if( p_sys->b_canseek && p_pmt && p_pmt->pcr.i_first > -1 &&
- !SeekToTime( p_demux, p_pmt, p_pmt->pcr.i_first + TO_SCALE(i_time) ) )
+ if( p_sys->b_canseek && p_pmt && p_pmt->pcr.i_first != VLC_TICK_INVALID &&
+ !SeekToTime( p_demux, p_pmt, p_pmt->pcr.i_first + i_time ) )
{
ReadyQueuesPostSeek( p_demux );
es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
- FROM_SCALE(p_pmt->pcr.i_first) + i_time - VLC_TICK_0 );
+ p_pmt->pcr.i_first + i_time - VLC_TICK_0 );
return VLC_SUCCESS;
}
break;
@@ -1046,20 +1045,19 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
}
}
- if( p_pmt && p_pmt->pcr.i_current > -1 && p_pmt->pcr.i_first > -1 )
+ if( p_pmt && p_pmt->pcr.i_current != VLC_TICK_INVALID && p_pmt->pcr.i_first != VLC_TICK_INVALID )
{
- stime_t i_pcr = TimeStampWrapAround( p_pmt->pcr.i_first, p_pmt->pcr.i_current );
- *va_arg( args, vlc_tick_t * ) = FROM_SCALE(i_pcr - p_pmt->pcr.i_first);
+ *va_arg( args, vlc_tick_t * ) = p_pmt->pcr.i_current - p_pmt->pcr.i_first;
return VLC_SUCCESS;
}
break;
case DEMUX_GET_NORMAL_TIME:
if ((p_sys->b_access_control && !EITCurrentEventTime( p_pmt, p_sys, NULL, NULL))
- || (!p_pmt || p_pmt->pcr.i_current == -1 || p_pmt->pcr.i_first == -1))
+ || (!p_pmt || p_pmt->pcr.i_current == VLC_TICK_INVALID || p_pmt->pcr.i_first == VLC_TICK_INVALID))
return VLC_EGENERIC; /* use VLC_TICK_0 as Normal Play Time*/
/* Use the first pcr of the current program as Normal Play Time */
- *va_arg( args, vlc_tick_t * ) = FROM_SCALE( p_pmt->pcr.i_first );
+ *va_arg( args, vlc_tick_t * ) = p_pmt->pcr.i_first;
return VLC_SUCCESS;
case DEMUX_GET_LENGTH:
@@ -1075,19 +1073,19 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
if( !p_sys->b_ignore_time_for_positions &&
p_pmt &&
- ( p_pmt->pcr.i_first > -1 || p_pmt->pcr.i_first_dts != -1 ) &&
- p_pmt->i_last_dts > 0 )
+ ( p_pmt->pcr.i_first != VLC_TICK_INVALID || p_pmt->pcr.i_first_dts != VLC_TICK_INVALID ) &&
+ p_pmt->i_last_dts != VLC_TICK_INVALID )
{
- stime_t i_start = (p_pmt->pcr.i_first > -1) ? p_pmt->pcr.i_first :
- p_pmt->pcr.i_first_dts;
- stime_t i_last = TimeStampWrapAround( p_pmt->pcr.i_first, p_pmt->i_last_dts );
+ vlc_tick_t i_start = (p_pmt->pcr.i_first != VLC_TICK_INVALID) ? p_pmt->pcr.i_first :
+ p_pmt->pcr.i_first_dts;
+ vlc_tick_t i_last = p_pmt->i_last_dts;
i_last += p_pmt->pcr.i_pcroffset;
if( i_start > i_last )
{
msg_Warn( p_demux, "Can't get stream duration. Edited ?" );
return VLC_EGENERIC;
}
- *va_arg( args, vlc_tick_t * ) = FROM_SCALE(i_last - i_start);
+ *va_arg( args, vlc_tick_t * ) = i_last - i_start;
return VLC_SUCCESS;
}
break;
@@ -1386,7 +1384,7 @@ static vlc_tick_t GetTimeForUntimed( const ts_pmt_t *p_pmt )
if( (p_pid->i_flags & FLAG_FILTERED) && SEEN(p_pid) &&
p_pid->type == TYPE_STREAM &&
p_pid->u.p_stream->p_es &&
- SETANDVALID(p_pid->u.p_stream->i_last_dts) )
+ p_pid->u.p_stream->i_last_dts != VLC_TICK_INVALID )
{
const ts_es_t *p_es = p_pid->u.p_stream->p_es;
if( p_es->fmt.i_cat == VIDEO_ES || p_es->fmt.i_cat == AUDIO_ES )
@@ -1425,24 +1423,19 @@ static block_t * ConvertPESBlock( demux_t *p_demux, ts_es_t *p_es,
{
const ts_pmt_t *p_pmt = p_es->p_program;
if( p_block->i_pts != VLC_TICK_INVALID &&
- p_pmt->pcr.i_current > -1 )
+ p_pmt->pcr.i_current != VLC_TICK_INVALID )
{
/* Teletext can have totally offset timestamps... RAI1, German */
- vlc_tick_t i_pcr = FROM_SCALE(TimeStampWrapAround( p_pmt->pcr.i_first,
- p_pmt->pcr.i_current ));
- if( i_pcr < p_block->i_pts || i_pcr - p_block->i_pts > CLOCK_FREQ )
+ if( p_pmt->pcr.i_current < p_block->i_pts || p_pmt->pcr.i_current - p_block->i_pts > CLOCK_FREQ )
p_block->i_dts = p_block->i_pts = VLC_TICK_INVALID;
}
if( p_block->i_pts == VLC_TICK_INVALID )
{
/* Teletext may have missing PTS (ETSI EN 300 472 Annexe A)
* In this case use the last PCR + 40ms */
- stime_t i_ts = GetTimeForUntimed( p_es->p_program );
- if( SETANDVALID(i_ts) )
- {
- i_ts = TimeStampWrapAround( p_pmt->pcr.i_first, i_ts );
- p_block->i_dts = p_block->i_pts = FROM_SCALE(i_ts) + VLC_TICK_FROM_MS(40);
- }
+ vlc_tick_t i_ts = GetTimeForUntimed( p_es->p_program );
+ if( i_ts != VLC_TICK_INVALID )
+ p_block->i_dts = p_block->i_pts = i_ts + VLC_TICK_FROM_MS(40);
}
}
else if( p_es->fmt.i_codec == VLC_CODEC_ARIB_A ||
@@ -1553,14 +1546,16 @@ static void SendDataChain( demux_t *p_demux, ts_es_t *p_es, block_t *p_chain )
* gathering stuff
****************************************************************************/
static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
- uint32_t i_flags, stime_t i_append_pcr )
+ uint32_t i_flags, ts_90khz_t i_append_pcr )
{
uint8_t header[34];
unsigned i_pes_size = 0;
unsigned i_skip = 0;
- stime_t i_dts = -1;
- stime_t i_pts = -1;
- vlc_tick_t i_length = 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;
@@ -1592,17 +1587,17 @@ 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_dts, &i_pts, &i_stream_id, &b_pes_scrambling ) == VLC_EGENERIC )
+ &i_pktdts, &i_pktpts, &i_stream_id, &b_pes_scrambling ) == VLC_EGENERIC )
{
block_ChainRelease( p_pes );
return;
}
else
{
- if( i_pts != -1 && p_es->p_program )
- i_pts = TimeStampWrapAround( p_es->p_program->pcr.i_first, i_pts );
- if( i_dts != -1 && p_es->p_program )
- i_dts = TimeStampWrapAround( p_es->p_program->pcr.i_first, i_dts );
+ 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 )
p_pes->i_flags |= BLOCK_FLAG_SCRAMBLED;
}
@@ -1661,10 +1656,10 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
}
/* ISO/IEC 13818-1 2.7.5: if no pts and no dts, then dts == pts */
- if( i_pts >= 0 && i_dts < 0 )
+ if( i_pts != VLC_TICK_INVALID && i_dts == VLC_TICK_INVALID )
i_dts = i_pts;
- if( i_dts >= 0 )
+ if( i_dts != TS_90KHZ_INVALID )
pid->u.p_stream->i_last_dts = i_dts;
if( p_pes )
@@ -1676,11 +1671,11 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
return;
}
- if( i_dts >= 0 )
- p_pes->i_dts = FROM_SCALE(i_dts);
+ if( i_dts != VLC_TICK_INVALID )
+ p_pes->i_dts = i_dts;
- if( i_pts >= 0 )
- p_pes->i_pts = FROM_SCALE(i_pts);
+ if( i_pts != VLC_TICK_INVALID )
+ p_pes->i_pts = i_pts;
p_pes->i_length = FROM_SCALE_NZ(i_length);
@@ -1700,7 +1695,7 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
if( !p_pmt->pcr.b_fix_done ) /* Not seen yet */
PCRFixHandle( p_demux, p_pmt, p_block );
- if( p_es->id && (p_pmt->pcr.i_current > -1 || p_pmt->pcr.b_disable) )
+ if( p_es->id && (p_pmt->pcr.i_current != VLC_TICK_INVALID || p_pmt->pcr.b_disable) )
{
if( pid->u.p_stream->prepcr.p_head )
{
@@ -1718,27 +1713,24 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
if ( p_pmt->pcr.b_disable && p_block->i_dts != VLC_TICK_INVALID &&
( p_pmt->i_pid_pcr == pid->i_pid || p_pmt->i_pid_pcr == 0x1FFF ) )
{
- stime_t i_pcr = ( p_block->i_dts > p_sys->i_generated_pcr_dpb_offset )
- ? TO_SCALE(p_block->i_dts - p_sys->i_generated_pcr_dpb_offset)
- : TO_SCALE(p_block->i_dts);
+ vlc_tick_t i_pcr = p_block->i_dts;
+ if( i_pcr > VLC_TICK_0 + p_sys->i_generated_pcr_dpb_offset )
+ i_pcr -= p_sys->i_generated_pcr_dpb_offset;
ProgramSetPCR( p_demux, p_pmt, i_pcr );
}
/* Compute PCR/DTS offset if any */
- stime_t i_pcrref = SETANDVALID(i_append_pcr) ? i_append_pcr : p_pmt->pcr.i_first;
+ vlc_tick_t i_pcrref = (i_append_pcr != TS_90KHZ_INVALID) ? FROM_SCALE(i_append_pcr) : p_pmt->pcr.i_first;
if( p_pmt->pcr.i_pcroffset == -1 && p_block->i_dts != VLC_TICK_INVALID &&
- SETANDVALID(i_pcrref) &&
- (p_es->fmt.i_cat == VIDEO_ES || p_es->fmt.i_cat == AUDIO_ES) )
+ i_pcrref != VLC_TICK_INVALID &&
+ (p_es->fmt.i_cat == VIDEO_ES || p_es->fmt.i_cat == AUDIO_ES) )
{
- stime_t i_dts27 = TO_SCALE(p_block->i_dts);
- i_dts27 = TimeStampWrapAround( i_pcrref, i_dts27 );
- i_pcrref = TimeStampWrapAround( p_pmt->pcr.i_first, i_pcrref );
- if( i_dts27 + (CLOCK_FREQ/90000) < i_pcrref )
+ if( p_block->i_dts + FROM_SCALE_NZ(CLOCK_FREQ/90000) < i_pcrref )
{
- p_pmt->pcr.i_pcroffset = i_pcrref - i_dts27 + TO_SCALE_NZ(VLC_TICK_FROM_MS(80));
+ p_pmt->pcr.i_pcroffset = i_pcrref - p_block->i_dts + VLC_TICK_FROM_MS(80);
msg_Warn( p_demux, "Broken stream: pid %d sends packets with dts %"PRId64
"us later than pcr, applying delay",
- pid->i_pid, FROM_SCALE_NZ(i_pcrref - i_dts27) );
+ pid->i_pid, i_pcrref - p_block->i_dts );
}
else p_pmt->pcr.i_pcroffset = 0;
}
@@ -1746,9 +1738,9 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
if( p_pmt->pcr.i_pcroffset != -1 )
{
if( p_block->i_dts != VLC_TICK_INVALID )
- p_block->i_dts += FROM_SCALE_NZ(p_pmt->pcr.i_pcroffset);
+ p_block->i_dts += p_pmt->pcr.i_pcroffset;
if( p_block->i_pts != VLC_TICK_INVALID )
- p_block->i_pts += FROM_SCALE_NZ(p_pmt->pcr.i_pcroffset);
+ p_block->i_pts += p_pmt->pcr.i_pcroffset;
}
/*** From here, block can become a chain again though conversion below ***/
@@ -1783,7 +1775,7 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
block_ChainLastAppend( &pid->u.p_stream->prepcr.pp_last, p_block );
/* PCR Seen and no es->id, cleanup current and prepcr blocks */
- if( p_pmt->pcr.i_current > -1)
+ if( p_pmt->pcr.i_current != VLC_TICK_INVALID )
{
block_ChainRelease( pid->u.p_stream->prepcr.p_head );
pid->u.p_stream->prepcr.p_head = NULL;
@@ -1799,7 +1791,7 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
}
static void PESDataChainHandle( vlc_object_t *p_obj, void *priv, block_t *p_data,
- uint32_t i_flags, stime_t i_appendpcr )
+ uint32_t i_flags, ts_90khz_t i_appendpcr )
{
ParsePESDataChain( (demux_t *)p_obj, (ts_pid_t *) priv, p_data, i_flags, i_appendpcr );
}
@@ -1882,11 +1874,11 @@ static block_t* ReadTSPacket( demux_t *p_demux )
return p_pkt;
}
-static stime_t GetPCR( const block_t *p_pkt )
+static ts_90khz_t GetPCR( const block_t *p_pkt )
{
const uint8_t *p = p_pkt->p_buffer;
- stime_t i_pcr = -1;
+ ts_90khz_t i_pcr = TS_90KHZ_INVALID;
if(unlikely(p_pkt->i_buffer < 12))
return i_pcr;
@@ -1899,11 +1891,11 @@ static stime_t GetPCR( const block_t *p_pkt )
( p[5] & 0x10 ) ) /* PCR carry flag */
{
/* PCR is 33 bits */
- i_pcr = ( (stime_t)p[6] << 25 ) |
- ( (stime_t)p[7] << 17 ) |
- ( (stime_t)p[8] << 9 ) |
- ( (stime_t)p[9] << 1 ) |
- ( (stime_t)p[10] >> 7 );
+ 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;
}
@@ -1986,7 +1978,7 @@ static void ReadyQueuesPostSeek( demux_t *p_demux )
for( ts_es_t *p_es = p_pes->p_es; p_es; p_es = p_es->p_next )
p_es->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
- pid->u.p_stream->i_last_dts = -1;
+ pid->u.p_stream->i_last_dts = VLC_TICK_INVALID;
if( pid->u.p_stream->prepcr.p_head )
{
@@ -2000,16 +1992,16 @@ static void ReadyQueuesPostSeek( demux_t *p_demux )
FlushESBuffer( pid->u.p_stream );
}
- p_pmt->pcr.i_current = -1;
+ p_pmt->pcr.i_current = VLC_TICK_INVALID;
}
}
-static int SeekToTime( demux_t *p_demux, const ts_pmt_t *p_pmt, stime_t i_scaledtime )
+static int SeekToTime( demux_t *p_demux, const ts_pmt_t *p_pmt, vlc_tick_t i_seektime )
{
demux_sys_t *p_sys = p_demux->p_sys;
/* Deal with common but worst binary search case */
- if( p_pmt->pcr.i_first == i_scaledtime && p_sys->b_canseek )
+ if( p_pmt->pcr.i_first == i_seektime && p_sys->b_canseek )
return vlc_stream_Seek( p_sys->stream, 0 );
const int64_t i_stream_size = stream_Size( p_sys->stream );
@@ -2038,7 +2030,7 @@ static int SeekToTime( demux_t *p_demux, const ts_pmt_t *p_pmt, stime_t i_scaled
uint64_t i_pos = i_splitpos;
while( i_pos < i_tail_pos )
{
- stime_t i_pcr = -1;
+ ts_90khz_t i_pktpcr = TS_90KHZ_INVALID;
block_t *p_pkt = ReadTSPacket( p_demux );
if( !p_pkt )
{
@@ -2058,37 +2050,37 @@ static int SeekToTime( demux_t *p_demux, const ts_pmt_t *p_pmt, stime_t i_scaled
if( p_pkt->i_buffer >= 4 + 2 + 5 )
{
if( p_pmt->i_pid_pcr == i_pid )
- i_pcr = GetPCR( p_pkt );
+ i_pktpcr = GetPCR( p_pkt );
i_skip += 1 + __MIN(p_pkt->p_buffer[4], 182);
}
}
- if( i_pcr == -1 && p_pid->type == TYPE_STREAM &&
+ 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 */
)
{
- stime_t i_dts = -1;
- stime_t i_pts = -1;
+ 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_dts, &i_pts, &i_stream_id, NULL ) )
+ &i_pktdts, &i_pktpts, &i_stream_id, NULL ) )
{
- if( i_dts > -1 )
- i_pcr = i_dts;
+ if( i_pktdts != TS_90KHZ_INVALID )
+ i_pktpcr = i_pktdts;
}
}
}
block_Release( p_pkt );
- if( i_pcr != -1 )
+ if( i_pktpcr != TS_90KHZ_INVALID )
{
- stime_t i_diff = i_scaledtime - TimeStampWrapAround( p_pmt->pcr.i_first, i_pcr );
+ vlc_tick_t i_diff = i_seektime - TimeStampWrapAround( p_pmt->pcr.i_first, FROM_SCALE(i_pktpcr) );
if ( i_diff < 0 )
i_tail_pos = (i_splitpos >= p_sys->i_packet_size) ? i_splitpos - p_sys->i_packet_size : 0;
- else if( i_diff < TO_SCALE(VLC_TICK_0 + VLC_TICK_FROM_MS(500)) )
+ else if( i_diff < VLC_TICK_FROM_MS(500) )
b_found = true;
else
i_head_pos = i_pos;
@@ -2118,7 +2110,7 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, bool *pb_fou
for( ;; )
{
- stime_t i_pcr = -1;
+ ts_90khz_t i_pcr = TS_90KHZ_INVALID;
if( i_count++ > PROBE_CHUNK_COUNT || !( p_pkt = ReadTSPacket( p_demux ) ) )
{
@@ -2146,10 +2138,10 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, bool *pb_fou
i_pcr = GetPCR( p_pkt );
/* Designated PCR pid will be valid, don't repick (on the fly probing) */
- if( i_pcr != -1 && !p_pid->probed.i_pcr_count )
+ if( i_pcr != TS_90KHZ_INVALID && !p_pid->probed.i_pcr_count )
p_pid->probed.i_pcr_count++;
- if( i_pcr == -1 &&
+ if( i_pcr == TS_90KHZ_INVALID &&
(p_pkt->p_buffer[1] & 0xC0) == 0x40 && /* payload start */
(p_pkt->p_buffer[3] & 0xD0) == 0x10 && /* Has payload but is not encrypted */
p_pid->type == TYPE_STREAM &&
@@ -2157,8 +2149,8 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, bool *pb_fou
)
{
b_pcrresult = false;
- stime_t i_dts = -1;
- stime_t i_pts = -1;
+ 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
@@ -2168,14 +2160,14 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, bool *pb_fou
p_pkt->i_buffer - i_skip, &i_skip,
&i_dts, &i_pts, &i_stream_id, NULL ) )
{
- if( i_dts != -1 )
+ if( i_dts != TS_90KHZ_INVALID )
i_pcr = i_dts;
- else if( i_pts != -1 )
+ else if( i_pts != TS_90KHZ_INVALID )
i_pcr = i_pts;
}
}
- if( i_pcr != -1 )
+ if( i_pcr != TS_90KHZ_INVALID )
{
ts_pat_t *p_pat = GetPID(p_sys, 0)->u.p_pat;
for( int i=0; i<p_pat->programs.i_size; i++ )
@@ -2188,17 +2180,17 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, bool *pb_fou
{
if( b_end )
{
- p_pmt->i_last_dts = i_pcr;
+ p_pmt->i_last_dts = FROM_SCALE(i_pcr);
p_pmt->i_last_dts_byte = vlc_stream_Tell( p_sys->stream );
}
/* Start, only keep first */
- else if( b_pcrresult && p_pmt->pcr.i_first == -1 )
+ else if( b_pcrresult && p_pmt->pcr.i_first == VLC_TICK_INVALID )
{
- p_pmt->pcr.i_first = i_pcr;
+ p_pmt->pcr.i_first = FROM_SCALE(i_pcr);
}
- else if( p_pmt->pcr.i_first_dts == -1 )
+ else if( p_pmt->pcr.i_first_dts == VLC_TICK_INVALID )
{
- p_pmt->pcr.i_first_dts = i_pcr;
+ p_pmt->pcr.i_first_dts = FROM_SCALE(i_pcr);
}
if( i_program == 0 || i_program == p_pmt->i_number )
@@ -2280,13 +2272,13 @@ int ProbeEnd( demux_t *p_demux, int i_program )
return (b_found) ? VLC_SUCCESS : VLC_EGENERIC;
}
-static void ProgramSetPCR( demux_t *p_demux, ts_pmt_t *p_pmt, stime_t i_pcr )
+static void ProgramSetPCR( demux_t *p_demux, ts_pmt_t *p_pmt, vlc_tick_t i_pcr )
{
demux_sys_t *p_sys = p_demux->p_sys;
/* Check if we have enqueued blocks waiting the/before the
PCR barrier, and then adapt pcr so they have valid PCR when dequeuing */
- if( p_pmt->pcr.i_current == -1 && p_pmt->pcr.b_fix_done )
+ if( p_pmt->pcr.i_current == VLC_TICK_INVALID && p_pmt->pcr.b_fix_done )
{
vlc_tick_t i_mindts = VLC_TICK_INVALID;
@@ -2312,21 +2304,22 @@ static void ProgramSetPCR( demux_t *p_demux, ts_pmt_t *p_pmt, stime_t i_pcr )
{
msg_Dbg( p_demux, "Program %d PCR prequeue fixup %"PRId64"->%"PRId64,
p_pmt->i_number, TO_SCALE(i_mindts), i_pcr );
- i_pcr = TO_SCALE(i_mindts);
+ i_pcr = i_mindts;
}
else i_pcr = p_pmt->pcr.i_first;
}
}
p_pmt->pcr.i_current = i_pcr;
- if( p_pmt->pcr.i_first == -1 )
+
+ if( p_pmt->pcr.i_first == VLC_TICK_INVALID )
{
p_pmt->pcr.i_first = i_pcr; // now seen
}
if ( p_sys->i_pmt_es )
{
- es_out_Control( p_demux->out, ES_OUT_SET_GROUP_PCR, p_pmt->i_number, FROM_SCALE(i_pcr) );
+ es_out_Control( p_demux->out, ES_OUT_SET_GROUP_PCR, p_pmt->i_number, i_pcr );
/* growing files/named fifo handling */
if( p_sys->b_access_control == false &&
vlc_stream_Tell( p_sys->stream ) > p_pmt->i_last_dts_byte )
@@ -2364,7 +2357,7 @@ static int IsVideoEnd( ts_pid_t *p_pid )
( tail[ i_tail - 1 ] == 0xb7 || tail[ i_tail - 1 ] == 0x0a ) );
}
-static void PCRCheckDTS( demux_t *p_demux, ts_pmt_t *p_pmt, stime_t i_pcr)
+static void PCRCheckDTS( demux_t *p_demux, ts_pmt_t *p_pmt, vlc_tick_t i_pcr)
{
for( int i=0; i<p_pmt->e_streams.i_size; i++ )
{
@@ -2394,33 +2387,35 @@ static void PCRCheckDTS( demux_t *p_demux, ts_pmt_t *p_pmt, stime_t i_pcr)
continue;
unsigned i_skip = 0;
- stime_t i_dts = -1;
- stime_t i_pts = -1;
+ 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_dts, &i_pts, &i_stream_id, NULL ) == VLC_EGENERIC )
+ &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 (p_pmt->pcr.i_pcroffset > 0) {
- if( i_dts != -1 )
+ if( i_dts != VLC_TICK_INVALID )
i_dts += p_pmt->pcr.i_pcroffset;
- if( i_pts != -1 )
+ if( i_pts != VLC_TICK_INVALID )
i_pts += p_pmt->pcr.i_pcroffset;
}
- if( i_dts != -1 )
- i_dts = TimeStampWrapAround( i_pcr, i_dts );
- if( i_pts != -1 )
- i_pts = TimeStampWrapAround( i_pcr, i_pts );
-
- if(( i_dts != -1 && i_dts <= i_pcr ) ||
- ( i_pts != -1 && i_pts <= i_pcr ))
+ if(( i_dts != VLC_TICK_INVALID && i_dts <= i_pcr ) ||
+ ( i_pts != VLC_TICK_INVALID && i_pts <= i_pcr ))
{
if( IsVideoEnd( p_pid ) )
{
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);
+ p_pid->i_pid, i_dts != VLC_TICK_INVALID ? i_dts : i_pts, i_pcr);
ts_pes_parse_callback cb = { .p_obj = VLC_OBJECT(p_demux),
.priv = p_pid,
.pf_parse = PESDataChainHandle };
@@ -2430,7 +2425,7 @@ static void PCRCheckDTS( demux_t *p_demux, ts_pmt_t *p_pmt, stime_t i_pcr)
}
}
-static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, stime_t i_pcr )
+static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, ts_90khz_t i_pcr )
{
demux_sys_t *p_sys = p_demux->p_sys;
@@ -2449,7 +2444,12 @@ static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, stime_t i_pcr )
ts_pmt_t *p_pmt = p_pat->programs.p_elems[i]->u.p_pmt;
if( p_pmt->pcr.b_disable )
continue;
- stime_t i_program_pcr = TimeStampWrapAround( p_pmt->pcr.i_first, i_pcr );
+
+ vlc_tick_t i_past_pcr = p_pmt->pcr.i_current;
+ if( i_past_pcr == VLC_TICK_INVALID )
+ i_past_pcr = p_pmt->pcr.i_first;
+
+ vlc_tick_t i_program_pcr = TimeStampWrapAround( i_past_pcr, FROM_SCALE(i_pcr) );
if( p_pmt->i_pid_pcr == 0x1FFF ) /* That program has no dedicated PCR pid ISO/IEC 13818-1 2.4.4.9 */
{
@@ -2465,7 +2465,7 @@ static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, stime_t i_pcr )
if( p_pmt->i_pid_pcr == pid->i_pid ) /* If that program references current pid as PCR */
{
/* We've found a target group for update */
- PCRCheckDTS( p_demux, p_pmt, i_pcr );
+ PCRCheckDTS( p_demux, p_pmt, FROM_SCALE(i_pcr) );
ProgramSetPCR( p_demux, p_pmt, i_program_pcr );
}
}
@@ -2525,13 +2525,13 @@ static void PCRFixHandle( demux_t *p_demux, ts_pmt_t *p_pmt, block_t *p_block )
return;
}
/* Record the first data packet timestamp in case there won't be any PCR */
- else if( p_pmt->pcr.i_first_dts == TS_TICK_UNKNOWN )
+ else if( p_pmt->pcr.i_first_dts == VLC_TICK_INVALID )
{
p_pmt->pcr.i_first_dts = TO_SCALE(p_block->i_dts);
}
else if( p_block->i_dts - FROM_SCALE(p_pmt->pcr.i_first_dts) > VLC_TICK_FROM_MS(500) ) /* "PCR repeat rate shall not exceed 100ms" */
{
- if( p_pmt->pcr.i_current < 0 &&
+ if( p_pmt->pcr.i_current == VLC_TICK_INVALID &&
GetPID( p_sys, p_pmt->i_pid_pcr )->probed.i_pcr_count == 0 )
{
int i_cand = FindPCRCandidate( p_pmt );
@@ -2697,12 +2697,14 @@ static bool GatherPESData( demux_t *p_demux, ts_pid_t *p_pid, block_t *p_pkt, si
.priv = p_pid,
.pf_parse = PESDataChainHandle };
const bool b_unit_start = p_pkt->p_buffer[1]&0x40;
+
p_pkt->p_buffer += i_skip; /* point to PES */
p_pkt->i_buffer -= i_skip;
const ts_es_t *p_es = p_pid->u.p_stream->p_es;
- stime_t i_append_pcr = ( p_es && p_es->p_program )
- ? p_es->p_program->pcr.i_current : TS_TICK_UNKNOWN;
+ ts_90khz_t i_append_pcr = ( p_es && p_es->p_program && p_es->p_program->pcr.i_current != VLC_TICK_INVALID )
+ ? TO_SCALE(p_es->p_program->pcr.i_current)
+ : TS_90KHZ_INVALID;
return ts_pes_Gather( &cb, p_pid->u.p_stream,
p_pkt, b_unit_start,
=====================================
modules/demux/mpeg/ts.h
=====================================
@@ -31,12 +31,6 @@ typedef struct csa_t csa_t;
#define TS_PSI_PAT_PID 0x00
-_Static_assert (VLC_TICK_INVALID + 1 == VLC_TICK_0,
- "can't define TS_UNKNOWN reference");
-#define TS_TICK_UNKNOWN (VLC_TICK_INVALID - 1)
-
-#define SETANDVALID(a) (a != TS_TICK_UNKNOWN && a != VLC_TICK_INVALID)
-
typedef enum ts_standards_e
{
TS_STANDARD_AUTO = 0,
@@ -130,7 +124,7 @@ struct demux_sys_t
struct
{
- stime_t i_first_dts; /* first dts encountered for the stream */
+ vlc_tick_t i_first_dts; /* first dts encountered for the stream */
int i_timesourcepid; /* which pid we saved the dts from */
bool b_pcrhasnopcrfield;
enum { PAT_WAITING = 0, PAT_MISSING, PAT_FIXTRIED } status; /* set if we haven't seen PAT within MIN_PAT_INTERVAL */
=====================================
modules/demux/mpeg/ts_hotfixes.c
=====================================
@@ -82,7 +82,7 @@ void ProbePES( demux_t *p_demux, ts_pid_t *pid, const uint8_t *p_pesstart, size_
return;
size_t i_pesextoffset = 8;
- stime_t i_dts = -1;
+ ts_90khz_t i_dts = TS_90KHZ_INVALID;
if( p_pes[7] & 0x80 ) // PTS
{
i_pesextoffset += 5;
@@ -197,15 +197,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 > -1 )
+ if( !p_sys->patfix.i_timesourcepid && i_dts != TS_90KHZ_INVALID )
{
- p_sys->patfix.i_first_dts = i_dts;
+ p_sys->patfix.i_first_dts = FROM_SCALE(i_dts);
p_sys->patfix.i_timesourcepid = pid->i_pid;
}
- else if( p_sys->patfix.i_timesourcepid == pid->i_pid && i_dts > -1 &&
+ else if( p_sys->patfix.i_timesourcepid == pid->i_pid && i_dts != TS_90KHZ_INVALID &&
p_sys->patfix.status == PAT_WAITING )
{
- if( i_dts - p_sys->patfix.i_first_dts > TO_SCALE(MIN_PAT_INTERVAL) )
+ if( i_dts - p_sys->patfix.i_first_dts > MIN_PAT_INTERVAL )
p_sys->patfix.status = PAT_MISSING;
}
=====================================
modules/demux/mpeg/ts_pes.c
=====================================
@@ -98,7 +98,7 @@ static uint8_t *FindNextPESHeader( uint8_t *p_buf, size_t i_buffer )
static bool ts_pes_Push( ts_pes_parse_callback *cb,
ts_stream_t *p_pes, block_t *p_pkt,
- bool b_unit_start, stime_t i_append_pcr )
+ bool b_unit_start, ts_90khz_t i_append_pcr )
{
bool b_ret = false;
@@ -167,7 +167,7 @@ bool ts_pes_Drain( ts_pes_parse_callback *cb, ts_stream_t *p_pes )
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,
- stime_t i_append_pcr )
+ ts_90khz_t i_append_pcr )
{
bool b_ret = false;
bool b_single_payload = b_unit_start; /* Single payload in case of unit start */
=====================================
modules/demux/mpeg/ts_pes.h
=====================================
@@ -20,6 +20,8 @@
#ifndef VLC_TS_PES_H
#define VLC_TS_PES_H
+#include "timestamps.h"
+
#define BLOCK_FLAG_PRIVATE_SOURCE_RANDOM_ACCESS (1 << BLOCK_FLAG_PRIVATE_SHIFT)
#define BLOCK_FLAG_PRIVATE_PACKET_LOSS (2 << BLOCK_FLAG_PRIVATE_SHIFT)
@@ -29,7 +31,7 @@ typedef struct
{
vlc_object_t *p_obj;
void *priv;
- void(*pf_parse)(vlc_object_t *, void *, block_t *, uint32_t, stime_t );
+ void(*pf_parse)(vlc_object_t *, void *, block_t *, uint32_t, ts_90khz_t );
} ts_pes_parse_callback;
bool ts_pes_Drain( ts_pes_parse_callback *cb, ts_stream_t *p_pes );
@@ -37,7 +39,7 @@ bool ts_pes_Drain( ts_pes_parse_callback *cb, ts_stream_t *p_pes );
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,
- stime_t i_append_pcr );
+ ts_90khz_t i_append_pcr );
#endif
=====================================
modules/demux/mpeg/ts_psi.c
=====================================
@@ -2227,11 +2227,11 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt )
UpdatePESFilters( p_demux, p_sys->seltype == PROGRAM_ALL );
/* Probe Boundaries */
- if( p_sys->b_canfastseek && p_pmt->i_last_dts == TS_TICK_UNKNOWN )
+ if( p_sys->b_canfastseek && !p_pmt->b_last_dts_probed )
{
- p_pmt->i_last_dts = 0;
ProbeStart( p_demux, p_pmt->i_number );
ProbeEnd( p_demux, p_pmt->i_number );
+ p_pmt->b_last_dts_probed = true;
}
dvbpsi_pmt_delete( p_dvbpsipmt );
=====================================
modules/demux/mpeg/ts_scte.c
=====================================
@@ -61,10 +61,9 @@ void SCTE18_Section_Callback( dvbpsi_t *p_handle, const dvbpsi_psi_section_t* p_
continue;
const ts_pmt_t *p_pmt = p_es->p_program;
- const stime_t i_date = TimeStampWrapAround( p_pmt->pcr.i_first, p_pmt->pcr.i_current );
block_t *p_block = block_Alloc( p_section->p_payload_end - p_section->p_payload_start );
memcpy( p_block->p_buffer, p_section->p_payload_start, i_payload );
- p_block->i_dts = p_block->i_pts = FROM_SCALE( i_date );
+ p_block->i_dts = p_block->i_pts = p_pmt->pcr.i_current;
es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, p_es->id, true );
es_out_Send( p_demux->out, p_es->id, p_block );
@@ -81,7 +80,7 @@ void SCTE27_Section_Callback( demux_t *p_demux,
ts_stream_t *p_pes = (ts_stream_t *) p_pes_cb_data;
assert( p_pes->p_es->fmt.i_codec == VLC_CODEC_SCTE_27 );
ts_pmt_t *p_pmt = p_pes->p_es->p_program;
- stime_t i_date = p_pmt->pcr.i_current;
+ vlc_tick_t i_date = p_pmt->pcr.i_current;
block_t *p_content = block_Alloc( i_sectiondata );
if( unlikely(!p_content) || unlikely(!p_pes->p_es->id) )
@@ -102,9 +101,9 @@ void SCTE27_Section_Callback( demux_t *p_demux,
bool is_immediate = p_content->p_buffer[i_offset + 3] & 0x40;
if( !is_immediate )
{
- stime_t i_display_in = GetDWBE( &p_content->p_buffer[i_offset + 4] );
+ vlc_tick_t i_display_in = FROM_SCALE(GetDWBE( &p_content->p_buffer[i_offset + 4] ));
if( i_display_in < i_date )
- i_date = i_display_in + (1ll << 32);
+ i_date = i_display_in + FROM_SCALE_NZ(1ll << 32);
else
i_date = i_display_in;
}
=====================================
modules/demux/mpeg/ts_streams.c
=====================================
@@ -104,16 +104,17 @@ ts_pmt_t *ts_pmt_New( demux_t *p_demux )
pmt->od.i_version = -1;
ARRAY_INIT( pmt->od.objects );
- pmt->i_last_dts = TS_TICK_UNKNOWN;
+ pmt->i_last_dts = VLC_TICK_INVALID;
pmt->i_last_dts_byte = 0;
+ pmt->b_last_dts_probed = false;
pmt->p_atsc_si_basepid = NULL;
pmt->p_si_sdt_pid = NULL;
- pmt->pcr.i_current = TS_TICK_UNKNOWN;
- pmt->pcr.i_first = TS_TICK_UNKNOWN;
+ pmt->pcr.i_current = VLC_TICK_INVALID;
+ pmt->pcr.i_first = VLC_TICK_INVALID;
pmt->pcr.b_disable = false;
- pmt->pcr.i_first_dts = TS_TICK_UNKNOWN;
+ pmt->pcr.i_first_dts = VLC_TICK_INVALID;
pmt->pcr.i_pcroffset = -1;
pmt->pcr.b_fix_done = false;
@@ -270,14 +271,14 @@ ts_stream_t *ts_stream_New( demux_t *p_demux, ts_pmt_t *p_program )
pes->gather.pp_last = &pes->gather.p_data;
pes->gather.i_saved = 0;
pes->gather.i_block_flags = 0;
- pes->gather.i_append_pcr = VLC_TICK_INVALID;
+ pes->gather.i_append_pcr = TS_90KHZ_INVALID;
pes->b_broken_PUSI_conformance = false;
pes->b_always_receive = false;
pes->p_sections_proc = NULL;
pes->p_proc = NULL;
pes->prepcr.p_head = NULL;
pes->prepcr.pp_last = &pes->prepcr.p_head;
- pes->i_last_dts = -1;
+ pes->i_last_dts = VLC_TICK_INVALID;
return pes;
}
=====================================
modules/demux/mpeg/ts_streams_private.h
=====================================
@@ -59,11 +59,11 @@ struct ts_pmt_t
struct
{
- stime_t i_current;
- stime_t i_first; // seen <> != TS_TICK_UNKNOWN
+ vlc_tick_t i_current;
+ vlc_tick_t i_first; // seen <> != TS_TICK_UNKNOWN
/* broken PCR handling */
- stime_t i_first_dts;
- stime_t i_pcroffset;
+ vlc_tick_t i_first_dts;
+ vlc_tick_t i_pcroffset;
bool b_disable; /* ignore PCR field, use dts */
bool b_fix_done;
} pcr;
@@ -74,8 +74,9 @@ struct ts_pmt_t
time_t i_event_length;
} eit;
- stime_t i_last_dts;
+ vlc_tick_t i_last_dts;
uint64_t i_last_dts_byte;
+ bool b_last_dts_probed;
/* CA */
//en50221_capmt_info_t *capmt;
@@ -131,7 +132,7 @@ struct ts_stream_t
block_t **pp_last;
uint8_t saved[5];
size_t i_saved;
- stime_t i_append_pcr;
+ ts_90khz_t i_append_pcr;
uint32_t i_block_flags;
} gather;
@@ -146,7 +147,7 @@ struct ts_stream_t
block_t **pp_last;
} prepcr;
- stime_t i_last_dts;
+ vlc_tick_t i_last_dts;
};
typedef struct ts_si_context_t ts_si_context_t;
=====================================
modules/demux/pva.c
=====================================
@@ -148,7 +148,7 @@ static int Demux( demux_t *p_demux )
const uint8_t *p_peek;
int i_size;
block_t *p_frame;
- int64_t i_pts;
+ ts_90khz_t i_pts;
int i_skip;
if( vlc_stream_Peek( p_demux->s, &p_peek, 8 ) < 8 )
@@ -190,7 +190,7 @@ static int Demux( demux_t *p_demux )
p_sys->i_vc = p_peek[3];
/* read the PTS and potential extra bytes TODO: make it a bit more optimised */
- i_pts = -1;
+ i_pts = TS_90KHZ_INVALID;
i_skip = 8;
if( p_peek[5]&0x10 )
{
@@ -233,7 +233,7 @@ static int Demux( demux_t *p_demux )
{
p_frame->p_buffer += i_skip;
p_frame->i_buffer -= i_skip;
- if( i_pts >= 0 )
+ if( i_pts != TS_90KHZ_INVALID )
p_frame->i_pts = FROM_SCALE(i_pts);
block_ChainAppend( &p_sys->p_es, p_frame );
}
@@ -399,8 +399,8 @@ static void ParsePES( demux_t *p_demux )
uint8_t hdr[30];
unsigned i_skip;
- stime_t i_dts = -1;
- stime_t i_pts = -1;
+ ts_90khz_t i_dts = TS_90KHZ_INVALID;
+ ts_90khz_t i_pts = TS_90KHZ_INVALID;
p_sys->p_pes = NULL;
@@ -442,9 +442,9 @@ static void ParsePES( demux_t *p_demux )
p_pes->i_buffer -= i_skip;
p_pes->p_buffer += i_skip;
- if( i_dts >= 0 )
+ if( i_dts != TS_90KHZ_INVALID )
p_pes->i_dts = FROM_SCALE(i_dts);
- if( i_pts >= 0 )
+ if( i_pts != TS_90KHZ_INVALID )
p_pes->i_pts = FROM_SCALE(i_pts);
/* Set PCR */
=====================================
modules/demux/ty.c
=====================================
@@ -565,7 +565,7 @@ static void Close( vlc_object_t *p_this )
* Assume buf points to beginning of PTS */
static vlc_tick_t get_pts( const uint8_t *buf )
{
- stime_t i_pts = GetPESTimestamp( buf );
+ ts_90khz_t i_pts = GetPESTimestamp( buf );
return FROM_SCALE_NZ(i_pts); /* convert PTS (90Khz clock) to microseconds */
}
=====================================
test/Makefile.am
=====================================
@@ -54,6 +54,7 @@ check_PROGRAMS = \
test_modules_packetizer_mpegvideo \
test_modules_codec_hxxx_helper \
test_modules_keystore \
+ test_modules_demux_timestamps \
test_modules_demux_timestamps_filter \
test_modules_demux_ts_pes \
test_modules_playlist_m3u \
@@ -254,6 +255,7 @@ test_modules_keystore_SOURCES = modules/keystore/test.c
test_modules_keystore_LDADD = $(LIBVLCCORE) $(LIBVLC)
test_modules_tls_SOURCES = modules/misc/tls.c
test_modules_tls_LDADD = $(LIBVLCCORE) $(LIBVLC)
+test_modules_demux_timestamps_SOURCES = modules/demux/timestamps.c
test_modules_demux_timestamps_filter_LDADD = $(LIBVLCCORE) $(LIBVLC)
test_modules_demux_timestamps_filter_SOURCES = modules/demux/timestamps_filter.c
test_modules_demux_ts_pes_LDADD = $(LIBVLCCORE) $(LIBVLC)
=====================================
test/modules/demux/timestamps.c
=====================================
@@ -0,0 +1,97 @@
+/*****************************************************************************
+ * timestamps.c:
+ *****************************************************************************
+ * Copyright © 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 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_tick.h>
+
+#include "../../../modules/demux/mpeg/timestamps.h"
+
+#define ASSERT(a) do {\
+if(!(a)) { \
+ fprintf(stderr, "failed line %d\n", __LINE__); \
+ return 1; } \
+} while(0)
+
+int main(void)
+{
+ /* Should not wrap without reference */
+ vlc_tick_t ts1 = 50;
+ vlc_tick_t ts2 = TimeStampWrapAround(VLC_TICK_INVALID, ts1);
+ ASSERT(ts2 == ts1);
+
+ ts1 = TS_33BITS_ROLL_NZ * 3/4;
+ ts2 = TimeStampWrapAround(VLC_TICK_INVALID, ts1);
+ ASSERT(ts2 == ts1);
+
+ /* Should not wrap */
+ ts1 = VLC_TICK_0 + TS_33BITS_HALF_ROLL_NZ;
+ ts2 = TimeStampWrapAround(VLC_TICK_0, ts1);
+ ASSERT(ts2 == ts1);
+
+ ts1 = VLC_TICK_0 + TS_33BITS_ROLL_NZ;
+ ts2 = TimeStampWrapAround(VLC_TICK_0, ts1);
+ ASSERT(ts2 == ts1);
+
+ ts1 = VLC_TICK_0 + TS_33BITS_ROLL_NZ;
+ ts2 = TimeStampWrapAround(ts1, ts1);
+ ASSERT(ts2 == ts1);
+
+ ts1 = VLC_TICK_0 + TS_33BITS_ROLL_NZ;
+ ts2 = TimeStampWrapAround(ts1 - 100, ts1);
+ ASSERT(ts2 == ts1);
+
+ ts1 = VLC_TICK_0 + TS_33BITS_ROLL_NZ;
+ ts2 = TimeStampWrapAround(VLC_TICK_0 + TS_33BITS_HALF_ROLL_NZ, ts1);
+ ASSERT(ts2 == ts1);
+
+ /* Should wrap */
+ ts1 = VLC_TICK_0;
+ ts2 = TimeStampWrapAround(VLC_TICK_0 + TS_33BITS_HALF_ROLL_NZ, ts1);
+ ASSERT(ts2 > ts1);
+ ASSERT(ts2 == ts1 + TS_33BITS_ROLL_NZ);
+
+ ts1 = VLC_TICK_0;
+ ts2 = TimeStampWrapAround(VLC_TICK_0 + TS_33BITS_ROLL_NZ * 3/4, ts1);
+ ASSERT(ts2 == ts1 + TS_33BITS_ROLL_NZ);
+
+ ts1 = VLC_TICK_0;
+ ts2 = TimeStampWrapAround(VLC_TICK_0 + TS_33BITS_ROLL_NZ, ts1);
+ ASSERT(ts2 == ts1 + TS_33BITS_ROLL_NZ);
+
+ ts1 = VLC_TICK_0 + TS_33BITS_HALF_ROLL_NZ;
+ ts2 = TimeStampWrapAround(VLC_TICK_0 + TS_33BITS_ROLL_NZ, ts1);
+ ASSERT(ts2 == ts1 + TS_33BITS_ROLL_NZ);
+
+ /* Should wrap multiple times */
+ ts1 = VLC_TICK_0;
+ ts2 = TimeStampWrapAround(VLC_TICK_0 + TS_33BITS_ROLL_NZ * 2, ts1);
+ ASSERT(ts2 > ts1);
+ ASSERT(ts2 == ts1 + TS_33BITS_ROLL_NZ * 2);
+
+ ts1 = VLC_TICK_0 + TS_33BITS_HALF_ROLL_NZ;
+ ts2 = TimeStampWrapAround(VLC_TICK_0 + TS_33BITS_ROLL_NZ * 5, ts1);
+ ASSERT(ts2 > ts1);
+ ASSERT(ts2 == ts1 + TS_33BITS_ROLL_NZ * 5);
+
+ return 0;
+}
=====================================
test/modules/demux/ts_pes.c
=====================================
@@ -32,7 +32,7 @@
#include "../../libvlc/test.h"
static void Parse(vlc_object_t *obj, void *priv, block_t *data,
- uint32_t i_flags, stime_t t)
+ uint32_t i_flags, ts_90khz_t t)
{
VLC_UNUSED(obj);
VLC_UNUSED(t);
=====================================
test/modules/meson.build
=====================================
@@ -75,6 +75,12 @@ vlc_tests += {
}
endif
+vlc_tests += {
+ 'name' : 'test_modules_demux_timestamps',
+ 'sources' : files('demux/timestamps.c'),
+ 'suite' : ['modules', 'test_modules']
+}
+
vlc_tests += {
'name' : 'test_modules_demux_timestamps_filter',
'sources' : files('demux/timestamps_filter.c'),
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/0626b7cdc0ddae673595ef6c1a72a53377023e29...caf3ea133abc93da7d640fbec5243e3478c3e1d8
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/0626b7cdc0ddae673595ef6c1a72a53377023e29...caf3ea133abc93da7d640fbec5243e3478c3e1d8
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