FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/intra_utils.c
Date: 2025-08-19 23:55:23
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 113399 int ff_vvc_get_mip_size_id(const int w, const int h)
34 {
35
4/4
✓ Branch 0 taken 32953 times.
✓ Branch 1 taken 80446 times.
✓ Branch 2 taken 16464 times.
✓ Branch 3 taken 16489 times.
113399 if (w == 4 && h == 4)
36 16464 return 0;
37
8/8
✓ Branch 0 taken 80446 times.
✓ Branch 1 taken 16489 times.
✓ Branch 2 taken 55983 times.
✓ Branch 3 taken 24463 times.
✓ Branch 4 taken 18528 times.
✓ Branch 5 taken 37455 times.
✓ Branch 6 taken 10937 times.
✓ Branch 7 taken 7591 times.
96935 if ((w == 4 || h == 4) || (w == 8 && h == 8))
38 51889 return 1;
39 45046 return 2;
40 }
41
42 321254 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 321254 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 161115 times.
✓ Branch 3 taken 160139 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 161115 times.
321254 av_assert0(mode < INTRA_LT_CCLM && !(mode > INTRA_HORZ && mode < INTRA_VERT));
46
3/6
✓ Branch 0 taken 321254 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 321254 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 321254 times.
✗ Branch 5 not taken.
321254 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
47
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 321254 times.
321254 mode == INTRA_HORZ || mode == INTRA_VERT) {
48 nscale = (av_log2(w) + av_log2(h) - 2) >> 2;
49 } else {
50 321254 const int intra_pred_angle = ff_vvc_intra_pred_angle_derive(mode);
51 321254 const int inv_angle = ff_vvc_intra_inv_angle_derive(intra_pred_angle);
52
2/2
✓ Branch 0 taken 161115 times.
✓ Branch 1 taken 160139 times.
321254 if (mode >= INTRA_VERT)
53 161115 side_size = h;
54
2/2
✓ Branch 0 taken 160139 times.
✓ Branch 1 taken 161115 times.
321254 if (mode <= INTRA_HORZ)
55 160139 side_size = w;
56 321254 nscale = FFMIN(2, av_log2(side_size) - av_log2(3 * inv_angle - 2) + 8);
57 }
58 321254 return nscale;
59 }
60
61 1111311 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 1111311 times.
1111311 av_assert0(mode < INTRA_LT_CCLM);
64
7/8
✓ Branch 0 taken 1111311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1011325 times.
✓ Branch 3 taken 99986 times.
✓ Branch 4 taken 966511 times.
✓ Branch 5 taken 44814 times.
✓ Branch 6 taken 955528 times.
✓ Branch 7 taken 10983 times.
1111311 if ((w >= 4 && h >= 4) && !ref_idx && !bdpcm_flag) {
65 int nscale;
66
6/6
✓ Branch 0 taken 601257 times.
✓ Branch 1 taken 354271 times.
✓ Branch 2 taken 521781 times.
✓ Branch 3 taken 79476 times.
✓ Branch 4 taken 464047 times.
✓ Branch 5 taken 57734 times.
955528 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
67
2/2
✓ Branch 0 taken 59962 times.
✓ Branch 1 taken 404085 times.
464047 mode == INTRA_HORZ || mode == INTRA_VERT)
68 551443 return 1;
69
4/4
✓ Branch 0 taken 281408 times.
✓ Branch 1 taken 122677 times.
✓ Branch 2 taken 164679 times.
✓ Branch 3 taken 116729 times.
404085 if (mode > INTRA_HORZ && mode < INTRA_VERT)
70 164679 return 0;
71 239406 nscale = ff_vvc_nscale_derive(w, h, mode);
72 239406 return nscale >= 0;
73
74 }
75 155783 return 0;
76 }
77
78 3870570 static const ReconstructedArea* get_reconstructed_area(const VVCLocalContext *lc, const int x, const int y, const int c_idx)
79 {
80 3870570 const int ch_type = c_idx > 0;
81
2/2
✓ Branch 0 taken 37325027 times.
✓ Branch 1 taken 64333 times.
37389360 for (int i = lc->num_ras[ch_type] - 1; i >= 0; i--) {
82 37325027 const ReconstructedArea* a = &lc->ras[ch_type][i];
83 37325027 const int r = (a->x + a->w);
84 37325027 const int b = (a->y + a->h);
85
8/8
✓ Branch 0 taken 20234948 times.
✓ Branch 1 taken 17090079 times.
✓ Branch 2 taken 6589576 times.
✓ Branch 3 taken 13645372 times.
✓ Branch 4 taken 4307070 times.
✓ Branch 5 taken 2282506 times.
✓ Branch 6 taken 3096230 times.
✓ Branch 7 taken 1210840 times.
37325027 if (a->x <= x && x < r && a->y <= y && y < b)
86 3096230 return a;
87
88 //it's too far away, no need check it;
89
4/4
✓ Branch 0 taken 13645372 times.
✓ Branch 1 taken 20583425 times.
✓ Branch 2 taken 710007 times.
✓ Branch 3 taken 12935365 times.
34228797 if (x >= r && y >= b)
90 710007 break;
91 }
92 774340 return NULL;
93 }
94
95 1242727 int ff_vvc_get_top_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
96 {
97 1242727 const VVCFrameContext *fc = lc->fc;
98 1242727 const VVCSPS *sps = fc->ps.sps;
99 1242727 const int hs = sps->hshift[c_idx];
100 1242727 const int vs = sps->vshift[c_idx];
101 1242727 const int log2_ctb_size_v = sps->ctb_log2_size_y - vs;
102 1242727 const int end_of_ctb_x = ((lc->cu->x0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
103 1242727 const int y0b = av_zero_extend(y, log2_ctb_size_v);
104 1242727 const int max_x = FFMIN(fc->ps.pps->width, end_of_ctb_x) >> hs;
105 const ReconstructedArea *a;
106 1242727 int px = x;
107
108
2/2
✓ Branch 0 taken 126314 times.
✓ Branch 1 taken 1116413 times.
1242727 if (!y0b) {
109
2/2
✓ Branch 0 taken 30107 times.
✓ Branch 1 taken 96207 times.
126314 if (!lc->ctb_up_flag)
110 30107 return 0;
111 96207 target_size = FFMIN(target_size, (lc->end_of_tiles_x >> hs) - x);
112
2/2
✓ Branch 0 taken 4760 times.
✓ Branch 1 taken 91447 times.
96207 if (sps->r->sps_entropy_coding_sync_enabled_flag)
113 4760 target_size = FFMIN(target_size, (end_of_ctb_x >> hs) - x);
114 96207 return target_size;
115 }
116
117 1116413 target_size = FFMAX(0, FFMIN(target_size, max_x - x));
118
4/4
✓ Branch 0 taken 1940234 times.
✓ Branch 1 taken 730941 times.
✓ Branch 3 taken 1554762 times.
✓ Branch 4 taken 385472 times.
2671175 while (target_size > 0 && (a = get_reconstructed_area(lc, px, y - 1, c_idx))) {
119 1554762 const int sz = FFMIN(target_size, a->x + a->w - px);
120 1554762 px += sz;
121 1554762 target_size -= sz;
122 }
123 1116413 return px - x;
124 }
125
126 1240655 int ff_vvc_get_left_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
127 {
128 1240655 const VVCFrameContext *fc = lc->fc;
129 1240655 const VVCSPS *sps = fc->ps.sps;
130 1240655 const int hs = sps->hshift[c_idx];
131 1240655 const int vs = sps->vshift[c_idx];
132 1240655 const int log2_ctb_size_h = sps->ctb_log2_size_y - hs;
133 1240655 const int x0b = av_zero_extend(x, log2_ctb_size_h);
134 1240655 const int end_of_ctb_y = ((lc->cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
135 1240655 const int max_y = FFMIN(fc->ps.pps->height, end_of_ctb_y) >> vs;
136 const ReconstructedArea *a;
137 1240655 int py = y;
138
139
4/4
✓ Branch 0 taken 163487 times.
✓ Branch 1 taken 1077168 times.
✓ Branch 2 taken 30451 times.
✓ Branch 3 taken 133036 times.
1240655 if (!x0b && !lc->ctb_left_flag)
140 30451 return 0;
141
142 1210204 target_size = FFMAX(0, FFMIN(target_size, max_y - y));
143
2/2
✓ Branch 0 taken 133036 times.
✓ Branch 1 taken 1077168 times.
1210204 if (!x0b)
144 133036 return target_size;
145
146
4/4
✓ Branch 0 taken 1930336 times.
✓ Branch 1 taken 688300 times.
✓ Branch 3 taken 1541468 times.
✓ Branch 4 taken 388868 times.
2618636 while (target_size > 0 && (a = get_reconstructed_area(lc, x - 1, py, c_idx))) {
147 1541468 const int sz = FFMIN(target_size, a->y + a->h - py);
148 1541468 py += sz;
149 1541468 target_size -= sz;
150 }
151 1077168 return py - y;
152 }
153
154 3711735 static int less(const void *a, const void *b)
155 {
156 3711735 return *(const int*)a - *(const int*)b;
157 }
158
159 997912 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 997912 return bsearch(&mode, modes, FF_ARRAY_ELEMS(modes), sizeof(int), less) != NULL;
163 }
164
165 1123992 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 1123992 int sign = 1, idx, intra_pred_angle;
172
2/2
✓ Branch 0 taken 568901 times.
✓ Branch 1 taken 555091 times.
1123992 if (pred_mode > INTRA_DIAG) {
173 568901 idx = pred_mode - INTRA_VERT;
174
2/2
✓ Branch 0 taken 504305 times.
✓ Branch 1 taken 50786 times.
555091 } else if (pred_mode > 0) {
175 504305 idx = INTRA_HORZ - pred_mode;
176 } else {
177 50786 idx = INTRA_HORZ - 2 - pred_mode;
178 }
179
2/2
✓ Branch 0 taken 412734 times.
✓ Branch 1 taken 711258 times.
1123992 if (idx < 0) {
180 412734 idx = -idx;
181 412734 sign = -1;
182 }
183 1123992 intra_pred_angle = sign * angles[idx];
184 1123992 return intra_pred_angle;
185 }
186
187 804471 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 598104 times.
✓ Branch 1 taken 206367 times.
804471 if (intra_pred_angle > 0)
191 598104 return ROUNDED_DIV(32*512, intra_pred_angle);
192 else
193 206367 return -ROUNDED_DIV(32*512, -intra_pred_angle);
194 }
195
196 //8.4.5.2.7 Wide angle intra prediction mode mapping process
197 1286145 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 237142 times.
✓ Branch 1 taken 1049003 times.
✓ Branch 2 taken 8338 times.
✓ Branch 3 taken 228804 times.
1286145 if (cu->isp_split_type == ISP_NO_SPLIT || c_idx) {
203 1057341 nw = tb_width;
204 1057341 nh = tb_height;
205 } else {
206 228804 nw = cu->cb_width;
207 228804 nh = cu->cb_height;
208 }
209 1286145 wh_ratio = FFABS(ff_log2(nw) - ff_log2(nh));
210
2/2
✓ Branch 0 taken 303387 times.
✓ Branch 1 taken 982758 times.
1286145 max = (wh_ratio > 1) ? (8 + 2 * wh_ratio) : 8;
211
2/2
✓ Branch 0 taken 303387 times.
✓ Branch 1 taken 982758 times.
1286145 min = (wh_ratio > 1) ? (60 - 2 * wh_ratio) : 60;
212
213
6/6
✓ Branch 0 taken 511707 times.
✓ Branch 1 taken 774438 times.
✓ Branch 2 taken 282766 times.
✓ Branch 3 taken 228941 times.
✓ Branch 4 taken 45531 times.
✓ Branch 5 taken 237235 times.
1286145 if (nw > nh && pred_mode_intra >=2 && pred_mode_intra < max)
214 45531 pred_mode_intra += 65;
215
5/6
✓ Branch 0 taken 336603 times.
✓ Branch 1 taken 904011 times.
✓ Branch 2 taken 336603 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15892 times.
✓ Branch 5 taken 320711 times.
1240614 else if (nh > nw && pred_mode_intra <= 66 && pred_mode_intra > min)
216 15892 pred_mode_intra -= 67;
217 1286145 return pred_mode_intra;
218 }
219