Attached.
From 7b0a8586adc0a142f0b7afcdbdf36ce526f4cd34 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <one...@gmail.com>
Date: Sat, 6 May 2023 22:52:47 +0200
Subject: [PATCH] avfilter: add zoneplate video test source

Signed-off-by: Paul B Mahol <one...@gmail.com>
---
 libavfilter/Makefile       |   1 +
 libavfilter/allfilters.c   |   1 +
 libavfilter/vsrc_testsrc.c | 142 +++++++++++++++++++++++++++++++++++++
 3 files changed, 144 insertions(+)

diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 93c614eeb7..9fb9a1095f 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -598,6 +598,7 @@ OBJS-$(CONFIG_SMPTEHDBARS_FILTER)            += vsrc_testsrc.o
 OBJS-$(CONFIG_TESTSRC_FILTER)                += vsrc_testsrc.o
 OBJS-$(CONFIG_TESTSRC2_FILTER)               += vsrc_testsrc.o
 OBJS-$(CONFIG_YUVTESTSRC_FILTER)             += vsrc_testsrc.o
+OBJS-$(CONFIG_ZONEPLATE_FILTER)              += vsrc_testsrc.o
 
 OBJS-$(CONFIG_NULLSINK_FILTER)               += vsink_nullsink.o
 
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 1c0bc12a92..025966dc45 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -563,6 +563,7 @@ extern const AVFilter ff_vsrc_smptehdbars;
 extern const AVFilter ff_vsrc_testsrc;
 extern const AVFilter ff_vsrc_testsrc2;
 extern const AVFilter ff_vsrc_yuvtestsrc;
+extern const AVFilter ff_vsrc_zoneplate;
 
 extern const AVFilter ff_vsink_nullsink;
 
diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c
index f391ac02e0..b1f7873a9c 100644
--- a/libavfilter/vsrc_testsrc.c
+++ b/libavfilter/vsrc_testsrc.c
@@ -88,6 +88,14 @@ typedef struct TestSourceContext {
 
     /* only used by haldclut */
     int level;
+
+    /* only used by zoneplate */
+    int k0, kx, ky, kt;
+    int kxt, kyt, kxy;
+    int kx2, ky2, kt2;
+    int xo, yo, kU, kV;
+    int lut_precision;
+    uint8_t *lut;
 } TestSourceContext;
 
 #define OFFSET(x) offsetof(TestSourceContext, x)
@@ -135,6 +143,7 @@ static av_cold void uninit(AVFilterContext *ctx)
     TestSourceContext *test = ctx->priv;
 
     av_frame_free(&test->picref);
+    av_freep(&test->lut);
 }
 
 static int config_props(AVFilterLink *outlink)
@@ -2049,3 +2058,136 @@ const AVFilter ff_vsrc_colorchart = {
 };
 
 #endif /* CONFIG_COLORCHART_FILTER */
+
+#if CONFIG_COLORCHART_FILTER
+
+static const AVOption zoneplate_options[] = {
+    COMMON_OPTIONS
+    { "precision", "set LUT precision", OFFSET(lut_precision), AV_OPT_TYPE_INT, {.i64=10}, 4, 16, FLAGS },
+    { "xo", "set x-axis offset", OFFSET(xo), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "yo", "set y-axis offset", OFFSET(yo), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "k0", "set zero order phase", OFFSET(k0), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "kx", "set 1st order x-axis phase", OFFSET(kx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "ky", "set 1st order y-axis phase", OFFSET(ky), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "kt", "set 1st order t-axis phase", OFFSET(kt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "kxt", "set x*t product phase", OFFSET(kxt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "kyt", "set y*t product phase", OFFSET(kyt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "kxy", "set x*y product phase", OFFSET(kxy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "kx2", "set 2nd order x-axis phase", OFFSET(kx2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "ky2", "set 2nd order y-axis phase", OFFSET(ky2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "kt2", "set 2nd order t-axis phase", OFFSET(kt2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "kU", "set zero order U-color phase", OFFSET(kU), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { "kV", "set zero order V-color phase", OFFSET(kV), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(zoneplate);
+
+static int zoneplate_config_props(AVFilterLink *inlink)
+{
+    AVFilterContext *ctx = inlink->src;
+    TestSourceContext *s = ctx->priv;
+
+    if (av_image_check_size(s->w, s->h, 0, ctx) < 0)
+        return AVERROR(EINVAL);
+    return config_props(inlink);
+}
+
+static void zoneplate_fill_picture(AVFilterContext *ctx, AVFrame *frame)
+{
+    TestSourceContext *test = ctx->priv;
+    const int w = frame->width;
+    const int h = frame->height;
+    const int kxt = test->kxt, kyt = test->kyt, kx2 = test->kx2;
+    const int t = test->pts, k0 = test->k0;
+    const int kt = test->kt, kt2 = test->kt2, ky2 = test->ky2;
+    const int ky = test->ky, kx = test->kx, kxy = test->kxy;
+    const int lut_mask = (1 << test->lut_precision) - 1;
+    int akx, akxt, aky, akyt, akxy, nky2kt2;
+    const int nkt2 = kt2 * t * t, nkt = kt * t;
+    const int xreset = -(w / 2) - test->xo;
+    const int yreset = -(h / 2) - test->yo;
+    const int kU = test->kU, kV = test->kV;
+    const int dkxt = kxt * t;
+    int skxy = 0xffff / (w / 2);
+    int skx2 = 0xffff / w;
+    uint8_t *ydst = frame->data[0];
+    uint8_t *udst = frame->data[1];
+    uint8_t *vdst = frame->data[2];
+    const uint8_t *lut = test->lut;
+
+    aky = 0;
+    akyt = 0;
+    for (int j = 0, y = yreset; j < h; j++, y++) {
+        const int dkxy = kxy * y * skxy;
+        akx = 0;
+        akxt = 0;
+        aky += ky;
+        akyt += kyt * t;
+        akxy = dkxy * xreset;
+        nky2kt2 = (ky2 * y * y) / h + (nkt2 >> 1);
+        for (int i = 0, x = xreset; i < w; i++, x++) {
+            int phase = k0, uphase = kU, vphase = kV;
+
+            akx += kx;
+            phase += akx + aky + nkt;
+
+            akxt += dkxt;
+            akxy += dkxy;
+            phase += akxt + akyt;
+            phase += akxy >> 16;
+            phase += ((kx2 * x * x * skx2) >> 16) + nky2kt2;
+            uphase += phase;
+            vphase += phase;
+
+            ydst[i] = lut[phase & lut_mask];
+            udst[i] = lut[uphase & lut_mask];
+            vdst[i] = lut[vphase & lut_mask];
+        }
+
+        ydst += frame->linesize[0];
+        udst += frame->linesize[1];
+        vdst += frame->linesize[2];
+    }
+}
+
+static av_cold int zoneplate_init(AVFilterContext *ctx)
+{
+    TestSourceContext *test = ctx->priv;
+    const int lut_size = 1 << test->lut_precision;
+
+    test->lut = av_calloc(lut_size, sizeof(*test->lut));
+    if (!test->lut)
+        return AVERROR(ENOMEM);
+
+    for (int i = 0; i < lut_size; i++)
+        test->lut[i] = lrintf(255.f * (0.5f + 0.5f * sinf((2.f * M_PI * i) / lut_size)));
+
+    test->draw_once = 0;
+    test->fill_picture_fn = zoneplate_fill_picture;
+    return init(ctx);
+}
+
+static const AVFilterPad avfilter_vsrc_zoneplate_outputs[] = {
+    {
+        .name          = "default",
+        .type          = AVMEDIA_TYPE_VIDEO,
+        .config_props  = zoneplate_config_props,
+    },
+};
+
+const AVFilter ff_vsrc_zoneplate = {
+    .name          = "zoneplate",
+    .description   = NULL_IF_CONFIG_SMALL("Generate zone-plate."),
+    .priv_size     = sizeof(TestSourceContext),
+    .priv_class    = &zoneplate_class,
+    .init          = zoneplate_init,
+    .uninit        = uninit,
+    .activate      = activate,
+    .inputs        = NULL,
+    FILTER_OUTPUTS(avfilter_vsrc_zoneplate_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_YUV444P),
+    .process_command = ff_filter_process_command,
+};
+
+#endif /* CONFIG_COLORCHART_FILTER */
-- 
2.39.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to