Browse code

lavfi/transpose: support slice threading

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2013/08/15 04:01:06
Showing 1 changed files
... ...
@@ -133,31 +133,19 @@ static AVFrame *get_video_buffer(AVFilterLink *inlink, int w, int h)
133 133
         ff_default_get_video_buffer(inlink, w, h);
134 134
 }
135 135
 
136
-static int filter_frame(AVFilterLink *inlink, AVFrame *in)
136
+typedef struct ThreadData {
137
+    AVFrame *in, *out;
138
+} ThreadData;
139
+
140
+static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr,
141
+                        int nb_jobs)
137 142
 {
138
-    TransContext *trans = inlink->dst->priv;
139
-    AVFilterLink *outlink = inlink->dst->outputs[0];
140
-    AVFrame *out;
143
+    TransContext *trans = ctx->priv;
144
+    ThreadData *td = arg;
145
+    AVFrame *out = td->out;
146
+    AVFrame *in = td->in;
141 147
     int plane;
142 148
 
143
-    if (trans->passthrough)
144
-        return ff_filter_frame(outlink, in);
145
-
146
-    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
147
-    if (!out) {
148
-        av_frame_free(&in);
149
-        return AVERROR(ENOMEM);
150
-    }
151
-
152
-    out->pts = in->pts;
153
-
154
-    if (in->sample_aspect_ratio.num == 0) {
155
-        out->sample_aspect_ratio = in->sample_aspect_ratio;
156
-    } else {
157
-        out->sample_aspect_ratio.num = in->sample_aspect_ratio.den;
158
-        out->sample_aspect_ratio.den = in->sample_aspect_ratio.num;
159
-    }
160
-
161 149
     for (plane = 0; out->data[plane]; plane++) {
162 150
         int hsub = plane == 1 || plane == 2 ? trans->hsub : 0;
163 151
         int vsub = plane == 1 || plane == 2 ? trans->vsub : 0;
... ...
@@ -165,12 +153,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
165 165
         int inh  = in->height  >> vsub;
166 166
         int outw = FF_CEIL_RSHIFT(out->width,  hsub);
167 167
         int outh = FF_CEIL_RSHIFT(out->height, vsub);
168
+        int start = (outh *  jobnr   ) / nb_jobs;
169
+        int end   = (outh * (jobnr+1)) / nb_jobs;
168 170
         uint8_t *dst, *src;
169 171
         int dstlinesize, srclinesize;
170 172
         int x, y;
171 173
 
172
-        dst = out->data[plane];
173 174
         dstlinesize = out->linesize[plane];
175
+        dst = out->data[plane] + start * dstlinesize;
174 176
         src = in->data[plane];
175 177
         srclinesize = in->linesize[plane];
176 178
 
... ...
@@ -180,11 +170,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
180 180
         }
181 181
 
182 182
         if (trans->dir&2) {
183
-            dst += out->linesize[plane] * (outh-1);
183
+            dst = out->data[plane] + dstlinesize * (outh-start-1);
184 184
             dstlinesize *= -1;
185 185
         }
186 186
 
187
-        for (y = 0; y < outh; y++) {
187
+        for (y = start; y < end; y++) {
188 188
             switch (pixstep) {
189 189
             case 1:
190 190
                 for (x = 0; x < outw; x++)
... ...
@@ -219,6 +209,37 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
219 219
         }
220 220
     }
221 221
 
222
+    return 0;
223
+}
224
+
225
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
226
+{
227
+    AVFilterContext *ctx = inlink->dst;
228
+    TransContext *trans = ctx->priv;
229
+    AVFilterLink *outlink = ctx->outputs[0];
230
+    ThreadData td;
231
+    AVFrame *out;
232
+
233
+    if (trans->passthrough)
234
+        return ff_filter_frame(outlink, in);
235
+
236
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
237
+    if (!out) {
238
+        av_frame_free(&in);
239
+        return AVERROR(ENOMEM);
240
+    }
241
+
242
+    out->pts = in->pts;
243
+
244
+    if (in->sample_aspect_ratio.num == 0) {
245
+        out->sample_aspect_ratio = in->sample_aspect_ratio;
246
+    } else {
247
+        out->sample_aspect_ratio.num = in->sample_aspect_ratio.den;
248
+        out->sample_aspect_ratio.den = in->sample_aspect_ratio.num;
249
+    }
250
+
251
+    td.in = in, td.out = out;
252
+    ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outlink->h, ctx->graph->nb_threads));
222 253
     av_frame_free(&in);
223 254
     return ff_filter_frame(outlink, out);
224 255
 }
... ...
@@ -274,4 +295,5 @@ AVFilter avfilter_vf_transpose = {
274 274
 
275 275
     .inputs    = avfilter_vf_transpose_inputs,
276 276
     .outputs   = avfilter_vf_transpose_outputs,
277
+    .flags     = AVFILTER_FLAG_SLICE_THREADS,
277 278
 };