[FFmpeg-devel] [PATCH] avfilter/vf_lut: implement slice threading

Paul B Mahol onemda at gmail.com
Fri Jul 10 13:29:40 CEST 2015


Signed-off-by: Paul B Mahol <onemda at gmail.com>
---
 libavfilter/vf_lut.c | 89 +++++++++++++++++++++++++++++++++-------------------
 1 file changed, 57 insertions(+), 32 deletions(-)

diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c
index 3f0524d..e0e7a86 100644
--- a/libavfilter/vf_lut.c
+++ b/libavfilter/vf_lut.c
@@ -316,40 +316,34 @@ static int config_props(AVFilterLink *inlink)
     return 0;
 }
 
-static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+typedef struct ThreadData {
+    AVFrame *in, *out;
+} ThreadData;
+
+static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
-    AVFilterContext *ctx = inlink->dst;
     LutContext *s = ctx->priv;
-    AVFilterLink *outlink = ctx->outputs[0];
-    AVFrame *out;
-    int i, j, plane, direct = 0;
-
-    if (av_frame_is_writable(in)) {
-        direct = 1;
-        out = in;
-    } else {
-        out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-        if (!out) {
-            av_frame_free(&in);
-            return AVERROR(ENOMEM);
-        }
-        av_frame_copy_props(out, in);
-    }
+    ThreadData *td = arg;
+    AVFrame *in = td->in;
+    AVFrame *out = td->out;
+    int i, j, plane;
 
     if (s->is_rgb) {
         /* packed */
         uint8_t *inrow, *outrow, *inrow0, *outrow0;
-        const int w = inlink->w;
+        const int w = in->width;
         const int h = in->height;
+        int slice_start = (h *  jobnr   ) / nb_jobs;
+        int slice_end   = (h * (jobnr+1)) / nb_jobs;
         const uint16_t (*tab)[256*256] = (const uint16_t (*)[256*256])s->lut;
         const int in_linesize  =  in->linesize[0];
         const int out_linesize = out->linesize[0];
         const int step = s->step;
 
-        inrow0  = in ->data[0];
-        outrow0 = out->data[0];
+        inrow0  = in ->data[0] + slice_start *  in_linesize;
+        outrow0 = out->data[0] + slice_start * out_linesize;
 
-        for (i = 0; i < h; i ++) {
+        for (i = slice_start; i < slice_end; i++) {
             inrow  = inrow0;
             outrow = outrow0;
             for (j = 0; j < w; j++) {
@@ -372,16 +366,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) {
             int vsub = plane == 1 || plane == 2 ? s->vsub : 0;
             int hsub = plane == 1 || plane == 2 ? s->hsub : 0;
-            int h = FF_CEIL_RSHIFT(inlink->h, vsub);
-            int w = FF_CEIL_RSHIFT(inlink->w, hsub);
+            int h = FF_CEIL_RSHIFT(in->height, vsub);
+            int w = FF_CEIL_RSHIFT(in->width, hsub);
+            int slice_start = (h *  jobnr   ) / nb_jobs;
+            int slice_end   = (h * (jobnr+1)) / nb_jobs;
             const uint16_t *tab = s->lut[plane];
             const int in_linesize  =  in->linesize[plane] / 2;
             const int out_linesize = out->linesize[plane] / 2;
 
-            inrow  = (uint16_t *)in ->data[plane];
-            outrow = (uint16_t *)out->data[plane];
+            inrow  = (uint16_t *)in ->data[plane] + slice_start *  in_linesize;
+            outrow = (uint16_t *)out->data[plane] + slice_start * out_linesize;
 
-            for (i = 0; i < h; i++) {
+            for (i = slice_start; i < slice_end; i++) {
                 for (j = 0; j < w; j++) {
 #if HAVE_BIGENDIAN
                     outrow[j] = av_bswap16(tab[av_bswap16(inrow[j])]);
@@ -400,16 +396,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) {
             int vsub = plane == 1 || plane == 2 ? s->vsub : 0;
             int hsub = plane == 1 || plane == 2 ? s->hsub : 0;
-            int h = FF_CEIL_RSHIFT(inlink->h, vsub);
-            int w = FF_CEIL_RSHIFT(inlink->w, hsub);
+            int h = FF_CEIL_RSHIFT(in->height, vsub);
+            int w = FF_CEIL_RSHIFT(in->width, hsub);
+            int slice_start = (h *  jobnr   ) / nb_jobs;
+            int slice_end   = (h * (jobnr+1)) / nb_jobs;
             const uint16_t *tab = s->lut[plane];
             const int in_linesize  =  in->linesize[plane];
             const int out_linesize = out->linesize[plane];
 
-            inrow  = in ->data[plane];
-            outrow = out->data[plane];
+            inrow  = in ->data[plane] + slice_start *  in_linesize;
+            outrow = out->data[plane] + slice_start * out_linesize;
 
-            for (i = 0; i < h; i++) {
+            for (i = slice_start; i < slice_end; i++) {
                 for (j = 0; j < w; j++)
                     outrow[j] = tab[inrow[j]];
                 inrow  += in_linesize;
@@ -418,6 +416,32 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         }
     }
 
+    return 0;
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    AVFilterContext *ctx = inlink->dst;
+    AVFilterLink *outlink = ctx->outputs[0];
+    AVFrame *out;
+    ThreadData td;
+    int direct = 0;
+
+    if (av_frame_is_writable(in)) {
+        direct = 1;
+        out = in;
+    } else {
+        out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+        if (!out) {
+            av_frame_free(&in);
+            return AVERROR(ENOMEM);
+        }
+        av_frame_copy_props(out, in);
+    }
+
+    td.in = in; td.out = out;
+    ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outlink->h, ctx->graph->nb_threads));
+
     if (!direct)
         av_frame_free(&in);
 
@@ -450,7 +474,8 @@ static const AVFilterPad outputs[] = {
         .query_formats = query_formats,                                 \
         .inputs        = inputs,                                        \
         .outputs       = outputs,                                       \
-        .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,        \
+        .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |       \
+                                    AVFILTER_FLAG_SLICE_THREADS,        \
     }
 
 #if CONFIG_LUT_FILTER
-- 
1.7.11.2



More information about the ffmpeg-devel mailing list