+typedef struct ThreadData {
+ AVFrame *in;
+ AVFrame *threshold;
+ AVFrame *min;
+ AVFrame *max;
+ AVFrame *out;
+} ThreadData;
+
+static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+ ThresholdContext *s = ctx->priv;
+ ThreadData *td = arg;
+ AVFrame *min = td->min;
+ AVFrame *max = td->max;
+ AVFrame *threshold = td->threshold;
+ AVFrame *in = td->in;
+ AVFrame *out = td->out;
+
+ for (int p = 0; p < s->nb_planes; p++) {
+ const int h = s->height[p];
+ const int slice_start = (h * jobnr) / nb_jobs;
+ const int slice_end = (h * (jobnr+1)) / nb_jobs;
+
+ if (!(s->planes & (1 << p))) {
+ av_image_copy_plane(out->data[p] + slice_start * out->linesize[p],
+ out->linesize[p],
+ in->data[p] + slice_start * in->linesize[p],
+ in->linesize[p],
+ s->width[p] * s->bpc,
+ slice_end - slice_start);
+ continue;
+ }
+ s->threshold(in->data[p] + slice_start * in->linesize[p],
+ threshold->data[p] + slice_start * threshold->linesize[p],
+ min->data[p] + slice_start * min->linesize[p],
+ max->data[p] + slice_start * max->linesize[p],
+ out->data[p] + slice_start * out->linesize[p],
+ in->linesize[p], threshold->linesize[p],
+ min->linesize[p], max->linesize[p],
+ out->linesize[p],
+ s->width[p], slice_end - slice_start);
+ }
+
+ return 0;
+}
+