From: Panagiotis H.M. Issaris <[email protected]>

Enhance seeking by demuxing until the requested timestamp is
reached within the segment selected by the seek code using the
playlist info.

Some mpegts streams don't have dts set for all packets though,
this seeking method doesn't work well for that case.
---
 libavformat/applehttp.c |   55 ++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/libavformat/applehttp.c b/libavformat/applehttp.c
index 32a51fe..f5e4087 100644
--- a/libavformat/applehttp.c
+++ b/libavformat/applehttp.c
@@ -100,6 +100,8 @@ typedef struct AppleHTTPContext {
     int end_of_segment;
     int first_packet;
     int64_t first_timestamp;
+    int64_t seek_timestamp;
+    int seek_flags;
     AVIOInterruptCB *interrupt_callback;
 } AppleHTTPContext;
 
@@ -545,6 +547,7 @@ static int applehttp_read_header(AVFormatContext *s)
 
     c->first_packet = 1;
     c->first_timestamp = AV_NOPTS_VALUE;
+    c->seek_timestamp  = AV_NOPTS_VALUE;
 
     return 0;
 fail:
@@ -604,14 +607,37 @@ start:
         /* Make sure we've got one buffered packet from each open variant
          * stream */
         if (var->needed && !var->pkt.data) {
-            ret = av_read_frame(var->ctx, &var->pkt);
-            if (ret < 0) {
-                if (!var->pb.eof_reached)
-                    return ret;
-                reset_packet(&var->pkt);
-            } else {
-                if (c->first_timestamp == AV_NOPTS_VALUE)
-                    c->first_timestamp = var->pkt.dts;
+            while (1) {
+                int64_t ts_diff;
+                AVStream *st;
+                ret = av_read_frame(var->ctx, &var->pkt);
+                if (ret < 0) {
+                    if (!var->pb.eof_reached)
+                        return ret;
+                    reset_packet(&var->pkt);
+                    break;
+                } else {
+                    if (c->first_timestamp == AV_NOPTS_VALUE)
+                        c->first_timestamp = var->pkt.dts;
+                }
+
+                if (c->seek_timestamp == AV_NOPTS_VALUE)
+                    break;
+
+                if (var->pkt.dts == AV_NOPTS_VALUE) {
+                    c->seek_timestamp = AV_NOPTS_VALUE;
+                    break;
+                }
+
+                st = var->ctx->streams[var->pkt.stream_index];
+                ts_diff = av_rescale_rnd(var->pkt.dts, AV_TIME_BASE,
+                                         st->time_base.den, AV_ROUND_DOWN) -
+                          c->seek_timestamp;
+                if (ts_diff >= 0 && (c->seek_flags  & AVSEEK_FLAG_ANY ||
+                                     var->pkt.flags & AV_PKT_FLAG_KEY)) {
+                    c->seek_timestamp = AV_NOPTS_VALUE;
+                    break;
+                }
             }
         }
         /* Check if this stream has the packet with the lowest dts */
@@ -652,10 +678,21 @@ static int applehttp_read_seek(AVFormatContext *s, int 
stream_index,
     if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished)
         return AVERROR(ENOSYS);
 
+    c->seek_flags     = flags;
+    c->seek_timestamp = stream_index < 0 ? timestamp :
+                        av_rescale_rnd(timestamp, AV_TIME_BASE,
+                                       s->streams[stream_index]->time_base.den,
+                                       flags & AVSEEK_FLAG_BACKWARD ?
+                                       AV_ROUND_DOWN : AV_ROUND_UP);
     timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ?
                                s->streams[stream_index]->time_base.den :
                                AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ?
                                AV_ROUND_DOWN : AV_ROUND_UP);
+    if (s->duration < c->seek_timestamp) {
+        c->seek_timestamp = AV_NOPTS_VALUE;
+        return AVERROR(EIO);
+    }
+
     ret = AVERROR(EIO);
     for (i = 0; i < c->n_variants; i++) {
         /* Reset reading */
@@ -682,6 +719,8 @@ static int applehttp_read_seek(AVFormatContext *s, int 
stream_index,
             }
             pos += var->segments[j]->duration;
         }
+        if (ret)
+            c->seek_timestamp = AV_NOPTS_VALUE;
     }
     return ret;
 }
-- 
1.7.3.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to