Skip to content

Commit 225e0bc

Browse files
committed
demux: ts: check pcr offset with value prior matching sync code
otherwise the last value is always overwritten with a more recent one and triggers the dts < pcr case ref #25034
1 parent b318f85 commit 225e0bc

File tree

6 files changed

+63
-46
lines changed

6 files changed

+63
-46
lines changed

modules/demux/mpeg/ts.c

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,7 +1532,8 @@ static void SendDataChain( demux_t *p_demux, ts_es_t *p_es, block_t *p_chain )
15321532
/****************************************************************************
15331533
* gathering stuff
15341534
****************************************************************************/
1535-
static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
1535+
static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
1536+
stime_t i_append_pcr )
15361537
{
15371538
uint8_t header[34];
15381539
unsigned i_pes_size = 0;
@@ -1698,19 +1699,20 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
16981699
}
16991700

17001701
/* Compute PCR/DTS offset if any */
1702+
stime_t i_pcrref = SETANDVALID(i_append_pcr) ? i_append_pcr : p_pmt->pcr.i_first;
17011703
if( p_pmt->pcr.i_pcroffset == -1 && p_block->i_dts != VLC_TICK_INVALID &&
1702-
SETANDVALID(p_pmt->pcr.i_current) &&
1704+
SETANDVALID(i_pcrref) &&
17031705
(p_es->fmt.i_cat == VIDEO_ES || p_es->fmt.i_cat == AUDIO_ES) )
17041706
{
17051707
stime_t i_dts27 = TO_SCALE(p_block->i_dts);
1706-
i_dts27 = TimeStampWrapAround( p_pmt->pcr.i_first, i_dts27 );
1707-
stime_t i_pcr = TimeStampWrapAround( p_pmt->pcr.i_first, p_pmt->pcr.i_current );
1708-
if( i_dts27 < i_pcr )
1708+
i_dts27 = TimeStampWrapAround( i_pcrref, i_dts27 );
1709+
i_pcrref = TimeStampWrapAround( p_pmt->pcr.i_first, i_pcrref );
1710+
if( i_dts27 + (CLOCK_FREQ/90000) < i_pcrref )
17091711
{
1710-
p_pmt->pcr.i_pcroffset = i_pcr - i_dts27 + TO_SCALE_NZ(VLC_TICK_FROM_MS(80));
1712+
p_pmt->pcr.i_pcroffset = i_pcrref - i_dts27 + TO_SCALE_NZ(VLC_TICK_FROM_MS(80));
17111713
msg_Warn( p_demux, "Broken stream: pid %d sends packets with dts %"PRId64
17121714
"us later than pcr, applying delay",
1713-
pid->i_pid, FROM_SCALE_NZ(p_pmt->pcr.i_pcroffset) );
1715+
pid->i_pid, FROM_SCALE_NZ(i_pcrref - i_dts27) );
17141716
}
17151717
else p_pmt->pcr.i_pcroffset = 0;
17161718
}
@@ -1762,9 +1764,9 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
17621764
}
17631765
}
17641766

1765-
static void PESDataChainHandle( vlc_object_t *p_obj, void *priv, block_t *p_data )
1767+
static void PESDataChainHandle( vlc_object_t *p_obj, void *priv, block_t *p_data, stime_t i_appendpcr )
17661768
{
1767-
ParsePESDataChain( (demux_t *)p_obj, (ts_pid_t *) priv, p_data );
1769+
ParsePESDataChain( (demux_t *)p_obj, (ts_pid_t *) priv, p_data, i_appendpcr );
17681770
}
17691771

17701772
static block_t* ReadTSPacket( demux_t *p_demux )
@@ -2640,9 +2642,15 @@ static bool GatherPESData( demux_t *p_demux, ts_pid_t *p_pid, block_t *p_pkt, si
26402642
const bool b_unit_start = p_pkt->p_buffer[1]&0x40;
26412643
p_pkt->p_buffer += i_skip; /* point to PES */
26422644
p_pkt->i_buffer -= i_skip;
2645+
2646+
const ts_es_t *p_es = p_pid->u.p_stream->p_es;
2647+
stime_t i_append_pcr = ( p_es && p_es->p_program )
2648+
? p_es->p_program->pcr.i_current : TS_TICK_UNKNOWN;
2649+
26432650
return ts_pes_Gather( &cb, p_pid->u.p_stream,
26442651
p_pkt, b_unit_start,
2645-
p_sys->b_valid_scrambling );
2652+
p_sys->b_valid_scrambling,
2653+
i_append_pcr );
26462654
}
26472655

26482656
static bool GatherSectionsData( demux_t *p_demux, ts_pid_t *p_pid, block_t *p_pkt, size_t i_skip )

modules/demux/mpeg/ts_pes.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ static uint8_t *FindNextPESHeader( uint8_t *p_buf, size_t i_buffer )
9797
}
9898

9999
static bool ts_pes_Push( ts_pes_parse_callback *cb,
100-
ts_stream_t *p_pes, block_t *p_pkt, bool b_unit_start )
100+
ts_stream_t *p_pes, block_t *p_pkt,
101+
bool b_unit_start, stime_t i_append_pcr )
101102
{
102103
bool b_ret = false;
103104

@@ -109,10 +110,13 @@ static bool ts_pes_Push( ts_pes_parse_callback *cb,
109110
p_pes->gather.i_data_size = 0;
110111
p_pes->gather.i_gathered = 0;
111112
p_pes->gather.pp_last = &p_pes->gather.p_data;
112-
cb->pf_parse( cb->p_obj, cb->priv, p_datachain );
113+
cb->pf_parse( cb->p_obj, cb->priv, p_datachain, p_pes->gather.i_append_pcr );
113114
b_ret = true;
114115
}
115116

117+
if( b_unit_start )
118+
p_pes->gather.i_append_pcr = i_append_pcr;
119+
116120
if( p_pkt == NULL )
117121
return b_ret;
118122

@@ -137,20 +141,21 @@ static bool ts_pes_Push( ts_pes_parse_callback *cb,
137141
{
138142
/* re-enter in Flush above */
139143
assert(p_pes->gather.p_data);
140-
return ts_pes_Push( cb, p_pes, NULL, true );
144+
return ts_pes_Push( cb, p_pes, NULL, true, i_append_pcr );
141145
}
142146

143147
return b_ret;
144148
}
145149

146150
bool ts_pes_Drain( ts_pes_parse_callback *cb, ts_stream_t *p_pes )
147151
{
148-
return ts_pes_Push( cb, p_pes, NULL, true );
152+
return ts_pes_Push( cb, p_pes, NULL, true, VLC_TICK_INVALID );
149153
}
150154

151155
bool ts_pes_Gather( ts_pes_parse_callback *cb,
152156
ts_stream_t *p_pes, block_t *p_pkt,
153-
bool b_unit_start, bool b_valid_scrambling )
157+
bool b_unit_start, bool b_valid_scrambling,
158+
stime_t i_append_pcr )
154159
{
155160
bool b_ret = false;
156161
bool b_single_payload = b_unit_start; /* Single payload in case of unit start */
@@ -169,7 +174,7 @@ bool ts_pes_Gather( ts_pes_parse_callback *cb,
169174
if( (p_pkt->i_flags & BLOCK_FLAG_SCRAMBLED) && b_valid_scrambling )
170175
{
171176
block_Release( p_pkt );
172-
return ts_pes_Push( cb, p_pes, NULL, true );
177+
return ts_pes_Push( cb, p_pes, NULL, true, i_append_pcr );
173178
}
174179

175180
/* Seek discontinuity, we need to drop or output currently
@@ -178,7 +183,7 @@ bool ts_pes_Gather( ts_pes_parse_callback *cb,
178183
{
179184
p_pes->gather.i_saved = 0;
180185
/* Flush/output current */
181-
b_ret |= ts_pes_Push( cb, p_pes, NULL, true );
186+
b_ret |= ts_pes_Push( cb, p_pes, NULL, true, i_append_pcr );
182187
/* Propagate to output block to notify packetizers/decoders */
183188
if( p_pes->p_es )
184189
p_pes->p_es->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
@@ -260,7 +265,7 @@ bool ts_pes_Gather( ts_pes_parse_callback *cb,
260265
/* Append whole block */
261266
if( likely(p_pkt->i_buffer <= i_remain) )
262267
{
263-
b_ret |= ts_pes_Push( cb, p_pes, p_pkt, p_pes->gather.p_data == NULL );
268+
b_ret |= ts_pes_Push( cb, p_pes, p_pkt, p_pes->gather.p_data == NULL, i_append_pcr );
264269
p_pkt = NULL;
265270
}
266271
else /* p_pkt->i_buffer > i_remain */
@@ -271,7 +276,7 @@ bool ts_pes_Gather( ts_pes_parse_callback *cb,
271276
block_Release( p_pkt );
272277
return false;
273278
}
274-
b_ret |= ts_pes_Push( cb, p_pes, p_pkt, p_pes->gather.p_data == NULL );
279+
b_ret |= ts_pes_Push( cb, p_pes, p_pkt, p_pes->gather.p_data == NULL, i_append_pcr );
275280
p_pkt = p_split;
276281
b_first_sync_done = false;
277282
}
@@ -280,7 +285,7 @@ bool ts_pes_Gather( ts_pes_parse_callback *cb,
280285
{
281286
if( likely(b_aligned_ts_payload) && b_unit_start )
282287
{
283-
b_ret |= ts_pes_Push( cb, p_pes, NULL, true );
288+
b_ret |= ts_pes_Push( cb, p_pes, NULL, true, i_append_pcr );
284289
/* now points to PES header */
285290
if( p_pkt->i_buffer >= 6 )
286291
{
@@ -290,7 +295,7 @@ bool ts_pes_Gather( ts_pes_parse_callback *cb,
290295
}
291296
}
292297
/* Append or finish current/start new PES depending on unit_start */
293-
b_ret |= ts_pes_Push( cb, p_pes, p_pkt, b_unit_start );
298+
b_ret |= ts_pes_Push( cb, p_pes, p_pkt, b_unit_start, i_append_pcr );
294299
p_pkt = NULL;
295300
}
296301
}

modules/demux/mpeg/ts_pes.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,15 @@ typedef struct
2626
{
2727
vlc_object_t *p_obj;
2828
void *priv;
29-
void(*pf_parse)(vlc_object_t *, void *, block_t *);
29+
void(*pf_parse)(vlc_object_t *, void *, block_t *, stime_t);
3030
} ts_pes_parse_callback;
3131

3232
bool ts_pes_Drain( ts_pes_parse_callback *cb, ts_stream_t *p_pes );
3333

3434
bool ts_pes_Gather( ts_pes_parse_callback *cb,
3535
ts_stream_t *p_pes, block_t *p_pkt,
36-
bool b_unit_start, bool b_valid_scrambling );
36+
bool b_unit_start, bool b_valid_scrambling,
37+
stime_t i_append_pcr );
3738

3839

3940
#endif

modules/demux/mpeg/ts_streams.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ ts_stream_t *ts_stream_New( demux_t *p_demux, ts_pmt_t *p_program )
287287
pes->gather.p_data = NULL;
288288
pes->gather.pp_last = &pes->gather.p_data;
289289
pes->gather.i_saved = 0;
290+
pes->gather.i_append_pcr = VLC_TICK_INVALID;
290291
pes->b_broken_PUSI_conformance = false;
291292
pes->b_always_receive = false;
292293
pes->p_sections_proc = NULL;

modules/demux/mpeg/ts_streams_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ struct ts_stream_t
126126
block_t **pp_last;
127127
uint8_t saved[5];
128128
size_t i_saved;
129+
stime_t i_append_pcr;
129130
} gather;
130131

131132
bool b_always_receive;

test/modules/demux/ts_pes.c

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@
3131

3232
#include "../../libvlc/test.h"
3333

34-
static void Parse(vlc_object_t *obj, void *priv, block_t *data)
34+
static void Parse(vlc_object_t *obj, void *priv, block_t *data, stime_t t)
3535
{
3636
VLC_UNUSED(obj);
37+
VLC_UNUSED(t);
3738
block_t **pp_append = (block_t **) priv;
3839
fprintf(stderr, "recv: ");
3940
data = block_ChainGather(data);
@@ -95,7 +96,7 @@ int main()
9596
0x00, 0x00, 0x01, 0xe0, 0x00, 0x03, 0x80, 0x00, 0x00,
9697
};
9798
PKT_FROM(aligned0);
98-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
99+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
99100
ASSERT(output);
100101
block_ChainProperties(output, &outputcount, &outputsize, NULL);
101102
ASSERT(outputcount == 1);
@@ -104,13 +105,13 @@ int main()
104105
RESET;
105106
/* no output if not unit start */
106107
PKT_FROM(aligned0);
107-
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true));
108+
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true, 0));
108109
ASSERT(!output);
109110
RESET;
110111
/* no output if not unit start */
111112
PKT_FROM(aligned0);
112113
pkt->i_buffer = 1;
113-
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true));
114+
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true, 0));
114115
ASSERT(!output);
115116
RESET;
116117

@@ -120,7 +121,7 @@ int main()
120121
0xAA, 0xBB, 0xAA, 0xBB, 0xAA, 0xBB,
121122
};
122123
PKT_FROM(aligned1);
123-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
124+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
124125
ASSERT(output);
125126
block_ChainProperties(output, &outputcount, &outputsize, NULL);
126127
ASSERT(outputcount == 1);
@@ -129,25 +130,25 @@ int main()
129130
RESET;
130131
/* no output if not unit start */
131132
PKT_FROM(aligned1);
132-
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true));
133+
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true, 0));
133134
ASSERT(!output);
134135
RESET;
135136

136137
/* payload == 30, uncomplete */
137138
PKT_FROM(aligned1);
138139
SetWBE(&pkt->p_buffer[4], 30);
139-
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
140+
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
140141
ASSERT(!output);
141142
RESET;
142143

143144
/* packets assembly, payload > 188 - 6 - 4 */
144145
PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
145146
SetWBE(&pkt->p_buffer[4], 250);
146-
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
147+
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
147148
ASSERT(!output);
148149
ASSERT(pes.gather.i_data_size == 256);
149150
PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
150-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, false, true));
151+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, false, true, 0));
151152
ASSERT(output);
152153
block_ChainProperties(output, &outputcount, &outputsize, NULL);
153154
ASSERT(outputcount == 1);
@@ -157,11 +158,11 @@ int main()
157158
/* no packets assembly from unit start */
158159
PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
159160
SetWBE(&pkt->p_buffer[4], 250);
160-
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
161+
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
161162
ASSERT(!output);
162163
ASSERT(pes.gather.i_data_size == 256);
163164
PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
164-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
165+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
165166
ASSERT(output);
166167
block_ChainProperties(output, &outputcount, &outputsize, NULL);
167168
ASSERT(outputcount == 2);
@@ -170,12 +171,12 @@ int main()
170171
/* packets assembly, payload undef, use next sync code from another payload undef */
171172
PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
172173
SetWBE(&pkt->p_buffer[4], 0);
173-
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
174+
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
174175
ASSERT(!output);
175176
ASSERT(pes.gather.i_data_size == 0);
176177
PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
177178
SetWBE(&pkt->p_buffer[4], 0);
178-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
179+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
179180
ASSERT(output);
180181
block_ChainProperties(output, &outputcount, &outputsize, NULL);
181182
ASSERT(outputcount == 1);
@@ -185,11 +186,11 @@ int main()
185186
/* packets assembly, payload undef, use next sync code from fixed size */
186187
PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
187188
SetWBE(&pkt->p_buffer[4], 0);
188-
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
189+
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
189190
ASSERT(!output);
190191
ASSERT(pes.gather.i_data_size == 0);
191192
PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
192-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
193+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
193194
ASSERT(output);
194195
block_ChainProperties(output, &outputcount, &outputsize, NULL);
195196
ASSERT(outputcount == 2); /* secondary */
@@ -198,17 +199,17 @@ int main()
198199
/* packets assembly, payload undef, use next sync code from fixed size but uncomplete */
199200
PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
200201
SetWBE(&pkt->p_buffer[4], 0);
201-
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
202+
ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
202203
ASSERT(!output);
203204
ASSERT(pes.gather.i_data_size == 0);
204205
PKT_FROM(aligned1);
205206
pkt->i_buffer = 6;
206-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
207+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
207208
ASSERT(output);
208209
block_ChainProperties(output, &outputcount, &outputsize, NULL);
209210
ASSERT(outputcount == 1); /* can't output */
210211
PKT_FROM(aligned1);
211-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, false, true)); /* add data for last output */
212+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, false, true, 0)); /* add data for last output */
212213
ASSERT(output); /* output */
213214
RESET;
214215

@@ -225,7 +226,7 @@ int main()
225226
/* If the payload_unit_start_indicator is set to '1', then one and only one
226227
* PES packet starts in this transport stream packet. */
227228
PKT_FROM(aligned2);
228-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
229+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
229230
ASSERT(output);
230231
block_ChainProperties(output, &outputcount, &outputsize, NULL);
231232
ASSERT(outputcount == 1);
@@ -234,7 +235,7 @@ int main()
234235
/* Broken PUSI tests */
235236
pes.b_broken_PUSI_conformance = true;
236237
PKT_FROM(aligned2);
237-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
238+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
238239
ASSERT(output);
239240
block_ChainProperties(output, &outputcount, &outputsize, NULL);
240241
ASSERT(outputcount == 3);
@@ -243,7 +244,7 @@ int main()
243244
pes.b_broken_PUSI_conformance = true;
244245
PKT_FROM(aligned2);
245246
pkt->p_buffer[0] = 0xFF;
246-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
247+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
247248
ASSERT(output);
248249
block_ChainProperties(output, &outputcount, &outputsize, NULL);
249250
ASSERT(outputcount == 2);
@@ -254,13 +255,13 @@ int main()
254255
pes.b_broken_PUSI_conformance = true;
255256
PKT_FROM(aligned2);
256257
pkt->i_buffer = split;
257-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
258+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
258259
ASSERT(output);
259260

260261
PKT_FROM(aligned2);
261262
pkt->p_buffer += split;
262263
pkt->i_buffer -= split;
263-
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
264+
ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
264265
ASSERT(output);
265266

266267
RESET;

0 commit comments

Comments
 (0)