[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