FFmpeg
Loading...
Searching...
No Matches
intra_utils.c
Go to the documentation of this file.
1/*
2 * VVC intra prediction utils
3 *
4 * Copyright (C) 2021 Nuo Mi
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <stdint.h>
24#include <stdlib.h>
25#include "libavutil/avassert.h"
26#include "libavutil/macros.h"
27#include "libavutil/common.h"
28#include "ctu.h"
29#include "intra.h"
30#include "ps.h"
31#include "dec.h"
32
33int ff_vvc_get_mip_size_id(const int w, const int h)
34{
35 if (w == 4 && h == 4)
36 return 0;
37 if ((w == 4 || h == 4) || (w == 8 && h == 8))
38 return 1;
39 return 2;
40}
41
42int ff_vvc_nscale_derive(const int w, const int h, const int mode)
43{
44 int side_size, nscale;
46 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
47 mode == INTRA_HORZ || mode == INTRA_VERT) {
48 nscale = (av_log2(w) + av_log2(h) - 2) >> 2;
49 } else {
50 const int intra_pred_angle = ff_vvc_intra_pred_angle_derive(mode);
51 const int inv_angle = ff_vvc_intra_inv_angle_derive(intra_pred_angle);
52 if (mode >= INTRA_VERT)
53 side_size = h;
54 if (mode <= INTRA_HORZ)
55 side_size = w;
56 nscale = FFMIN(2, av_log2(side_size) - av_log2(3 * inv_angle - 2) + 8);
57 }
58 return nscale;
59}
60
61int ff_vvc_need_pdpc(const int w, const int h, const uint8_t bdpcm_flag, const int mode, const int ref_idx)
62{
64 if ((w >= 4 && h >= 4) && !ref_idx && !bdpcm_flag) {
65 int nscale;
66 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
68 return 1;
69 if (mode > INTRA_HORZ && mode < INTRA_VERT)
70 return 0;
71 nscale = ff_vvc_nscale_derive(w, h, mode);
72 return nscale >= 0;
73
74 }
75 return 0;
76}
77
78static const ReconstructedArea* get_reconstructed_area(const VVCLocalContext *lc, const int x, const int y, const int c_idx)
79{
80 const int ch_type = c_idx > 0;
81 for (int i = lc->num_ras[ch_type] - 1; i >= 0; i--) {
82 const ReconstructedArea* a = &lc->ras[ch_type][i];
83 const int r = (a->x + a->w);
84 const int b = (a->y + a->h);
85 if (a->x <= x && x < r && a->y <= y && y < b)
86 return a;
87
88 //it's too far away, no need check it;
89 if (x >= r && y >= b)
90 break;
91 }
92 return NULL;
93}
94
95int ff_vvc_get_top_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
96{
97 const VVCFrameContext *fc = lc->fc;
98 const VVCSPS *sps = fc->ps.sps;
99 const int hs = sps->hshift[c_idx];
100 const int vs = sps->vshift[c_idx];
101 const int log2_ctb_size_v = sps->ctb_log2_size_y - vs;
102 const int end_of_ctb_x = ((lc->cu->x0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
103 const int y0b = av_zero_extend(y, log2_ctb_size_v);
104 const int max_x = FFMIN(fc->ps.pps->width, end_of_ctb_x) >> hs;
105 const ReconstructedArea *a;
106 int px = x;
107
108 if (!y0b) {
109 if (!lc->ctb_up_flag)
110 return 0;
111 target_size = FFMIN(target_size, (lc->end_of_tiles_x >> hs) - x);
112 if (sps->r->sps_entropy_coding_sync_enabled_flag)
113 target_size = FFMIN(target_size, (end_of_ctb_x >> hs) - x);
114 return target_size;
115 }
116
117 target_size = FFMAX(0, FFMIN(target_size, max_x - x));
118 while (target_size > 0 && (a = get_reconstructed_area(lc, px, y - 1, c_idx))) {
119 const int sz = FFMIN(target_size, a->x + a->w - px);
120 px += sz;
121 target_size -= sz;
122 }
123 return px - x;
124}
125
126int ff_vvc_get_left_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
127{
128 const VVCFrameContext *fc = lc->fc;
129 const VVCSPS *sps = fc->ps.sps;
130 const int hs = sps->hshift[c_idx];
131 const int vs = sps->vshift[c_idx];
132 const int log2_ctb_size_h = sps->ctb_log2_size_y - hs;
133 const int x0b = av_zero_extend(x, log2_ctb_size_h);
134 const int end_of_ctb_y = ((lc->cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
135 const int max_y = FFMIN(fc->ps.pps->height, end_of_ctb_y) >> vs;
136 const ReconstructedArea *a;
137 int py = y;
138
139 if (!x0b && !lc->ctb_left_flag)
140 return 0;
141
142 target_size = FFMAX(0, FFMIN(target_size, max_y - y));
143 if (!x0b)
144 return target_size;
145
146 while (target_size > 0 && (a = get_reconstructed_area(lc, x - 1, py, c_idx))) {
147 const int sz = FFMIN(target_size, a->y + a->h - py);
148 py += sz;
149 target_size -= sz;
150 }
151 return py - y;
152}
153
154static int less(const void *a, const void *b)
155{
156 return *(const int*)a - *(const int*)b;
157}
158
160{
161 static const int modes[] = { -14, -12, -10, -6, INTRA_PLANAR, 2, 34, 66, 72, 76, 78, 80};
162 return bsearch(&mode, modes, FF_ARRAY_ELEMS(modes), sizeof(int), less) != NULL;
163}
164
165int ff_vvc_intra_pred_angle_derive(const int pred_mode)
166{
167 static const int angles[] = {
168 0, 1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 23, 26, 29,
169 32, 35, 39, 45, 51, 57, 64, 73, 86, 102, 128, 171, 256, 341, 512
170 };
171 int sign = 1, idx, intra_pred_angle;
172 if (pred_mode > INTRA_DIAG) {
173 idx = pred_mode - INTRA_VERT;
174 } else if (pred_mode > 0) {
175 idx = INTRA_HORZ - pred_mode;
176 } else {
177 idx = INTRA_HORZ - 2 - pred_mode;
178 }
179 if (idx < 0) {
180 idx = -idx;
181 sign = -1;
182 }
183 intra_pred_angle = sign * angles[idx];
184 return intra_pred_angle;
185}
186
187int ff_vvc_intra_inv_angle_derive(const int intra_pred_angle)
188{
189 av_assert2(intra_pred_angle != 0);
190 if (intra_pred_angle > 0)
191 return ROUNDED_DIV(32*512, intra_pred_angle);
192 else
193 return -ROUNDED_DIV(32*512, -intra_pred_angle);
194}
195
196//8.4.5.2.7 Wide angle intra prediction mode mapping process
198 const int tb_width, const int tb_height, const int c_idx, int pred_mode_intra)
199{
200 int nw, nh, wh_ratio, min, max;
201
202 if (cu->isp_split_type == ISP_NO_SPLIT || c_idx) {
203 nw = tb_width;
204 nh = tb_height;
205 } else {
206 nw = cu->cb_width;
207 nh = cu->cb_height;
208 }
209 wh_ratio = FFABS(ff_log2(nw) - ff_log2(nh));
210 max = (wh_ratio > 1) ? (8 + 2 * wh_ratio) : 8;
211 min = (wh_ratio > 1) ? (60 - 2 * wh_ratio) : 60;
212
213 if (nw > nh && pred_mode_intra >=2 && pred_mode_intra < max)
214 pred_mode_intra += 65;
215 else if (nh > nw && pred_mode_intra <= 66 && pred_mode_intra > min)
216 pred_mode_intra -= 67;
217 return pred_mode_intra;
218}
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition avassert.h:68
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
static int FUNC sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
common internal and external API header
#define ROUNDED_DIV(a, b)
Definition common.h:58
#define av_zero_extend
Definition common.h:151
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition common.h:74
#define NULL
Definition coverity.c:32
static int less(const void *a, const void *b)
Definition ctu.c:679
@ ISP_NO_SPLIT
Definition ctu.h:122
@ INTRA_HORZ
Definition ctu.h:237
@ INTRA_DIAG
Definition ctu.h:238
@ INTRA_LT_CCLM
Definition ctu.h:241
@ INTRA_VERT
Definition ctu.h:239
#define min(a, b)
#define max(a, b)
static const uint16_t fc[]
Definition dcaenc.h:43
int a
@ INTRA_DC
Definition hevcdec.h:126
@ INTRA_PLANAR
Definition hevcdec.h:125
#define r
Definition input.c:42
#define b
Definition input.c:43
#define av_log2
Definition intmath.h:84
#define ff_log2
Definition intmath.h:51
int ff_vvc_need_pdpc(const int w, const int h, const uint8_t bdpcm_flag, const int mode, const int ref_idx)
Definition intra_utils.c:61
int ff_vvc_intra_inv_angle_derive(const int intra_pred_angle)
int ff_vvc_get_mip_size_id(const int w, const int h)
Definition intra_utils.c:33
int ff_vvc_intra_pred_angle_derive(const int pred_mode)
int ff_vvc_get_left_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
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 ff_vvc_nscale_derive(const int w, const int h, const int mode)
Definition intra_utils.c:42
static int less(const void *a, const void *b)
int ff_vvc_get_top_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
Definition intra_utils.c:95
static const ReconstructedArea * get_reconstructed_area(const VVCLocalContext *lc, const int x, const int y, const int c_idx)
Definition intra_utils.c:78
int ff_vvc_ref_filter_flag_derive(const int mode)
uint8_t w
Definition llvidencdsp.c:39
Utility Preprocessor macros.
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
#define FF_ARRAY_ELEMS(a)
static const SiprModeParam modes[MODE_COUNT]
Definition sipr.c:70
enum IspType isp_split_type
IntraSubPartitionsSplitType.
Definition ctu.h:317
int cb_width
Definition ctu.h:293
int cb_height
Definition ctu.h:294
int x0
Definition ctu.h:291
int y0
Definition ctu.h:292
CodingUnit * cu
Definition ctu.h:425
uint8_t ctb_up_flag
Definition ctu.h:388
VVCFrameContext * fc
Definition ctu.h:421
ReconstructedArea ras[2][MAX_PARTS_IN_CTU]
Definition ctu.h:438
int end_of_tiles_x
Definition ctu.h:391
uint8_t ctb_left_flag
Definition ctu.h:387
int num_ras[2]
Definition ctu.h:437
Definition ps.h:58
Definition swscale.c:71