From patchwork Tue Feb 2 12:35:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Young X-Patchwork-Id: 25341 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 25CEA44808B for ; Tue, 2 Feb 2021 14:35:57 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 02F666897BF; Tue, 2 Feb 2021 14:35:57 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id BD1B5687F30 for ; Tue, 2 Feb 2021 14:35:50 +0200 (EET) Received: by mail-wr1-f49.google.com with SMTP id v15so20308063wrx.4 for ; Tue, 02 Feb 2021 04:35:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=ME5oUVt6S1r82Gkg0rMztFGlfT6NsPudzQn2oxFP78Q=; b=LQPqi5qUHHOZiEinyytbnF1xl2cB5JuJ7+4ML53bOuKmHghmo5QPH/Aqq2P8ccArL+ 2qUOOPGJtSNYdODQxDzUnSEdlQRxwYOB7I9ytPD65UpzwzxlZpSeAR8SWHmq0SPhiUVL lAVxLl6WJrqZE+Z7IekFTaWMlpGvitOExStpGYtKYd9n0aqPXnj3RLlTgaXMLaEnW0dc hh+XMRoUNAN7xk5t3B0UXG7WEJVA5sJaOchksDFspbRw3ayoliAfaVYSEMFAOHexjpoM Jc8uiM2woo1vjY/ig9Y9Wi5sHMiXAXSt0PJtGqXqsW8bJhSabtJE+BpchNAEqWlCibpv MDjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-language; bh=ME5oUVt6S1r82Gkg0rMztFGlfT6NsPudzQn2oxFP78Q=; b=l6cZKR7Kp6MjeAL65xpaanZl02qQyKOIGV+0mow0DYgSDXpG53pcPH5x+W+fUV1Rsl JUXnxXgOKw/BkEG96Nlvh6JDIDoNxf/1N85/Z0qj13UB65slX9ns9zDIH0ZgQ+GORX0j VMsSvTFxfdPx9WSnZNWqyrAZJvkFLOmOdKQhPaRLBUQ6GS6YlQ794WkxO0sTBKuoOUru bDtKeg5d493qjnZTskUTEEICbgROGQSJrb2jXwf1gXPteNjcc/CRd2Fngymh4eC0uUTw dgg9MfIyzcLdpPv3EkTkMiKqQkUjXpy7ZMCEnll9glS1W2uD03VfTXCM2QldWZjhxt1y VkAA== X-Gm-Message-State: AOAM532RN7gsIwgEcpcCfAWux3QX/Kps1OzhjLQoSQqRzrnUnNtb8LpN lzJyEWacbQO5hgyQE2VoeDIwi1G9QCvR5g== X-Google-Smtp-Source: ABdhPJwwdZCtHRTLITBSjl4fScjwBc08y+zKsmLrP6FdL6YYUgpkxMgqo6EMmcvvRWGr0OosVGjVDw== X-Received: by 2002:adf:f2d1:: with SMTP id d17mr23720034wrp.110.1612269350270; Tue, 02 Feb 2021 04:35:50 -0800 (PST) Received: from [192.168.11.11] (29.160.159.143.dyn.plus.net. [143.159.160.29]) by smtp.googlemail.com with ESMTPSA id c20sm2792729wmb.38.2021.02.02.04.35.49 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 02 Feb 2021 04:35:49 -0800 (PST) To: ffmpeg-devel@ffmpeg.org From: Alan Young Message-ID: <094074d6-8afd-ac91-a7e9-71e29e783cea@gmail.com> Date: Tue, 2 Feb 2021 12:35:49 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0 MIME-Version: 1.0 Content-Language: en-GB X-Content-Filtered-By: Mailman/MimeDel 2.1.20 Subject: [FFmpeg-devel] ffmpeg-devel@ffmpeg.org X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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) {