+typedef struct ThreadData {
+ AVFrame *base, *overlay, *mask;
+ AVFrame *out;
+} ThreadData;
+
+static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+ MaskedMergeContext *s = ctx->priv;
+ ThreadData *td = arg;
+ AVFrame *base = td->base;
+ AVFrame *overlay = td->overlay;
+ AVFrame *mask = td->mask;
+ AVFrame *out = td->out;
+ int p;
+
+ for (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 (!((1 << p) & s->planes)) {
+ av_image_copy_plane(out->data[p] + slice_start * out->linesize[p],
+ out->linesize[p],
+ base->data[p] + slice_start * base->linesize[p],
+ base->linesize[p],
+ s->linesize[p], slice_end - slice_start);
+ continue;
+ }
+
+ s->maskedmerge(base->data[p] + slice_start * base->linesize[p],
+ overlay->data[p] + slice_start * overlay->linesize[p],
+ mask->data[p] + slice_start * mask->linesize[p],
+ out->data[p] + slice_start * out->linesize[p],
+ base->linesize[p], overlay->linesize[p],
+ mask->linesize[p], out->linesize[p],
+ s->width[p], slice_end - slice_start,
+ s->half, s->depth);
+ }
+
+ return 0;
+}
+