From patchwork Fri Jan 28 20:23:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gustav Grusell X-Patchwork-Id: 33897 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6602:2c4e:0:0:0:0 with SMTP id x14csp754912iov; Fri, 28 Jan 2022 12:24:25 -0800 (PST) X-Google-Smtp-Source: ABdhPJybL+25L+E+Z6+B3wYXcvhq5+G2JUV35XfW4+gAMRoGndAcILyHj4dbV6UicXijLSRxycEZ X-Received: by 2002:a17:907:60cb:: with SMTP id hv11mr8241630ejc.122.1643401465703; Fri, 28 Jan 2022 12:24:25 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1643401465; cv=none; d=google.com; s=arc-20160816; b=ndX7oI4plbI8YaJ9vsK5g+t6+eYBtMzSKbBGO5XjFbC/xiuQfHGGYuo7cuByO5hp1Y NE4o6YO2jNIINIIfSnanOBuRLpZgXvOnO0KNUNqJ/DjJSEytzz+VutHIKMSVUFo88l2o NhMQnQSgiGRvtLH17kNa2UvcYDciqd/Mp7/C6UdR3WAEpFYMmvrwQJiIvjp6nPzvxh7c 95GZOHakgMj2f2blrWVVsdTianG8AjLGs70CtRvOt9NSnf5cKg9pPojDL9hy+OjjNmQV 2mKQvWiZSr0/XNox4Wc4Nl/JB2wzLfZ0nCCGZiiECRK4oSzx1aWn170R3D3BTNFK3Hwb UiCA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=8VQhZ13QXn4mhO6WWisXHBpaZoWPBeZ4joeL/yBT/Vs=; b=VJvr6qqLA8Q9iOT0+WwWT/FImAFx31dXOpyUNiBBGUKbiyTs6mCpKKWD+0G6lU6cmO uurEL4OwD5zuGSEQNCH0yZqMlmo0Q/LuNPv3XVqQQsyg47bd8mnha5h9H/FTgMRYcTWA ef77V/YSZYhfiW44J/zFV6y4z3y0OuflshpLTGTzsPDQP2zvyCuh2AvSJdhWUaC7K/lI Y84KMArfFjd8MWyC3lmX0Q7ajyUDRM3tSCYZ6LHrapY2fWmhdTwCiMb9VI09Qn/9QZpy MHkefoaeV7B+t8sYb3NBKNGuxRoEZzW17dNBT+j0YA7CKwvROyLm4AXZIAZNzVW3QqKD xw6A== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=ONxwYDvX; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id d8si3722056edk.347.2022.01.28.12.24.24; Fri, 28 Jan 2022 12:24:25 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=ONxwYDvX; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 3EFF168B1CD; Fri, 28 Jan 2022 22:24:21 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lj1-f178.google.com (mail-lj1-f178.google.com [209.85.208.178]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 52DBA68AF75 for ; Fri, 28 Jan 2022 22:24:14 +0200 (EET) Received: by mail-lj1-f178.google.com with SMTP id c15so10592458ljf.11 for ; Fri, 28 Jan 2022 12:24:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=U7AGIPaW0lsuqGH2JOIAjlt528WW9RVUHGV92pmnkng=; b=ONxwYDvXEy2JOST7tL03kX3Bp5ZGre/6xv8H3tMwOsN1n8YcSMjeBtpET431P11Gg7 J11LOV8COf8IwxJ0XT1PX5PgP/OP9iZQ9iFk8Jf9F2/BVN8wbmyKug/ZSwZTEoGtmfjX CFLjyDPCv/l3gk3t2QMmM4C87bpol9LNKxs131HR7fENR+ycc+SMPF4+AnYTcTjC+1AE foZx8hYFGoQDQ5/ag7Fj/jmTngCGC+H3Rp6D5ElSR2f1NK5mZH0eCqkYFzXoFaEqbvyD lGx3IwXiiH8WQ1BL5uKHlsAwlxOt4u4JHnYpmrZUyqprKayjLY7+tIfCwuPqA/RcG4tY ry9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=U7AGIPaW0lsuqGH2JOIAjlt528WW9RVUHGV92pmnkng=; b=LYpTVOiDSgI0Q6dO/76Fk4R4ciPBAAvDUg4tmi40p9tpUsnfhrDNFOkCM+0MyPJbNC HlEmlD9sHz+tq5xzIPYe5kX9k0j22bBN0Cyw3l2M53944Mpyk1LvIzs2SQmm8Qf61glc 4HeW5d8PkuyvjKHzFeUygUjC+sbKafDfDrDK1y3zNQgcC4Z+KPKkFmQCrsiDZycv+Cem Lvcwo1xQto2wtyd7bQMS6y7BUY9b0ew/KHLU2dMdNShoSWbt0a8Js4xatjSCu4pBCuqf /7s8bOXFnRi1mgGZvGRWIU/CjUDwecFN7ME7PdJUp0jE95ca2isdpWA+ieHXGMlBzQS6 f91w== X-Gm-Message-State: AOAM530GZovQ5+mwjdjoOg+i98x/02HBjdBCUA4OCA9O3oeBqPuaZRx7 u1V2YpTYoTfWJ95Eshil5dKidHBHjp8= X-Received: by 2002:a2e:a378:: with SMTP id i24mr7064151ljn.240.1643401453187; Fri, 28 Jan 2022 12:24:13 -0800 (PST) Received: from localhost.localdomain (c80-216-190-179.bredband.tele2.se. [80.216.190.179]) by smtp.googlemail.com with ESMTPSA id k10sm2168287lfo.187.2022.01.28.12.24.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Jan 2022 12:24:12 -0800 (PST) From: Gustav Grusell To: ffmpeg-devel@ffmpeg.org Date: Fri, 28 Jan 2022 21:23:20 +0100 Message-Id: <20220128202320.1711694-1-gustav.grusell@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220128185254.1662873-1-gustav.grusell@gmail.com> References: <20220128185254.1662873-1-gustav.grusell@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4] avformat/hls: Implement support for using AVSEEK_FLAG_BACKWARD when seeking X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: Gustav Grusell Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: zAdmHDhBzzVb Before, seeking in hls streams would always seek to the next keyframe after the given timestamp. With this fix, if seeking in videostream and AVSEEK_FLAG_BACKWARD is set, seeking will be to the first keyframe of the segment containing the given timestamp. This fixes #7485. Signed-off-by: Gustav Grusell --- libavformat/hls.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 4568e72cb2..44afdaab42 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1653,7 +1653,8 @@ static void add_metadata_from_renditions(AVFormatContext *s, struct playlist *pl /* if timestamp was in valid range: returns 1 and sets seq_no * if not: returns 0 and sets seq_no to closest segment */ static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls, - int64_t timestamp, int64_t *seq_no) + int64_t timestamp, int64_t *seq_no, + int64_t *seg_start_ts) { int i; int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? @@ -1668,6 +1669,9 @@ static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls, int64_t diff = pos + pls->segments[i]->duration - timestamp; if (diff > 0) { *seq_no = pls->start_seq_no + i; + if (seg_start_ts) { + *seg_start_ts = pos; + } return 1; } pos += pls->segments[i]->duration; @@ -1691,7 +1695,7 @@ static int64_t select_cur_seq_no(HLSContext *c, struct playlist *pls) * playlist) and this is a complete file, find the matching segment * by counting durations. */ if (pls->finished && c->cur_timestamp != AV_NOPTS_VALUE) { - find_timestamp_in_playlist(c, pls, c->cur_timestamp, &seq_no); + find_timestamp_in_playlist(c, pls, c->cur_timestamp, &seq_no, NULL); return seq_no; } @@ -2362,7 +2366,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, int i, j; int stream_subdemuxer_index; int64_t first_timestamp, seek_timestamp, duration; - int64_t seq_no; + int64_t seq_no, seg_start_ts; if ((flags & AVSEEK_FLAG_BYTE) || (c->ctx->ctx_flags & AVFMTCTX_UNSEEKABLE)) return AVERROR(ENOSYS); @@ -2372,8 +2376,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, seek_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); + AV_ROUND_DOWN); duration = s->duration == AV_NOPTS_VALUE ? 0 : s->duration; @@ -2394,9 +2397,16 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, } /* check if the timestamp is valid for the playlist with the * specified stream index */ - if (!seek_pls || !find_timestamp_in_playlist(c, seek_pls, seek_timestamp, &seq_no)) + if (!seek_pls || !find_timestamp_in_playlist(c, seek_pls, seek_timestamp, &seq_no, &seg_start_ts)) return AVERROR(EIO); + if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + flags & AVSEEK_FLAG_BACKWARD && !(flags & AVSEEK_FLAG_ANY)) { + /* Seeking to start of segment ensures we seek to a keyframe located + * before the given timestamp. */ + seek_timestamp = seg_start_ts; + } + /* set segment now so we do not need to search again below */ seek_pls->cur_seq_no = seq_no; seek_pls->seek_stream_index = stream_subdemuxer_index; @@ -2423,7 +2433,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, if (pls != seek_pls) { /* set closest segment seq_no for playlists not handled above */ - find_timestamp_in_playlist(c, pls, seek_timestamp, &pls->cur_seq_no); + find_timestamp_in_playlist(c, pls, seek_timestamp, &pls->cur_seq_no, NULL); /* seek the playlist to the given position without taking * keyframes into account since this playlist does not have the * specified stream where we should look for the keyframes */