From patchwork Mon May 1 15:02:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 41436 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:dca6:b0:f3:34fa:f187 with SMTP id ky38csp3261346pzb; Mon, 1 May 2023 08:03:40 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5pq6Zm71T0lzdCPNi9kOWNYq+/ptA+xJVQ5fgadwkXFvlFXtIbxhh3MmfbjED0pydbsbDC X-Received: by 2002:a17:907:36c4:b0:94e:4b26:233c with SMTP id bj4-20020a17090736c400b0094e4b26233cmr13840299ejc.16.1682953419961; Mon, 01 May 2023 08:03:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1682953419; cv=none; d=google.com; s=arc-20160816; b=txaT/ro1dP4WSrlezm8fayGylcdtrVpLIr2a69GCBqxXUo1TQJkFTke6jpIcDXhpGS 6zRNyFGUpK+tZTpa/+RgT+I/JbGwfG9X3ahe16tWeUd7qm49tFvI8JWQpRG9u8BsfLua jOGVtatm4SI9J8EecHBb+uH3c5cGowv0p0LivGVug3mJR56wScNpdvVxbDTsZkor+8Oc hoNwHsYGw0dz4pGPNlnif3B06x4qoj6oSbmTVsnNEtz6j61M25+gTEZHMQ56jnnJXfA8 l6bVpg3IUL4ka2qvoBfF51mnYZDSomeGkYN+x2JUDX4CGjQUsl+3VV8z6WnnP2c3Tz/W SG4g== 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:message-id:date:to:from :dkim-signature:delivered-to; bh=SlNZXaJ9o12t6SVYC/r0W9V8Fbc67uLc3aaWfDCk564=; b=mi48aSbsMNC9qNrAH7Va2HWUsQRy0me6Hg/Ofc50eNZerYg9roSvpI2TWZ2FXLpC4g 8VUivRMgo7zIUSz5vYg5DMSyv/sJ0udzsdApRWfOsiCifMKTeIj5GwBGz06nl1fHmyQk Rev+FwwLmPNGzfZHgCOcuiRTkKolaZyySdmf5S7IW9oXeZSEKSYIkD1fQO8piHliq7Vk YUGLAwvNZcHLB1W+SFpaAWoqKQiKjgHwK24xuZEUo0dYDj69lIi+FwKh6Uyhd82U/dmy +apm+t/NERMndRzMKft9Q/AQKlgzCmFHmpl8my3EcXRR3bzTeiiUQLBNUqzUH4ODqVdw qDpw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=aZNFsKgN; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id z20-20020a1709067e5400b0094f507a9f21si20378266ejr.710.2023.05.01.08.03.15; Mon, 01 May 2023 08:03:39 -0700 (PDT) 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=@haasn.xyz header.s=mail header.b=aZNFsKgN; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0839468C0CB; Mon, 1 May 2023 18:03:11 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 17FE568BEC4 for ; Mon, 1 May 2023 18:03:05 +0300 (EEST) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 14B094264E; Mon, 1 May 2023 17:03:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1682953384; bh=8x1GvaNVFPNOgp5NdBjMaxU2qB2+iXJdsSoJs+UsSW8=; h=From:To:Cc:Subject:Date:From; b=aZNFsKgNK0mRcbhqlWmoAdUVKRhRHUOtcu2H8n5zdcDL/byEHyKymXE3A5+Q3oYrQ tV9pEYmGMw6zU3f9NPiAZ8iOqSyvUrZ9gwmawYYpgflsMhhTmCT68RPWYVkfoXdjbX p/Z0LGOQy8ibAc1IspmA4LOrIPY+RQ5ZrDaqrZgo= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Mon, 1 May 2023 17:02:59 +0200 Message-Id: <20230501150301.55718-1-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.40.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/3] avfilter/vf_libplacebo: add fillcolor option 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: eI9OpI+Mw2w6 From: Niklas Haas In some circumstances, libplacebo will clear the background as a result of cropping/padding. Currently, this uses the hard-coded default fill color of black. This option makes this behavior configurable. --- doc/filters.texi | 6 ++++++ libavfilter/vf_libplacebo.c | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 6d2672063c1..35df5c339a7 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16018,6 +16018,12 @@ content with black borders, while a value of @code{1.0} always crops off parts of the content. Intermediate values are possible, leading to a mix of the two approaches. +@item fillcolor +Set the color used to fill the output area not covered by the output image, for +example as a result of @ref{normalize_sar}. For the general syntax of this +option, check the @ref{color syntax,,"Color" section in the ffmpeg-utils +manual,ffmpeg-utils}. Defaults to @code{black}. + @item colorspace @item color_primaries @item color_trc diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 66929223dd9..fcdc97e48e2 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -18,6 +18,7 @@ #include "libavutil/file.h" #include "libavutil/opt.h" +#include "libavutil/parseutils.h" #include "internal.h" #include "vulkan_filter.h" #include "scale_eval.h" @@ -73,6 +74,7 @@ typedef struct LibplaceboContext { /* settings */ char *out_format_string; enum AVPixelFormat out_format; + char *fillcolor; char *w_expr; char *h_expr; AVRational target_sar; @@ -225,6 +227,24 @@ static int find_scaler(AVFilterContext *avctx, return AVERROR(EINVAL); } +static int parse_fillcolor(AVFilterContext *avctx, + struct pl_render_params *params, + const char *color_str) +{ + int err = 0; + uint8_t color_rgba[4]; + + RET(av_parse_color(color_rgba, color_str, -1, avctx)); + params->background_color[0] = (float) color_rgba[0] / UINT8_MAX; + params->background_color[1] = (float) color_rgba[1] / UINT8_MAX; + params->background_color[2] = (float) color_rgba[2] / UINT8_MAX; + params->background_transparency = 1.0f - (float) color_rgba[3] / UINT8_MAX; + return 0; + +fail: + return err; +} + static void libplacebo_uninit(AVFilterContext *avctx); static int libplacebo_init(AVFilterContext *avctx) @@ -469,6 +489,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) RET(find_scaler(avctx, ¶ms.upscaler, s->upscaler)); RET(find_scaler(avctx, ¶ms.downscaler, s->downscaler)); + RET(parse_fillcolor(avctx, ¶ms, s->fillcolor)); pl_render_image(s->renderer, &image, &target, ¶ms); pl_unmap_avframe(s->gpu, &image); @@ -703,6 +724,7 @@ static const AVOption libplacebo_options[] = { { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 256, STATIC }, { "normalize_sar", "force SAR normalization to 1:1", OFFSET(normalize_sar), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, STATIC }, { "pad_crop_ratio", "ratio between padding and cropping when normalizing SAR (0=pad, 1=crop)", OFFSET(pad_crop_ratio), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, 1.0, DYNAMIC }, + { "fillcolor", "Background fill color", OFFSET(fillcolor), AV_OPT_TYPE_STRING, {.str = "black"}, .flags = DYNAMIC }, {"colorspace", "select colorspace", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_SPC_NB-1, DYNAMIC, "colorspace"}, {"auto", "keep the same colorspace", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, "colorspace"}, From patchwork Mon May 1 15:03:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 41438 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:dca6:b0:f3:34fa:f187 with SMTP id ky38csp3261478pzb; Mon, 1 May 2023 08:03:48 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7d0krg/soRgk7RDGOz5lC5RcDXAw3kHG+FuKJLWmwaxN7mxKn9SQWTOWr9SsReIupZcCAc X-Received: by 2002:a17:907:6d8c:b0:8a5:8620:575 with SMTP id sb12-20020a1709076d8c00b008a586200575mr13215222ejc.3.1682953428648; Mon, 01 May 2023 08:03:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1682953428; cv=none; d=google.com; s=arc-20160816; b=mIuYnxYhJUnIrPAUcqAHIkQmH/KPZHE03RnQhBuD34HPjlzKTREVpN2A0zxblSq5yp ZbtJH92PGwzv5TOur6S/WWE3xMyjP3QkwgAsihxCabuiSi8Ueb4IJ2VApp7JgHRBJVBO GhDIZ9MZSbDJhVbC2FAhU04Vh3EZSXyJ86pjbuo+Q2LHcVwmYL12bV0wOwUkVgIPU2bq G8ojqAhPbX9xzA+kiP//8oubidKWpbxZyysZfQ8FTSO2dW3+m9aiHzeqZ636FYHMqzo4 QmCc6wdNil9OeGVjNvemBJm6RmGZTIfjALI3iF1S00Rd7V1h0cHrpj+AR7Yw9LCaRcXm NXPQ== 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=a4LEMVdehobQAvQpvRTxAh6X0yCndblshpmG4IGmOgI=; b=KQ38cJlpLUQab6Yf/CshH+oXyWy/SY1DmqgB944q7nHAZEXEOyrXDO7aJMVHz22/rK U53/b+RL9pPVCZbSk2Rrl47Xt+98G9s/TZdcoPj3UxF94iHu9m6FU3zQtJz4XzRJW64/ 44Xuro9+W0nXAjWglUu/i+BCjHZhNr33D2w6fffPF1LLElsznbSnQ37MMfb6opLynSqI u1k/3zkzL/sxprYJ80DW708rCbjwgjGymgIsrZz4UTfbdyoNtgSoGJqryALM1inMCAVv Ih6mSOd1yv2ttibqG5cknzksCG54Xm4gKTHb8XA+42LYnA9g1/c0FDHTawFZb4/eLpgG PfOw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=vApx+y2V; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id us5-20020a170906bfc500b0094ed677a55dsi19764998ejb.51.2023.05.01.08.03.46; Mon, 01 May 2023 08:03:48 -0700 (PDT) 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=@haasn.xyz header.s=mail header.b=vApx+y2V; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9063268C0EF; Mon, 1 May 2023 18:03:13 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1B08F68C0AA for ; Mon, 1 May 2023 18:03:05 +0300 (EEST) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 5871342AA4; Mon, 1 May 2023 17:03:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1682953384; bh=c6H/tuJ2FymOu3DsEzfzCpgX2yZBqig6ztkKf+thyTA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vApx+y2V6tq7QLfuOw4zCdKMF4m2Gx8Ds+0nDMcvXkpSsTPRBALED9sAiDgdH0kri mxKjv2n5kWxstluG0/pD46mWFKbyH6DVAsFLtdPbxRwn9nBVjMCbi17uF1SbuunFEh TNfLsHVpU+NesJ4heb/HURbj3AsfWxGl4pNLbDh8= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Mon, 1 May 2023 17:03:00 +0200 Message-Id: <20230501150301.55718-2-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.40.0 In-Reply-To: <20230501150301.55718-1-ffmpeg@haasn.xyz> References: <20230501150301.55718-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/3] avfilter/vf_libplacebo: add flexible crop exprs 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: k3hoMMlzDycx From: Niklas Haas Motivated by a desire to use vf_libplacebo as a GPU-accelerated cropping/padding/zooming filter. This commit adds support for setting the `input/target.crop` fields as dynamic expressions. Re-use the same generic variables available to other scale and crop type filters, and also add some more that we can afford as a result of being able to set these properties dynamically. It's worth pointing out that `out_t/ot` is currently redundant with `in_t/t` since it will always contain the same PTS values, but I plan on changing this in the near future. I decided to also expose `crop_w/crop_h` and `pos_w/pos_h` as variables in the expression parser itself, since this enables the fairly common use case of determining dimensions first and then placing the image appropriately, such as is done in the default behavior (which centers the cropped/placed region by default). --- doc/filters.texi | 55 ++++++++++++-- libavfilter/vf_libplacebo.c | 145 +++++++++++++++++++++++++++++++++++- 2 files changed, 192 insertions(+), 8 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 35df5c339a7..2d49f93b9e2 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -15991,10 +15991,31 @@ in source frames. @table @option @item w @item h -Set the output video dimension expression. Default value is the input dimension. +Set the output video dimension expression. Default values are @code{iw} and +@code{ih}. Allows for the same expressions as the @ref{scale} filter. +@item crop_x +@item crop_y +Set the input crop x/y expressions, default values are @code{(iw-cw)/2} and +@code{(ih-ch)/2}. + +@item crop_w +@item crop_h +Set the input crop width/height expressions, default values are @code{iw} and +@code{ih}. + +@item pos_x +@item pos_y +Set the output placement x/y expressions, default values are @code{(ow-pw)/2} +and @code{(oh-ph)/2}. + +@item pos_w +@item pos_h +Set the output placement width/height expressions, default values are @code{ow} +and @code{oh}. + @item format Set the output format override. If unset (the default), frames will be output in the same format as the respective input frames. Otherwise, format conversion @@ -16006,9 +16027,9 @@ Work the same as the identical @ref{scale} filter options. @item normalize_sar If enabled, output frames will always have a pixel aspect ratio of 1:1. This -will introduce padding/cropping as necessary. If disabled (the default), any -aspect ratio mismatches, including those from e.g. anamorphic video sources, -are forwarded to the output pixel aspect ratio. +will introduce additional padding/cropping as necessary. If disabled (the +default), any aspect ratio mismatches, including those from e.g. anamorphic +video sources, are forwarded to the output pixel aspect ratio. @item pad_crop_ratio Specifies a ratio (between @code{0.0} and @code{1.0}) between padding and @@ -16020,7 +16041,7 @@ approaches. @item fillcolor Set the color used to fill the output area not covered by the output image, for -example as a result of @ref{normalize_sar}. For the general syntax of this +example as a result of @option{normalize_sar}. For the general syntax of this option, check the @ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. Defaults to @code{black}. @@ -16045,6 +16066,30 @@ BT.2020+PQ, overriding the usual input frame metadata. These will also be picked as the values of @code{auto} for the respective frame output options. @end table +In addition to the expression constants documented for the @ref{scale} filter, +the @option{crop_w}, @option{crop_h}, @option{crop_x}, @option{crop_y}, +@option{pos_w}, @option{pos_h}, @option{pos_x} and @option{pos_y} options can +also contain the following constants: + +@table @option +@item crop_w, cw +@item crop_h, ch +The computed values of @option{crop_w} and @option{crop_h}. + +@item pos_w, pw +@item pos_h, ph +The computed values of @option{pos_w} and @option{pos_h}. + +@item in_t, t +The input frame timestamp, in seconds. NAN if input timestamp is unknown. + +@item out_t, ot +The input frame timestamp, in seconds. NAN if input timestamp is unknown. + +@item n +The input frame number, starting with 0. +@end table + @subsubsection Scaling The options in this section control how libplacebo performs upscaling and (if necessary) downscaling. Note that libplacebo will always internally operate on diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index fcdc97e48e2..6fe3e0ea882 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -16,6 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/eval.h" #include "libavutil/file.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" @@ -60,6 +61,50 @@ static const struct pl_tone_map_function * const tonemapping_funcs[TONE_MAP_COUN [TONE_MAP_LINEAR] = &pl_tone_map_linear, }; +static const char *const var_names[] = { + "in_w", "iw", ///< width of the input video frame + "in_h", "ih", ///< height of the input video frame + "out_w", "ow", ///< width of the output video frame + "out_h", "oh", ///< height of the output video frame + "crop_w", "cw", ///< evaluated input crop width + "crop_h", "ch", ///< evaluated input crop height + "pos_w", "pw", ///< evaluated output placement width + "pos_h", "ph", ///< evaluated output placement height + "a", ///< iw/ih + "sar", ///< input pixel aspect ratio + "dar", ///< output pixel aspect ratio + "hsub", ///< input horizontal subsampling factor + "vsub", ///< input vertical subsampling factor + "ohsub", ///< output horizontal subsampling factor + "ovsub", ///< output vertical subsampling factor + "in_t", "t", ///< input frame pts + "out_t", "ot", ///< output frame pts + "n", ///< number of frame + NULL, +}; + +enum var_name { + VAR_IN_W, VAR_IW, + VAR_IN_H, VAR_IH, + VAR_OUT_W, VAR_OW, + VAR_OUT_H, VAR_OH, + VAR_CROP_W, VAR_CW, + VAR_CROP_H, VAR_CH, + VAR_POS_W, VAR_PW, + VAR_POS_H, VAR_PH, + VAR_A, + VAR_SAR, + VAR_DAR, + VAR_HSUB, + VAR_VSUB, + VAR_OHSUB, + VAR_OVSUB, + VAR_IN_T, VAR_T, + VAR_OUT_T, VAR_OT, + VAR_N, + VAR_VARS_NB +}; + typedef struct LibplaceboContext { /* lavfi vulkan*/ FFVulkanContext vkctx; @@ -75,8 +120,16 @@ typedef struct LibplaceboContext { char *out_format_string; enum AVPixelFormat out_format; char *fillcolor; + double var_values[VAR_VARS_NB]; char *w_expr; char *h_expr; + char *crop_x_expr, *crop_y_expr; + char *crop_w_expr, *crop_h_expr; + char *pos_x_expr, *pos_y_expr; + char *pos_w_expr, *pos_h_expr; + // Parsed expressions for input/output crop + AVExpr *crop_x_pexpr, *crop_y_pexpr, *crop_w_pexpr, *crop_h_pexpr; + AVExpr *pos_x_pexpr, *pos_y_pexpr, *pos_w_pexpr, *pos_h_pexpr; AVRational target_sar; float pad_crop_ratio; int force_original_aspect_ratio; @@ -249,6 +302,7 @@ static void libplacebo_uninit(AVFilterContext *avctx); static int libplacebo_init(AVFilterContext *avctx) { + int err = 0; LibplaceboContext *s = avctx->priv; /* Create libplacebo log context */ @@ -273,8 +327,28 @@ static int libplacebo_init(AVFilterContext *avctx) s->out_format = AV_PIX_FMT_NONE; } + RET(av_expr_parse(&s->crop_x_pexpr, s->crop_x_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->crop_y_pexpr, s->crop_y_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->crop_w_pexpr, s->crop_w_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->crop_h_pexpr, s->crop_h_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->pos_x_pexpr, s->pos_x_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->pos_y_pexpr, s->pos_y_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->pos_w_pexpr, s->pos_w_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + RET(av_expr_parse(&s->pos_h_pexpr, s->pos_h_expr, var_names, + NULL, NULL, NULL, NULL, 0, s)); + /* Note: s->vulkan etc. are initialized later, when hwctx is available */ return 0; + +fail: + return err; } static int init_vulkan(AVFilterContext *avctx) @@ -364,6 +438,15 @@ static void libplacebo_uninit(AVFilterContext *avctx) pl_log_destroy(&s->log); ff_vk_uninit(&s->vkctx); s->gpu = NULL; + + av_expr_free(s->crop_x_pexpr); + av_expr_free(s->crop_y_pexpr); + av_expr_free(s->crop_w_pexpr); + av_expr_free(s->crop_h_pexpr); + av_expr_free(s->pos_x_pexpr); + av_expr_free(s->pos_y_pexpr); + av_expr_free(s->pos_w_pexpr); + av_expr_free(s->pos_h_pexpr); } static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) @@ -398,6 +481,25 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) if (!s->apply_filmgrain) image.film_grain.type = PL_FILM_GRAIN_NONE; + s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = + av_expr_eval(s->crop_w_pexpr, s->var_values, NULL); + s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = + av_expr_eval(s->crop_h_pexpr, s->var_values, NULL); + s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = + av_expr_eval(s->pos_w_pexpr, s->var_values, NULL); + s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = + av_expr_eval(s->pos_h_pexpr, s->var_values, NULL); + + image.crop.x0 = av_expr_eval(s->crop_x_pexpr, s->var_values, NULL); + image.crop.y0 = av_expr_eval(s->crop_y_pexpr, s->var_values, NULL); + image.crop.x1 = image.crop.x0 + s->var_values[VAR_CROP_W]; + image.crop.y1 = image.crop.y0 + s->var_values[VAR_CROP_H]; + + target.crop.x0 = av_expr_eval(s->pos_x_pexpr, s->var_values, NULL); + target.crop.y0 = av_expr_eval(s->pos_y_pexpr, s->var_values, NULL); + target.crop.x1 = target.crop.x0 + s->var_values[VAR_POS_W]; + target.crop.y1 = target.crop.y0 + s->var_values[VAR_POS_H]; + if (s->target_sar.num) { float aspect = pl_rect2df_aspect(&target.crop) * av_q2d(s->target_sar); pl_rect2df_aspect_set(&target.crop, aspect, s->pad_crop_ratio); @@ -530,6 +632,18 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) out->width = outlink->w; out->height = outlink->h; + /* Dynamic variables */ + s->var_values[VAR_IN_T] = s->var_values[VAR_T] = + in->pts == AV_NOPTS_VALUE ? NAN : in->pts * av_q2d(link->time_base); + s->var_values[VAR_OUT_T] = s->var_values[VAR_OT] = + out->pts == AV_NOPTS_VALUE ? NAN : out->pts * av_q2d(outlink->time_base); + s->var_values[VAR_N] = link->frame_count_out; + /* Will be evaluated/set by `process_frames` */ + s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = NAN; + s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = NAN; + s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = NAN; + s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = NAN; + if (s->apply_dovi && av_frame_get_side_data(in, AV_FRAME_DATA_DOVI_METADATA)) { /* Output of dovi reshaping is always BT.2020+PQ, so infer the correct * output colorspace defaults */ @@ -660,6 +774,8 @@ static int libplacebo_config_output(AVFilterLink *outlink) AVFilterContext *avctx = outlink->src; LibplaceboContext *s = avctx->priv; AVFilterLink *inlink = outlink->src->inputs[0]; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format); AVHWFramesContext *hwfc; AVVulkanFramesContext *vkfc; AVRational scale_sar; @@ -687,6 +803,21 @@ static int libplacebo_config_output(AVFilterLink *outlink) outlink->sample_aspect_ratio = scale_sar; } + /* Static variables */ + s->var_values[VAR_IN_W] = s->var_values[VAR_IW] = inlink->w; + s->var_values[VAR_IN_H] = s->var_values[VAR_IH] = inlink->h; + s->var_values[VAR_OUT_W] = s->var_values[VAR_OW] = outlink->w; + s->var_values[VAR_OUT_H] = s->var_values[VAR_OH] = outlink->h; + s->var_values[VAR_A] = (double) inlink->w / inlink->h; + s->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? + av_q2d(inlink->sample_aspect_ratio) : 1.0; + s->var_values[VAR_DAR] = outlink->sample_aspect_ratio.num ? + av_q2d(outlink->sample_aspect_ratio) : 1.0; + s->var_values[VAR_HSUB] = 1 << desc->log2_chroma_w; + s->var_values[VAR_VSUB] = 1 << desc->log2_chroma_h; + s->var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w; + s->var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h; + if (outlink->format != AV_PIX_FMT_VULKAN) return 0; @@ -714,15 +845,23 @@ fail: #define DYNAMIC (STATIC | AV_OPT_FLAG_RUNTIME_PARAM) static const AVOption libplacebo_options[] = { - { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = STATIC }, - { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = STATIC }, + { "w", "Output video frame width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = STATIC }, + { "h", "Output video frame height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = STATIC }, + { "crop_x", "Input video crop x", OFFSET(crop_x_expr), AV_OPT_TYPE_STRING, {.str = "(iw-cw)/2"}, .flags = DYNAMIC }, + { "crop_y", "Input video crop y", OFFSET(crop_y_expr), AV_OPT_TYPE_STRING, {.str = "(ih-ch)/2"}, .flags = DYNAMIC }, + { "crop_w", "Input video crop w", OFFSET(crop_w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = DYNAMIC }, + { "crop_h", "Input video crop h", OFFSET(crop_h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = DYNAMIC }, + { "pos_x", "Output video placement x", OFFSET(pos_x_expr), AV_OPT_TYPE_STRING, {.str = "(ow-pw)/2"}, .flags = DYNAMIC }, + { "pos_y", "Output video placement y", OFFSET(pos_y_expr), AV_OPT_TYPE_STRING, {.str = "(oh-ph)/2"}, .flags = DYNAMIC }, + { "pos_w", "Output video placement w", OFFSET(pos_w_expr), AV_OPT_TYPE_STRING, {.str = "ow"}, .flags = DYNAMIC }, + { "pos_h", "Output video placement h", OFFSET(pos_h_expr), AV_OPT_TYPE_STRING, {.str = "oh"}, .flags = DYNAMIC }, { "format", "Output video format", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = STATIC }, { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, STATIC, "force_oar" }, { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, STATIC, "force_oar" }, { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, STATIC, "force_oar" }, { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, STATIC, "force_oar" }, { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 256, STATIC }, - { "normalize_sar", "force SAR normalization to 1:1", OFFSET(normalize_sar), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, STATIC }, + { "normalize_sar", "force SAR normalization to 1:1 by adjusting pos_x/y/w/h", OFFSET(normalize_sar), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, STATIC }, { "pad_crop_ratio", "ratio between padding and cropping when normalizing SAR (0=pad, 1=crop)", OFFSET(pad_crop_ratio), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, 1.0, DYNAMIC }, { "fillcolor", "Background fill color", OFFSET(fillcolor), AV_OPT_TYPE_STRING, {.str = "black"}, .flags = DYNAMIC }, From patchwork Mon May 1 15:03:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 41437 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:dca6:b0:f3:34fa:f187 with SMTP id ky38csp3261433pzb; Mon, 1 May 2023 08:03:47 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4TADfTfvd2kLTUakk2xZ6vhUSW3nkxVKrNPbHmO0r+rW1CMNYiXFmP6dWIRgaUM8SoRN/E X-Received: by 2002:a17:906:fe45:b0:94f:296d:75d0 with SMTP id wz5-20020a170906fe4500b0094f296d75d0mr13078149ejb.30.1682953426684; Mon, 01 May 2023 08:03:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1682953426; cv=none; d=google.com; s=arc-20160816; b=NzJYT1D4DmY6SPNeIJQ9RirAVihB5Ur1CKvjKpfD/bsBvb01awPhMqmMQHJ8vABhud ju8URgUvSz7q8exn4jZjoo615A3qceuziWXZwqmmqD1S/F2yiI6v8+J18/CjMIcXjzzU B/Iy+OeITFLoq1oNuMwxitFS8vju0GJGbnN87HtbFyyY43Dlk+boojExdO6G5CTuadmy p79BapekXbQVG5WHEi32hnhcD41W6pyCncjJCxCiHWWdf4f4rlIIe+PNbQcykTZcEF4U AI00p1LqP5DxioCAtwXLd4Aa8obBzovsQg+dSwprIDyY1AKGELiIw16R+0i9/GuQPOIZ vBoA== 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=6TaM2TeXg84KEljme853/XYVvmvmOaBcsLJswqBVdF4=; b=Ad5T91OJmYW8Vk7PNTEUdYAzUe09LqMKqYWStUDanYSC4exEY7m7a6iK67t3y75+Lx gO5CBNFJv6pqdsbsWrQ7ledBJQ3kUSYBsLTrEt0zDbc20mhMvrjnnIjvmmbWuX8ARHcQ csMnw3BLDbhSFQu90iLynybahHt240gaZcBkc6rb2wX2QURcLsRWxPzWmgo/aUvmptYU Ak5XxD96IlpTS6L9Kz0pH+mtYXbAoMvZ2jM+4SvZFvNb4hlN7KmVqHC0AQP2jKW5bPK2 PyW7kI/x29tXy9l+hkOXAjJrqIBKOFnSHmadu849tnP1P929ZFKrEY+/VtX3/CZM3HGl EHcg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=fowQQUuh; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id rv10-20020a17090710ca00b009538cae8327si19222202ejb.971.2023.05.01.08.03.31; Mon, 01 May 2023 08:03:46 -0700 (PDT) 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=@haasn.xyz header.s=mail header.b=fowQQUuh; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9481868C0DE; Mon, 1 May 2023 18:03:12 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1996268BF40 for ; Mon, 1 May 2023 18:03:05 +0300 (EEST) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id A612C43062; Mon, 1 May 2023 17:03:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1682953384; bh=uvnadPJvpEjTmArX9CaQ9ro4ISuOmZT8C1e33pi6jZk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fowQQUuhhZlvnQW/QQRewXXdvTWF/2BKf1xIcCDsiEX4XZN1PkfSlqSxuel4Ofn5s SjMF4dkaeuB3b2JHJH+ysiwM0WYSc6IrUbdNpIwb/ItjlKjJ0RPqDgKJCQZtx1UrSe iLzu5sflpUnlrIGMlzLWFEMT3acv8min++S7Zzj0= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Mon, 1 May 2023 17:03:01 +0200 Message-Id: <20230501150301.55718-3-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.40.0 In-Reply-To: <20230501150301.55718-1-ffmpeg@haasn.xyz> References: <20230501150301.55718-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/3] doc/filters/libplacebo: fix outdated/wrong note 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: c+BPrg72DF7r From: Niklas Haas This has not been the case since c0b93c4f8+48c385fb4c. --- doc/filters.texi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 2d49f93b9e2..9ffa9dfe22f 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -15976,8 +15976,7 @@ ffmpeg -i input.mov -vf lensfun=make=Canon:model="Canon EOS 100D":lens_model="Ca @section libplacebo Flexible GPU-accelerated processing filter based on libplacebo -(@url{https://code.videolan.org/videolan/libplacebo}). Note that this filter -currently only accepts Vulkan input frames. +(@url{https://code.videolan.org/videolan/libplacebo}). @subsection Options