[vlc-commits] demux: ts: check pcr offset with value prior matching sync code

Francois Cartegnie git at videolan.org
Mon Mar 29 07:57:41 UTC 2021


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Mar 25 23:43:38 2021 +0100| [225e0bc09b847167433d49a591b25a8da4e7655f] | committer: Francois Cartegnie

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

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

 modules/demux/mpeg/ts.c                 | 28 +++++++++++++-------
 modules/demux/mpeg/ts_pes.c             | 27 +++++++++++--------
 modules/demux/mpeg/ts_pes.h             |  5 ++--
 modules/demux/mpeg/ts_streams.c         |  1 +
 modules/demux/mpeg/ts_streams_private.h |  1 +
 test/modules/demux/ts_pes.c             | 47 +++++++++++++++++----------------
 6 files changed, 63 insertions(+), 46 deletions(-)

diff --git a/modules/demux/mpeg/ts.c b/modules/demux/mpeg/ts.c
index 6361715cc6..c0a7830cce 100644
--- a/modules/demux/mpeg/ts.c
+++ b/modules/demux/mpeg/ts.c
@@ -1532,7 +1532,8 @@ 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 )
+static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes,
+                               stime_t i_append_pcr )
 {
     uint8_t header[34];
     unsigned i_pes_size = 0;
@@ -1698,19 +1699,20 @@ static void ParsePESDataChain( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
                 }
 
                 /* Compute PCR/DTS offset if any */
+                stime_t i_pcrref = SETANDVALID(i_append_pcr) ? i_append_pcr : p_pmt->pcr.i_first;
                 if( p_pmt->pcr.i_pcroffset == -1 && p_block->i_dts != VLC_TICK_INVALID &&
-                    SETANDVALID(p_pmt->pcr.i_current) &&
+                    SETANDVALID(i_pcrref) &&
                    (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( p_pmt->pcr.i_first, i_dts27 );
-                    stime_t i_pcr = TimeStampWrapAround( p_pmt->pcr.i_first, p_pmt->pcr.i_current );
-                    if( i_dts27 < i_pcr )
+                    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 )
                     {
-                        p_pmt->pcr.i_pcroffset = i_pcr - i_dts27 + TO_SCALE_NZ(VLC_TICK_FROM_MS(80));
+                        p_pmt->pcr.i_pcroffset = i_pcrref - i_dts27 + TO_SCALE_NZ(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(p_pmt->pcr.i_pcroffset) );
+                                  pid->i_pid, FROM_SCALE_NZ(i_pcrref - i_dts27) );
                     }
                     else p_pmt->pcr.i_pcroffset = 0;
                 }
@@ -1762,9 +1764,9 @@ 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 )
+static void PESDataChainHandle( vlc_object_t *p_obj, void *priv, block_t *p_data, stime_t i_appendpcr )
 {
-    ParsePESDataChain( (demux_t *)p_obj, (ts_pid_t *) priv, p_data );
+    ParsePESDataChain( (demux_t *)p_obj, (ts_pid_t *) priv, p_data, i_appendpcr );
 }
 
 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
     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;
+
     return ts_pes_Gather( &cb, p_pid->u.p_stream,
                           p_pkt, b_unit_start,
-                          p_sys->b_valid_scrambling );
+                          p_sys->b_valid_scrambling,
+                          i_append_pcr );
 }
 
 static bool GatherSectionsData( demux_t *p_demux, ts_pid_t *p_pid, block_t *p_pkt, size_t i_skip )
diff --git a/modules/demux/mpeg/ts_pes.c b/modules/demux/mpeg/ts_pes.c
index 55dbd147ad..ae07d7e295 100644
--- a/modules/demux/mpeg/ts_pes.c
+++ b/modules/demux/mpeg/ts_pes.c
@@ -97,7 +97,8 @@ 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 )
+                  ts_stream_t *p_pes, block_t *p_pkt,
+                  bool b_unit_start, stime_t i_append_pcr )
 {
     bool b_ret = false;
 
@@ -109,10 +110,13 @@ static bool ts_pes_Push( ts_pes_parse_callback *cb,
         p_pes->gather.i_data_size = 0;
         p_pes->gather.i_gathered = 0;
         p_pes->gather.pp_last = &p_pes->gather.p_data;
-        cb->pf_parse( cb->p_obj, cb->priv, p_datachain );
+        cb->pf_parse( cb->p_obj, cb->priv, p_datachain, p_pes->gather.i_append_pcr );
         b_ret = true;
     }
 
+    if( b_unit_start )
+        p_pes->gather.i_append_pcr = i_append_pcr;
+
     if( p_pkt == NULL )
         return b_ret;
 
@@ -137,7 +141,7 @@ static bool ts_pes_Push( ts_pes_parse_callback *cb,
     {
         /* re-enter in Flush above */
         assert(p_pes->gather.p_data);
-        return ts_pes_Push( cb, p_pes, NULL, true );
+        return ts_pes_Push( cb, p_pes, NULL, true, i_append_pcr );
     }
 
     return b_ret;
@@ -145,12 +149,13 @@ static bool ts_pes_Push( ts_pes_parse_callback *cb,
 
 bool ts_pes_Drain( ts_pes_parse_callback *cb, ts_stream_t *p_pes )
 {
-    return ts_pes_Push( cb, p_pes, NULL, true );
+    return ts_pes_Push( cb, p_pes, NULL, true, VLC_TICK_INVALID );
 }
 
 bool ts_pes_Gather( ts_pes_parse_callback *cb,
                     ts_stream_t *p_pes, block_t *p_pkt,
-                    bool b_unit_start, bool b_valid_scrambling )
+                    bool b_unit_start, bool b_valid_scrambling,
+                    stime_t i_append_pcr )
 {
     bool b_ret = false;
     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,
     if( (p_pkt->i_flags & BLOCK_FLAG_SCRAMBLED) && b_valid_scrambling )
     {
         block_Release( p_pkt );
-        return ts_pes_Push( cb, p_pes, NULL, true );
+        return ts_pes_Push( cb, p_pes, NULL, true, i_append_pcr );
     }
 
     /* Seek discontinuity, we need to drop or output currently
@@ -178,7 +183,7 @@ bool ts_pes_Gather( ts_pes_parse_callback *cb,
     {
         p_pes->gather.i_saved = 0;
         /* Flush/output current */
-        b_ret |= ts_pes_Push( cb, p_pes, NULL, true );
+        b_ret |= ts_pes_Push( cb, p_pes, NULL, true, i_append_pcr );
         /* Propagate to output block to notify packetizers/decoders */
         if( p_pes->p_es )
             p_pes->p_es->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
@@ -260,7 +265,7 @@ bool ts_pes_Gather( ts_pes_parse_callback *cb,
                 /* Append whole block */
                 if( likely(p_pkt->i_buffer <= i_remain) )
                 {
-                    b_ret |= ts_pes_Push( cb, p_pes, p_pkt, p_pes->gather.p_data == NULL );
+                    b_ret |= ts_pes_Push( cb, p_pes, p_pkt, p_pes->gather.p_data == NULL, i_append_pcr );
                     p_pkt = NULL;
                 }
                 else /* p_pkt->i_buffer > i_remain */
@@ -271,7 +276,7 @@ bool ts_pes_Gather( ts_pes_parse_callback *cb,
                         block_Release( p_pkt );
                         return false;
                     }
-                    b_ret |= ts_pes_Push( cb, p_pes, p_pkt, p_pes->gather.p_data == NULL );
+                    b_ret |= ts_pes_Push( cb, p_pes, p_pkt, p_pes->gather.p_data == NULL, i_append_pcr );
                     p_pkt = p_split;
                     b_first_sync_done = false;
                 }
@@ -280,7 +285,7 @@ bool ts_pes_Gather( ts_pes_parse_callback *cb,
             {
                 if( likely(b_aligned_ts_payload) && b_unit_start )
                 {
-                    b_ret |= ts_pes_Push( cb, p_pes, NULL, true );
+                    b_ret |= ts_pes_Push( cb, p_pes, NULL, true, i_append_pcr );
                     /* now points to PES header */
                     if( p_pkt->i_buffer >= 6 )
                     {
@@ -290,7 +295,7 @@ bool ts_pes_Gather( ts_pes_parse_callback *cb,
                     }
                 }
                 /* Append or finish current/start new PES depending on unit_start */
-                b_ret |= ts_pes_Push( cb, p_pes, p_pkt, b_unit_start );
+                b_ret |= ts_pes_Push( cb, p_pes, p_pkt, b_unit_start, i_append_pcr );
                 p_pkt = NULL;
             }
         }
diff --git a/modules/demux/mpeg/ts_pes.h b/modules/demux/mpeg/ts_pes.h
index ffa68a68d0..d970c313c9 100644
--- a/modules/demux/mpeg/ts_pes.h
+++ b/modules/demux/mpeg/ts_pes.h
@@ -26,14 +26,15 @@ typedef struct
 {
     vlc_object_t *p_obj;
     void *priv;
-    void(*pf_parse)(vlc_object_t *, void *, block_t *);
+    void(*pf_parse)(vlc_object_t *, void *, block_t *, stime_t);
 } ts_pes_parse_callback;
 
 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 );
+                    bool b_unit_start, bool b_valid_scrambling,
+                    stime_t i_append_pcr );
 
 
 #endif
diff --git a/modules/demux/mpeg/ts_streams.c b/modules/demux/mpeg/ts_streams.c
index 84e2cbeccf..467230e318 100644
--- a/modules/demux/mpeg/ts_streams.c
+++ b/modules/demux/mpeg/ts_streams.c
@@ -287,6 +287,7 @@ ts_stream_t *ts_stream_New( demux_t *p_demux, ts_pmt_t *p_program )
     pes->gather.p_data = NULL;
     pes->gather.pp_last = &pes->gather.p_data;
     pes->gather.i_saved = 0;
+    pes->gather.i_append_pcr = VLC_TICK_INVALID;
     pes->b_broken_PUSI_conformance = false;
     pes->b_always_receive = false;
     pes->p_sections_proc = NULL;
diff --git a/modules/demux/mpeg/ts_streams_private.h b/modules/demux/mpeg/ts_streams_private.h
index b5646c41d7..b25e092689 100644
--- a/modules/demux/mpeg/ts_streams_private.h
+++ b/modules/demux/mpeg/ts_streams_private.h
@@ -126,6 +126,7 @@ struct ts_stream_t
         block_t     **pp_last;
         uint8_t     saved[5];
         size_t      i_saved;
+        stime_t     i_append_pcr;
     } gather;
 
     bool        b_always_receive;
diff --git a/test/modules/demux/ts_pes.c b/test/modules/demux/ts_pes.c
index 1e694e0eaa..c0255e1df5 100644
--- a/test/modules/demux/ts_pes.c
+++ b/test/modules/demux/ts_pes.c
@@ -31,9 +31,10 @@
 
 #include "../../libvlc/test.h"
 
-static void Parse(vlc_object_t *obj, void *priv, block_t *data)
+static void Parse(vlc_object_t *obj, void *priv, block_t *data, stime_t t)
 {
     VLC_UNUSED(obj);
+    VLC_UNUSED(t);
     block_t **pp_append = (block_t **) priv;
     fprintf(stderr, "recv: ");
     data = block_ChainGather(data);
@@ -95,7 +96,7 @@ int main()
         0x00, 0x00, 0x01, 0xe0, 0x00, 0x03, 0x80, 0x00, 0x00,
     };
     PKT_FROM(aligned0);
-    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(output);
     block_ChainProperties(output, &outputcount, &outputsize, NULL);
     ASSERT(outputcount == 1);
@@ -104,13 +105,13 @@ int main()
     RESET;
     /* no output if not unit start */
     PKT_FROM(aligned0);
-    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true));
+    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true, 0));
     ASSERT(!output);
     RESET;
     /* no output if not unit start */
     PKT_FROM(aligned0);
     pkt->i_buffer = 1;
-    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true));
+    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true, 0));
     ASSERT(!output);
     RESET;
 
@@ -120,7 +121,7 @@ int main()
         0xAA, 0xBB, 0xAA, 0xBB, 0xAA, 0xBB,
     };
     PKT_FROM(aligned1);
-    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(output);
     block_ChainProperties(output, &outputcount, &outputsize, NULL);
     ASSERT(outputcount == 1);
@@ -129,25 +130,25 @@ int main()
     RESET;
     /* no output if not unit start */
     PKT_FROM(aligned1);
-    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true));
+    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, false, true, 0));
     ASSERT(!output);
     RESET;
 
     /* payload == 30, uncomplete */
     PKT_FROM(aligned1);
     SetWBE(&pkt->p_buffer[4], 30);
-    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(!output);
     RESET;
 
     /* packets assembly, payload > 188 - 6 - 4 */
     PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
     SetWBE(&pkt->p_buffer[4], 250);
-    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(!output);
     ASSERT(pes.gather.i_data_size == 256);
     PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
-    ASSERT(ts_pes_Gather(&cb, &pes, pkt, false, true));
+    ASSERT(ts_pes_Gather(&cb, &pes, pkt, false, true, 0));
     ASSERT(output);
     block_ChainProperties(output, &outputcount, &outputsize, NULL);
     ASSERT(outputcount == 1);
@@ -157,11 +158,11 @@ int main()
     /* no packets assembly from unit start */
     PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
     SetWBE(&pkt->p_buffer[4], 250);
-    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(!output);
     ASSERT(pes.gather.i_data_size == 256);
     PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
-    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(output);
     block_ChainProperties(output, &outputcount, &outputsize, NULL);
     ASSERT(outputcount == 2);
@@ -170,12 +171,12 @@ int main()
     /* packets assembly, payload undef, use next sync code from another payload undef */
     PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
     SetWBE(&pkt->p_buffer[4], 0);
-    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(!output);
     ASSERT(pes.gather.i_data_size == 0);
     PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
     SetWBE(&pkt->p_buffer[4], 0);
-    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(output);
     block_ChainProperties(output, &outputcount, &outputsize, NULL);
     ASSERT(outputcount == 1);
@@ -185,11 +186,11 @@ int main()
     /* packets assembly, payload undef, use next sync code from fixed size */
     PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
     SetWBE(&pkt->p_buffer[4], 0);
-    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(!output);
     ASSERT(pes.gather.i_data_size == 0);
     PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
-    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(output);
     block_ChainProperties(output, &outputcount, &outputsize, NULL);
     ASSERT(outputcount == 2); /* secondary */
@@ -198,17 +199,17 @@ int main()
     /* packets assembly, payload undef, use next sync code from fixed size but uncomplete */
     PKT_FROMSZ(aligned1, 188-sizeof(aligned1));
     SetWBE(&pkt->p_buffer[4], 0);
-    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(!ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(!output);
     ASSERT(pes.gather.i_data_size == 0);
     PKT_FROM(aligned1);
     pkt->i_buffer = 6;
-    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(output);
     block_ChainProperties(output, &outputcount, &outputsize, NULL);
     ASSERT(outputcount == 1); /* can't output */
     PKT_FROM(aligned1);
-    ASSERT(ts_pes_Gather(&cb, &pes, pkt, false, true)); /* add data for last output */
+    ASSERT(ts_pes_Gather(&cb, &pes, pkt, false, true, 0)); /* add data for last output */
     ASSERT(output); /* output */
     RESET;
 
@@ -225,7 +226,7 @@ int main()
     /* If the payload_unit_start_indicator is set to '1', then one and only one
      * PES packet starts in this transport stream packet. */
     PKT_FROM(aligned2);
-    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(output);
     block_ChainProperties(output, &outputcount, &outputsize, NULL);
     ASSERT(outputcount == 1);
@@ -234,7 +235,7 @@ int main()
     /* Broken PUSI tests */
     pes.b_broken_PUSI_conformance = true;
     PKT_FROM(aligned2);
-    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(output);
     block_ChainProperties(output, &outputcount, &outputsize, NULL);
     ASSERT(outputcount == 3);
@@ -243,7 +244,7 @@ int main()
     pes.b_broken_PUSI_conformance = true;
     PKT_FROM(aligned2);
     pkt->p_buffer[0] = 0xFF;
-    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
+    ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
     ASSERT(output);
     block_ChainProperties(output, &outputcount, &outputsize, NULL);
     ASSERT(outputcount == 2);
@@ -254,13 +255,13 @@ int main()
         pes.b_broken_PUSI_conformance = true;
         PKT_FROM(aligned2);
         pkt->i_buffer = split;
-        ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
+        ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
         ASSERT(output);
 
         PKT_FROM(aligned2);
         pkt->p_buffer += split;
         pkt->i_buffer -= split;
-        ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true));
+        ASSERT(ts_pes_Gather(&cb, &pes, pkt, true, true, 0));
         ASSERT(output);
 
         RESET;



More information about the vlc-commits mailing list