Browse Source

avfilter/curves: support slice threading.

tags/n2.2-rc1
Clément Bœsch 11 years ago
parent
commit
0e97ec54de
1 changed files with 41 additions and 25 deletions
  1. +41
    -25
      libavfilter/vf_curves.c

+ 41
- 25
libavfilter/vf_curves.c View File

@@ -69,6 +69,10 @@ typedef struct {
int step; int step;
} CurvesContext; } CurvesContext;


typedef struct ThreadData {
AVFrame *in, *out;
} ThreadData;

#define OFFSET(x) offsetof(CurvesContext, x) #define OFFSET(x) offsetof(CurvesContext, x)
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
static const AVOption curves_options[] = { static const AVOption curves_options[] = {
@@ -473,23 +477,46 @@ static int config_input(AVFilterLink *inlink)
return 0; 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 int step = curves->step;
const uint8_t r = curves->rgba_map[R]; const uint8_t r = curves->rgba_map[R];
const uint8_t g = curves->rgba_map[G]; const uint8_t g = curves->rgba_map[G];
const uint8_t b = curves->rgba_map[B]; const uint8_t b = curves->rgba_map[B];
const uint8_t a = curves->rgba_map[A]; 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)) { if (av_frame_is_writable(in)) {
direct = 1;
out = in; out = in;
} else { } else {
out = ff_get_video_buffer(outlink, outlink->w, outlink->h); 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); av_frame_copy_props(out, in);
} }


dst = out->data[0];
src = in ->data[0];

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];
}
td.in = in;
td.out = out;
ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outlink->h, ctx->graph->nb_threads));


if (!direct)
if (out != in)
av_frame_free(&in); av_frame_free(&in);


return ff_filter_frame(outlink, out); return ff_filter_frame(outlink, out);
@@ -548,5 +564,5 @@ AVFilter ff_vf_curves = {
.inputs = curves_inputs, .inputs = curves_inputs,
.outputs = curves_outputs, .outputs = curves_outputs,
.priv_class = &curves_class, .priv_class = &curves_class,
.flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
.flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
}; };

Loading…
Cancel
Save