From patchwork Mon Feb 25 20:25:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Britt Cyr X-Patchwork-Id: 12156 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 7955744738A for ; Mon, 25 Feb 2019 22:25:41 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 58FC5680888; Mon, 25 Feb 2019 22:25:41 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8933E6805ED for ; Mon, 25 Feb 2019 22:25:35 +0200 (EET) Received: by mail-yb1-f201.google.com with SMTP id w7so836755ybo.22 for ; Mon, 25 Feb 2019 12:25:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=6hOElXinTAsdWspDvYcN4BUugidOo7sz5xcVajq8zZs=; b=R0h/bBDgeiRGpB2gZ0JGo68MOv1oVU5lKsRHpxCaT0xGxdAXrgSNC24n8fqX4si4Yq 0oywWLR2uBPcNI00oj13wt+ZEQHGRZEhRMvYWGkEw/nkZK6HSW9ZKyRR0HBwyWJgtDQ5 /puz10fqPspXSCr95Q61Ywat7HFptKe8ARvm1SAY+5FwOoSaXX7ufBha4MuXncoMdR/6 gmfcRr5UZGW8xH34Ud7xCJpazkezjiLVtIDZpsRl7DOmXguEfMA4U2KxcYUC8305Hv1l awbKKD/+pc3+ZXqZLdq2CCmFBVrMAx0Vu0lggFCDFPWQ0Xa+kQfuBLgYs75JKIk3Cfj0 JZ0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=6hOElXinTAsdWspDvYcN4BUugidOo7sz5xcVajq8zZs=; b=X7VPgX9LutvppagPTDeNOMawokHZk3G+vXqY9wezvLxYYJkbnl+73OjLD1sbU7Fjn7 s2lA9MtSfhsh+puViIz6fHCqCboDbyLJUBzCyR6YlwbzDYbrZI9pxqLCksJ6OmibohW1 FBBUvHfibAmHy9CeKtooOFfAqezWqgvQ4oN1jSWq0mADPKitrJcnAGQqAQwblrGq4Dq+ WtXM0LQCR8Q29CFSJrP6GWEC8zwHN/b/7CBQtogzoLv7gRSLd8lz7QOgWM0zC7kqgW/0 l79dXGrc9JliT05Sd9nnqx05Qqqk1zUFTR6zH2LDmUJECqxhOm4PbRjQ+IbdUxBW9VKV jLfg== X-Gm-Message-State: AHQUAuYuyw1y/CSPNa3lvKqU8Y4Aua1A4f2J2tSOTIo0M33b4HtfCNzX RpneJExVxnszLEKJqesSMqESilx9KGNvsxYSGPyi/YxhuWwz+mlMmsSHsd/KcGlp5osiajGed+f 0x1T9gSgTYO018cNXuxB0UQ8EaRTbARu2iHjl60kox4mfp7IzsuNQD8M= X-Google-Smtp-Source: AHgI3IYdGu6LjeVsGKqHByxw2Te/2amVrhujT207oO/knj0tf4ouXgyJHoFCrcvQhdCwg329cPdcBkM= X-Received: by 2002:a25:9c88:: with SMTP id y8mr6317815ybo.2.1551126333904; Mon, 25 Feb 2019 12:25:33 -0800 (PST) Date: Mon, 25 Feb 2019 15:25:30 -0500 Message-Id: <20190225202530.24526-1-cyr@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.21.0.rc0.258.g878e2cd30e-goog From: Britt Cyr To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] [PATCH] Parallelize vf_lut X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Britt Cyr Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" --- libavfilter/vf_lut.c | 106 ++++++++++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 36 deletions(-) diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c index c815ddc194..14386938be 100644 --- a/libavfilter/vf_lut.c +++ b/libavfilter/vf_lut.c @@ -72,6 +72,12 @@ typedef struct LutContext { int negate_alpha; /* only used by negate */ } LutContext; +typedef struct ThreadData { + AVFrame *in; + AVFrame *out; + AVFilterLink *link; +} ThreadData; + #define Y 0 #define U 1 #define V 2 @@ -337,26 +343,13 @@ static int config_props(AVFilterLink *inlink) return 0; } -static int filter_frame(AVFilterLink *inlink, AVFrame *in) -{ - AVFilterContext *ctx = inlink->dst; +static int lookup_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { 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); - } - + int i, j, plane = 0; + const ThreadData *td = arg; + const AVFrame *in = td->in; + AVFrame *out = td->out; + const AVFilterLink *inlink = td->link; if (s->is_rgb && s->is_16bit && !s->is_planar) { /* packed, 16-bit */ uint16_t *inrow, *outrow, *inrow0, *outrow0; @@ -366,11 +359,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) const int in_linesize = in->linesize[0] / 2; const int out_linesize = out->linesize[0] / 2; const int step = s->step; + const int row_min = jobnr / nb_jobs * h; + const int row_max = (jobnr + 1) / nb_jobs * h; inrow0 = (uint16_t*) in ->data[0]; outrow0 = (uint16_t*) out->data[0]; - for (i = 0; i < h; i ++) { + for (i = row_min; i < row_max; i ++) { inrow = inrow0; outrow = outrow0; for (j = 0; j < w; j++) { @@ -403,11 +398,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) const int in_linesize = in->linesize[0]; const int out_linesize = out->linesize[0]; const int step = s->step; + const int row_min = jobnr / nb_jobs * h; + const int row_max = (jobnr + 1) / nb_jobs * h; inrow0 = in ->data[0]; outrow0 = out->data[0]; - for (i = 0; i < h; i ++) { + for (i = row_min; i < row_max; i ++) { inrow = inrow0; outrow = outrow0; for (j = 0; j < w; j++) { @@ -435,11 +432,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) const uint16_t *tab = s->lut[plane]; const int in_linesize = in->linesize[plane] / 2; const int out_linesize = out->linesize[plane] / 2; + const int row_min = jobnr / nb_jobs * h; + const int row_max = (jobnr + 1) / nb_jobs * h; inrow = (uint16_t *)in ->data[plane]; outrow = (uint16_t *)out->data[plane]; - for (i = 0; i < h; i++) { + for (i = row_min; i < row_max; i++) { for (j = 0; j < w; j++) { #if HAVE_BIGENDIAN outrow[j] = av_bswap16(tab[av_bswap16(inrow[j])]); @@ -463,11 +462,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) const uint16_t *tab = s->lut[plane]; const int in_linesize = in->linesize[plane]; const int out_linesize = out->linesize[plane]; + const int row_min = jobnr / nb_jobs * h; + const int row_max = (jobnr + 1) / nb_jobs * h; inrow = in ->data[plane]; outrow = out->data[plane]; - for (i = 0; i < h; i++) { + for (i = row_min; i < row_max; i++) { for (j = 0; j < w; j++) outrow[j] = tab[inrow[j]]; inrow += in_linesize; @@ -476,9 +477,42 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } } - if (!direct) + return 0; +} + +static AVFrame *apply_lut(AVFilterLink *inlink, AVFrame *in) { + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + ThreadData td; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return NULL; + } + av_frame_copy_props(out, in); + } + td.in = in; + td.out = out; + td.link = inlink; + ctx->internal->execute(ctx, lookup_slice, &td, NULL, FFMIN(outlink->h, 1)); + + if (out != in) av_frame_free(&in); + return out; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterLink *outlink = inlink->dst->outputs[0]; + AVFrame *out = apply_lut(inlink, in); + if (!out) + return AVERROR(ENOMEM); return ff_filter_frame(outlink, out); } @@ -497,18 +531,18 @@ static const AVFilterPad outputs[] = { { NULL } }; -#define DEFINE_LUT_FILTER(name_, description_) \ - AVFilter ff_vf_##name_ = { \ - .name = #name_, \ - .description = NULL_IF_CONFIG_SMALL(description_), \ - .priv_size = sizeof(LutContext), \ - .priv_class = &name_ ## _class, \ - .init = name_##_init, \ - .uninit = uninit, \ - .query_formats = query_formats, \ - .inputs = inputs, \ - .outputs = outputs, \ - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, \ +#define DEFINE_LUT_FILTER(name_, description_) \ + AVFilter ff_vf_##name_ = { \ + .name = #name_, \ + .description = NULL_IF_CONFIG_SMALL(description_), \ + .priv_size = sizeof(LutContext), \ + .priv_class = &name_ ## _class, \ + .init = name_##_init, \ + .uninit = uninit, \ + .query_formats = query_formats, \ + .inputs = inputs, \ + .outputs = outputs, \ + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, \ } #if CONFIG_LUT_FILTER