... | ... |
@@ -69,6 +69,10 @@ typedef struct { |
69 | 69 |
int step; |
70 | 70 |
} CurvesContext; |
71 | 71 |
|
72 |
+typedef struct ThreadData { |
|
73 |
+ AVFrame *in, *out; |
|
74 |
+} ThreadData; |
|
75 |
+ |
|
72 | 76 |
#define OFFSET(x) offsetof(CurvesContext, x) |
73 | 77 |
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM |
74 | 78 |
static const AVOption curves_options[] = { |
... | ... |
@@ -473,23 +477,46 @@ static int config_input(AVFilterLink *inlink) |
473 | 473 |
return 0; |
474 | 474 |
} |
475 | 475 |
|
476 |
-static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
|
476 |
+static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) |
|
477 | 477 |
{ |
478 |
- int x, y, direct = 0; |
|
479 |
- AVFilterContext *ctx = inlink->dst; |
|
480 |
- CurvesContext *curves = ctx->priv; |
|
481 |
- AVFilterLink *outlink = ctx->outputs[0]; |
|
482 |
- AVFrame *out; |
|
483 |
- uint8_t *dst; |
|
484 |
- const uint8_t *src; |
|
478 |
+ int x, y; |
|
479 |
+ const CurvesContext *curves = ctx->priv; |
|
480 |
+ const ThreadData *td = arg; |
|
481 |
+ const AVFrame *in = td->in; |
|
482 |
+ const AVFrame *out = td->out; |
|
483 |
+ const int direct = out == in; |
|
485 | 484 |
const int step = curves->step; |
486 | 485 |
const uint8_t r = curves->rgba_map[R]; |
487 | 486 |
const uint8_t g = curves->rgba_map[G]; |
488 | 487 |
const uint8_t b = curves->rgba_map[B]; |
489 | 488 |
const uint8_t a = curves->rgba_map[A]; |
489 |
+ const int slice_start = (in->height * jobnr ) / nb_jobs; |
|
490 |
+ const int slice_end = (in->height * (jobnr+1)) / nb_jobs; |
|
491 |
+ uint8_t *dst = out->data[0] + slice_start * out->linesize[0]; |
|
492 |
+ const uint8_t *src = in->data[0] + slice_start * in->linesize[0]; |
|
493 |
+ |
|
494 |
+ for (y = slice_start; y < slice_end; y++) { |
|
495 |
+ for (x = 0; x < in->width * step; x += step) { |
|
496 |
+ dst[x + r] = curves->graph[R][src[x + r]]; |
|
497 |
+ dst[x + g] = curves->graph[G][src[x + g]]; |
|
498 |
+ dst[x + b] = curves->graph[B][src[x + b]]; |
|
499 |
+ if (!direct && step == 4) |
|
500 |
+ dst[x + a] = src[x + a]; |
|
501 |
+ } |
|
502 |
+ dst += out->linesize[0]; |
|
503 |
+ src += in ->linesize[0]; |
|
504 |
+ } |
|
505 |
+ return 0; |
|
506 |
+} |
|
507 |
+ |
|
508 |
+static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
|
509 |
+{ |
|
510 |
+ AVFilterContext *ctx = inlink->dst; |
|
511 |
+ AVFilterLink *outlink = ctx->outputs[0]; |
|
512 |
+ AVFrame *out; |
|
513 |
+ ThreadData td; |
|
490 | 514 |
|
491 | 515 |
if (av_frame_is_writable(in)) { |
492 |
- direct = 1; |
|
493 | 516 |
out = in; |
494 | 517 |
} else { |
495 | 518 |
out = ff_get_video_buffer(outlink, outlink->w, outlink->h); |
... | ... |
@@ -500,22 +527,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
500 | 500 |
av_frame_copy_props(out, in); |
501 | 501 |
} |
502 | 502 |
|
503 |
- dst = out->data[0]; |
|
504 |
- src = in ->data[0]; |
|
505 |
- |
|
506 |
- for (y = 0; y < inlink->h; y++) { |
|
507 |
- for (x = 0; x < inlink->w * step; x += step) { |
|
508 |
- dst[x + r] = curves->graph[R][src[x + r]]; |
|
509 |
- dst[x + g] = curves->graph[G][src[x + g]]; |
|
510 |
- dst[x + b] = curves->graph[B][src[x + b]]; |
|
511 |
- if (!direct && step == 4) |
|
512 |
- dst[x + a] = src[x + a]; |
|
513 |
- } |
|
514 |
- dst += out->linesize[0]; |
|
515 |
- src += in ->linesize[0]; |
|
516 |
- } |
|
503 |
+ td.in = in; |
|
504 |
+ td.out = out; |
|
505 |
+ ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outlink->h, ctx->graph->nb_threads)); |
|
517 | 506 |
|
518 |
- if (!direct) |
|
507 |
+ if (out != in) |
|
519 | 508 |
av_frame_free(&in); |
520 | 509 |
|
521 | 510 |
return ff_filter_frame(outlink, out); |
... | ... |
@@ -548,5 +564,5 @@ AVFilter ff_vf_curves = { |
548 | 548 |
.inputs = curves_inputs, |
549 | 549 |
.outputs = curves_outputs, |
550 | 550 |
.priv_class = &curves_class, |
551 |
- .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, |
|
551 |
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, |
|
552 | 552 |
}; |