From patchwork Wed Dec 26 14:23:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Uwe Freese X-Patchwork-Id: 11554 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 8F5F444D036 for ; Wed, 26 Dec 2018 16:29:12 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 44DFE68AEF8; Wed, 26 Dec 2018 16:29:09 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mout.kundenserver.de (mout.kundenserver.de [212.227.126.187]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5C6D868A946 for ; Wed, 26 Dec 2018 16:29:03 +0200 (EET) Received: from butler2.ufnet ([84.57.61.127]) by mrelayeu.kundenserver.de (mreue010 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MoOIi-1h943r1pCC-00olLM for ; Wed, 26 Dec 2018 15:23:59 +0100 Received: from localhost ([127.0.0.1] helo=[IPv6:::1]) by butler2.ufnet with esmtp (Exim 4.89) (envelope-from ) id 1gcA6I-00029V-Mt for ffmpeg-devel@ffmpeg.org; Wed, 26 Dec 2018 15:23:58 +0100 To: ffmpeg-devel@ffmpeg.org References: <04cf53a1-0749-a4b5-1d1a-cef28c086a57@uwe-freese.de> <984b88c3-605e-a281-ec48-4b73956a4288@uwe-freese.de> From: Uwe Freese Message-ID: <5f86c630-efe4-0b8b-9a68-8c624e522573@gmx.de> Date: Wed, 26 Dec 2018 15:23:58 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.3.0 MIME-Version: 1.0 In-Reply-To: <984b88c3-605e-a281-ec48-4b73956a4288@uwe-freese.de> Content-Language: en-US X-Provags-ID: V03:K1:8THVX84UKpqgbI+3EoY6AaGPxmYR4zIbawi38A6m2wNIJ9rCo6s aPGz+bkVMupHykjIEDpq7OeUoEv33OPTfDVfWxkNBWXVSD3KqJReAjOrlYJcoQyUOEzQS1u 9AQiOefse7imG6MRlvy4M1e9XOaHWn6n2+KEiQdHbJH78DPHTu6PFEITkT2LE53UX6LViqu wOERes4M4pXKFI0uCbvWw== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:o2/QilD2BPY=:UkiW02bSb2b7+5OVCKxTrF NOL/SBDTC+WiaVwBHTPiTHjAdIIp4qFeZ4Yyzt/WjS/IMBMGQ23KTzcydQwa9lyokq7VpEoVf vNEBcTDFTlTO7Uw33J+98dhn8rkdbF25nASc7Fd/FRUGEj1Vw+bk83+AJGFMrclKlN6vZdikY lL07qrm6tVpxDUyRx4BBCftip//qAdE8Gou3XE3dk9AUv6mxpZHCBEbO2d4TY3Uy2I+rwUGEG 4jF5T32FuXdTyuDkGewljawrY1Ni8op0+QnkbSd72SHiAsv/FhmnwHXBs7XTDrCI4cIvceDLM j++w25Nz6OjsEwYg0JYHd9phyUCvyIxiWM81jM6Y2SHs3sKmgr01PWOkiNM2uJWbuFIpSJN4d p/PGxXZ9of4jW97UPoJKMS5vphnQtMWbSyF7GDHuDWO2vIbn3hVE9SBHpRSZfrhXQJ2Yf9a0X 1c6n9UMtR5V1bsntmrluRtM86DIPuWFpgHeLIkmLij2dxfty8kNsvDiR3re95/vbLlwY2RH3l TAmWr6S1/0b5srh9EpF1AdJ/FBOUUCa8ozp837Zn36QCb+wlsyBM1GL/PlMRQeOJPCqLlovQv kOoQ1VYb77FNMyZxi79wAWYgp+5pV9NaM3tXJdjwLoiVr6hpp6kONp/+xb6yBwXOGO5fJiI9e cubcGfckwUNcg96/wrLQeR7DBSdD8eE1XwMdov5YmkA/1LUiS/Hj94PkgBCdJXiR8Cmts1X9g eKGXQd5c8w//QVdVUeyU+W95oc5pvydTmwzemQ== Subject: [FFmpeg-devel] [PATCH] delogo filter: new "uglarm" interpolation mode added 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Hello, so now I've taken the time to integrate the alternative interpolation algorithm 'uglarm' into the delogo filter. I took the code from ffdshow's logoaway, which took over the code from LogoAway for VirtualDub, where I originally added it 2001. :) I tested the code with several different options and had temporarily added many debug outputs (to the console) to see the internally calculated values. So I'm pretty confident about the correct functioning of the code. I also made some improvements compared to the logoaway filter to minimize the lookup tables (which was also a reason for me to test it thoroughly). Of course, it would be nice if the addition will now also find it's way into the normal development branch. The current "xy" mode tends to flicker and show horizontal and vertical lines, which sometimes produces an "eye catcher" at the logo area. In contrast, the new UGLARM mode IMHO shows a much more non-distracting blurred area while keeping the same simple usage (only entering the coordinates of the logo). Can someone please review and add the code? Who would be primarily responsible to add this to libavfilter? You can test the filter (after compiling with the attached patch for vf_delogo.c) with the following command to show the old xy mode and the new uglarm mode next to each other by: ./ffmpeg -i "yourtestvideo.mkv" -map 0:v:0 -vframes 100 -filter_complex "crop=200:200:100:100,split=2[L][R];[L]delogo=x=50:y=50:w=100:h=100[L2];[R]delogo=x=50:y=50:w=100:h=100:mode=uglarm:power=15[R2];[L2][R2]hstack=inputs=2" -c:v huffyuv delogotest.mkv && ffplay delogotest.mkv (power can be from 0 to 30, 15 is default and need not be specified) Here are some details of what I added and how / why: - a new parameter "mode" is used to select the mode   Note: It defaults to the current xy mode.   Note: I preferred using a string / enum parameter instead of a boolean so the parameter could stay backwards compatible in case another mode would be added some day. - a "power" value can be used to set the strength of the effect   Note: Named "power" (and not "strength") because the distance between logo pixels to the border is calculated by using the power of the diagonal distance.   Note: The default value results in exponent 3 (cubic), which corresponds to how e.g. a magnetic field is behaving and what I used all the years for logoaway. - Two lookup tables (per plane) are generated at startup (if the new mode is set). - Memory is cleaned up in the new "uninit" function. - The SAR (sample aspect ratio) is considered to calculate the interpolated inner pixels of the logo area. - As I saw, the filter is applied to three planes, I think it's for Y U V, because of the YUV color model.   Question: How many planes can there be? I used an array of pointers to 10 possible lookup tables (one per plane).   Can there be more? Are 3 enough? Is there a constant to get the max. number of planes at compile time? - Only a band / border of 1 pixel is used for interpolation. This is because the "band" option in the delogo filter is planned to be removed anyway. It's also not necessary for the new mode. - I added comments and description as I thought would be useful to understand the code. I hope it's ok as it's done. - I tried to use the same formatting etc. as in the original source code. Is there anything I have to change? I would be really glad for any feedback, comments, improvement ideas,..., and of course a review and integration of the code. :) Of course, I would support adding documentation about the filter as well. Just let me know what's needed. Best Regards, Uwe Am 13.12.18 um 07:55 schrieb uwe.freese@gmx.de: > Hello Kyle, >> You should also try vf_removelogo. It is supposedly better than the >> more simple vf_delogo. > > I tried (with a box in a PNG mask as logo cover). > > That is no alternative both quality wise and from usability point of > view: > > 1. It gave me blurry borders with several pixels widths from outside > to the inner. They were very symmetrical and showed a 45 degree > "lines" from the edges to the middle. Hardly the nice blurred box I > wanted. > > 2. If you want to cover the logo by simple coordinates (a box), it's > unnecessary effort to create a PNG mask with that box in it instead of > giving the coordinates as parameter. > > > Because removelogo can handle arbitrary masks and the calculation I > posted is using a simple rectangular box (and this is my typical use > case), I suggested to add it to the "delogo" filter. > > So my offer stands, would be nice if someone can add this additional > mode. > [...] From 9431911dbef4179663f1fc30efc4b37b696ed7d9 Mon Sep 17 00:00:00 2001 From: breaker27 Date: Wed, 26 Dec 2018 14:37:35 +0100 Subject: [PATCH] Add new delogo interpolation mode uglarm. --- libavfilter/vf_delogo.c | 330 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 247 insertions(+), 83 deletions(-) diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c index 065d093641..12b4c5d2df 100644 --- a/libavfilter/vf_delogo.c +++ b/libavfilter/vf_delogo.c @@ -2,6 +2,7 @@ * Copyright (c) 2002 Jindrich Makovicka * Copyright (c) 2011 Stefano Sabatini * Copyright (c) 2013, 2015 Jean Delvare + * Copyright (c) 2019 Uwe Freese * * This file is part of FFmpeg. * @@ -25,6 +26,9 @@ * A very simple tv station logo remover * Originally imported from MPlayer libmpcodecs/vf_delogo.c, * the algorithm was later improved. + * The "UGLARM" mode was first implemented 2001 by Uwe Freese for Virtual + * Dub's LogoAway filter (by Krzysztof Wojdon), taken over into ffdshow's + * logoaway filter (by Milan Cutka), from where it was ported to ffmpeg. */ #include "libavutil/common.h" @@ -43,27 +47,32 @@ * The algorithm is only applied to the region specified by the logo * parameters. * - * @param w width of the input image - * @param h height of the input image - * @param logo_x x coordinate of the top left corner of the logo region - * @param logo_y y coordinate of the top left corner of the logo region - * @param logo_w width of the logo - * @param logo_h height of the logo - * @param band the size of the band around the processed area - * @param show show a rectangle around the processed area, useful for - * parameters tweaking - * @param direct if non-zero perform in-place processing + * @param w width of the input image + * @param h height of the input image + * @param logo_x x coordinate of the top left corner of the logo region + * @param logo_y y coordinate of the top left corner of the logo region + * @param logo_w width of the logo + * @param logo_h height of the logo + * @param band the size of the band around the processed area + * @param *uglarmtable pointer to weight table in UGLARM interpolation mode, + * zero when x-y mode is used + * @param *uglarmweightsum pointer to weight sum table in UGLARM interpolation mode, + * zero when x-y mode is used + * @param show show a rectangle around the processed area, useful for + * parameters tweaking + * @param direct if non-zero perform in-place processing */ static void apply_delogo(uint8_t *dst, int dst_linesize, uint8_t *src, int src_linesize, int w, int h, AVRational sar, int logo_x, int logo_y, int logo_w, int logo_h, - unsigned int band, int show, int direct) + unsigned int band, double *uglarmtable, + double *uglarmweightsum, int show, int direct) { int x, y; uint64_t interp, weightl, weightr, weightt, weightb, weight; uint8_t *xdst, *xsrc; - + uint8_t *topleft, *botleft, *topright; unsigned int left_sample, right_sample; int xclipl, xclipr, yclipt, yclipb; @@ -88,90 +97,204 @@ static void apply_delogo(uint8_t *dst, int dst_linesize, dst += (logo_y1 + 1) * dst_linesize; src += (logo_y1 + 1) * src_linesize; - - for (y = logo_y1+1; y < logo_y2; y++) { - left_sample = topleft[src_linesize*(y-logo_y1)] + - topleft[src_linesize*(y-logo_y1-1)] + - topleft[src_linesize*(y-logo_y1+1)]; - right_sample = topright[src_linesize*(y-logo_y1)] + - topright[src_linesize*(y-logo_y1-1)] + - topright[src_linesize*(y-logo_y1+1)]; - - for (x = logo_x1+1, - xdst = dst+logo_x1+1, - xsrc = src+logo_x1+1; x < logo_x2; x++, xdst++, xsrc++) { - - if (show && (y == logo_y1+1 || y == logo_y2-1 || - x == logo_x1+1 || x == logo_x2-1)) { - *xdst = 0; - continue; + + if (!uglarmtable) { + for (y = logo_y1+1; y < logo_y2; y++) { + left_sample = topleft[src_linesize*(y-logo_y1)] + + topleft[src_linesize*(y-logo_y1-1)] + + topleft[src_linesize*(y-logo_y1+1)]; + right_sample = topright[src_linesize*(y-logo_y1)] + + topright[src_linesize*(y-logo_y1-1)] + + topright[src_linesize*(y-logo_y1+1)]; + + for (x = logo_x1+1, + xdst = dst+logo_x1+1, + xsrc = src+logo_x1+1; x < logo_x2; x++, xdst++, xsrc++) { + + if (show && (y == logo_y1+1 || y == logo_y2-1 || + x == logo_x1+1 || x == logo_x2-1)) { + *xdst = 0; + continue; + } + + /* Weighted interpolation based on relative distances, taking SAR into account */ + weightl = (uint64_t) (logo_x2-x) * (y-logo_y1) * (logo_y2-y) * sar.den; + weightr = (uint64_t)(x-logo_x1) * (y-logo_y1) * (logo_y2-y) * sar.den; + weightt = (uint64_t)(x-logo_x1) * (logo_x2-x) * (logo_y2-y) * sar.num; + weightb = (uint64_t)(x-logo_x1) * (logo_x2-x) * (y-logo_y1) * sar.num; + + interp = + left_sample * weightl + + + right_sample * weightr + + + (topleft[x-logo_x1] + + topleft[x-logo_x1-1] + + topleft[x-logo_x1+1]) * weightt + + + (botleft[x-logo_x1] + + botleft[x-logo_x1-1] + + botleft[x-logo_x1+1]) * weightb; + weight = (weightl + weightr + weightt + weightb) * 3U; + interp = ROUNDED_DIV(interp, weight); + + if (y >= logo_y+band && y < logo_y+logo_h-band && + x >= logo_x+band && x < logo_x+logo_w-band) { + *xdst = interp; + } else { + unsigned dist = 0; + + if (x < logo_x+band) + dist = FFMAX(dist, logo_x-x+band); + else if (x >= logo_x+logo_w-band) + dist = FFMAX(dist, x-(logo_x+logo_w-1-band)); + + if (y < logo_y+band) + dist = FFMAX(dist, logo_y-y+band); + else if (y >= logo_y+logo_h-band) + dist = FFMAX(dist, y-(logo_y+logo_h-1-band)); + + *xdst = (*xsrc*dist + interp*(band-dist))/band; + } } - /* Weighted interpolation based on relative distances, taking SAR into account */ - weightl = (uint64_t) (logo_x2-x) * (y-logo_y1) * (logo_y2-y) * sar.den; - weightr = (uint64_t)(x-logo_x1) * (y-logo_y1) * (logo_y2-y) * sar.den; - weightt = (uint64_t)(x-logo_x1) * (logo_x2-x) * (logo_y2-y) * sar.num; - weightb = (uint64_t)(x-logo_x1) * (logo_x2-x) * (y-logo_y1) * sar.num; - - interp = - left_sample * weightl - + - right_sample * weightr - + - (topleft[x-logo_x1] + - topleft[x-logo_x1-1] + - topleft[x-logo_x1+1]) * weightt - + - (botleft[x-logo_x1] + - botleft[x-logo_x1-1] + - botleft[x-logo_x1+1]) * weightb; - weight = (weightl + weightr + weightt + weightb) * 3U; - interp = ROUNDED_DIV(interp, weight); - - if (y >= logo_y+band && y < logo_y+logo_h-band && - x >= logo_x+band && x < logo_x+logo_w-band) { + dst += dst_linesize; + src += src_linesize; + } + } else { + int bx, by; + double interpd; + + for (y = logo_y1 + 1; y < logo_y2; y++) { + for (x = logo_x1 + 1, + xdst = dst + logo_x1 + 1, + xsrc = src + logo_x1 + 1; x < logo_x2; x++, xdst++, xsrc++) { + + if (show && (y == logo_y1 + 1 || y == logo_y2 - 1 || + x == logo_x1 + 1 || x == logo_x2 - 1)) { + *xdst = 0; + continue; + } + + interpd = 0; + + for (bx = 0; bx < logo_w; bx++) { + interpd += topleft[bx] * + uglarmtable[abs(bx - (x - logo_x1)) + (y - logo_y1) * (logo_w - 1)]; + interpd += botleft[bx] * + uglarmtable[abs(bx - (x - logo_x1)) + (logo_h - (y - logo_y1) - 1) * (logo_w - 1)]; + } + + for (by = 1; by < logo_h - 1; by++) { + interpd += topleft[by * src_linesize] * + uglarmtable[(x - logo_x1) + abs(by - (y - logo_y1)) * (logo_w - 1)]; + interpd += topleft[by * src_linesize + (logo_w - 1)] * + uglarmtable[logo_w - (x - logo_x1) - 1 + abs(by - (y - logo_y1)) * (logo_w - 1)]; + } + + interp = (uint64_t)(interpd / + uglarmweightsum[(x - logo_x1) - 1 + (y - logo_y1 - 1) * (logo_w - 2)]); *xdst = interp; - } else { - unsigned dist = 0; - - if (x < logo_x+band) - dist = FFMAX(dist, logo_x-x+band); - else if (x >= logo_x+logo_w-band) - dist = FFMAX(dist, x-(logo_x+logo_w-1-band)); - - if (y < logo_y+band) - dist = FFMAX(dist, logo_y-y+band); - else if (y >= logo_y+logo_h-band) - dist = FFMAX(dist, y-(logo_y+logo_h-1-band)); + } + + dst += dst_linesize; + src += src_linesize; + } + } +} - *xdst = (*xsrc*dist + interp*(band-dist))/band; +/** + * Calculate the lookup tables to be used in UGLARM interpolation mode. + * + * @param *uglarmtable Pointer to table containing weigths for each possible + * diagonal distance between a border pixel and an inner + * logo pixel. + * @param *uglarmweightsum Pointer to a table containing the weight sum to divide + * by for each pixel within the logo area. + * @param sar The sar to take into account when calculating lookup + * tables. + * @param logo_w width of the logo + * @param logo_h height of the logo + * @param power power of uglarm interpolation + */ +static void calcUGLARMTables(double *uglarmtable, double *uglarmweightsum, + AVRational sar, int logo_w, int logo_h, int power) +{ + double e = 0.2 * power; + double aspect = (double)sar.num / sar.den; + int x, y; + + /* uglarmtable will contain a weigth for each possible diagonal distance + * between a border pixel and an inner logo pixel. The maximum distance in + * each direction between border and an inner pixel can be logo_w - 1. The + * weight of a border pixel which is x,y pixels away is stored at position + * x + y * (logo_w - 1). */ + for (y = 0; y < logo_h - 1; y++) + for (x = 0; x < logo_w - 1; x++) { + if (x + y != 0) { + double d = pow(sqrt((double)(x * x * aspect * aspect + y * y)), e); + uglarmtable[x + y * (logo_w - 1)] = 1.0 / d; + } else { + uglarmtable[x + y * (logo_w - 1)] = 1.0; } } - dst += dst_linesize; - src += src_linesize; - } + /* uglarmweithsum will conatain the sum of all weigths which is used when + * an inner pixel of the logo at position x,y is calculated out of the + * border pixels. The aggregated value has to be divided by that. The value + * to use for the inner 1-based logo position x,y is stored at + * (x - 1) + (y - 1) * (logo_w - 2). */ + for (y = 1; y < logo_h - 1; y++) + for (x = 1; x < logo_w - 1; x++) { + double weightsum = 0; + + for (int bx = 0; bx < logo_w; bx++) { + /* top border */ + weightsum += uglarmtable[abs(bx - x) + y * (logo_w - 1)]; + /* bottom border */ + weightsum += uglarmtable[abs(bx - x) + (logo_h - y - 1) * (logo_w - 1)]; + } + + for (int by = 1; by < logo_h - 1; by++) { + /* left border */ + weightsum += uglarmtable[x + abs(by - y) * (logo_w - 1)]; + /* right border */ + weightsum += uglarmtable[(logo_w - x - 1) + abs(by - y) * (logo_w - 1)]; + } + + uglarmweightsum[(x - 1) + (y - 1) * (logo_w - 2)] = weightsum; + } } +enum mode { + MODE_XY, + MODE_UGLARM +}; + typedef struct DelogoContext { const AVClass *class; - int x, y, w, h, band, show; -} DelogoContext; + int x, y, w, h, band, mode, power, show; + double *uglarmtable[10], *uglarmweightsum[10]; +} DelogoContext; #define OFFSET(x) offsetof(DelogoContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption delogo_options[]= { - { "x", "set logo x position", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, - { "y", "set logo y position", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, - { "w", "set logo width", OFFSET(w), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, - { "h", "set logo height", OFFSET(h), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, + { "x", "set logo x position", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, + { "y", "set logo y position", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, + { "w", "set logo width", OFFSET(w), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, + { "h", "set logo height", OFFSET(h), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, #if LIBAVFILTER_VERSION_MAJOR < 7 /* Actual default value for band/t is 1, set in init */ - { "band", "set delogo area band size", OFFSET(band), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, - { "t", "set delogo area band size", OFFSET(band), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "band", "set delogo area band size", OFFSET(band), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "t", "set delogo area band size", OFFSET(band), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, #endif - { "show", "show delogo area", OFFSET(show), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, FLAGS }, + {"mode", "set the interpolation mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = MODE_XY}, 0, 1, FLAGS, "mode"}, + {"xy", "use pixels in straight x any y direction", OFFSET(mode), AV_OPT_TYPE_CONST, { .i64 = MODE_XY}, 0, 0, FLAGS, "mode"}, + {"uglarm", "UGLARM mode, use full border", OFFSET(mode), AV_OPT_TYPE_CONST, { .i64 = MODE_UGLARM}, 0, 0, FLAGS, "mode"}, + { "power", "power of UGLARM interpolation", OFFSET(power), AV_OPT_TYPE_INT, { .i64 = 15 }, 0, 30, FLAGS }, + { "show", "show delogo area", OFFSET(show), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, FLAGS }, { NULL } }; @@ -215,8 +338,8 @@ static av_cold int init(AVFilterContext *ctx) #else s->band = 1; #endif - av_log(ctx, AV_LOG_VERBOSE, "x:%d y:%d, w:%d h:%d band:%d show:%d\n", - s->x, s->y, s->w, s->h, s->band, s->show); + av_log(ctx, AV_LOG_VERBOSE, "x:%d y:%d, w:%d h:%d band:%d mode:%d power:%d show:%d\n", + s->x, s->y, s->w, s->h, s->band, s->mode, s->power, s->show); s->w += s->band*2; s->h += s->band*2; @@ -226,6 +349,21 @@ static av_cold int init(AVFilterContext *ctx) return 0; } +static av_cold void uninit(AVFilterContext *ctx) +{ + DelogoContext *s = ctx->priv; + + if (s->mode == MODE_UGLARM) + { + for (int plane = 0; plane < 10; plane++) { + if (s->uglarmtable[plane]) + av_free(s->uglarmtable[plane]); + if (s->uglarmweightsum[plane]) + av_free(s->uglarmweightsum[plane]); + } + } +} + static int config_input(AVFilterLink *inlink) { DelogoContext *s = inlink->dst->priv; @@ -273,17 +411,42 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) for (plane = 0; plane < desc->nb_components; plane++) { int hsub = plane == 1 || plane == 2 ? hsub0 : 0; int vsub = plane == 1 || plane == 2 ? vsub0 : 0; + + /* Up and left borders were rounded down, inject lost bits + * into width and height to avoid error accumulation */ + int logo_w = AV_CEIL_RSHIFT(s->w + (s->x & ((1<h + (s->y & ((1<mode == MODE_UGLARM) && (!s->uglarmtable[plane])) { + s->uglarmtable[plane] = + (double*)av_malloc((logo_w - 1) * (logo_h - 1) * sizeof(double)); + + if (!s->uglarmtable[plane]) { + return AVERROR(ENOMEM); + } + + s->uglarmweightsum[plane] = + (double*)av_malloc((logo_w - 2) * (logo_h - 2) * sizeof(double)); + + if (!s->uglarmweightsum[plane]) { + return AVERROR(ENOMEM); + } + + calcUGLARMTables(s->uglarmtable[plane], + s->uglarmweightsum[plane], + sar, logo_w, logo_h, s->power); + } apply_delogo(out->data[plane], out->linesize[plane], in ->data[plane], in ->linesize[plane], AV_CEIL_RSHIFT(inlink->w, hsub), AV_CEIL_RSHIFT(inlink->h, vsub), sar, s->x>>hsub, s->y>>vsub, - /* Up and left borders were rounded down, inject lost bits - * into width and height to avoid error accumulation */ - AV_CEIL_RSHIFT(s->w + (s->x & ((1<h + (s->y & ((1<band>>FFMIN(hsub, vsub), + s->uglarmtable[plane], + s->uglarmweightsum[plane], s->show, direct); } @@ -317,6 +480,7 @@ AVFilter ff_vf_delogo = { .priv_size = sizeof(DelogoContext), .priv_class = &delogo_class, .init = init, + .uninit = uninit, .query_formats = query_formats, .inputs = avfilter_vf_delogo_inputs, .outputs = avfilter_vf_delogo_outputs, -- 2.11.0