hls: Respect the different stream time bases when comparing dts
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 20 Aug 2012 23:00:05 +0000 (01:00 +0200)
committerMartin Storsjö <martin@martin.st>
Mon, 29 Jul 2013 06:50:08 +0000 (09:50 +0300)
Also adjust the streams timestamps according to their start
timestamp when comparing. This helps getting correctly interleaved
packets if one stream lacks timestamps (such as a plain ADTS
stream when the other variants are full mpegts) when the others
have timestamps that don't start from zero.

This probably doesn't work properly if such a stream is
temporarily disabled (via the discard flags) and then reenabled,
and such streams are hard to correctly sync against the other
streams as well - but this works better than before at least.

The segment number restriction makes sure all variants advance
roughly at the same pace as well.

Signed-off-by: Martin Storsjö <martin@martin.st>
libavformat/hls.c

index 86cf974..d69a380 100644 (file)
@@ -644,11 +644,28 @@ start:
         /* Check if this stream still is on an earlier segment number, or
          * has the packet with the lowest dts */
         if (var->pkt.data) {
-            if (minvariant < 0 ||
-                var->cur_seq_no <  c->variants[minvariant]->cur_seq_no ||
-               (var->cur_seq_no == c->variants[minvariant]->cur_seq_no &&
-                var->pkt.dts    <  c->variants[minvariant]->pkt.dts))
+            struct variant *minvar = c->variants[minvariant];
+            if (minvariant < 0 || var->cur_seq_no < minvar->cur_seq_no) {
                 minvariant = i;
+            } else if (var->cur_seq_no == minvar->cur_seq_no) {
+                int64_t dts     =    var->pkt.dts;
+                int64_t mindts  = minvar->pkt.dts;
+                AVStream *st    =    var->ctx->streams[var->pkt.stream_index];
+                AVStream *minst = minvar->ctx->streams[minvar->pkt.stream_index];
+
+                if (dts == AV_NOPTS_VALUE) {
+                    minvariant = i;
+                } else if (mindts != AV_NOPTS_VALUE) {
+                    if (st->start_time    != AV_NOPTS_VALUE)
+                        dts    -= st->start_time;
+                    if (minst->start_time != AV_NOPTS_VALUE)
+                        mindts -= minst->start_time;
+
+                    if (av_compare_ts(dts, st->time_base,
+                                      mindts, minst->time_base) < 0)
+                        minvariant = i;
+                }
+            }
         }
     }
     if (c->end_of_segment) {