FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/intra_utils.c
Date: 2026-11-01 05:14:56
Exec Total Coverage
Lines: 117 118 99.2%
Functions: 11 11 100.0%
Branches: 105 114 92.1%

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 116963 int ff_vvc_get_mip_size_id(const int w, const int h)
34 {
35
4/4
✓ Branch 0 taken 33923 times.
✓ Branch 1 taken 83040 times.
✓ Branch 2 taken 16804 times.
✓ Branch 3 taken 17119 times.
116963 if (w == 4 && h == 4)
36 16804 return 0;
37
8/8
✓ Branch 0 taken 83040 times.
✓ Branch 1 taken 17119 times.
✓ Branch 2 taken 57961 times.
✓ Branch 3 taken 25079 times.
✓ Branch 4 taken 19068 times.
✓ Branch 5 taken 38893 times.
✓ Branch 6 taken 11121 times.
✓ Branch 7 taken 7947 times.
100159 if ((w == 4 || h == 4) || (w == 8 && h == 8))
38 53319 return 1;
39 46840 return 2;
40 }
41
42 328527 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 328527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 164647 times.
✓ Branch 3 taken 163880 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 164647 times.
328527 av_assert0(mode < INTRA_LT_CCLM && !(mode > INTRA_HORZ && mode < INTRA_VERT));
46
3/6
✓ Branch 0 taken 328527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 328527 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 328527 times.
✗ Branch 5 not taken.
328527 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
47
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 328527 times.
328527 mode == INTRA_HORZ || mode == INTRA_VERT) {
48 ✗ nscale = (av_log2(w) + av_log2(h) - 2) >> 2;
49 } else {
50 328527 const int intra_pred_angle = ff_vvc_intra_pred_angle_derive(mode);
51 328527 const int inv_angle = ff_vvc_intra_inv_angle_derive(intra_pred_angle);
52
2/2
✓ Branch 0 taken 164647 times.
✓ Branch 1 taken 163880 times.
328527 if (mode >= INTRA_VERT)
53 164647 side_size = h;
54
2/2
✓ Branch 0 taken 163880 times.
✓ Branch 1 taken 164647 times.
328527 if (mode <= INTRA_HORZ)
55 163880 side_size = w;
56 328527 nscale = FFMIN(2, av_log2(side_size) - av_log2(3 * inv_angle - 2) + 8);
57 }
58 328527 return nscale;
59 }
60
61 1155168 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 1155168 times.
1155168 av_assert0(mode < INTRA_LT_CCLM);
64
7/8
✓ Branch 0 taken 1155168 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1054730 times.
✓ Branch 3 taken 100438 times.
✓ Branch 4 taken 1000000 times.
✓ Branch 5 taken 54730 times.
✓ Branch 6 taken 980535 times.
✓ Branch 7 taken 19465 times.
1155168 if ((w >= 4 && h >= 4) && !ref_idx && !bdpcm_flag) {
65 int nscale;
66
6/6
✓ Branch 0 taken 625034 times.
✓ Branch 1 taken 355501 times.
✓ Branch 2 taken 542232 times.
✓ Branch 3 taken 82802 times.
✓ Branch 4 taken 477702 times.
✓ Branch 5 taken 64530 times.
980535 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
67
2/2
✓ Branch 0 taken 66799 times.
✓ Branch 1 taken 410903 times.
477702 mode == INTRA_HORZ || mode == INTRA_VERT)
68 569632 return 1;
69
4/4
✓ Branch 0 taken 286357 times.
✓ Branch 1 taken 124546 times.
✓ Branch 2 taken 167934 times.
✓ Branch 3 taken 118423 times.
410903 if (mode > INTRA_HORZ && mode < INTRA_VERT)
70 167934 return 0;
71 242969 nscale = ff_vvc_nscale_derive(w, h, mode);
72 242969 return nscale >= 0;
73
74 }
75 174633 return 0;
76 }
77
78 3946468 static const ReconstructedArea* get_reconstructed_area(const VVCLocalContext *lc, const int x, const int y, const int c_idx)
79 {
80 3946468 const int ch_type = c_idx > 0;
81
2/2
✓ Branch 0 taken 37901312 times.
✓ Branch 1 taken 64856 times.
37966168 for (int i = lc->num_ras[ch_type] - 1; i >= 0; i--) {
82 37901312 const ReconstructedArea* a = &lc->ras[ch_type][i];
83 37901312 const int r = (a->x + a->w);
84 37901312 const int b = (a->y + a->h);
85
8/8
✓ Branch 0 taken 20556893 times.
✓ Branch 1 taken 17344419 times.
✓ Branch 2 taken 6705060 times.
✓ Branch 3 taken 13851833 times.
✓ Branch 4 taken 4384304 times.
✓ Branch 5 taken 2320756 times.
✓ Branch 6 taken 3168745 times.
✓ Branch 7 taken 1215559 times.
37901312 if (a->x <= x && x < r && a->y <= y && y < b)
86 3168745 return a;
87
88 //it's too far away, no need check it;
89
4/4
✓ Branch 0 taken 13851833 times.
✓ Branch 1 taken 20880734 times.
✓ Branch 2 taken 712867 times.
✓ Branch 3 taken 13138966 times.
34732567 if (x >= r && y >= b)
90 712867 break;
91 }
92 777723 return NULL;
93 }
94
95 1278879 int ff_vvc_get_top_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
96 {
97 1278879 const VVCFrameContext *fc = lc->fc;
98 1278879 const VVCSPS *sps = fc->ps.sps;
99 1278879 const int hs = sps->hshift[c_idx];
100 1278879 const int vs = sps->vshift[c_idx];
101 1278879 const int log2_ctb_size_v = sps->ctb_log2_size_y - vs;
102 1278879 const int end_of_ctb_x = ((lc->cu->x0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
103 1278879 const int y0b = av_zero_extend(y, log2_ctb_size_v);
104 1278879 const int max_x = FFMIN(fc->ps.pps->width, end_of_ctb_x) >> hs;
105 const ReconstructedArea *a;
106 1278879 int px = x;
107
108
2/2
✓ Branch 0 taken 131612 times.
✓ Branch 1 taken 1147267 times.
1278879 if (!y0b) {
109
2/2
✓ Branch 0 taken 30832 times.
✓ Branch 1 taken 100780 times.
131612 if (!lc->ctb_up_flag)
110 30832 return 0;
111 100780 target_size = FFMIN(target_size, (lc->end_of_tiles_x >> hs) - x);
112
2/2
✓ Branch 0 taken 4760 times.
✓ Branch 1 taken 96020 times.
100780 if (sps->r->sps_entropy_coding_sync_enabled_flag)
113 4760 target_size = FFMIN(target_size, (end_of_ctb_x >> hs) - x);
114 100780 return target_size;
115 }
116
117 1147267 target_size = FFMAX(0, FFMIN(target_size, max_x - x));
118
4/4
✓ Branch 0 taken 1978512 times.
✓ Branch 1 taken 760255 times.
✓ Branch 3 taken 1591500 times.
✓ Branch 4 taken 387012 times.
2738767 while (target_size > 0 && (a = get_reconstructed_area(lc, px, y - 1, c_idx))) {
119 1591500 const int sz = FFMIN(target_size, a->x + a->w - px);
120 1591500 px += sz;
121 1591500 target_size -= sz;
122 }
123 1147267 return px - x;
124 }
125
126 1276438 int ff_vvc_get_left_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
127 {
128 1276438 const VVCFrameContext *fc = lc->fc;
129 1276438 const VVCSPS *sps = fc->ps.sps;
130 1276438 const int hs = sps->hshift[c_idx];
131 1276438 const int vs = sps->vshift[c_idx];
132 1276438 const int log2_ctb_size_h = sps->ctb_log2_size_y - hs;
133 1276438 const int x0b = av_zero_extend(x, log2_ctb_size_h);
134 1276438 const int end_of_ctb_y = ((lc->cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
135 1276438 const int max_y = FFMIN(fc->ps.pps->height, end_of_ctb_y) >> vs;
136 const ReconstructedArea *a;
137 1276438 int py = y;
138
139
4/4
✓ Branch 0 taken 168939 times.
✓ Branch 1 taken 1107499 times.
✓ Branch 2 taken 30993 times.
✓ Branch 3 taken 137946 times.
1276438 if (!x0b && !lc->ctb_left_flag)
140 30993 return 0;
141
142 1245445 target_size = FFMAX(0, FFMIN(target_size, max_y - y));
143
2/2
✓ Branch 0 taken 137946 times.
✓ Branch 1 taken 1107499 times.
1245445 if (!x0b)
144 137946 return target_size;
145
146
4/4
✓ Branch 0 taken 1967956 times.
✓ Branch 1 taken 716788 times.
✓ Branch 3 taken 1577245 times.
✓ Branch 4 taken 390711 times.
2684744 while (target_size > 0 && (a = get_reconstructed_area(lc, x - 1, py, c_idx))) {
147 1577245 const int sz = FFMIN(target_size, a->y + a->h - py);
148 1577245 py += sz;
149 1577245 target_size -= sz;
150 }
151 1107499 return py - y;
152 }
153
154 3866367 static int less(const void *a, const void *b)
155 {
156 3866367 return *(const int*)a - *(const int*)b;
157 }
158
159 1041517 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 1041517 return bsearch(&mode, modes, FF_ARRAY_ELEMS(modes), sizeof(int), less) != NULL;
163 }
164
165 1163814 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 1163814 int sign = 1, idx, intra_pred_angle;
172
2/2
✓ Branch 0 taken 588626 times.
✓ Branch 1 taken 575188 times.
1163814 if (pred_mode > INTRA_DIAG) {
173 588626 idx = pred_mode - INTRA_VERT;
174
2/2
✓ Branch 0 taken 524178 times.
✓ Branch 1 taken 51010 times.
575188 } else if (pred_mode > 0) {
175 524178 idx = INTRA_HORZ - pred_mode;
176 } else {
177 51010 idx = INTRA_HORZ - 2 - pred_mode;
178 }
179
2/2
✓ Branch 0 taken 428701 times.
✓ Branch 1 taken 735113 times.
1163814 if (idx < 0) {
180 428701 idx = -idx;
181 428701 sign = -1;
182 }
183 1163814 intra_pred_angle = sign * angles[idx];
184 1163814 return intra_pred_angle;
185 }
186
187 817501 int ff_vvc_intra_inv_angle_derive(const int intra_pred_angle)
188 {
189 av_assert2(intra_pred_angle != 0);
190
2/2
✓ Branch 0 taken 610148 times.
✓ Branch 1 taken 207353 times.
817501 if (intra_pred_angle > 0)
191 610148 return ROUNDED_DIV(32*512, intra_pred_angle);
192 else
193 207353 return -ROUNDED_DIV(32*512, -intra_pred_angle);
194 }
195
196 //8.4.5.2.7 Wide angle intra prediction mode mapping process
197 1316537 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 238808 times.
✓ Branch 1 taken 1077729 times.
✓ Branch 2 taken 8710 times.
✓ Branch 3 taken 230098 times.
1316537 if (cu->isp_split_type == ISP_NO_SPLIT || c_idx) {
203 1086439 nw = tb_width;
204 1086439 nh = tb_height;
205 } else {
206 230098 nw = cu->cb_width;
207 230098 nh = cu->cb_height;
208 }
209 1316537 wh_ratio = FFABS(ff_log2(nw) - ff_log2(nh));
210
2/2
✓ Branch 0 taken 309873 times.
✓ Branch 1 taken 1006664 times.
1316537 max = (wh_ratio > 1) ? (8 + 2 * wh_ratio) : 8;
211
2/2
✓ Branch 0 taken 309873 times.
✓ Branch 1 taken 1006664 times.
1316537 min = (wh_ratio > 1) ? (60 - 2 * wh_ratio) : 60;
212
213
6/6
✓ Branch 0 taken 518823 times.
✓ Branch 1 taken 797714 times.
✓ Branch 2 taken 289360 times.
✓ Branch 3 taken 229463 times.
✓ Branch 4 taken 45613 times.
✓ Branch 5 taken 243747 times.
1316537 if (nw > nh && pred_mode_intra >=2 && pred_mode_intra < max)
214 45613 pred_mode_intra += 65;
215
5/6
✓ Branch 0 taken 349281 times.
✓ Branch 1 taken 921643 times.
✓ Branch 2 taken 349281 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15952 times.
✓ Branch 5 taken 333329 times.
1270924 else if (nh > nw && pred_mode_intra <= 66 && pred_mode_intra > min)
216 15952 pred_mode_intra -= 67;
217 1316537 return pred_mode_intra;
218 }
219