From patchwork Wed Feb 28 16:18:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 46620 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:a919:b0:19e:cdac:8cce with SMTP id cd25csp31109pzb; Wed, 28 Feb 2024 08:17:11 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCWIZKLDwu/2wZnbL6RyNM+05d24ZDn5rYUYLC8hs1cC/eLVgOxfa3u9TRPattyHDnWvqwoQp26/k/LH7SpbCMjz0fnB3a63LPE9hw== X-Google-Smtp-Source: AGHT+IFciePI/5x4TrdCLrQiEfZfYDPobrHLUnGHTtQnOy99mPHymsbJvku7oXxqH6EH1nNXOItB X-Received: by 2002:a17:906:1784:b0:a3f:870:535c with SMTP id t4-20020a170906178400b00a3f0870535cmr129691eje.44.1709137031518; Wed, 28 Feb 2024 08:17:11 -0800 (PST) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id p9-20020a170906614900b00a3f5b2c86f9si1815999ejl.820.2024.02.28.08.17.11; Wed, 28 Feb 2024 08:17:11 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@outlook.com header.s=selector1 header.b=dv75Tf9U; arc=fail (body hash mismatch); spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=outlook.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 23E9568CD84; Wed, 28 Feb 2024 18:17:05 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04olkn2089.outbound.protection.outlook.com [40.92.75.89]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id DABD368CCAF for ; Wed, 28 Feb 2024 18:16:58 +0200 (EET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=G60bMwipVpBdnH4slhdTd+bWYI44Yp7WauBhJ85Pwi4EwZ4Kc4KAHK3QMASwgXcDS77ltMhLzdjYsxvHE09M3Riq5kiAQqsmff/qv8geylvLXBqRTMFy6UFPmri2p+qT/kGRc82ZH4kTAGJvBCKL4pR7/dDOdV92mKGM1p1gql55VFYARHbDizlUjlO6PGPnmh9r7I2xth4UcmfKF/Q5f3gt7Apknyn+Z1mL2aBZEXGUXI8Y5dQJN+IXbrCLffrcREZW+PUlAFyUaJJB8+wUqPuTMwy4p8Oa7TPYdpXIqoqkS9S6KGtqhBeXCw7Adrw8fqzCz9QgJfwPy7492kiBWQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=cqeOC59ktoevdB5SBZJYAM5cSehafFmB95sHPL6TCRE=; b=RKpEkUUUAKrwvb1KPsQ8P/nXTdoadHwpQoH+zhdccBF5YnRQqSZ0cOCvOScHVqS4ZlM5feRhLxliYL7nYjoKO7OESQ9nodFEOhLl7LcUXstoG2W9vwX1sTfh/yWKt+6LHRrq3TFUrmPWiKnMZyzRK+JrqfIYOhmi/PhUs6Qvr8D1jM5129eZXn2OhKCXYK8iQKL6qPQofIJrN6dN8b2ThaAsrIHXYoTnwQi8mtNpuF5dLgMcJXyy+kc/2wph36swtzm8k6hA1sIXvnia6iVNSbSCq3HUwkVyvy52uJh9XtRv1TXuz4o0jPti2Tl5JAZ4C7COS/rXI6BztnASiAPDwQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=cqeOC59ktoevdB5SBZJYAM5cSehafFmB95sHPL6TCRE=; b=dv75Tf9UeCNm/JzO9960JUlUFTHtHnHrt33S6CT5stbnJzMYYZ2ljIkN4lRBl/T9X7GqhHG1hf+GgUmsVbVonLkBlIc/ZY2tr8TRIGCh6YmLJiIiEwUflxQiCnJHhJ/r9QwdrfEnCT4QE8NmyS6iEm8ga9JRb2U/UOCpSpn9Bd66f5gR3VQQK0oDtKJIZQPM0OYtDFbsiYDHvfPGGp6M8K8ODLwDm0NbH/69sBIQ5D+fbcCGABGlgnH9gF1klY13e6AkHNgCL3/V0A5xmuJDXfhRIzV3RGM6d2FBkM/Ml7OSDsjyTJ/yy7diT1qsTRn+1gWVLVOyTuVeL+/6ykrN3g== Received: from AS8P250MB0744.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:541::14) by AS4P250MB0512.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:4b7::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7316.34; Wed, 28 Feb 2024 16:16:56 +0000 Received: from AS8P250MB0744.EURP250.PROD.OUTLOOK.COM ([fe80::65aa:deb0:a18e:d48d]) by AS8P250MB0744.EURP250.PROD.OUTLOOK.COM ([fe80::65aa:deb0:a18e:d48d%5]) with mapi id 15.20.7316.023; Wed, 28 Feb 2024 16:16:56 +0000 From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Wed, 28 Feb 2024 17:18:41 +0100 Message-ID: X-Mailer: git-send-email 2.40.1 In-Reply-To: References: X-TMN: [cNY3J560TkQ7HyoodwnSFNfjMwfu7vC+FKM3ZnCpgz4=] X-ClientProxiedBy: ZR2P278CA0067.CHEP278.PROD.OUTLOOK.COM (2603:10a6:910:52::14) To AS8P250MB0744.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:541::14) X-Microsoft-Original-Message-ID: <20240228161844.2187053-2-andreas.rheinhardt@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AS8P250MB0744:EE_|AS4P250MB0512:EE_ X-MS-Office365-Filtering-Correlation-Id: a9e550a8-bddc-4182-3564-08dc3878af18 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: mHjfsKf0PK0syY/WkMOibIzPv8RHhqwXstmoCKwRUFBXXuiMG1BFJt33yf8c8mqHeRFPaNcPnJWjGfg8064QxKTrzTGEKs76IQcH7Homwkm+nbI5LKcbnJhg4F+8iQzUSQMSylqFm6DRQ7cnKDmQnjF1eTHKeVv4NZgHPBIitMNmmzmy1ArQb2rO4tMtT0/kth8VQARMkKdkriif+MYptP5NnNwl9ZtJJKVxLT2BdPx7upAsILlw2HAhG21RfBnpttY91DA1cUHYLQh6bejmOVuIhAL5rVrwNRWCZwm7s8jEjJhBlUwC4aYsHv96ruExR6hDwvIDKQ6Ca9qrFCPNEs6/P1cGILuSEizluJuMP6w8WA4rmTsasC7V0CMvRj8kWCs7huRYOZi3bDEBrrXjO22nA0UANjJYmhB1bSWJVlqG9iEcJxqokQ9TRQ0OFzjlknKbB1EDg0IvqarreGys+Z8RZR5TraE43SwNZ943AFPu2NUmefKTBn9Iyzn0bW7YGh+7bBAoLq2twPfjMukYmKWRZsBDDwWUbaY6ryBvLG9qC/jUsSVoNQClOIRG8JF1DkGV/8kV+5hiZVx3YpzFErfFfOH+DfF+gbZT7kPtWIIiJEV/JTuXROhEVWx85jpp X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: yqQSosahyiyrmBmMxi482t01uACWESW/Cq0+csJm1b+UORE8NGwp9hi9Ur6Fa5hr4IHV0YmSbD2xfDO298o2E86f/KWTzJUobXR3y3nNSKpp+tPf83fONxldHk60CNop2BWIRMYT35094520YXD3pIR/f9VjPfqFuKmYX3OZ3xxjZ79EFsz4ooZiiCyeZGib8ml0K8+Vn8F2xlfanFuONttEZfrrQ3n0h2BlNYXs0ZJtxmf0ijn6nyTVgxI0z9pWISkjLBKQ825Uo2fp5effNRWC/cPcDZ+BemPgTB32LEq9TSCvXSYhzsKZe8/4gw+D75pE4u5groaVAmXnrFAz3cnHbOjlXYzG/d9OM/hbK0fohfZapHdQV75ZzQLd5+qQJ3VHoLb3BtQ+eKXyjqtFRV0sLOH4wxq2TdzuPjYNqzxjovgSHNiGO+lOzzvNKODzv0iNddcEdlUCJcVQdoVsulXTgMTWvaMV3K0XalkP1xKq85isItpDprd7ADxfDzT3wqdlbsy0qSqPl05M4rzhfzSn7DGeF8On2Ya0b2x2tfTWokgeHCyd6cyw+5T1sSTsoHmq7Z+rBdDgQqXOJ6JT7wMdjfSOvXin//FRJtX+x92L1HZh2BIMQrchJv1QCQohaB4tpSjR8n30HI5/v4jsQz02tomhKZ6DaqhJA2LrCiK0s37ISL4lAaD6xA1TEw8Wmk4E0UXBHvj4HVxwxdqToK3+p/yNFHgar0Q/TOQ/TZr58zz0JOb9twR2i1D51tj1kf1CZ/1jsq0tAiv/9jyHd1YVsfnH76Pq5AwH76mzBu5rnw0VwjJUC8JZlXDaun1g2a4VZRuIbDeqCzKo20Dgi7QAJPfYI1JJhVAaZ7ZoqMcoTy9S37mDCcB7AawYKOJZshpmTmvWl9GWmiNJe5L3xBxsASAd+TIpA3KyPFopUZxEjpEZhkWvhOefWNSQ1Dkx5Fxu17kDRlwC/2a+1dspdB/1OryS51Kb1p5zDEKIvwo0MFvPTlkDb8hQB81vu4m3FI+tqT0TDsAL38DLZUwHtAbM2N6Uo6Wq+5FFLVqRsUeCSrObs1OvBXw6+s3J/C3RCSjRr496yZWDrVoOmUFkJDCszeZpEfTB4TPOji3M4HuSNJ1JSw4LQVyaWrx68AqZg4IsbL6NJcWBlYdF5eNigTA1cQsR30bZI0R95UgR6ds6werX4X/lUicV9UPoKLNoGxKvY11YMojA47MW0nVK8anudV8NLqsBqgQ00hlUzeen0J0U7NknQDPH+Kiw7Drib6Nuj5vkuLpOMbGLpmmtlg== X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: a9e550a8-bddc-4182-3564-08dc3878af18 X-MS-Exchange-CrossTenant-AuthSource: AS8P250MB0744.EURP250.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Feb 2024 16:16:56.6345 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS4P250MB0512 Subject: [FFmpeg-devel] [PATCH 3/6] avcodec/vvc/vvc_intra: Move utils out of svq1enc.c X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: drEqefPpUGop Otherwise vvc_intra.o gets pulled in by the vvc_mc checkasm test and it in turn pulls vvc_ctu.o and then the rest of vvcdec and lavc in. Besides being bad size-wise this also has the downside that it pulls in avpriv_(cga|vga16)_font from libavutil which are marked as being imported from another library when building libavcodec as a DLL and this breaks checkasm because it links both lavc and lavu statically. Signed-off-by: Andreas Rheinhardt --- libavcodec/vvc/Makefile | 1 + libavcodec/vvc/vvc_intra.c | 187 -------------------------- libavcodec/vvc/vvc_intra_utils.c | 218 +++++++++++++++++++++++++++++++ 3 files changed, 219 insertions(+), 187 deletions(-) create mode 100644 libavcodec/vvc/vvc_intra_utils.c diff --git a/libavcodec/vvc/Makefile b/libavcodec/vvc/Makefile index dc484e5fb9..2a0055d494 100644 --- a/libavcodec/vvc/Makefile +++ b/libavcodec/vvc/Makefile @@ -9,6 +9,7 @@ OBJS-$(CONFIG_VVC_DECODER) += vvc/vvcdec.o \ vvc/vvc_filter.o \ vvc/vvc_inter.o \ vvc/vvc_intra.o \ + vvc/vvc_intra_utils.o \ vvc/vvc_itx_1d.o \ vvc/vvc_mvs.o \ vvc/vvc_ps.o \ diff --git a/libavcodec/vvc/vvc_intra.c b/libavcodec/vvc/vvc_intra.c index 58dd492478..6d976320f8 100644 --- a/libavcodec/vvc/vvc_intra.c +++ b/libavcodec/vvc/vvc_intra.c @@ -26,7 +26,6 @@ #include "vvc_inter.h" #include "vvc_intra.h" #include "vvc_itx_1d.h" -#include "vvc_mvs.h" static int is_cclm(enum IntraPredMode mode) { @@ -694,189 +693,3 @@ int ff_vvc_reconstruct(VVCLocalContext *lc, const int rs, const int rx, const in return ret; } -int ff_vvc_get_mip_size_id(const int w, const int h) -{ - if (w == 4 && h == 4) - return 0; - if ((w == 4 || h == 4) || (w == 8 && h == 8)) - return 1; - return 2; -} - -int ff_vvc_nscale_derive(const int w, const int h, const int mode) -{ - int side_size, nscale; - av_assert0(mode < INTRA_LT_CCLM && !(mode > INTRA_HORZ && mode < INTRA_VERT)); - if (mode == INTRA_PLANAR || mode == INTRA_DC || - mode == INTRA_HORZ || mode == INTRA_VERT) { - nscale = (av_log2(w) + av_log2(h) - 2) >> 2; - } else { - const int intra_pred_angle = ff_vvc_intra_pred_angle_derive(mode); - const int inv_angle = ff_vvc_intra_inv_angle_derive(intra_pred_angle); - if (mode >= INTRA_VERT) - side_size = h; - if (mode <= INTRA_HORZ) - side_size = w; - nscale = FFMIN(2, av_log2(side_size) - av_log2(3 * inv_angle - 2) + 8); - } - return nscale; -} - -int ff_vvc_need_pdpc(const int w, const int h, const uint8_t bdpcm_flag, const int mode, const int ref_idx) -{ - av_assert0(mode < INTRA_LT_CCLM); - if ((w >= 4 && h >= 4) && !ref_idx && !bdpcm_flag) { - int nscale; - if (mode == INTRA_PLANAR || mode == INTRA_DC || - mode == INTRA_HORZ || mode == INTRA_VERT) - return 1; - if (mode > INTRA_HORZ && mode < INTRA_VERT) - return 0; - nscale = ff_vvc_nscale_derive(w, h, mode); - return nscale >= 0; - - } - return 0; -} - -static const ReconstructedArea* get_reconstructed_area(const VVCLocalContext *lc, const int x, const int y, const int c_idx) -{ - const int ch_type = c_idx > 0; - for (int i = lc->num_ras[ch_type] - 1; i >= 0; i--) { - const ReconstructedArea* a = &lc->ras[ch_type][i]; - const int r = (a->x + a->w); - const int b = (a->y + a->h); - if (a->x <= x && x < r && a->y <= y && y < b) - return a; - - //it's too far away, no need check it; - if (x >= r && y >= b) - break; - } - return NULL; -} - -int ff_vvc_get_top_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx) -{ - const VVCFrameContext *fc = lc->fc; - const VVCSPS *sps = fc->ps.sps; - const int hs = sps->hshift[c_idx]; - const int vs = sps->vshift[c_idx]; - const int log2_ctb_size_v = sps->ctb_log2_size_y - vs; - const int end_of_ctb_x = ((lc->cu->x0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y; - const int y0b = av_mod_uintp2(y, log2_ctb_size_v); - const int max_x = FFMIN(fc->ps.pps->width, end_of_ctb_x) >> hs; - const ReconstructedArea *a; - int px = x; - - if (!y0b) { - if (!lc->ctb_up_flag) - return 0; - target_size = FFMIN(target_size, (lc->end_of_tiles_x >> hs) - x); - if (sps->r->sps_entropy_coding_sync_enabled_flag) - target_size = FFMIN(target_size, (end_of_ctb_x >> hs) - x); - return target_size; - } - - target_size = FFMAX(0, FFMIN(target_size, max_x - x)); - while (target_size > 0 && (a = get_reconstructed_area(lc, px, y - 1, c_idx))) { - const int sz = FFMIN(target_size, a->x + a->w - px); - px += sz; - target_size -= sz; - } - return px - x; -} - -int ff_vvc_get_left_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx) -{ - const VVCFrameContext *fc = lc->fc; - const VVCSPS *sps = fc->ps.sps; - const int hs = sps->hshift[c_idx]; - const int vs = sps->vshift[c_idx]; - const int log2_ctb_size_h = sps->ctb_log2_size_y - hs; - const int x0b = av_mod_uintp2(x, log2_ctb_size_h); - const int end_of_ctb_y = ((lc->cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y; - const int max_y = FFMIN(fc->ps.pps->height, end_of_ctb_y) >> vs; - const ReconstructedArea *a; - int py = y; - - if (!x0b && !lc->ctb_left_flag) - return 0; - - target_size = FFMAX(0, FFMIN(target_size, max_y - y)); - if (!x0b) - return target_size; - - while (target_size > 0 && (a = get_reconstructed_area(lc, x - 1, py, c_idx))) { - const int sz = FFMIN(target_size, a->y + a->h - py); - py += sz; - target_size -= sz; - } - return py - y; -} - -static int less(const void *a, const void *b) -{ - return *(const int*)a - *(const int*)b; -} - -int ff_vvc_ref_filter_flag_derive(const int mode) -{ - static const int modes[] = { -14, -12, -10, -6, INTRA_PLANAR, 2, 34, 66, 72, 76, 78, 80}; - return bsearch(&mode, modes, FF_ARRAY_ELEMS(modes), sizeof(int), less) != NULL; -} - -int ff_vvc_intra_pred_angle_derive(const int pred_mode) -{ - static const int angles[] = { - 0, 1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 23, 26, 29, - 32, 35, 39, 45, 51, 57, 64, 73, 86, 102, 128, 171, 256, 341, 512 - }; - int sign = 1, idx, intra_pred_angle; - if (pred_mode > INTRA_DIAG) { - idx = pred_mode - INTRA_VERT; - } else if (pred_mode > 0) { - idx = INTRA_HORZ - pred_mode; - } else { - idx = INTRA_HORZ - 2 - pred_mode; - } - if (idx < 0) { - idx = -idx; - sign = -1; - } - intra_pred_angle = sign * angles[idx]; - return intra_pred_angle; -} - -#define ROUND(f) (int)(f < 0 ? -(-f + 0.5) : (f + 0.5)) -int ff_vvc_intra_inv_angle_derive(const int intra_pred_angle) -{ - float inv_angle; - av_assert0(intra_pred_angle); - inv_angle = 32 * 512.0 / intra_pred_angle; - return ROUND(inv_angle); -} - -//8.4.5.2.7 Wide angle intra prediction mode mapping proces -int ff_vvc_wide_angle_mode_mapping(const CodingUnit *cu, - const int tb_width, const int tb_height, const int c_idx, int pred_mode_intra) -{ - int nw, nh, wh_ratio, min, max; - - if (cu->isp_split_type == ISP_NO_SPLIT || c_idx) { - nw = tb_width; - nh = tb_height; - } else { - nw = cu->cb_width; - nh = cu->cb_height; - } - wh_ratio = FFABS(ff_log2(nw) - ff_log2(nh)); - max = (wh_ratio > 1) ? (8 + 2 * wh_ratio) : 8; - min = (wh_ratio > 1) ? (60 - 2 * wh_ratio) : 60; - - if (nw > nh && pred_mode_intra >=2 && pred_mode_intra < max) - pred_mode_intra += 65; - else if (nh > nw && pred_mode_intra <= 66 && pred_mode_intra > min) - pred_mode_intra -= 67; - return pred_mode_intra; -} diff --git a/libavcodec/vvc/vvc_intra_utils.c b/libavcodec/vvc/vvc_intra_utils.c new file mode 100644 index 0000000000..7d34cff023 --- /dev/null +++ b/libavcodec/vvc/vvc_intra_utils.c @@ -0,0 +1,218 @@ +/* + * VVC intra prediction utils + * + * Copyright (C) 2021 Nuo Mi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "libavutil/avassert.h" +#include "libavutil/macros.h" +#include "libavutil/common.h" +#include "vvc_ctu.h" +#include "vvc_intra.h" +#include "vvc_ps.h" +#include "vvcdec.h" + +int ff_vvc_get_mip_size_id(const int w, const int h) +{ + if (w == 4 && h == 4) + return 0; + if ((w == 4 || h == 4) || (w == 8 && h == 8)) + return 1; + return 2; +} + +int ff_vvc_nscale_derive(const int w, const int h, const int mode) +{ + int side_size, nscale; + av_assert0(mode < INTRA_LT_CCLM && !(mode > INTRA_HORZ && mode < INTRA_VERT)); + if (mode == INTRA_PLANAR || mode == INTRA_DC || + mode == INTRA_HORZ || mode == INTRA_VERT) { + nscale = (av_log2(w) + av_log2(h) - 2) >> 2; + } else { + const int intra_pred_angle = ff_vvc_intra_pred_angle_derive(mode); + const int inv_angle = ff_vvc_intra_inv_angle_derive(intra_pred_angle); + if (mode >= INTRA_VERT) + side_size = h; + if (mode <= INTRA_HORZ) + side_size = w; + nscale = FFMIN(2, av_log2(side_size) - av_log2(3 * inv_angle - 2) + 8); + } + return nscale; +} + +int ff_vvc_need_pdpc(const int w, const int h, const uint8_t bdpcm_flag, const int mode, const int ref_idx) +{ + av_assert0(mode < INTRA_LT_CCLM); + if ((w >= 4 && h >= 4) && !ref_idx && !bdpcm_flag) { + int nscale; + if (mode == INTRA_PLANAR || mode == INTRA_DC || + mode == INTRA_HORZ || mode == INTRA_VERT) + return 1; + if (mode > INTRA_HORZ && mode < INTRA_VERT) + return 0; + nscale = ff_vvc_nscale_derive(w, h, mode); + return nscale >= 0; + + } + return 0; +} + +static const ReconstructedArea* get_reconstructed_area(const VVCLocalContext *lc, const int x, const int y, const int c_idx) +{ + const int ch_type = c_idx > 0; + for (int i = lc->num_ras[ch_type] - 1; i >= 0; i--) { + const ReconstructedArea* a = &lc->ras[ch_type][i]; + const int r = (a->x + a->w); + const int b = (a->y + a->h); + if (a->x <= x && x < r && a->y <= y && y < b) + return a; + + //it's too far away, no need check it; + if (x >= r && y >= b) + break; + } + return NULL; +} + +int ff_vvc_get_top_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx) +{ + const VVCFrameContext *fc = lc->fc; + const VVCSPS *sps = fc->ps.sps; + const int hs = sps->hshift[c_idx]; + const int vs = sps->vshift[c_idx]; + const int log2_ctb_size_v = sps->ctb_log2_size_y - vs; + const int end_of_ctb_x = ((lc->cu->x0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y; + const int y0b = av_mod_uintp2(y, log2_ctb_size_v); + const int max_x = FFMIN(fc->ps.pps->width, end_of_ctb_x) >> hs; + const ReconstructedArea *a; + int px = x; + + if (!y0b) { + if (!lc->ctb_up_flag) + return 0; + target_size = FFMIN(target_size, (lc->end_of_tiles_x >> hs) - x); + if (sps->r->sps_entropy_coding_sync_enabled_flag) + target_size = FFMIN(target_size, (end_of_ctb_x >> hs) - x); + return target_size; + } + + target_size = FFMAX(0, FFMIN(target_size, max_x - x)); + while (target_size > 0 && (a = get_reconstructed_area(lc, px, y - 1, c_idx))) { + const int sz = FFMIN(target_size, a->x + a->w - px); + px += sz; + target_size -= sz; + } + return px - x; +} + +int ff_vvc_get_left_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx) +{ + const VVCFrameContext *fc = lc->fc; + const VVCSPS *sps = fc->ps.sps; + const int hs = sps->hshift[c_idx]; + const int vs = sps->vshift[c_idx]; + const int log2_ctb_size_h = sps->ctb_log2_size_y - hs; + const int x0b = av_mod_uintp2(x, log2_ctb_size_h); + const int end_of_ctb_y = ((lc->cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y; + const int max_y = FFMIN(fc->ps.pps->height, end_of_ctb_y) >> vs; + const ReconstructedArea *a; + int py = y; + + if (!x0b && !lc->ctb_left_flag) + return 0; + + target_size = FFMAX(0, FFMIN(target_size, max_y - y)); + if (!x0b) + return target_size; + + while (target_size > 0 && (a = get_reconstructed_area(lc, x - 1, py, c_idx))) { + const int sz = FFMIN(target_size, a->y + a->h - py); + py += sz; + target_size -= sz; + } + return py - y; +} + +static int less(const void *a, const void *b) +{ + return *(const int*)a - *(const int*)b; +} + +int ff_vvc_ref_filter_flag_derive(const int mode) +{ + static const int modes[] = { -14, -12, -10, -6, INTRA_PLANAR, 2, 34, 66, 72, 76, 78, 80}; + return bsearch(&mode, modes, FF_ARRAY_ELEMS(modes), sizeof(int), less) != NULL; +} + +int ff_vvc_intra_pred_angle_derive(const int pred_mode) +{ + static const int angles[] = { + 0, 1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 23, 26, 29, + 32, 35, 39, 45, 51, 57, 64, 73, 86, 102, 128, 171, 256, 341, 512 + }; + int sign = 1, idx, intra_pred_angle; + if (pred_mode > INTRA_DIAG) { + idx = pred_mode - INTRA_VERT; + } else if (pred_mode > 0) { + idx = INTRA_HORZ - pred_mode; + } else { + idx = INTRA_HORZ - 2 - pred_mode; + } + if (idx < 0) { + idx = -idx; + sign = -1; + } + intra_pred_angle = sign * angles[idx]; + return intra_pred_angle; +} + +#define ROUND(f) (int)(f < 0 ? -(-f + 0.5) : (f + 0.5)) +int ff_vvc_intra_inv_angle_derive(const int intra_pred_angle) +{ + float inv_angle; + av_assert0(intra_pred_angle); + inv_angle = 32 * 512.0 / intra_pred_angle; + return ROUND(inv_angle); +} + +//8.4.5.2.7 Wide angle intra prediction mode mapping proces +int ff_vvc_wide_angle_mode_mapping(const CodingUnit *cu, + const int tb_width, const int tb_height, const int c_idx, int pred_mode_intra) +{ + int nw, nh, wh_ratio, min, max; + + if (cu->isp_split_type == ISP_NO_SPLIT || c_idx) { + nw = tb_width; + nh = tb_height; + } else { + nw = cu->cb_width; + nh = cu->cb_height; + } + wh_ratio = FFABS(ff_log2(nw) - ff_log2(nh)); + max = (wh_ratio > 1) ? (8 + 2 * wh_ratio) : 8; + min = (wh_ratio > 1) ? (60 - 2 * wh_ratio) : 60; + + if (nw > nh && pred_mode_intra >=2 && pred_mode_intra < max) + pred_mode_intra += 65; + else if (nh > nw && pred_mode_intra <= 66 && pred_mode_intra > min) + pred_mode_intra -= 67; + return pred_mode_intra; +}