From patchwork Sat Nov 11 21:17:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 5919 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.161.94 with SMTP id m30csp488071jah; Sat, 11 Nov 2017 13:18:00 -0800 (PST) X-Google-Smtp-Source: AGs4zMYBpJM3Ujo+jCbpAiiJlUAmhUKxjq1r9uC66lcFNN5Py8IhvCpOd9nBPpk/dIfidBbdr/qo X-Received: by 10.223.150.204 with SMTP id u70mr3339316wrb.115.1510435080739; Sat, 11 Nov 2017 13:18:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1510435080; cv=none; d=google.com; s=arc-20160816; b=Z47UP/MHr+atgrIQC6uPLzpuXDHYETyOu199dtfiY394PN8X0qZAbeBrJ3n8aSZFnY h+vl8XzMeQyH7KHVfPsGHZHQBOnn476osVjzZ71WEoCV3HOU0FNUEIWoOTKWuvNNvdo3 JWihheLWTw+aSbD/Cm+AehlWUIJysUrHX5NVAbSTyUzAt5eFasqZpSxJ3QGaBEpEl78K +7+lhTzQo8AQWUt5dp/6+s/NKDP+R8GRdYXmf42NnbTPZpdierbMMMzY1360GLiWHUk1 rRgn1LcRVVF20fNC1wP7wUxzuPr7hjoRld1IxcENgjrvF5M0an4FdS98QtYpmTxRm3xG P5yQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:message-id:date:to:from:dkim-signature :delivered-to:arc-authentication-results; bh=fnmM4V4oBPG/Co0u//AD41xNgEhYFd2gsUGPC3DxppI=; b=Sd69HxD1vTSBUVzZ29xpaq8FF4gQFy/7+oKGbT16cbFsXaYa8W2LLJRm87xhA3rj/Y iYdmqP61FZH9DUqcC78hMlpH1J6BFLwbI3qVWUd3COikiiybbXZ3qvs7NOC8LRbhLFm9 HRdSNGahS8lof/mQzDYhThzDRG1h+e9EuOWTRwVkG+po+/ASy8i487f7TBiWSJBLQ51T UDxciwRiFeQT1JpD+xa+XJDRXt+6WjbtbnVapV5C13ABNJz6v0GfrCgV0nILXuZGsFa2 a+yac7CIgHN26vzdO1Y0BMNPifxmbAXC+SNDyhpu+Brm0WJn0z9MAtYtPTuOqv14PYcb kkBA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=qNLl29Uh; 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=NONE 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 k67si3662352wmi.159.2017.11.11.13.17.59; Sat, 11 Nov 2017 13:18:00 -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=20161025 header.b=qNLl29Uh; 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=NONE 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 DD64368A209; Sat, 11 Nov 2017 23:17:44 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm0-f65.google.com (mail-wm0-f65.google.com [74.125.82.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2EEA968A1FA for ; Sat, 11 Nov 2017 23:17:39 +0200 (EET) Received: by mail-wm0-f65.google.com with SMTP id b189so1778545wmd.0 for ; Sat, 11 Nov 2017 13:17:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=cO6ywlHmL0JTdgq+9z5h0NYNwtJ5mt6sToYVueQ+z8o=; b=qNLl29UhLCAwSdkh2TIsuyJBfUGf8GHTWWKKHCgc3BGm6bSrKEOn+yADw7UTnkG5m8 ko5Iey2U9Eyn4FOkkEyJO+pyaGz3FZ0hmyBc+n2cfRE1bqI0NzCV6S9we/pI+Eg1OeBR x4T+UPtNabUHCe+lSP0oWHBDUDyIBd0nZzZdeoj9+e60aKo2hHDFUIQOfl6Tu8aOa8+o Ta3EkMtopKXrLJ1xJJsfH1xnf/p3hYzK8kB6rgIIiib4mOAxNKn8QTVJ78Bs2rUjT/IC kIyU71koYYOQbHlq/RrXhHcbckTGCJHP15rbcdP+4c8+COo54lPgD4Fd8MNoRgpBQS58 i9wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=cO6ywlHmL0JTdgq+9z5h0NYNwtJ5mt6sToYVueQ+z8o=; b=JA+Dnh2+1L4IZcuVN3dAKFGR6e52xEI8PHUH2d+3OC+05m4WzYaFV5KrZwONoT7uDg 0RelhqvmAjqVQHvbaP+KvQ/4+DuTHpyMHMNDpRIfmYYu/GDEzikr0HkLkk1qSmkHm4tj NU2LLbm2jN0BzaRN/oxOa29W/ObEAVnk/+718is5/kUJr2THqH9feCdgPNayCkvzjhan l5+auG9kdJU6l19AyHjHCZGlwXaYA3AIH40V5fPpJduOG/aigvnpS06Te+htd3M45sW1 4fj4Lv4AuRMN9p5wLbSUjTHkOgUlgNcxAw7coLopo1Ty2rHKdXyuyqZJn0+gyxmZPjyh t9sQ== X-Gm-Message-State: AJaThX5o0UJSqT6Ezu4ToVmbb2/9mYvo4VCI7V0unoEmVCygq0/dzfSH 1rNHof+/9at5SliF2rMhtTOYRA== X-Received: by 10.28.203.195 with SMTP id b186mr2913480wmg.93.1510435072513; Sat, 11 Nov 2017 13:17:52 -0800 (PST) Received: from localhost.localdomain ([94.250.174.60]) by smtp.gmail.com with ESMTPSA id w76sm8768859wrc.79.2017.11.11.13.17.50 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 11 Nov 2017 13:17:51 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Sat, 11 Nov 2017 22:17:07 +0100 Message-Id: <20171111211707.7482-1-onemda@gmail.com> X-Mailer: git-send-email 2.11.0 Subject: [FFmpeg-devel] [PATCH] avfilter/vf_tile: add overlap option 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 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- doc/filters.texi | 5 +++++ libavfilter/vf_tile.c | 54 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 5c6729a484..6079290fbd 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -14441,6 +14441,11 @@ refer to the pad video filter. Specify the color of the unused area. For the syntax of this option, check the "Color" section in the ffmpeg-utils manual. The default value of @var{color} is "black". + +@item overlap +Set the number of frames to overlap when tiling several successive frames together. +The default value is @code{0}, meaning overlap @var{0} frames. If it is more +than @var{nb_frames - 1} its set to @var{nb_frames - 1} and warning is displayed. @end table @subsection Examples diff --git a/libavfilter/vf_tile.c b/libavfilter/vf_tile.c index e9d246fc73..7717ce12e7 100644 --- a/libavfilter/vf_tile.c +++ b/libavfilter/vf_tile.c @@ -37,11 +37,13 @@ typedef struct TileContext { unsigned w, h; unsigned margin; unsigned padding; + unsigned overlap; unsigned current; unsigned nb_frames; FFDrawContext draw; FFDrawColor blank; AVFrame *out_ref; + AVFrame *prev_out_ref; uint8_t rgba_color[4]; } TileContext; @@ -58,6 +60,8 @@ static const AVOption tile_options[] = { { "padding", "set inner border thickness in pixels", OFFSET(padding), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1024, FLAGS }, { "color", "set the color of the unused area", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = FLAGS }, + { "overlap", "set how many frames to overlap for each render", OFFSET(overlap), + AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS }, { NULL } }; @@ -90,6 +94,11 @@ static av_cold int init(AVFilterContext *ctx) return AVERROR(EINVAL); } + if (tile->overlap >= tile->nb_frames) { + av_log(ctx, AV_LOG_WARNING, "overlap must be less than %d\n", tile->nb_frames); + tile->overlap = tile->nb_frames - 1; + } + return 0; } @@ -120,19 +129,19 @@ static int config_props(AVFilterLink *outlink) outlink->h = tile->h * inlink->h + total_margin_h; outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; outlink->frame_rate = av_mul_q(inlink->frame_rate, - av_make_q(1, tile->nb_frames)); + av_make_q(1, tile->nb_frames - tile->overlap)); ff_draw_init(&tile->draw, inlink->format, 0); ff_draw_color(&tile->draw, &tile->blank, tile->rgba_color); return 0; } -static void get_current_tile_pos(AVFilterContext *ctx, unsigned *x, unsigned *y) +static void get_tile_pos(AVFilterContext *ctx, unsigned *x, unsigned *y, unsigned current) { TileContext *tile = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - const unsigned tx = tile->current % tile->w; - const unsigned ty = tile->current / tile->w; + const unsigned tx = current % tile->w; + const unsigned ty = current / tile->w; *x = tile->margin + (inlink->w + tile->padding) * tx; *y = tile->margin + (inlink->h + tile->padding) * ty; @@ -144,7 +153,7 @@ static void draw_blank_frame(AVFilterContext *ctx, AVFrame *out_buf) AVFilterLink *inlink = ctx->inputs[0]; unsigned x0, y0; - get_current_tile_pos(ctx, &x0, &y0); + get_tile_pos(ctx, &x0, &y0, tile->current); ff_fill_rectangle(&tile->draw, &tile->blank, out_buf->data, out_buf->linesize, x0, y0, inlink->w, inlink->h); @@ -160,8 +169,13 @@ static int end_last_frame(AVFilterContext *ctx) while (tile->current < tile->nb_frames) draw_blank_frame(ctx, out_buf); + tile->current = tile->overlap; + if (tile->current) { + av_frame_free(&tile->prev_out_ref); + tile->prev_out_ref = av_frame_clone(out_buf); + } ret = ff_filter_frame(outlink, out_buf); - tile->current = 0; + tile->out_ref = NULL; return ret; } @@ -176,7 +190,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) AVFilterLink *outlink = ctx->outputs[0]; unsigned x0, y0; - if (!tile->current) { + if (!tile->out_ref) { tile->out_ref = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!tile->out_ref) { av_frame_free(&picref); @@ -194,7 +208,21 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) 0, 0, outlink->w, outlink->h); } - get_current_tile_pos(ctx, &x0, &y0); + if (tile->prev_out_ref) { + unsigned x1, y1, i; + + for (i = tile->nb_frames - tile->overlap; i < tile->nb_frames; i++) { + get_tile_pos(ctx, &x1, &y1, i); + get_tile_pos(ctx, &x0, &y0, i - (tile->nb_frames - tile->overlap)); + ff_copy_rectangle2(&tile->draw, + tile->out_ref->data, tile->out_ref->linesize, + tile->prev_out_ref->data, tile->prev_out_ref->linesize, + x0, y0, x1, y1, inlink->w, inlink->h); + + } + } + + get_tile_pos(ctx, &x0, &y0, tile->current); ff_copy_rectangle2(&tile->draw, tile->out_ref->data, tile->out_ref->linesize, picref->data, picref->linesize, @@ -215,11 +243,18 @@ static int request_frame(AVFilterLink *outlink) int r; r = ff_request_frame(inlink); - if (r == AVERROR_EOF && tile->current) + if (r == AVERROR_EOF && tile->current && tile->out_ref) r = end_last_frame(ctx); return r; } +static av_cold void uninit(AVFilterContext *ctx) +{ + TileContext *tile = ctx->priv; + + av_frame_free(&tile->prev_out_ref); +} + static const AVFilterPad tile_inputs[] = { { .name = "default", @@ -243,6 +278,7 @@ AVFilter ff_vf_tile = { .name = "tile", .description = NULL_IF_CONFIG_SMALL("Tile several successive frames together."), .init = init, + .uninit = uninit, .query_formats = query_formats, .priv_size = sizeof(TileContext), .inputs = tile_inputs,