| @@ -88,6 +88,15 @@ typedef struct TestSourceContext { · 87 unmodified lines |
| 88 | | 88 | |
| 89 | /* only used by haldclut */ | 89 | /* only used by haldclut */ |
| 90 | int level; | 90 | int level; |
| | 91 | |
| | 92 | /* only used by zoneplate */ |
| | 93 | int k0, kx, ky, kt; |
| | 94 | int kxt, kyt, kxy; |
| | 95 | int kx2, ky2, kt2; |
| | 96 | int xo, yo, to, kU, kV; |
| | 97 | int lut_precision; |
| | 98 | uint8_t *lut; |
| | 99 | int (*fill_slice_fn)(AVFilterContext *ctx, void *arg, int job, int nb_jobs); |
| 91 | } TestSourceContext; | 100 | } TestSourceContext; |
| 92 | | 101 | |
| 93 | #define OFFSET(x) offsetof(TestSourceContext, x) | 102 | #define OFFSET(x) offsetof(TestSourceContext, x) |
| @@ -135,6 +144,7 @@ static av_cold void uninit(AVFilterContext *ctx) · 41 unmodified lines |
| 135 | TestSourceContext *test = ctx->priv; | 144 | TestSourceContext *test = ctx->priv; |
| 136 | | 145 | |
| 137 | av_frame_free(&test->picref); | 146 | av_frame_free(&test->picref); |
| | 147 | av_freep(&test->lut); |
| 138 | } | 148 | } |
| 139 | | 149 | |
| 140 | static int config_props(AVFilterLink *outlink) | 150 | static int config_props(AVFilterLink *outlink) |
| @@ -2049,3 +2059,190 @@ const AVFilter ff_vsrc_colorchart = { · 1908 unmodified lines |
| 2049 | }; | 2059 | }; |
| 2050 | | 2060 | |
| 2051 | #endif /* CONFIG_COLORCHART_FILTER */ | 2061 | #endif /* CONFIG_COLORCHART_FILTER */ |
| | 2062 | |
| | 2063 | #if CONFIG_ZONEPLATE_FILTER |
| | 2064 | |
| | 2065 | static const AVOption zoneplate_options[] = { |
| | 2066 | COMMON_OPTIONS |
| | 2067 | { "precision", "set LUT precision", OFFSET(lut_precision), AV_OPT_TYPE_INT, {.i64=10}, 4, 16, FLAGS }, |
| | 2068 | { "xo", "set X-axis offset", OFFSET(xo), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2069 | { "yo", "set Y-axis offset", OFFSET(yo), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2070 | { "to", "set T-axis offset", OFFSET(to), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2071 | { "k0", "set 0-order phase", OFFSET(k0), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2072 | { "kx", "set 1-order X-axis phase", OFFSET(kx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2073 | { "ky", "set 1-order Y-axis phase", OFFSET(ky), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2074 | { "kt", "set 1-order T-axis phase", OFFSET(kt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2075 | { "kxt", "set X-axis*T-axis product phase", OFFSET(kxt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2076 | { "kyt", "set Y-axis*T-axis product phase", OFFSET(kyt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2077 | { "kxy", "set X-axis*Y-axis product phase", OFFSET(kxy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2078 | { "kx2", "set 2-order X-axis phase", OFFSET(kx2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2079 | { "ky2", "set 2-order Y-axis phase", OFFSET(ky2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2080 | { "kt2", "set 2-order T-axis phase", OFFSET(kt2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2081 | { "ku", "set 0-order U-color phase", OFFSET(kU), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2082 | { "kv", "set 0-order V-color phase", OFFSET(kV), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, |
| | 2083 | { NULL } |
| | 2084 | }; |
| | 2085 | |
| | 2086 | AVFILTER_DEFINE_CLASS(zoneplate); |
| | 2087 | |
| | 2088 | #define ZONEPLATE_SLICE(name, type) \ |
| | 2089 | static int zoneplate_fill_slice_##name(AVFilterContext *ctx, \ |
| | 2090 | void *arg, int job, \ |
| | 2091 | int nb_jobs) \ |
| | 2092 | { \ |
| | 2093 | TestSourceContext *test = ctx->priv; \ |
| | 2094 | AVFrame *frame = arg; \ |
| | 2095 | const int w = frame->width; \ |
| | 2096 | const int h = frame->height; \ |
| | 2097 | const int kxt = test->kxt, kyt = test->kyt, kx2 = test->kx2; \ |
| | 2098 | const int t = test->pts + test->to, k0 = test->k0; \ |
| | 2099 | const int kt = test->kt, kt2 = test->kt2, ky2 = test->ky2; \ |
| | 2100 | const int ky = test->ky, kx = test->kx, kxy = test->kxy; \ |
| | 2101 | const int lut_mask = (1 << test->lut_precision) - 1; \ |
| | 2102 | const int nkt2t = kt2 * t * t, nktt = kt * t; \ |
| | 2103 | const int start = (h * job ) / nb_jobs; \ |
| | 2104 | const int end = (h * (job+1)) / nb_jobs; \ |
| | 2105 | const int ylinesize = frame->linesize[0] / sizeof(type); \ |
| | 2106 | const int ulinesize = frame->linesize[1] / sizeof(type); \ |
| | 2107 | const int vlinesize = frame->linesize[2] / sizeof(type); \ |
| | 2108 | const int xreset = -(w / 2) - test->xo; \ |
| | 2109 | const int yreset = -(h / 2) - test->yo + start; \ |
| | 2110 | const int kU = test->kU, kV = test->kV; \ |
| | 2111 | const int skxy = 0xffff / (w / 2); \ |
| | 2112 | const int skx2 = 0xffff / w; \ |
| | 2113 | const int dkxt = kxt * t; \ |
| | 2114 | type *ydst = ((type *)frame->data[0]) + start * ylinesize; \ |
| | 2115 | type *udst = ((type *)frame->data[1]) + start * ulinesize; \ |
| | 2116 | type *vdst = ((type *)frame->data[2]) + start * vlinesize; \ |
| | 2117 | const type *lut = (const type *)test->lut; \ |
| | 2118 | int akx, akxt, aky, akyt; \ |
| | 2119 | \ |
| | 2120 | aky = start * ky; \ |
| | 2121 | akyt = start * kyt * t; \ |
| | 2122 | \ |
| | 2123 | for (int j = start, y = yreset; j < end; j++, y++) { \ |
| | 2124 | const int dkxy = kxy * y * skxy; \ |
| | 2125 | const int nky2kt2 = (ky2 * y * y) / h + (nkt2t >> 1); \ |
| | 2126 | int akxy = dkxy * xreset; \ |
| | 2127 | \ |
| | 2128 | akx = 0; \ |
| | 2129 | akxt = 0; \ |
| | 2130 | aky += ky; \ |
| | 2131 | akyt += kyt * t; \ |
| | 2132 | \ |
| | 2133 | for (int i = 0, x = xreset; i < w; i++, x++) { \ |
| | 2134 | int phase = k0, uphase = kU, vphase = kV; \ |
| | 2135 | \ |
| | 2136 | akx += kx; \ |
| | 2137 | phase += akx + aky + nktt; \ |
| | 2138 | \ |
| | 2139 | akxt += dkxt; \ |
| | 2140 | akxy += dkxy; \ |
| | 2141 | phase += akxt + akyt; \ |
| | 2142 | phase += akxy >> 16; \ |
| | 2143 | phase += ((kx2 * x * x * skx2) >> 16) + nky2kt2; \ |
| | 2144 | uphase += phase; \ |
| | 2145 | vphase += phase; \ |
| | 2146 | \ |
| | 2147 | ydst[i] = lut[phase & lut_mask]; \ |
| | 2148 | udst[i] = lut[uphase & lut_mask]; \ |
| | 2149 | vdst[i] = lut[vphase & lut_mask]; \ |
| | 2150 | } \ |
| | 2151 | \ |
| | 2152 | ydst += ylinesize; \ |
| | 2153 | udst += ulinesize; \ |
| | 2154 | vdst += vlinesize; \ |
| | 2155 | } \ |
| | 2156 | \ |
| | 2157 | return 0; \ |
| | 2158 | } |
| | 2159 | |
| | 2160 | ZONEPLATE_SLICE( 8, uint8_t) |
| | 2161 | ZONEPLATE_SLICE( 9, uint16_t) |
| | 2162 | ZONEPLATE_SLICE(10, uint16_t) |
| | 2163 | ZONEPLATE_SLICE(12, uint16_t) |
| | 2164 | ZONEPLATE_SLICE(14, uint16_t) |
| | 2165 | ZONEPLATE_SLICE(16, uint16_t) |
| | 2166 | |
| | 2167 | static void zoneplate_fill_picture(AVFilterContext *ctx, AVFrame *frame) |
| | 2168 | { |
| | 2169 | TestSourceContext *test = ctx->priv; |
| | 2170 | ff_filter_execute(ctx, test->fill_slice_fn, frame, NULL, |
| | 2171 | FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); |
| | 2172 | } |
| | 2173 | |
| | 2174 | static int zoneplate_config_props(AVFilterLink *outlink) |
| | 2175 | { |
| | 2176 | AVFilterContext *ctx = outlink->src; |
| | 2177 | TestSourceContext *test = ctx->priv; |
| | 2178 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); |
| | 2179 | const int lut_size = 1 << test->lut_precision; |
| | 2180 | const int depth = desc->comp[0].depth; |
| | 2181 | uint16_t *lut16; |
| | 2182 | uint8_t *lut8; |
| | 2183 | |
| | 2184 | if (av_image_check_size(test->w, test->h, 0, ctx) < 0) |
| | 2185 | return AVERROR(EINVAL); |
| | 2186 | |
| | 2187 | test->lut = av_calloc(lut_size, sizeof(*test->lut) * ((depth + 7) / 8)); |
| | 2188 | if (!test->lut) |
| | 2189 | return AVERROR(ENOMEM); |
| | 2190 | |
| | 2191 | lut8 = test->lut; |
| | 2192 | lut16 = (uint16_t *)test->lut; |
| | 2193 | switch (depth) { |
| | 2194 | case 8: |
| | 2195 | for (int i = 0; i < lut_size; i++) |
| | 2196 | lut8[i] = lrintf(255.f * (0.5f + 0.5f * sinf((2.f * M_PI * i) / lut_size))); |
| | 2197 | break; |
| | 2198 | default: |
| | 2199 | for (int i = 0; i < lut_size; i++) |
| | 2200 | lut16[i] = lrintf(((1 << depth) - 1) * (0.5f + 0.5f * sinf((2.f * M_PI * i) / lut_size))); |
| | 2201 | break; |
| | 2202 | } |
| | 2203 | |
| | 2204 | test->draw_once = 0; |
| | 2205 | test->fill_picture_fn = zoneplate_fill_picture; |
| | 2206 | |
| | 2207 | switch (depth) { |
| | 2208 | case 8: test->fill_slice_fn = zoneplate_fill_slice_8; break; |
| | 2209 | case 9: test->fill_slice_fn = zoneplate_fill_slice_9; break; |
| | 2210 | case 10: test->fill_slice_fn = zoneplate_fill_slice_10; break; |
| | 2211 | case 12: test->fill_slice_fn = zoneplate_fill_slice_12; break; |
| | 2212 | case 14: test->fill_slice_fn = zoneplate_fill_slice_14; break; |
| | 2213 | case 16: test->fill_slice_fn = zoneplate_fill_slice_16; break; |
| | 2214 | } |
| | 2215 | return config_props(outlink); |
| | 2216 | } |
| | 2217 | |
| | 2218 | static const enum AVPixelFormat zoneplate_pix_fmts[] = { |
| | 2219 | AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P9, |
| | 2220 | AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, |
| | 2221 | AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16, |
| | 2222 | AV_PIX_FMT_NONE, |
| | 2223 | }; |
| | 2224 | |
| | 2225 | static const AVFilterPad avfilter_vsrc_zoneplate_outputs[] = { |
| | 2226 | { |
| | 2227 | .name = "default", |
| | 2228 | .type = AVMEDIA_TYPE_VIDEO, |
| | 2229 | .config_props = zoneplate_config_props, |
| | 2230 | }, |
| | 2231 | }; |
| | 2232 | |
| | 2233 | const AVFilter ff_vsrc_zoneplate = { |
| | 2234 | .name = "zoneplate", |
| | 2235 | .description = NULL_IF_CONFIG_SMALL("Generate zone-plate."), |
| | 2236 | .priv_size = sizeof(TestSourceContext), |
| | 2237 | .priv_class = &zoneplate_class, |
| | 2238 | .init = init, |
| | 2239 | .uninit = uninit, |
| | 2240 | .activate = activate, |
| | 2241 | .inputs = NULL, |
| | 2242 | FILTER_OUTPUTS(avfilter_vsrc_zoneplate_outputs), |
| | 2243 | FILTER_PIXFMTS_ARRAY(zoneplate_pix_fmts), |
| | 2244 | .flags = AVFILTER_FLAG_SLICE_THREADS, |
| | 2245 | .process_command = ff_filter_process_command, |
| | 2246 | }; |
| | 2247 | |
| | 2248 | #endif /* CONFIG_ZONEPLATE_FILTER */ |