FFmpeg
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 
33 int 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 
42 int 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 
61 int 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 ||
67  mode == INTRA_HORZ || mode == INTRA_VERT)
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 
78 static 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 
95 int 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 
126 int 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 
154 static 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 
165 int 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 
187 #define ROUND(f) (int)(f < 0 ? -(-f + 0.5) : (f + 0.5))
188 int ff_vvc_intra_inv_angle_derive(const int intra_pred_angle)
189 {
190  float inv_angle;
191  av_assert0(intra_pred_angle);
192  inv_angle = 32 * 512.0 / intra_pred_angle;
193  return ROUND(inv_angle);
194 }
195 
196 //8.4.5.2.7 Wide angle intra prediction mode mapping proces
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 }
VVCSPS
Definition: ps.h:58
ff_vvc_get_left_available
int ff_vvc_get_left_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
Definition: intra_utils.c:126
r
const char * r
Definition: vf_curves.c:127
CodingUnit
Definition: hevcdec.h:288
ff_vvc_ref_filter_flag_derive
int ff_vvc_ref_filter_flag_derive(const int mode)
Definition: intra_utils.c:159
w
uint8_t w
Definition: llviddspenc.c:38
ff_vvc_intra_inv_angle_derive
int ff_vvc_intra_inv_angle_derive(const int intra_pred_angle)
Definition: intra_utils.c:188
INTRA_DC
@ INTRA_DC
Definition: hevcdec.h:124
b
#define b
Definition: input.c:41
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:472
ReconstructedArea
Definition: ctu.h:340
max
#define max(a, b)
Definition: cuda_runtime.h:33
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
ff_vvc_nscale_derive
int ff_vvc_nscale_derive(const int w, const int h, const int mode)
Definition: intra_utils.c:42
VVCLocalContext::ras
ReconstructedArea ras[2][MAX_PARTS_IN_CTU]
Definition: ctu.h:419
ROUND
#define ROUND(f)
Definition: intra_utils.c:187
ps.h
VVCLocalContext::fc
VVCFrameContext * fc
Definition: ctu.h:435
macros.h
ff_vvc_get_top_available
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
less
static int less(const void *a, const void *b)
Definition: intra_utils.c:154
ff_vvc_get_mip_size_id
int ff_vvc_get_mip_size_id(const int w, const int h)
Definition: intra_utils.c:33
CodingUnit::cb_width
int cb_width
Definition: ctu.h:284
avassert.h
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
VVCLocalContext::num_ras
int num_ras[2]
Definition: ctu.h:420
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:74
NULL
#define NULL
Definition: coverity.c:32
VVCLocalContext
Definition: ctu.h:373
INTRA_HORZ
@ INTRA_HORZ
Definition: ctu.h:233
ff_log2
#define ff_log2
Definition: intmath.h:51
INTRA_PLANAR
@ INTRA_PLANAR
Definition: hevcdec.h:123
intra.h
VVCLocalContext::end_of_tiles_x
int end_of_tiles_x
Definition: ctu.h:378
VVCLocalContext::ctb_up_flag
uint8_t ctb_up_flag
Definition: ctu.h:375
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
av_zero_extend
#define av_zero_extend
Definition: common.h:151
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ISP_NO_SPLIT
@ ISP_NO_SPLIT
Definition: ctu.h:119
modes
static const SiprModeParam modes[MODE_COUNT]
Definition: sipr.c:70
common.h
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
CodingUnit::x0
int x0
Definition: ctu.h:282
VVCLocalContext::cu
CodingUnit * cu
Definition: ctu.h:418
INTRA_VERT
@ INTRA_VERT
Definition: ctu.h:235
get_reconstructed_area
static const ReconstructedArea * get_reconstructed_area(const VVCLocalContext *lc, const int x, const int y, const int c_idx)
Definition: intra_utils.c:78
sps
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
Definition: cbs_h264_syntax_template.c:260
INTRA_DIAG
@ INTRA_DIAG
Definition: ctu.h:234
CodingUnit::cb_height
int cb_height
Definition: ctu.h:285
ff_vvc_intra_pred_angle_derive
int ff_vvc_intra_pred_angle_derive(const int pred_mode)
Definition: intra_utils.c:165
mode
mode
Definition: ebur128.h:83
ff_vvc_wide_angle_mode_mapping
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)
Definition: intra_utils.c:197
CodingUnit::isp_split_type
enum IspType isp_split_type
IntraSubPartitionsSplitType.
Definition: ctu.h:308
VVCFrameContext
Definition: dec.h:117
ff_vvc_need_pdpc
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
h
h
Definition: vp9dsp_template.c:2070
ctu.h
INTRA_LT_CCLM
@ INTRA_LT_CCLM
Definition: ctu.h:237
av_log2
int av_log2(unsigned v)
Definition: intmath.c:26
VVCLocalContext::ctb_left_flag
uint8_t ctb_left_flag
Definition: ctu.h:374
CodingUnit::y0
int y0
Definition: ctu.h:283
dec.h
min
float min
Definition: vorbis_enc_data.h:429