diff options
author | Paul B Mahol <onemda@gmail.com> | 2021-11-14 00:17:10 +0100 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2021-11-16 20:41:39 +0100 |
commit | d401b1cceceacc93c90f6d239dd58e22632c013d (patch) | |
tree | b184822880a3a26bcf6676c59b7c7d8928655cd2 /libavfilter/vsrc_testsrc.c | |
parent | 08b4716a9ed277afb4af69b07b751c9bd046aa70 (diff) | |
download | ffmpeg-d401b1cceceacc93c90f6d239dd58e22632c013d.tar.gz |
avfilter: add colorspectrum source video filter
Diffstat (limited to 'libavfilter/vsrc_testsrc.c')
-rw-r--r-- | libavfilter/vsrc_testsrc.c | 92 |
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 */ |