From patchwork Sun Nov 14 10:10:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 31416 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:d206:0:0:0:0:0 with SMTP id q6csp4305373iob; Sun, 14 Nov 2021 02:10:28 -0800 (PST) X-Google-Smtp-Source: ABdhPJwRsXUMPaag5SBTBC/wRPPJ+zXXtjtg22gXsu+FVBlf2uBrIaqchOMfyHUYKktYaO1w0BA4 X-Received: by 2002:a17:906:403:: with SMTP id d3mr38242219eja.321.1636884628130; Sun, 14 Nov 2021 02:10:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1636884628; cv=none; d=google.com; s=arc-20160816; b=PPOOnH56gdt1bmZqcgdZ25yDXcZMpYNRNQmFSXkeyA+LH0HAziHwQKu2hkBNBnwgt7 Fht2/JD1YMn22VY4jmqD0qMHY1D08FLVb401n1Q92l11sMh2a+4bKYpp5Q8map5XjBIG 0gdoAejOaHzan1rrNNvOOwCgegaH5aGTYu6uO6LuRLKvaGp8JVfBeEzqFPqFwuHIOQJl 8b2yswKImyHbvUCyxwKel3+gnLEJERBgms43ABFPVLjuw9wSS1IR9KUxE9lNEgTU5k4U SHt+5RZa6rbcKnl0vAlyzep1eeg7FdVhWKP6SbQb1oAdhRK3PaxqWpecKCzz1rTAhxdK z4RA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding: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=jocSLBOYPqZYm7TrxyXf7jWtnEUlbjYBSYFWp/IzkWw=; b=0JBVAlgq0+/fueus/XNZhl+whbBN8drPLBnmJoHMehz68KtfxfBoQJDfYkwlIxn2+y ujHjwkC6d0dE2N3Uq6NockmjlYA8DSweOxn+OafhAUii/v3b/E1ksh0+AqR3EX2olx2l DGpyguKRGVooPPxMgV9rVww3ZVTJHGBM32Jo8YxUM3TsvBT0k18/HLissE46qKUlmuPW ptCvXYxMXKhbSgBff/Bwjcku4lgVrRwro0tkwOnSiY9ANgI6ecflepYSstDW91aqQxgJ jng6MQMSqfLIgmNMl9i2XrUraNs4j1al+l7MZ87LmTK5vMpGuPu6wIJiOXqatCIG4SYv UO/A== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=M4HjknAc; 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 ds9si26930330ejc.479.2021.11.14.02.10.27; Sun, 14 Nov 2021 02:10:28 -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=M4HjknAc; 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 51DB268AC65; Sun, 14 Nov 2021 12:10:23 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ed1-f47.google.com (mail-ed1-f47.google.com [209.85.208.47]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9C8B568A31F for ; Sun, 14 Nov 2021 12:10:16 +0200 (EET) Received: by mail-ed1-f47.google.com with SMTP id t18so38257784edd.8 for ; Sun, 14 Nov 2021 02:10:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=vINK7tb7yCaZ70Dl7D7EYzByuztD3YAdJzReCxyxCDI=; b=M4HjknAc+cv4Q/GhDdgq2FvA9nKBUNMWG5kv3vl2uDtv8S/rl60vM1DQXaRk+7OCxK fPV/YyPxCfIW2rS4mH2ZWlMakLoBYvx64+bRXZIqmZ/SVBRKbOhlOmJsJVBOrq2GkqI/ XbLIL8SIYsWvdOgYYS6iU/80CqBJVFqa7otEg3cpHgeAzuj5Rb/vF8ivnnMnvJm1PNTm 5ISSfBzC/8Eidsj0NIceRxC+6gOuQITTnYHR0PiWyrcfuBK4rL4I5jVRXLoXtWwx0xhG mOmhtAHG0ciHQT37KEDS7MsXBZx79bwW/TPtWrQ9a7+UneH621iU3pcA/I/VPB4+PeDA KQxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=vINK7tb7yCaZ70Dl7D7EYzByuztD3YAdJzReCxyxCDI=; b=1FUIA9BNMBkocHB/XcOkzx2CS6uVMAysbAOrkbYDTAkZH01tQ2dgqMLQKwTkwy5KZV WvmYFJ2w+SrQZvtNcL9fcpj9yMJ7+jQSW0Ev90eVHm/oUCmUIN3AUEGqHcV+H1bjJuBQ +09ZiqIpOfjopOZu84+UfSkCMTFkdxHZbwyZCdii+VpXWHdVBezcZR3jOWpOmC8nzP7+ 90c5FwM44hlOANA0y1QzZf7d4IL8HlnW2SeyRAQQ+8KLNU921DaPSYNenzrg5V/q4dzB Y3n32L7AzyO6QlHf95eI5XFIc3B30+uitFXxJapCU+woP/ODhg1VPe4FF9XYpUBO3qWQ oqEw== X-Gm-Message-State: AOAM533d67eIa4hiBU/zE3YcuYrT82JnQXUPBrOixFykvfK2CGJVQjn0 ja1kx4antHysAq1Jey5ouU/SsrVsf3Y= X-Received: by 2002:a05:6402:2792:: with SMTP id b18mr41675842ede.245.1636884616092; Sun, 14 Nov 2021 02:10:16 -0800 (PST) Received: from localhost.localdomain ([212.15.178.48]) by smtp.gmail.com with ESMTPSA id f17sm1945795edf.21.2021.11.14.02.10.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 14 Nov 2021 02:10:15 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Sun, 14 Nov 2021 11:10:29 +0100 Message-Id: <20211114101029.319648-1-onemda@gmail.com> X-Mailer: git-send-email 2.33.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avfilter: add colorspectrum source video filter 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: aMYtObgh/zFx Signed-off-by: Paul B Mahol --- doc/filters.texi | 15 ++++++- libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vsrc_testsrc.c | 92 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 6ab41706e5..dd6c9f1fee 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -25243,6 +25243,7 @@ ffplay -f lavfi life=s=300x200:mold=10:r=60:ratio=0.1:death_color=#C83232:life_c @anchor{allrgb} @anchor{allyuv} @anchor{color} +@anchor{colorspectrum} @anchor{haldclutsrc} @anchor{nullsrc} @anchor{pal75bars} @@ -25253,7 +25254,7 @@ ffplay -f lavfi life=s=300x200:mold=10:r=60:ratio=0.1:death_color=#C83232:life_c @anchor{testsrc} @anchor{testsrc2} @anchor{yuvtestsrc} -@section allrgb, allyuv, color, haldclutsrc, nullsrc, pal75bars, pal100bars, rgbtestsrc, smptebars, smptehdbars, testsrc, testsrc2, yuvtestsrc +@section allrgb, allyuv, color, colorspectrum, haldclutsrc, nullsrc, pal75bars, pal100bars, rgbtestsrc, smptebars, smptehdbars, testsrc, testsrc2, yuvtestsrc The @code{allrgb} source returns frames of size 4096x4096 of all rgb colors. @@ -25261,6 +25262,8 @@ The @code{allyuv} source returns frames of size 4096x4096 of all yuv colors. The @code{color} source provides an uniformly colored input. +The @code{colorspectrum} source provides a color spectrum input. + The @code{haldclutsrc} source provides an identity Hald CLUT. See also @ref{haldclut} filter. @@ -25352,6 +25355,16 @@ Set the number of decimals to show in the timestamp, only available in the The displayed timestamp value will correspond to the original timestamp value multiplied by the power of 10 of the specified value. Default value is 0. + +@item type +Set the type of the color spectrum, only available in the +@code{colorspectrum} source. Can be one of the following: + +@table @samp +@item black +@item white +@item all +@end table @end table @subsection Examples diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 8c5e565ed1..13c2be1671 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -528,6 +528,7 @@ OBJS-$(CONFIG_ALLRGB_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_ALLYUV_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_CELLAUTO_FILTER) += vsrc_cellauto.o OBJS-$(CONFIG_COLOR_FILTER) += vsrc_testsrc.o +OBJS-$(CONFIG_COLORSPECTRUM_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_COREIMAGESRC_FILTER) += vf_coreimage.o OBJS-$(CONFIG_FREI0R_SRC_FILTER) += vf_frei0r.o OBJS-$(CONFIG_GRADIENTS_FILTER) += vsrc_gradients.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index d7556bc93f..d0d9bbaeed 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -503,6 +503,7 @@ extern const AVFilter ff_vsrc_allrgb; extern const AVFilter ff_vsrc_allyuv; extern const AVFilter ff_vsrc_cellauto; extern const AVFilter ff_vsrc_color; +extern const AVFilter ff_vsrc_colorspectrum; extern const AVFilter ff_vsrc_coreimagesrc; extern const AVFilter ff_vsrc_frei0r_src; extern const AVFilter ff_vsrc_gradients; diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index 6f48a8f86c..8f5e9d71df 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -70,6 +70,9 @@ typedef struct TestSourceContext { /* only used by testsrc2 */ int alpha; + /* only used by colorspectrum */ + int type; + /* only used by color */ FFDrawContext draw; FFDrawColor color; @@ -1791,3 +1794,92 @@ const AVFilter ff_vsrc_allrgb = { }; #endif /* CONFIG_ALLRGB_FILTER */ + +#if CONFIG_ALLRGB_FILTER + +static const AVOption colorspectrum_options[] = { + COMMON_OPTIONS + { "type", "set the color spectrum type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "type" }, + { "black","fade to black", 0, AV_OPT_TYPE_CONST,{.i64=0},0, 0, FLAGS, "type" }, + { "white","fade to white", 0, AV_OPT_TYPE_CONST,{.i64=1},0, 0, FLAGS, "type" }, + { "all", "white to black", 0, AV_OPT_TYPE_CONST,{.i64=2},0, 0, FLAGS, "type" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(colorspectrum); + +static inline float mix(float a, float b, float mix) +{ + return a * mix + b * (1.f - mix); +} + +static void hsb2rgb(const float *c, float *rgb) +{ + rgb[0] = av_clipf(fabsf(fmodf(c[0] * 6.f + 0.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); + rgb[1] = av_clipf(fabsf(fmodf(c[0] * 6.f + 4.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); + rgb[2] = av_clipf(fabsf(fmodf(c[0] * 6.f + 2.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); + rgb[0] = mix(c[3], (rgb[0] * rgb[0] * (3.f - 2.f * rgb[0])), c[1]) * c[2]; + rgb[1] = mix(c[3], (rgb[1] * rgb[1] * (3.f - 2.f * rgb[1])), c[1]) * c[2]; + rgb[2] = mix(c[3], (rgb[2] * rgb[2] * (3.f - 2.f * rgb[2])), c[1]) * c[2]; +} + +static void colorspectrum_fill_picture(AVFilterContext *ctx, AVFrame *frame) +{ + TestSourceContext *test = ctx->priv; + const float w = frame->width - 1.f; + const float h = frame->height - 1.f; + float c[4]; + + for (int y = 0; y < frame->height; y++) { + float *r = (float *)(frame->data[2] + y * frame->linesize[2]); + float *g = (float *)(frame->data[0] + y * frame->linesize[0]); + float *b = (float *)(frame->data[1] + y * frame->linesize[1]); + const float yh = y / h; + + c[1] = test->type == 2 ? yh > 0.5f ? 2.f * (yh - 0.5f) : 1.f - 2.f * yh : test->type == 1 ? 1.f - yh : yh; + c[2] = 1.f; + c[3] = test->type == 1 ? 1.f : test->type == 2 ? (yh > 0.5f ? 0.f : 1.f): 0.f; + for (int x = 0; x < frame->width; x++) { + float rgb[3]; + + c[0] = x / w; + hsb2rgb(c, rgb); + + r[x] = rgb[0]; + g[x] = rgb[1]; + b[x] = rgb[2]; + } + } +} + +static av_cold int colorspectrum_init(AVFilterContext *ctx) +{ + TestSourceContext *test = ctx->priv; + + test->draw_once = 1; + test->fill_picture_fn = colorspectrum_fill_picture; + return init(ctx); +} + +static const AVFilterPad avfilter_vsrc_colorspectrum_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_props, + }, +}; + +const AVFilter ff_vsrc_colorspectrum = { + .name = "colorspectrum", + .description = NULL_IF_CONFIG_SMALL("Generate colors spectrum."), + .priv_size = sizeof(TestSourceContext), + .priv_class = &colorspectrum_class, + .init = colorspectrum_init, + .uninit = uninit, + .activate = activate, + .inputs = NULL, + FILTER_OUTPUTS(avfilter_vsrc_colorspectrum_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_GBRPF32), +}; + +#endif /* CONFIG_ALLRGB_FILTER */