FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/intra_utils.c
Date: 2026-10-19 08:11:58
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 113651 int ff_vvc_get_mip_size_id(const int w, const int h)
34 {
35
4/4
✓ Branch 0 taken 33089 times.
✓ Branch 1 taken 80562 times.
✓ Branch 2 taken 16522 times.
✓ Branch 3 taken 16567 times.
113651 if (w == 4 && h == 4)
36 16522 return 0;
37
8/8
✓ Branch 0 taken 80562 times.
✓ Branch 1 taken 16567 times.
✓ Branch 2 taken 56035 times.
✓ Branch 3 taken 24527 times.
✓ Branch 4 taken 18564 times.
✓ Branch 5 taken 37471 times.
✓ Branch 6 taken 10959 times.
✓ Branch 7 taken 7605 times.
97129 if ((w == 4 || h == 4) || (w == 8 && h == 8))
38 52053 return 1;
39 45076 return 2;
40 }
41
42 322893 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 322893 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 161830 times.
✓ Branch 3 taken 161063 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 161830 times.
322893 av_assert0(mode < INTRA_LT_CCLM && !(mode > INTRA_HORZ && mode < INTRA_VERT));
46
3/6
✓ Branch 0 taken 322893 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 322893 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 322893 times.
✗ Branch 5 not taken.
322893 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
47
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322893 times.
322893 mode == INTRA_HORZ || mode == INTRA_VERT) {
48 ✗ nscale = (av_log2(w) + av_log2(h) - 2) >> 2;
49 } else {
50 322893 const int intra_pred_angle = ff_vvc_intra_pred_angle_derive(mode);
51 322893 const int inv_angle = ff_vvc_intra_inv_angle_derive(intra_pred_angle);
52
2/2
✓ Branch 0 taken 161830 times.
✓ Branch 1 taken 161063 times.
322893 if (mode >= INTRA_VERT)
53 161830 side_size = h;
54
2/2
✓ Branch 0 taken 161063 times.
✓ Branch 1 taken 161830 times.
322893 if (mode <= INTRA_HORZ)
55 161063 side_size = w;
56 322893 nscale = FFMIN(2, av_log2(side_size) - av_log2(3 * inv_angle - 2) + 8);
57 }
58 322893 return nscale;
59 }
60
61 1140993 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 1140993 times.
1140993 av_assert0(mode < INTRA_LT_CCLM);
64
7/8
✓ Branch 0 taken 1140993 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1040555 times.
✓ Branch 3 taken 100438 times.
✓ Branch 4 taken 995275 times.
✓ Branch 5 taken 45280 times.
✓ Branch 6 taken 975810 times.
✓ Branch 7 taken 19465 times.
1140993 if ((w >= 4 && h >= 4) && !ref_idx && !bdpcm_flag) {
65 int nscale;
66
6/6
✓ Branch 0 taken 620309 times.
✓ Branch 1 taken 355501 times.
✓ Branch 2 taken 537507 times.
✓ Branch 3 taken 82802 times.
✓ Branch 4 taken 472977 times.
✓ Branch 5 taken 64530 times.
975810 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
67
2/2
✓ Branch 0 taken 66799 times.
✓ Branch 1 taken 406178 times.
472977 mode == INTRA_HORZ || mode == INTRA_VERT)
68 569632 return 1;
69
4/4
✓ Branch 0 taken 282832 times.
✓ Branch 1 taken 123346 times.
✓ Branch 2 taken 165609 times.
✓ Branch 3 taken 117223 times.
406178 if (mode > INTRA_HORZ && mode < INTRA_VERT)
70 165609 return 0;
71 240569 nscale = ff_vvc_nscale_derive(w, h, mode);
72 240569 return nscale >= 0;
73
74 }
75 165183 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 3817317 static int less(const void *a, const void *b)
155 {
156 3817317 return *(const int*)a - *(const int*)b;
157 }
158
159 1027342 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 1027342 return bsearch(&mode, modes, FF_ARRAY_ELEMS(modes), sizeof(int), less) != NULL;
163 }
164
165 1129725 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 1129725 int sign = 1, idx, intra_pred_angle;
172
2/2
✓ Branch 0 taken 571814 times.
✓ Branch 1 taken 557911 times.
1129725 if (pred_mode > INTRA_DIAG) {
173 571814 idx = pred_mode - INTRA_VERT;
174
2/2
✓ Branch 0 taken 506901 times.
✓ Branch 1 taken 51010 times.
557911 } else if (pred_mode > 0) {
175 506901 idx = INTRA_HORZ - pred_mode;
176 } else {
177 51010 idx = INTRA_HORZ - 2 - pred_mode;
178 }
179
2/2
✓ Branch 0 taken 414706 times.
✓ Branch 1 taken 715019 times.
1129725 if (idx < 0) {
180 414706 idx = -idx;
181 414706 sign = -1;
182 }
183 1129725 intra_pred_angle = sign * angles[idx];
184 1129725 return intra_pred_angle;
185 }
186
187 808633 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 601280 times.
✓ Branch 1 taken 207353 times.
808633 if (intra_pred_angle > 0)
191 601280 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