>From 3692430935d7987a41225eec289adb9f2561dd98 Mon Sep 17 00:00:00 2001 From: Alan Young <consult....@gmail.com> Date: Tue, 2 Feb 2021 12:18:34 +0000 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(+) 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(×tamp, 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) { -- 2.28.0
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".