FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/intra_utils.c
Date: 2025-04-25 22:50:00
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 108985 int ff_vvc_get_mip_size_id(const int w, const int h)
34 {
35
4/4
✓ Branch 0 taken 31106 times.
✓ Branch 1 taken 77879 times.
✓ Branch 2 taken 15329 times.
✓ Branch 3 taken 15777 times.
108985 if (w == 4 && h == 4)
36 15329 return 0;
37
8/8
✓ Branch 0 taken 77879 times.
✓ Branch 1 taken 15777 times.
✓ Branch 2 taken 54860 times.
✓ Branch 3 taken 23019 times.
✓ Branch 4 taken 18065 times.
✓ Branch 5 taken 36795 times.
✓ Branch 6 taken 10615 times.
✓ Branch 7 taken 7450 times.
93656 if ((w == 4 || h == 4) || (w == 8 && h == 8))
38 49411 return 1;
39 44245 return 2;
40 }
41
42 311532 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 311532 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 156676 times.
✓ Branch 3 taken 154856 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 156676 times.
311532 av_assert0(mode < INTRA_LT_CCLM && !(mode > INTRA_HORZ && mode < INTRA_VERT));
46
3/6
✓ Branch 0 taken 311532 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 311532 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 311532 times.
✗ Branch 5 not taken.
311532 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
47
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 311532 times.
311532 mode == INTRA_HORZ || mode == INTRA_VERT) {
48 nscale = (av_log2(w) + av_log2(h) - 2) >> 2;
49 } else {
50 311532 const int intra_pred_angle = ff_vvc_intra_pred_angle_derive(mode);
51 311532 const int inv_angle = ff_vvc_intra_inv_angle_derive(intra_pred_angle);
52
2/2
✓ Branch 0 taken 156676 times.
✓ Branch 1 taken 154856 times.
311532 if (mode >= INTRA_VERT)
53 156676 side_size = h;
54
2/2
✓ Branch 0 taken 154856 times.
✓ Branch 1 taken 156676 times.
311532 if (mode <= INTRA_HORZ)
55 154856 side_size = w;
56 311532 nscale = FFMIN(2, av_log2(side_size) - av_log2(3 * inv_angle - 2) + 8);
57 }
58 311532 return nscale;
59 }
60
61 1041463 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 1041463 times.
1041463 av_assert0(mode < INTRA_LT_CCLM);
64
7/8
✓ Branch 0 taken 1041463 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 945433 times.
✓ Branch 3 taken 96030 times.
✓ Branch 4 taken 901828 times.
✓ Branch 5 taken 43605 times.
✓ Branch 6 taken 901784 times.
✓ Branch 7 taken 44 times.
1041463 if ((w >= 4 && h >= 4) && !ref_idx && !bdpcm_flag) {
65 int nscale;
66
6/6
✓ Branch 0 taken 554863 times.
✓ Branch 1 taken 346921 times.
✓ Branch 2 taken 479956 times.
✓ Branch 3 taken 74907 times.
✓ Branch 4 taken 437558 times.
✓ Branch 5 taken 42398 times.
901784 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
67
2/2
✓ Branch 0 taken 46511 times.
✓ Branch 1 taken 391047 times.
437558 mode == INTRA_HORZ || mode == INTRA_VERT)
68 510737 return 1;
69
4/4
✓ Branch 0 taken 272856 times.
✓ Branch 1 taken 118191 times.
✓ Branch 2 taken 159718 times.
✓ Branch 3 taken 113138 times.
391047 if (mode > INTRA_HORZ && mode < INTRA_VERT)
70 159718 return 0;
71 231329 nscale = ff_vvc_nscale_derive(w, h, mode);
72 231329 return nscale >= 0;
73
74 }
75 139679 return 0;
76 }
77
78 3670810 static const ReconstructedArea* get_reconstructed_area(const VVCLocalContext *lc, const int x, const int y, const int c_idx)
79 {
80 3670810 const int ch_type = c_idx > 0;
81
2/2
✓ Branch 0 taken 35392726 times.
✓ Branch 1 taken 62801 times.
35455527 for (int i = lc->num_ras[ch_type] - 1; i >= 0; i--) {
82 35392726 const ReconstructedArea* a = &lc->ras[ch_type][i];
83 35392726 const int r = (a->x + a->w);
84 35392726 const int b = (a->y + a->h);
85
8/8
✓ Branch 0 taken 19173925 times.
✓ Branch 1 taken 16218801 times.
✓ Branch 2 taken 6261295 times.
✓ Branch 3 taken 12912630 times.
✓ Branch 4 taken 4092770 times.
✓ Branch 5 taken 2168525 times.
✓ Branch 6 taken 2920035 times.
✓ Branch 7 taken 1172735 times.
35392726 if (a->x <= x && x < r && a->y <= y && y < b)
86 2920035 return a;
87
88 //it's too far away, no need check it;
89
4/4
✓ Branch 0 taken 12912630 times.
✓ Branch 1 taken 19560061 times.
✓ Branch 2 taken 687974 times.
✓ Branch 3 taken 12224656 times.
32472691 if (x >= r && y >= b)
90 687974 break;
91 }
92 750775 return NULL;
93 }
94
95 1165569 int ff_vvc_get_top_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
96 {
97 1165569 const VVCFrameContext *fc = lc->fc;
98 1165569 const VVCSPS *sps = fc->ps.sps;
99 1165569 const int hs = sps->hshift[c_idx];
100 1165569 const int vs = sps->vshift[c_idx];
101 1165569 const int log2_ctb_size_v = sps->ctb_log2_size_y - vs;
102 1165569 const int end_of_ctb_x = ((lc->cu->x0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
103 1165569 const int y0b = av_zero_extend(y, log2_ctb_size_v);
104 1165569 const int max_x = FFMIN(fc->ps.pps->width, end_of_ctb_x) >> hs;
105 const ReconstructedArea *a;
106 1165569 int px = x;
107
108
2/2
✓ Branch 0 taken 118685 times.
✓ Branch 1 taken 1046884 times.
1165569 if (!y0b) {
109
2/2
✓ Branch 0 taken 28531 times.
✓ Branch 1 taken 90154 times.
118685 if (!lc->ctb_up_flag)
110 28531 return 0;
111 90154 target_size = FFMIN(target_size, (lc->end_of_tiles_x >> hs) - x);
112
2/2
✓ Branch 0 taken 4760 times.
✓ Branch 1 taken 85394 times.
90154 if (sps->r->sps_entropy_coding_sync_enabled_flag)
113 4760 target_size = FFMIN(target_size, (end_of_ctb_x >> hs) - x);
114 90154 return target_size;
115 }
116
117 1046884 target_size = FFMAX(0, FFMIN(target_size, max_x - x));
118
4/4
✓ Branch 0 taken 1840057 times.
✓ Branch 1 taken 673254 times.
✓ Branch 3 taken 1466427 times.
✓ Branch 4 taken 373630 times.
2513311 while (target_size > 0 && (a = get_reconstructed_area(lc, px, y - 1, c_idx))) {
119 1466427 const int sz = FFMIN(target_size, a->x + a->w - px);
120 1466427 px += sz;
121 1466427 target_size -= sz;
122 }
123 1046884 return px - x;
124 }
125
126 1163865 int ff_vvc_get_left_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
127 {
128 1163865 const VVCFrameContext *fc = lc->fc;
129 1163865 const VVCSPS *sps = fc->ps.sps;
130 1163865 const int hs = sps->hshift[c_idx];
131 1163865 const int vs = sps->vshift[c_idx];
132 1163865 const int log2_ctb_size_h = sps->ctb_log2_size_y - hs;
133 1163865 const int x0b = av_zero_extend(x, log2_ctb_size_h);
134 1163865 const int end_of_ctb_y = ((lc->cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
135 1163865 const int max_y = FFMIN(fc->ps.pps->height, end_of_ctb_y) >> vs;
136 const ReconstructedArea *a;
137 1163865 int py = y;
138
139
4/4
✓ Branch 0 taken 154690 times.
✓ Branch 1 taken 1009175 times.
✓ Branch 2 taken 29534 times.
✓ Branch 3 taken 125156 times.
1163865 if (!x0b && !lc->ctb_left_flag)
140 29534 return 0;
141
142 1134331 target_size = FFMAX(0, FFMIN(target_size, max_y - y));
143
2/2
✓ Branch 0 taken 125156 times.
✓ Branch 1 taken 1009175 times.
1134331 if (!x0b)
144 125156 return target_size;
145
146
4/4
✓ Branch 0 taken 1830753 times.
✓ Branch 1 taken 632030 times.
✓ Branch 3 taken 1453608 times.
✓ Branch 4 taken 377145 times.
2462783 while (target_size > 0 && (a = get_reconstructed_area(lc, x - 1, py, c_idx))) {
147 1453608 const int sz = FFMIN(target_size, a->y + a->h - py);
148 1453608 py += sz;
149 1453608 target_size -= sz;
150 }
151 1009175 return py - y;
152 }
153
154 3478776 static int less(const void *a, const void *b)
155 {
156 3478776 return *(const int*)a - *(const int*)b;
157 }
158
159 932478 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 932478 return bsearch(&mode, modes, FF_ARRAY_ELEMS(modes), sizeof(int), less) != NULL;
163 }
164
165 1090562 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 1090562 int sign = 1, idx, intra_pred_angle;
172
2/2
✓ Branch 0 taken 553568 times.
✓ Branch 1 taken 536994 times.
1090562 if (pred_mode > INTRA_DIAG) {
173 553568 idx = pred_mode - INTRA_VERT;
174
2/2
✓ Branch 0 taken 486840 times.
✓ Branch 1 taken 50154 times.
536994 } else if (pred_mode > 0) {
175 486840 idx = INTRA_HORZ - pred_mode;
176 } else {
177 50154 idx = INTRA_HORZ - 2 - pred_mode;
178 }
179
2/2
✓ Branch 0 taken 401026 times.
✓ Branch 1 taken 689536 times.
1090562 if (idx < 0) {
180 401026 idx = -idx;
181 401026 sign = -1;
182 }
183 1090562 intra_pred_angle = sign * angles[idx];
184 1090562 return intra_pred_angle;
185 }
186
187 781250 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 580737 times.
✓ Branch 1 taken 200513 times.
781250 if (intra_pred_angle > 0)
191 580737 return ROUNDED_DIV(32*512, intra_pred_angle);
192 else
193 200513 return -ROUNDED_DIV(32*512, -intra_pred_angle);
194 }
195
196 //8.4.5.2.7 Wide angle intra prediction mode mapping proces
197 1212544 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 229974 times.
✓ Branch 1 taken 982570 times.
✓ Branch 2 taken 7810 times.
✓ Branch 3 taken 222164 times.
1212544 if (cu->isp_split_type == ISP_NO_SPLIT || c_idx) {
203 990380 nw = tb_width;
204 990380 nh = tb_height;
205 } else {
206 222164 nw = cu->cb_width;
207 222164 nh = cu->cb_height;
208 }
209 1212544 wh_ratio = FFABS(ff_log2(nw) - ff_log2(nh));
210
2/2
✓ Branch 0 taken 284246 times.
✓ Branch 1 taken 928298 times.
1212544 max = (wh_ratio > 1) ? (8 + 2 * wh_ratio) : 8;
211
2/2
✓ Branch 0 taken 284246 times.
✓ Branch 1 taken 928298 times.
1212544 min = (wh_ratio > 1) ? (60 - 2 * wh_ratio) : 60;
212
213
6/6
✓ Branch 0 taken 484885 times.
✓ Branch 1 taken 727659 times.
✓ Branch 2 taken 261855 times.
✓ Branch 3 taken 223030 times.
✓ Branch 4 taken 44006 times.
✓ Branch 5 taken 217849 times.
1212544 if (nw > nh && pred_mode_intra >=2 && pred_mode_intra < max)
214 44006 pred_mode_intra += 65;
215
5/6
✓ Branch 0 taken 313425 times.
✓ Branch 1 taken 855113 times.
✓ Branch 2 taken 313425 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15712 times.
✓ Branch 5 taken 297713 times.
1168538 else if (nh > nw && pred_mode_intra <= 66 && pred_mode_intra > min)
216 15712 pred_mode_intra -= 67;
217 1212544 return pred_mode_intra;
218 }
219