From patchwork Sun May 3 18:08:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manolis Stamatogiannakis X-Patchwork-Id: 19452 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 4B1D7449F56 for ; Sun, 3 May 2020 21:08:44 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1F02168BDAB; Sun, 3 May 2020 21:08:44 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A992C68BDAB for ; Sun, 3 May 2020 21:08:36 +0300 (EEST) Received: by mail-wm1-f48.google.com with SMTP id x4so5814978wmj.1 for ; Sun, 03 May 2020 11:08:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=hdHyfSqP5ehg3Kadl4HEf/PuXgpx5VF9/raVApXbkvo=; b=GDg0HyJch9askxiYkw6TyOJCcXoA8zMiMSlSaX0MEclJ/FQ4+OUPnmdlXxbxuN7TX7 jAcn0JZhpoTzTAnRKyHqQq9cSs3Rz5Y+KGcUazKMP6jeBeZQm3Nb0w8W8iNVPAjNmmOb cT7RSWALk6giqCiBvbSUWS9P7S1GPm8PWEmMBJgrOC7zgk8aELWpijGXEekuep7nNTox 5psQzL0NcohqHYfGLo6WQTXnGloXDXR2vg3tH8/jaLtrMQZrqedGdn6xXlfCSAARpAj5 XRt2N5PWTGSFjMYP51ggdOlJo1oNViD/CpU6KBSAnYlKzb5oAjcNmIhUCmzWWB1yVpgK U1HA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=hdHyfSqP5ehg3Kadl4HEf/PuXgpx5VF9/raVApXbkvo=; b=KxaPK0fy2An8kZ+2jQgg7L7tv45w2pwHqmWby5Fnkcj2yBKaMvKyoBngHYliweww4V nipmZ+gO0ptT9+SC2ZkNGpgy3nDMzJuW+UYG4xGwzdUqLnWlBuE5yretuyb7b7VnMo4k auZ+ZuUGiDo10OHLe6RBzrefznSCx0wYUW2M1ydj99nha0b7ChwnbLx7TeL7UYzCm5q1 TLyTrPKi77ND/uQvSWRUJJ5mfbXTJeAURSEKMuN+LS4Uz2iP0PcI7QmIArOvHbKv1d9S IO2eVYG7WQJ7chzFHwVx0gFInfETihd0p8t0HvaVnXBJWwJrkhgv9ShNkHsrGk3Eil6y 7TeA== X-Gm-Message-State: AGi0PuYAMF/ij9/RqDobVIxzDGu5V15xQjfBa3oQqQYL8XtCpf0TLJRR tRSJbiPel13PDsdxaw1XecNnnPRgeRI6CA== X-Google-Smtp-Source: APiQypKkgX5h+ssBXEztQdETRAqcIBS4lq7DJJi68ZKZ9YPY+aB+aQRBYybbduUOofAQ5HFLY3wkIw== X-Received: by 2002:a05:600c:c5:: with SMTP id u5mr10923304wmm.134.1588529315175; Sun, 03 May 2020 11:08:35 -0700 (PDT) Received: from wasteland.vu.local (PC-041923.clients.vu.nl. [145.108.189.179]) by smtp.gmail.com with ESMTPSA id e2sm14836379wrv.89.2020.05.03.11.08.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 03 May 2020 11:08:34 -0700 (PDT) From: Manolis Stamatogiannakis To: ffmpeg-devel@ffmpeg.org Date: Sun, 3 May 2020 20:08:29 +0200 Message-Id: <20200503180829.6767-1-mstamat@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: Subject: [FFmpeg-devel] [PATCH] avfilter/vf_subtitles: add shift options 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 Cc: Manolis Stamatogiannakis MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Allows shifting of subtitle display times to align them with the video. This avoids having to rewrite the subtitle file in order to display subtitles correctly when input is seeked (-ss). Also handy for minor subtitle timing corrections without rewriting the subtitles file. Signed-off-by: Manolis Stamatogiannakis --- doc/filters.texi | 8 ++++++++ libavfilter/vf_subtitles.c | 29 +++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index d19fd346ae..94323495f0 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -17851,6 +17851,9 @@ The filter accepts the following options: @item filename, f Set the filename of the subtitle file to read. It must be specified. +@item shift +Shift subtitles timings by the specified amount. + @item original_size Specify the size of the original video, the video for which the ASS file was composed. For the syntax of this option, check the @@ -17907,6 +17910,11 @@ To make the subtitles stream from @file{sub.srt} appear in 80% transparent blue subtitles=sub.srt:force_style='FontName=DejaVu Serif,PrimaryColour=&HCCFF0000' @end example +To re-sync subtitles after seeking the input e.g. with @code{-ss 20:20}, use: +@example +subtitles=filename=sub.srt:shift=-20\:20 +@end example + @section super2xsai Scale the input by 2x and smooth using the Super2xSaI (Scale and diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c index a3b4029af4..74a902941a 100644 --- a/libavfilter/vf_subtitles.c +++ b/libavfilter/vf_subtitles.c @@ -52,6 +52,8 @@ typedef struct AssContext { char *filename; char *fontsdir; char *charenc; + int64_t shift; + char *shift_opt; char *force_style; int stream_index; int alpha; @@ -68,6 +70,7 @@ typedef struct AssContext { #define COMMON_OPTIONS \ {"filename", "set the filename of file to read", OFFSET(filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, \ {"f", "set the filename of file to read", OFFSET(filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, \ + {"shift", "set the tilename of file to read", OFFSET(shift_opt), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, \ {"original_size", "set the size of the original video (used to scale fonts)", OFFSET(original_w), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, FLAGS }, \ {"fontsdir", "set the directory containing the fonts to read", OFFSET(fontsdir), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, \ {"alpha", "enable processing of alpha channel", OFFSET(alpha), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, FLAGS }, \ @@ -103,6 +106,16 @@ static av_cold int init(AVFilterContext *ctx) return AVERROR(EINVAL); } + if (ass->shift_opt) { + if (av_parse_time(&ass->shift, ass->shift_opt, 1) < 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid subtitles shift: %s\n", + ass->shift_opt); + return AVERROR(EINVAL); + } + ass->shift = av_rescale_q(ass->shift, AV_TIME_BASE_Q, av_make_q(1, 1000)); + av_log(ctx, AV_LOG_DEBUG, "Shifting subtitles by %0.3fsec.\n", ass->shift/1000.0); + } + ass->library = ass_library_init(); if (!ass->library) { av_log(ctx, AV_LOG_ERROR, "Could not initialize libass.\n"); @@ -297,7 +310,7 @@ AVFILTER_DEFINE_CLASS(subtitles); static av_cold int init_subtitles(AVFilterContext *ctx) { - int j, ret, sid; + int j, ret, sid, nskip; int k = 0; AVDictionary *codec_opts = NULL; AVFormatContext *fmt = NULL; @@ -448,6 +461,7 @@ static av_cold int init_subtitles(AVFilterContext *ctx) av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; + nskip = 0; while (av_read_frame(fmt, &pkt) >= 0) { int i, got_subtitle; AVSubtitle sub = {0}; @@ -458,8 +472,17 @@ static av_cold int init_subtitles(AVFilterContext *ctx) av_log(ctx, AV_LOG_WARNING, "Error decoding: %s (ignored)\n", av_err2str(ret)); } else if (got_subtitle) { - const int64_t start_time = av_rescale_q(sub.pts, AV_TIME_BASE_Q, av_make_q(1, 1000)); + const int64_t start_time = av_rescale_q(sub.pts, AV_TIME_BASE_Q, av_make_q(1, 1000)) + ass->shift; const int64_t duration = sub.end_display_time; + + if (start_time + duration < 0) { + nskip++; + goto pkt_end; + } else if (nskip > 0) { + av_log(ctx, AV_LOG_INFO, "Skipped %d subtitles out of time range.\n", nskip); + nskip = 0; + } + for (i = 0; i < sub.num_rects; i++) { char *ass_line = sub.rects[i]->ass; if (!ass_line) @@ -472,6 +495,8 @@ static av_cold int init_subtitles(AVFilterContext *ctx) } } } + +pkt_end: av_packet_unref(&pkt); avsubtitle_free(&sub); }