-static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
-{
- ThreadData *td = arg;
- AVFrame *in = td->in;
- AVFrame *out = td->out;
-
- const int w = td->w, h = td->h;
- const int xcenter = td->xcenter;
- const int ycenter = td->ycenter;
- const int start = (h * job ) / nb_jobs;
- const int end = (h * (job+1)) / nb_jobs;
- const int plane = td->plane;
- const int inlinesize = in->linesize[plane];
- const int outlinesize = out->linesize[plane];
- const uint8_t *indata = in->data[plane];
- uint8_t *outrow = out->data[plane] + start * outlinesize;
- int i;
- for (i = start; i < end; i++, outrow += outlinesize) {
- const int off_y = i - ycenter;
- uint8_t *out = outrow;
- int j;
- for (j = 0; j < w; j++) {
- const int off_x = j - xcenter;
- const int64_t radius_mult = td->correction[j + i*w];
- const int x = xcenter + ((radius_mult * off_x + (1<<23))>>24);
- const int y = ycenter + ((radius_mult * off_y + (1<<23))>>24);
- const char isvalid = x > 0 && x < w - 1 && y > 0 && y < h - 1;
- *out++ = isvalid ? indata[y * inlinesize + x] : 0;
- }
- }
- return 0;
+#define NEAREST(type, name) \
+static int filter##name##_slice(AVFilterContext *ctx, void *arg, int job, \
+ int nb_jobs, int plane) \
+{ \
+ LenscorrectionCtx *rect = ctx->priv; \
+ ThreadData *td = arg; \
+ AVFrame *in = td->in; \
+ AVFrame *out = td->out; \
+ \
+ const int32_t *correction = rect->correction[plane]; \
+ const int fill_color = rect->fill_color[plane]; \
+ const int w = rect->planewidth[plane], h = rect->planeheight[plane]; \
+ const int xcenter = rect->cx * w; \
+ const int ycenter = rect->cy * h; \
+ const int start = (h * job ) / nb_jobs; \
+ const int end = (h * (job+1)) / nb_jobs; \
+ const int inlinesize = in->linesize[plane] / sizeof(type); \
+ const int outlinesize = out->linesize[plane] / sizeof(type); \
+ const type *indata = (const type *)in->data[plane]; \
+ type *outrow = (type *)out->data[plane] + start * outlinesize; \
+ for (int i = start; i < end; i++, outrow += outlinesize) { \
+ const int off_y = i - ycenter; \
+ type *out = outrow; \
+ for (int j = 0; j < w; j++) { \
+ const int off_x = j - xcenter; \
+ const int64_t radius_mult = correction[j + i*w]; \
+ const int x = xcenter + ((radius_mult * off_x + (1<<23))>>24); \
+ const int y = ycenter + ((radius_mult * off_y + (1<<23))>>24); \
+ const char isvalid = x >= 0 && x < w && y >= 0 && y < h; \
+ *out++ = isvalid ? indata[y * inlinesize + x] : fill_color; \
+ } \
+ } \
+ return 0; \
+}
+
+
+NEAREST(uint8_t, 8)
+NEAREST(uint16_t, 16)
+
+#define BILINEAR(type, name) \
+static int filter##name##_slice_bilinear(AVFilterContext *ctx, void *arg, \
+ int job, int nb_jobs, int plane) \
+{ \
+ LenscorrectionCtx *rect = ctx->priv; \
+ ThreadData *td = arg; \
+ AVFrame *in = td->in; \
+ AVFrame *out = td->out; \
+ \
+ const int32_t *correction = rect->correction[plane]; \
+ const int fill_color = rect->fill_color[plane]; \
+ const int depth = rect->depth; \
+ const uint64_t max = (1 << 24) - 1; \
+ const uint64_t add = (1 << 23); \
+ const int w = rect->planewidth[plane], h = rect->planeheight[plane]; \
+ const int xcenter = rect->cx * w; \
+ const int ycenter = rect->cy * h; \
+ const int start = (h * job ) / nb_jobs; \
+ const int end = (h * (job+1)) / nb_jobs; \
+ const int inlinesize = in->linesize[plane] / sizeof(type); \
+ const int outlinesize = out->linesize[plane] / sizeof(type); \
+ const type *indata = (const type *)in->data[plane]; \
+ type *outrow = (type *)out->data[plane] + start * outlinesize; \
+ \
+ for (int i = start; i < end; i++, outrow += outlinesize) { \
+ const int off_y = i - ycenter; \
+ type *out = outrow; \
+ \
+ for (int j = 0; j < w; j++) { \
+ const int off_x = j - xcenter; \
+ const int64_t radius_mult = correction[j + i*w]; \
+ const int x = xcenter + ((radius_mult * off_x + (1<<23)) >> 24); \
+ const int y = ycenter + ((radius_mult * off_y + (1<<23)) >> 24); \
+ const char isvalid = x >= 0 && x <= w - 1 && y >= 0 && y <= h - 1; \
+ \
+ if (isvalid) { \
+ const int nx = FFMIN(x + 1, w - 1); \
+ const int ny = FFMIN(y + 1, h - 1); \
+ const uint64_t du = off_x >= 0 ? (radius_mult * off_x + add) & max : max - ((radius_mult * -off_x + add) & max); \
+ const uint64_t dv = off_y >= 0 ? (radius_mult * off_y + add) & max : max - ((radius_mult * -off_y + add) & max); \
+ const uint64_t p0 = indata[ y * inlinesize + x]; \
+ const uint64_t p1 = indata[ y * inlinesize + nx]; \
+ const uint64_t p2 = indata[ny * inlinesize + x]; \
+ const uint64_t p3 = indata[ny * inlinesize + nx]; \
+ uint64_t sum = 0; \
+ \
+ sum += (max - du) * (max - dv) * p0; \
+ sum += ( du) * (max - dv) * p1; \
+ sum += (max - du) * ( dv) * p2; \
+ sum += ( du) * ( dv) * p3; \
+ \
+ out[j] = av_clip_uintp2_c((sum + (1ULL << 47)) >> 48, depth); \
+ } else { \
+ out[j] = fill_color; \
+ } \
+ } \
+ } \
+ \
+ return 0; \