From 0e97ec54dea9330041f8a7ed30e4cd9a53c60e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Thu, 13 Feb 2014 14:34:58 +0100 Subject: [PATCH] avfilter/curves: support slice threading. --- libavfilter/vf_curves.c | 66 +++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/libavfilter/vf_curves.c b/libavfilter/vf_curves.c index 51234305fe..93799b0b1d 100644 --- a/libavfilter/vf_curves.c +++ b/libavfilter/vf_curves.c @@ -69,6 +69,10 @@ typedef struct { int step; } CurvesContext; +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + #define OFFSET(x) offsetof(CurvesContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption curves_options[] = { @@ -473,23 +477,46 @@ static int config_input(AVFilterLink *inlink) return 0; } -static int filter_frame(AVFilterLink *inlink, AVFrame *in) +static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - int x, y, direct = 0; - AVFilterContext *ctx = inlink->dst; - CurvesContext *curves = ctx->priv; - AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *out; - uint8_t *dst; - const uint8_t *src; + int x, y; + const CurvesContext *curves = ctx->priv; + const ThreadData *td = arg; + const AVFrame *in = td->in; + const AVFrame *out = td->out; + const int direct = out == in; const int step = curves->step; const uint8_t r = curves->rgba_map[R]; const uint8_t g = curves->rgba_map[G]; const uint8_t b = curves->rgba_map[B]; const uint8_t a = curves->rgba_map[A]; + const int slice_start = (in->height * jobnr ) / nb_jobs; + const int slice_end = (in->height * (jobnr+1)) / nb_jobs; + uint8_t *dst = out->data[0] + slice_start * out->linesize[0]; + const uint8_t *src = in->data[0] + slice_start * in->linesize[0]; + + for (y = slice_start; y < slice_end; y++) { + for (x = 0; x < in->width * step; x += step) { + dst[x + r] = curves->graph[R][src[x + r]]; + dst[x + g] = curves->graph[G][src[x + g]]; + dst[x + b] = curves->graph[B][src[x + b]]; + if (!direct && step == 4) + dst[x + a] = src[x + a]; + } + dst += out->linesize[0]; + src += in ->linesize[0]; + } + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + ThreadData td; if (av_frame_is_writable(in)) { - direct = 1; out = in; } else { out = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -500,22 +527,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } - dst = out->data[0]; - src = in ->data[0]; + td.in = in; + td.out = out; + ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outlink->h, ctx->graph->nb_threads)); - for (y = 0; y < inlink->h; y++) { - for (x = 0; x < inlink->w * step; x += step) { - dst[x + r] = curves->graph[R][src[x + r]]; - dst[x + g] = curves->graph[G][src[x + g]]; - dst[x + b] = curves->graph[B][src[x + b]]; - if (!direct && step == 4) - dst[x + a] = src[x + a]; - } - dst += out->linesize[0]; - src += in ->linesize[0]; - } - - if (!direct) + if (out != in) av_frame_free(&in); return ff_filter_frame(outlink, out); @@ -548,5 +564,5 @@ AVFilter ff_vf_curves = { .inputs = curves_inputs, .outputs = curves_outputs, .priv_class = &curves_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, };