summaryrefslogtreecommitdiff
path: root/libavfilter/vsrc_testsrc.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2021-11-14 00:17:10 +0100
committerPaul B Mahol <onemda@gmail.com>2021-11-16 20:41:39 +0100
commitd401b1cceceacc93c90f6d239dd58e22632c013d (patch)
treeb184822880a3a26bcf6676c59b7c7d8928655cd2 /libavfilter/vsrc_testsrc.c
parent08b4716a9ed277afb4af69b07b751c9bd046aa70 (diff)
downloadffmpeg-d401b1cceceacc93c90f6d239dd58e22632c013d.tar.gz
avfilter: add colorspectrum source video filter
Diffstat (limited to 'libavfilter/vsrc_testsrc.c')
-rw-r--r--libavfilter/vsrc_testsrc.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c
index 6f48a8f86c..20b915d472 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_COLORSPECTRUM_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_COLORSPECTRUM_FILTER */