diff mbox series

[FFmpeg-devel] ffmpeg-devel@ffmpeg.org

Message ID 094074d6-8afd-ac91-a7e9-71e29e783cea@gmail.com
State New
Headers show
Series [FFmpeg-devel] ffmpeg-devel@ffmpeg.org
Related show

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Alan Young Feb. 2, 2021, 12:35 p.m. UTC
Subject: [PATCH] avformat/hls: Use #EXT-X-PROGRAM-DATE-TIME if available

If all the segments in an HLS playlist have #EXT-X-PROGRAM-DATE-TIME
timestamps then they provide better seeking than (just) using #EXTINF.

Parse timestamp in hls.c:parse_playlist() and use in
find_timestamp_in_playlist() if available.

This results in significantly faster startup when seeking long
distances (say > 30 minutes) into HLS/AAC streams.
---
 libavformat/hls.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

Comments

Steven Liu Feb. 2, 2021, 1:14 p.m. UTC | #1
> 2021年2月2日 下午8:35,Alan Young <consult.awy@gmail.com> 写道:
> 
> <0001-avformat-hls-Use-EXT-X-PROGRAM-DATE-TIME-if-availabl.patch>
LGTM


> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

Thanks

Steven Liu
diff mbox series

Patch

diff --git a/libavformat/hls.c b/libavformat/hls.c
index 3c7e197ce7..b0df06151d 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -34,6 +34,7 @@ 
 #include "libavutil/opt.h"
 #include "libavutil/dict.h"
 #include "libavutil/time.h"
+#include "libavutil/parseutils.h"
 #include "avformat.h"
 #include "internal.h"
 #include "avio_internal.h"
@@ -67,6 +68,7 @@  enum KeyType {
 
 struct segment {
     int64_t duration;
+    int64_t timestamp;
     int64_t url_offset;
     int64_t size;
     char *url;
@@ -714,6 +716,7 @@  static int parse_playlist(HLSContext *c, const char *url,
 {
     int ret = 0, is_segment = 0, is_variant = 0;
     int64_t duration = 0;
+    int64_t timestamp = 0;
     enum KeyType key_type = KEY_NONE;
     uint8_t iv[16] = "";
     int has_iv = 0;
@@ -868,6 +871,11 @@  static int parse_playlist(HLSContext *c, const char *url,
         } else if (av_strstart(line, "#EXTINF:", &ptr)) {
             is_segment = 1;
             duration   = atof(ptr) * AV_TIME_BASE;
+        } else if (av_strstart(line, "#EXT-X-PROGRAM-DATE-TIME:", &ptr)) {
+            if (av_parse_time(&timestamp, ptr, 0) < 0) {
+                av_log(c->ctx, AV_LOG_INFO, "Cannot parse ('%s')\n", line);
+                timestamp = 0;
+            }
         } else if (av_strstart(line, "#EXT-X-BYTERANGE:", &ptr)) {
             seg_size = strtoll(ptr, NULL, 10);
             ptr = strchr(ptr, '@');
@@ -941,6 +949,8 @@  static int parse_playlist(HLSContext *c, const char *url,
                     duration = 0.001 * AV_TIME_BASE;
                 }
                 seg->duration = duration;
+                seg->timestamp = timestamp;
+                timestamp = 0;
                 seg->key_type = key_type;
                 dynarray_add(&pls->segments, &pls->n_segments, seg);
                 is_segment = 0;
@@ -1644,6 +1654,21 @@  static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls,
         return 0;
     }
 
+    /* If all segments have timestamps then more accurate than using segment duration */
+    if (pls->n_segments && pls->segments[0]->timestamp) {
+        int64_t initial_timestamp = pls->segments[0]->timestamp;
+        for (i = 1; i < pls->n_segments; i++) {
+            if (!pls->segments[i]->timestamp) break;
+            if (timestamp < pls->segments[i]->timestamp - initial_timestamp) {
+                *seq_no = pls->start_seq_no + i - 1;
+                return 1;
+            } else if (i == pls->n_segments - 1) {
+                *seq_no = pls->start_seq_no + i;
+                return 1;
+            }
+        }
+    }
+
     for (i = 0; i < pls->n_segments; i++) {
         int64_t diff = pos + pls->segments[i]->duration - timestamp;
         if (diff > 0) {