Browse code

avfilter/curves: support slice threading.

Clément Bœsch authored on 2014/02/13 22:34:58
Showing 1 changed files
... ...
@@ -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
 };