FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/intra_utils.c
Date: 2024-05-03 15:42:48
Exec Total Coverage
Lines: 117 118 99.2%
Functions: 11 11 100.0%
Branches: 106 116 91.4%

Line Branch Exec Source
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 75239 int ff_vvc_get_mip_size_id(const int w, const int h)
34 {
35
4/4
✓ Branch 0 taken 18437 times.
✓ Branch 1 taken 56802 times.
✓ Branch 2 taken 7867 times.
✓ Branch 3 taken 10570 times.
75239 if (w == 4 && h == 4)
36 7867 return 0;
37
8/8
✓ Branch 0 taken 56802 times.
✓ Branch 1 taken 10570 times.
✓ Branch 2 taken 40944 times.
✓ Branch 3 taken 15858 times.
✓ Branch 4 taken 13284 times.
✓ Branch 5 taken 27660 times.
✓ Branch 6 taken 7645 times.
✓ Branch 7 taken 5639 times.
67372 if ((w == 4 || h == 4) || (w == 8 && h == 8))
38 34073 return 1;
39 33299 return 2;
40 }
41
42 209933 int ff_vvc_nscale_derive(const int w, const int h, const int mode)
43 {
44 int side_size, nscale;
45
4/6
✓ Branch 0 taken 209933 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 106990 times.
✓ Branch 3 taken 102943 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 106990 times.
209933 av_assert0(mode < INTRA_LT_CCLM && !(mode > INTRA_HORZ && mode < INTRA_VERT));
46
3/6
✓ Branch 0 taken 209933 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 209933 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 209933 times.
✗ Branch 5 not taken.
209933 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
47
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 209933 times.
209933 mode == INTRA_HORZ || mode == INTRA_VERT) {
48 nscale = (av_log2(w) + av_log2(h) - 2) >> 2;
49 } else {
50 209933 const int intra_pred_angle = ff_vvc_intra_pred_angle_derive(mode);
51 209933 const int inv_angle = ff_vvc_intra_inv_angle_derive(intra_pred_angle);
52
2/2
✓ Branch 0 taken 106990 times.
✓ Branch 1 taken 102943 times.
209933 if (mode >= INTRA_VERT)
53 106990 side_size = h;
54
2/2
✓ Branch 0 taken 102943 times.
✓ Branch 1 taken 106990 times.
209933 if (mode <= INTRA_HORZ)
55 102943 side_size = w;
56 209933 nscale = FFMIN(2, av_log2(side_size) - av_log2(3 * inv_angle - 2) + 8);
57 }
58 209933 return nscale;
59 }
60
61 732607 int ff_vvc_need_pdpc(const int w, const int h, const uint8_t bdpcm_flag, const int mode, const int ref_idx)
62 {
63
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 732607 times.
732607 av_assert0(mode < INTRA_LT_CCLM);
64
7/8
✓ Branch 0 taken 732607 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 665895 times.
✓ Branch 3 taken 66712 times.
✓ Branch 4 taken 643577 times.
✓ Branch 5 taken 22318 times.
✓ Branch 6 taken 643537 times.
✓ Branch 7 taken 40 times.
732607 if ((w >= 4 && h >= 4) && !ref_idx && !bdpcm_flag) {
65 int nscale;
66
6/6
✓ Branch 0 taken 377046 times.
✓ Branch 1 taken 266491 times.
✓ Branch 2 taken 325622 times.
✓ Branch 3 taken 51424 times.
✓ Branch 4 taken 298707 times.
✓ Branch 5 taken 26915 times.
643537 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
67
2/2
✓ Branch 0 taken 31184 times.
✓ Branch 1 taken 267523 times.
298707 mode == INTRA_HORZ || mode == INTRA_VERT)
68 376014 return 1;
69
4/4
✓ Branch 0 taken 189985 times.
✓ Branch 1 taken 77538 times.
✓ Branch 2 taken 113215 times.
✓ Branch 3 taken 76770 times.
267523 if (mode > INTRA_HORZ && mode < INTRA_VERT)
70 113215 return 0;
71 154308 nscale = ff_vvc_nscale_derive(w, h, mode);
72 154308 return nscale >= 0;
73
74 }
75 89070 return 0;
76 }
77
78 2573867 static const ReconstructedArea* get_reconstructed_area(const VVCLocalContext *lc, const int x, const int y, const int c_idx)
79 {
80 2573867 const int ch_type = c_idx > 0;
81
2/2
✓ Branch 0 taken 24663213 times.
✓ Branch 1 taken 45319 times.
24708532 for (int i = lc->num_ras[ch_type] - 1; i >= 0; i--) {
82 24663213 const ReconstructedArea* a = &lc->ras[ch_type][i];
83 24663213 const int r = (a->x + a->w);
84 24663213 const int b = (a->y + a->h);
85
8/8
✓ Branch 0 taken 13342939 times.
✓ Branch 1 taken 11320274 times.
✓ Branch 2 taken 4389699 times.
✓ Branch 3 taken 8953240 times.
✓ Branch 4 taken 2867741 times.
✓ Branch 5 taken 1521958 times.
✓ Branch 6 taken 2042384 times.
✓ Branch 7 taken 825357 times.
24663213 if (a->x <= x && x < r && a->y <= y && y < b)
86 2042384 return a;
87
88 //it's too far away, no need check it;
89
4/4
✓ Branch 0 taken 8953240 times.
✓ Branch 1 taken 13667589 times.
✓ Branch 2 taken 486164 times.
✓ Branch 3 taken 8467076 times.
22620829 if (x >= r && y >= b)
90 486164 break;
91 }
92 531483 return NULL;
93 }
94
95 814723 int ff_vvc_get_top_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
96 {
97 814723 const VVCFrameContext *fc = lc->fc;
98 814723 const VVCSPS *sps = fc->ps.sps;
99 814723 const int hs = sps->hshift[c_idx];
100 814723 const int vs = sps->vshift[c_idx];
101 814723 const int log2_ctb_size_v = sps->ctb_log2_size_y - vs;
102 814723 const int end_of_ctb_x = ((lc->cu->x0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
103 814723 const int y0b = av_mod_uintp2(y, log2_ctb_size_v);
104 814723 const int max_x = FFMIN(fc->ps.pps->width, end_of_ctb_x) >> hs;
105 const ReconstructedArea *a;
106 814723 int px = x;
107
108
2/2
✓ Branch 0 taken 86007 times.
✓ Branch 1 taken 728716 times.
814723 if (!y0b) {
109
2/2
✓ Branch 0 taken 19192 times.
✓ Branch 1 taken 66815 times.
86007 if (!lc->ctb_up_flag)
110 19192 return 0;
111 66815 target_size = FFMIN(target_size, (lc->end_of_tiles_x >> hs) - x);
112
2/2
✓ Branch 0 taken 4029 times.
✓ Branch 1 taken 62786 times.
66815 if (sps->r->sps_entropy_coding_sync_enabled_flag)
113 4029 target_size = FFMIN(target_size, (end_of_ctb_x >> hs) - x);
114 66815 return target_size;
115 }
116
117 728716 target_size = FFMAX(0, FFMIN(target_size, max_x - x));
118
4/4
✓ Branch 0 taken 1292987 times.
✓ Branch 1 taken 461471 times.
✓ Branch 3 taken 1025742 times.
✓ Branch 4 taken 267245 times.
1754458 while (target_size > 0 && (a = get_reconstructed_area(lc, px, y - 1, c_idx))) {
119 1025742 const int sz = FFMIN(target_size, a->x + a->w - px);
120 1025742 px += sz;
121 1025742 target_size -= sz;
122 }
123 728716 return px - x;
124 }
125
126 813253 int ff_vvc_get_left_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
127 {
128 813253 const VVCFrameContext *fc = lc->fc;
129 813253 const VVCSPS *sps = fc->ps.sps;
130 813253 const int hs = sps->hshift[c_idx];
131 813253 const int vs = sps->vshift[c_idx];
132 813253 const int log2_ctb_size_h = sps->ctb_log2_size_y - hs;
133 813253 const int x0b = av_mod_uintp2(x, log2_ctb_size_h);
134 813253 const int end_of_ctb_y = ((lc->cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
135 813253 const int max_y = FFMIN(fc->ps.pps->height, end_of_ctb_y) >> vs;
136 const ReconstructedArea *a;
137 813253 int py = y;
138
139
4/4
✓ Branch 0 taken 113308 times.
✓ Branch 1 taken 699945 times.
✓ Branch 2 taken 19154 times.
✓ Branch 3 taken 94154 times.
813253 if (!x0b && !lc->ctb_left_flag)
140 19154 return 0;
141
142 794099 target_size = FFMAX(0, FFMIN(target_size, max_y - y));
143
2/2
✓ Branch 0 taken 94154 times.
✓ Branch 1 taken 699945 times.
794099 if (!x0b)
144 94154 return target_size;
145
146
4/4
✓ Branch 0 taken 1280880 times.
✓ Branch 1 taken 435707 times.
✓ Branch 3 taken 1016642 times.
✓ Branch 4 taken 264238 times.
1716587 while (target_size > 0 && (a = get_reconstructed_area(lc, x - 1, py, c_idx))) {
147 1016642 const int sz = FFMIN(target_size, a->y + a->h - py);
148 1016642 py += sz;
149 1016642 target_size -= sz;
150 }
151 699945 return py - y;
152 }
153
154 2459536 static int less(const void *a, const void *b)
155 {
156 2459536 return *(const int*)a - *(const int*)b;
157 }
158
159 657368 int ff_vvc_ref_filter_flag_derive(const int mode)
160 {
161 static const int modes[] = { -14, -12, -10, -6, INTRA_PLANAR, 2, 34, 66, 72, 76, 78, 80};
162 657368 return bsearch(&mode, modes, FF_ARRAY_ELEMS(modes), sizeof(int), less) != NULL;
163 }
164
165 740359 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 740359 int sign = 1, idx, intra_pred_angle;
172
2/2
✓ Branch 0 taken 372390 times.
✓ Branch 1 taken 367969 times.
740359 if (pred_mode > INTRA_DIAG) {
173 372390 idx = pred_mode - INTRA_VERT;
174
2/2
✓ Branch 0 taken 333451 times.
✓ Branch 1 taken 34518 times.
367969 } else if (pred_mode > 0) {
175 333451 idx = INTRA_HORZ - pred_mode;
176 } else {
177 34518 idx = INTRA_HORZ - 2 - pred_mode;
178 }
179
2/2
✓ Branch 0 taken 282994 times.
✓ Branch 1 taken 457365 times.
740359 if (idx < 0) {
180 282994 idx = -idx;
181 282994 sign = -1;
182 }
183 740359 intra_pred_angle = sign * angles[idx];
184 740359 return intra_pred_angle;
185 }
186
187 #define ROUND(f) (int)(f < 0 ? -(-f + 0.5) : (f + 0.5))
188 530771 int ff_vvc_intra_inv_angle_derive(const int intra_pred_angle)
189 {
190 float inv_angle;
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 530771 times.
530771 av_assert0(intra_pred_angle);
192 530771 inv_angle = 32 * 512.0 / intra_pred_angle;
193
2/2
✓ Branch 0 taken 141497 times.
✓ Branch 1 taken 389274 times.
530771 return ROUND(inv_angle);
194 }
195
196 //8.4.5.2.7 Wide angle intra prediction mode mapping proces
197 852570 int ff_vvc_wide_angle_mode_mapping(const CodingUnit *cu,
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
4/4
✓ Branch 0 taken 180698 times.
✓ Branch 1 taken 671872 times.
✓ Branch 2 taken 7660 times.
✓ Branch 3 taken 173038 times.
852570 if (cu->isp_split_type == ISP_NO_SPLIT || c_idx) {
203 679532 nw = tb_width;
204 679532 nh = tb_height;
205 } else {
206 173038 nw = cu->cb_width;
207 173038 nh = cu->cb_height;
208 }
209 852570 wh_ratio = FFABS(ff_log2(nw) - ff_log2(nh));
210
2/2
✓ Branch 0 taken 210441 times.
✓ Branch 1 taken 642129 times.
852570 max = (wh_ratio > 1) ? (8 + 2 * wh_ratio) : 8;
211
2/2
✓ Branch 0 taken 210441 times.
✓ Branch 1 taken 642129 times.
852570 min = (wh_ratio > 1) ? (60 - 2 * wh_ratio) : 60;
212
213
6/6
✓ Branch 0 taken 358003 times.
✓ Branch 1 taken 494567 times.
✓ Branch 2 taken 189043 times.
✓ Branch 3 taken 168960 times.
✓ Branch 4 taken 31384 times.
✓ Branch 5 taken 157659 times.
852570 if (nw > nh && pred_mode_intra >=2 && pred_mode_intra < max)
214 31384 pred_mode_intra += 65;
215
5/6
✓ Branch 0 taken 231229 times.
✓ Branch 1 taken 589957 times.
✓ Branch 2 taken 231229 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10949 times.
✓ Branch 5 taken 220280 times.
821186 else if (nh > nw && pred_mode_intra <= 66 && pred_mode_intra > min)
216 10949 pred_mode_intra -= 67;
217 852570 return pred_mode_intra;
218 }
219