[FFmpeg-cvslog] Enhance HLS seeking.

Panagiotis H.M. Issaris git at videolan.org
Mon Jan 16 03:53:12 CET 2012


ffmpeg | branch: master | Panagiotis H.M. Issaris <takis.issaris at uhasselt.be> | Tue Jan 10 14:48:57 2012 +0100| [811de351eab675ca108db9b0c018fe82afa577fc] | committer: Michael Niedermayer

Enhance HLS seeking.

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

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=811de351eab675ca108db9b0c018fe82afa577fc
---

 libavformat/applehttp.c |   58 ++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/libavformat/applehttp.c b/libavformat/applehttp.c
index 5733f5f..883427c 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, AVFormatParameters *ap)
 
     c->first_packet = 1;
     c->first_timestamp = AV_NOPTS_VALUE;
+    c->seek_timestamp = AV_NOPTS_VALUE;
 
     return 0;
 fail:
@@ -604,14 +607,44 @@ 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 (!url_feof(&var->pb))
-                    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;
+                ret = av_read_frame(var->ctx, &var->pkt);
+                if (ret < 0) {
+                    if (!url_feof(&var->pb)) {
+                        return ret;
+                    } else {
+                        if ((var->cur_seq_no - var->start_seq_no) == (var->n_segments)) {
+                            return AVERROR_EOF;
+                        }
+                    }
+                    reset_packet(&var->pkt);
+                } 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;
+                }
+
+                ts_diff = var->pkt.dts - c->seek_timestamp;
+                if (ts_diff >= 0) {
+                    if (c->seek_flags & AVSEEK_FLAG_ANY) {
+                        c->seek_timestamp = AV_NOPTS_VALUE;
+                        break;
+                    }
+
+                    /* Seek to keyframe */
+                    if (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 +685,17 @@ static int applehttp_read_seek(AVFormatContext *s, int stream_index,
     if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished)
         return AVERROR(ENOSYS);
 
+    c->seek_timestamp = timestamp;
+    c->seek_flags = flags;
     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 */
@@ -683,6 +723,8 @@ static int applehttp_read_seek(AVFormatContext *s, int stream_index,
             }
             pos += var->segments[j]->duration;
         }
+        if (ret != 0)
+            c->seek_timestamp = AV_NOPTS_VALUE;
     }
     return ret;
 }



More information about the ffmpeg-cvslog mailing list