+#define FILTER_ROW(type, name) \
+static void filter_row##name(const uint8_t *ssrc, uint8_t *ddst, \
+ const uint8_t *ssrcf[SIZE], \
+ int w, int mid, int size, \
+ int thra, int thrb) \
+{ \
+ const type *src = (const type *)ssrc; \
+ const type **srcf = (const type **)ssrcf; \
+ type *dst = (type *)ddst; \
+ \
+ for (int x = 0; x < w; x++) { \
+ const int srcx = src[x]; \
+ unsigned lsumdiff = 0, rsumdiff = 0; \
+ unsigned ldiff, rdiff; \
+ unsigned sum = srcx; \
+ int l = 0, r = 0; \
+ int srcjx, srcix; \
+ \
+ for (int j = mid - 1, i = mid + 1; j >= 0 && i < size; j--, i++) { \
+ srcjx = srcf[j][x]; \
+ \
+ ldiff = FFABS(srcx - srcjx); \
+ lsumdiff += ldiff; \
+ if (ldiff > thra || \
+ lsumdiff > thrb) \
+ break; \
+ l++; \
+ sum += srcjx; \
+ \
+ srcix = srcf[i][x]; \
+ \
+ rdiff = FFABS(srcx - srcix); \
+ rsumdiff += rdiff; \
+ if (rdiff > thra || \
+ rsumdiff > thrb) \
+ break; \
+ r++; \
+ sum += srcix; \
+ } \
+ \
+ dst[x] = (sum + ((r + l + 1) >> 1)) / (r + l + 1); \
+ } \
+}
+
+FILTER_ROW(uint8_t, 8)
+FILTER_ROW(uint16_t, 16)
+
+#define FILTER_ROW_SERIAL(type, name) \
+static void filter_row##name##_serial(const uint8_t *ssrc, uint8_t *ddst, \
+ const uint8_t *ssrcf[SIZE], \
+ int w, int mid, int size, \
+ int thra, int thrb) \
+{ \
+ const type *src = (const type *)ssrc; \
+ const type **srcf = (const type **)ssrcf; \
+ type *dst = (type *)ddst; \
+ \
+ for (int x = 0; x < w; x++) { \
+ const int srcx = src[x]; \
+ unsigned lsumdiff = 0, rsumdiff = 0; \
+ unsigned ldiff, rdiff; \
+ unsigned sum = srcx; \
+ int l = 0, r = 0; \
+ int srcjx, srcix; \
+ \
+ for (int j = mid - 1; j >= 0; j--) { \
+ srcjx = srcf[j][x]; \
+ \
+ ldiff = FFABS(srcx - srcjx); \
+ lsumdiff += ldiff; \
+ if (ldiff > thra || \
+ lsumdiff > thrb) \
+ break; \
+ l++; \
+ sum += srcjx; \
+ } \
+ \
+ for (int i = mid + 1; i < size; i++) { \
+ srcix = srcf[i][x]; \
+ \
+ rdiff = FFABS(srcx - srcix); \
+ rsumdiff += rdiff; \
+ if (rdiff > thra || \
+ rsumdiff > thrb) \
+ break; \
+ r++; \
+ sum += srcix; \
+ } \
+ \
+ dst[x] = (sum + ((r + l + 1) >> 1)) / (r + l + 1); \
+ } \
+}
+
+FILTER_ROW_SERIAL(uint8_t, 8)
+FILTER_ROW_SERIAL(uint16_t, 16)
+
+static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)