From patchwork Sun May 5 07:51:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lance Wang X-Patchwork-Id: 12991 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 E57FC44995B for ; Sun, 5 May 2019 10:51:48 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C23E668AC64; Sun, 5 May 2019 10:51:48 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pf1-f171.google.com (mail-pf1-f171.google.com [209.85.210.171]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7EE0D68A7E6 for ; Sun, 5 May 2019 10:51:41 +0300 (EEST) Received: by mail-pf1-f171.google.com with SMTP id v80so5093429pfa.3 for ; Sun, 05 May 2019 00:51:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=AX0AxgjLxdxu1uBwUK7E5w1DHrV27HSGaVbTl29oqY4=; b=JRcLVPMNBBgXUEB80HGZZGUi2bl1CY7yfcNYkBsqhaiQuFqth3WXw1XbrLDLpouBhp DyEU3ckD3xpQu5TDn6O3YEp2m2+koH+hEkg5jPBYuDjU0TrIKlTBPIWqnXUFkOopiP96 Ogu/x0oWem+Vylx6RWtLLm2GDOK/58ZnLo3Z+S2zvRL8pUvgEGcr/wFB6IDJD0+ZsK1W xWsuuo8dgCg16n1B6HGcNnfGUI78w4VBxIJ4tNNh0jHOIGqBbYJS/TGnX9XdHxstcPqb CgvYNav9ghzYC0iavl23/pBVKczBAM9WaSsxTbh3+JrbVv7/jtr7RlDes2u3K/4FsMas VuLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=AX0AxgjLxdxu1uBwUK7E5w1DHrV27HSGaVbTl29oqY4=; b=FDbuKfStT8ylmH6/9Ohy1MlZi4jTDtXnfUR7W8+m5PmJB2lVmP9wjLBSFEp295KVGy dbWo9q3/n01jK4jHkiNcSEEsllNTYOvXSC5MP1Xh4QjpZNjFcb2/ZFX8vutwaRwudLcS WKRtqLIa0qAIvlB2o6k9S0FdlmWqqdlV2+1ThueqHSiSya5CAHEmPMw9WHmvuDS75KIO W96jsEBU11RRbp1SiX6GuW8AH1cRp+IUp+hkBv2CSwUPbIf+pxhB4h/w4KYFYy+RkSyE ypvDHzATK2CnrVAftHE538Avg8LmHB28f49M7dHmcXOpgHkIwyctYlyNVcl5zQtrkJrE 1ZWQ== X-Gm-Message-State: APjAAAXEKgfrZmn4KtOBOagHrdEp7Z2dyHwmcUrBfJSGatAJ9j/xqdBs +LPFIX/J5DnNhhXHT5iav0IWZYdbloc= X-Google-Smtp-Source: APXvYqyfeyh6pXKAtlTZ/8aO2kfOM379PaK5MZtUqGh8qStKVOvc+SjbxD1hZP2FOPc9AMWsIQE/nA== X-Received: by 2002:a63:2c4a:: with SMTP id s71mr23001863pgs.373.1557042699484; Sun, 05 May 2019 00:51:39 -0700 (PDT) Received: from localhost.localdomain ([47.90.99.151]) by smtp.gmail.com with ESMTPSA id c127sm11226924pfc.132.2019.05.05.00.51.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 05 May 2019 00:51:38 -0700 (PDT) From: lance.lmwang@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Sun, 5 May 2019 15:51:20 +0800 Message-Id: <20190505075120.11987-1-lance.lmwang@gmail.com> X-Mailer: git-send-email 2.21.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] vf_tonemap.c: Support for slice thread for performance 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: Limin Wang Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Limin Wang --- libavfilter/vf_tonemap.c | 109 +++++++++++++++++++++++++++++---------- 1 file changed, 81 insertions(+), 28 deletions(-) diff --git a/libavfilter/vf_tonemap.c b/libavfilter/vf_tonemap.c index efd4af5466..0b26dd5e7f 100644 --- a/libavfilter/vf_tonemap.c +++ b/libavfilter/vf_tonemap.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Vittorio Giovara + * Copyright (c) 2019 Limin Wang * * This file is part of FFmpeg. * @@ -71,6 +72,13 @@ typedef struct TonemapContext { const struct LumaCoefficients *coeffs; } TonemapContext; +typedef struct ThreadData { + AVFrame *in, *out; + double peak; + const struct AVPixFmtDescriptor *desc; + const struct AVPixFmtDescriptor *odesc; +} ThreadData; + static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, @@ -127,15 +135,10 @@ static float mobius(float in, float j, double peak) } #define MIX(x,y,a) (x) * (1 - (a)) + (y) * (a) -static void tonemap(TonemapContext *s, AVFrame *out, const AVFrame *in, - const AVPixFmtDescriptor *desc, int x, int y, double peak) +static void tonemap(TonemapContext *s, float *r_out, float *b_out, float *g_out, + const float *r_in, const float *b_in, const float *g_in, + const AVPixFmtDescriptor *desc, double peak) { - const float *r_in = (const float *)(in->data[0] + x * desc->comp[0].step + y * in->linesize[0]); - const float *b_in = (const float *)(in->data[1] + x * desc->comp[1].step + y * in->linesize[1]); - const float *g_in = (const float *)(in->data[2] + x * desc->comp[2].step + y * in->linesize[2]); - float *r_out = (float *)(out->data[0] + x * desc->comp[0].step + y * out->linesize[0]); - float *b_out = (float *)(out->data[1] + x * desc->comp[1].step + y * out->linesize[1]); - float *g_out = (float *)(out->data[2] + x * desc->comp[2].step + y * out->linesize[2]); float sig, sig_orig; /* load values */ @@ -189,17 +192,78 @@ static void tonemap(TonemapContext *s, AVFrame *out, const AVFrame *in, *r_out *= sig / sig_orig; *g_out *= sig / sig_orig; *b_out *= sig / sig_orig; + +} + +static int do_tonemap_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + TonemapContext *s = ctx->priv; + const ThreadData *td = arg; + const AVFrame *in = td->in; + AVFrame *out = td->out; + int x, y; + const AVPixFmtDescriptor *desc = td->desc; + const AVPixFmtDescriptor *odesc = td->odesc; + const int slice_start = (out->height * jobnr ) / nb_jobs; + const int slice_end = (out->height * (jobnr+1)) / nb_jobs; + const int slice_h = slice_end - slice_start; + uint8_t *dstr = out->data[0] + slice_start * out->linesize[0]; + uint8_t *dstb = out->data[1] + slice_start * out->linesize[1]; + uint8_t *dstg = out->data[2] + slice_start * out->linesize[2]; + const uint8_t *srcr = in->data[0] + slice_start * in->linesize[0]; + const uint8_t *srcb = in->data[1] + slice_start * in->linesize[1]; + const uint8_t *srcg = in->data[2] + slice_start * in->linesize[2]; + uint8_t *dsta = out->data[3] + slice_start * out->linesize[3]; + const uint8_t *srca = in ->data[3] + slice_start * in->linesize[3]; + + /* do the tone map */ + for (y = slice_start; y < slice_end; y++) { + for (x = 0; x < out->width; x++) { + const float *r_in = (const float *)(srcr + x * desc->comp[0].step); + const float *b_in = (const float *)(srcb + x * desc->comp[1].step); + const float *g_in = (const float *)(srcg + x * desc->comp[2].step); + float *r_out = (float *)(dstr + x * desc->comp[0].step); + float *b_out = (float *)(dstb + x * desc->comp[1].step); + float *g_out = (float *)(dstg + x * desc->comp[2].step); + + tonemap(s, r_out, b_out, g_out, r_in, b_in, g_in, desc, td->peak); + } + srcr += in->linesize[0]; + srcg += in->linesize[1]; + srcb += in->linesize[2]; + dstr += out->linesize[0]; + dstg += out->linesize[1]; + dstb += out->linesize[2]; + } + + /* copy/generate alpha if needed */ + if (desc->flags & AV_PIX_FMT_FLAG_ALPHA && odesc->flags & AV_PIX_FMT_FLAG_ALPHA) { + av_image_copy_plane(dsta, out->linesize[3], + srca, in->linesize[3], + out->linesize[3], slice_h); + } else if (odesc->flags & AV_PIX_FMT_FLAG_ALPHA) { + for (y = slice_start; y < slice_end; y++) { + for (x = 0; x < out->width; x++) { + AV_WN32(dsta + x * odesc->comp[3].step + y * out->linesize[3], + av_float2int(1.0f)); + } + } + } + + return 0; } static int filter_frame(AVFilterLink *link, AVFrame *in) { - TonemapContext *s = link->dst->priv; + AVFilterContext *ctx = link->dst; + TonemapContext *s = ctx->priv; AVFilterLink *outlink = link->dst->outputs[0]; AVFrame *out; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); const AVPixFmtDescriptor *odesc = av_pix_fmt_desc_get(outlink->format); - int ret, x, y; + int ret; double peak = s->peak; + ThreadData td; if (!desc || !odesc) { av_frame_free(&in); @@ -244,24 +308,12 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) s->desat = 0; } - /* do the tone map */ - for (y = 0; y < out->height; y++) - for (x = 0; x < out->width; x++) - tonemap(s, out, in, desc, x, y, peak); - - /* copy/generate alpha if needed */ - if (desc->flags & AV_PIX_FMT_FLAG_ALPHA && odesc->flags & AV_PIX_FMT_FLAG_ALPHA) { - av_image_copy_plane(out->data[3], out->linesize[3], - in->data[3], in->linesize[3], - out->linesize[3], outlink->h); - } else if (odesc->flags & AV_PIX_FMT_FLAG_ALPHA) { - for (y = 0; y < out->height; y++) { - for (x = 0; x < out->width; x++) { - AV_WN32(out->data[3] + x * odesc->comp[3].step + y * out->linesize[3], - av_float2int(1.0f)); - } - } - } + td.in = in; + td.out = out; + td.desc = desc; + td.odesc = odesc; + td.peak = peak; + ctx->internal->execute(ctx, do_tonemap_slice, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); av_frame_free(&in); @@ -315,4 +367,5 @@ AVFilter ff_vf_tonemap = { .priv_class = &tonemap_class, .inputs = tonemap_inputs, .outputs = tonemap_outputs, + .flags = AVFILTER_FLAG_SLICE_THREADS, };