FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/intra_utils.c
Date: 2025-01-20 09:27: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 108949 int ff_vvc_get_mip_size_id(const int w, const int h)
34 {
35
4/4
✓ Branch 0 taken 31092 times.
✓ Branch 1 taken 77857 times.
✓ Branch 2 taken 15321 times.
✓ Branch 3 taken 15771 times.
108949 if (w == 4 && h == 4)
36 15321 return 0;
37
8/8
✓ Branch 0 taken 77857 times.
✓ Branch 1 taken 15771 times.
✓ Branch 2 taken 54848 times.
✓ Branch 3 taken 23009 times.
✓ Branch 4 taken 18063 times.
✓ Branch 5 taken 36785 times.
✓ Branch 6 taken 10613 times.
✓ Branch 7 taken 7450 times.
93628 if ((w == 4 || h == 4) || (w == 8 && h == 8))
38 49393 return 1;
39 44235 return 2;
40 }
41
42 311312 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 311312 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 156610 times.
✓ Branch 3 taken 154702 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 156610 times.
311312 av_assert0(mode < INTRA_LT_CCLM && !(mode > INTRA_HORZ && mode < INTRA_VERT));
46
3/6
✓ Branch 0 taken 311312 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 311312 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 311312 times.
✗ Branch 5 not taken.
311312 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
47
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 311312 times.
311312 mode == INTRA_HORZ || mode == INTRA_VERT) {
48 nscale = (av_log2(w) + av_log2(h) - 2) >> 2;
49 } else {
50 311312 const int intra_pred_angle = ff_vvc_intra_pred_angle_derive(mode);
51 311312 const int inv_angle = ff_vvc_intra_inv_angle_derive(intra_pred_angle);
52
2/2
✓ Branch 0 taken 156610 times.
✓ Branch 1 taken 154702 times.
311312 if (mode >= INTRA_VERT)
53 156610 side_size = h;
54
2/2
✓ Branch 0 taken 154702 times.
✓ Branch 1 taken 156610 times.
311312 if (mode <= INTRA_HORZ)
55 154702 side_size = w;
56 311312 nscale = FFMIN(2, av_log2(side_size) - av_log2(3 * inv_angle - 2) + 8);
57 }
58 311312 return nscale;
59 }
60
61 1040561 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 1040561 times.
1040561 av_assert0(mode < INTRA_LT_CCLM);
64
7/8
✓ Branch 0 taken 1040561 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 944571 times.
✓ Branch 3 taken 95990 times.
✓ Branch 4 taken 901036 times.
✓ Branch 5 taken 43535 times.
✓ Branch 6 taken 900992 times.
✓ Branch 7 taken 44 times.
1040561 if ((w >= 4 && h >= 4) && !ref_idx && !bdpcm_flag) {
65 int nscale;
66
6/6
✓ Branch 0 taken 554335 times.
✓ Branch 1 taken 346657 times.
✓ Branch 2 taken 479454 times.
✓ Branch 3 taken 74881 times.
✓ Branch 4 taken 437124 times.
✓ Branch 5 taken 42330 times.
900992 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
67
2/2
✓ Branch 0 taken 46321 times.
✓ Branch 1 taken 390803 times.
437124 mode == INTRA_HORZ || mode == INTRA_VERT)
68 510189 return 1;
69
4/4
✓ Branch 0 taken 272764 times.
✓ Branch 1 taken 118039 times.
✓ Branch 2 taken 159684 times.
✓ Branch 3 taken 113080 times.
390803 if (mode > INTRA_HORZ && mode < INTRA_VERT)
70 159684 return 0;
71 231119 nscale = ff_vvc_nscale_derive(w, h, mode);
72 231119 return nscale >= 0;
73
74 }
75 139569 return 0;
76 }
77
78 3667474 static const ReconstructedArea* get_reconstructed_area(const VVCLocalContext *lc, const int x, const int y, const int c_idx)
79 {
80 3667474 const int ch_type = c_idx > 0;
81
2/2
✓ Branch 0 taken 35362770 times.
✓ Branch 1 taken 62751 times.
35425521 for (int i = lc->num_ras[ch_type] - 1; i >= 0; i--) {
82 35362770 const ReconstructedArea* a = &lc->ras[ch_type][i];
83 35362770 const int r = (a->x + a->w);
84 35362770 const int b = (a->y + a->h);
85
8/8
✓ Branch 0 taken 19159945 times.
✓ Branch 1 taken 16202825 times.
✓ Branch 2 taken 6255657 times.
✓ Branch 3 taken 12904288 times.
✓ Branch 4 taken 4089262 times.
✓ Branch 5 taken 2166395 times.
✓ Branch 6 taken 2917213 times.
✓ Branch 7 taken 1172049 times.
35362770 if (a->x <= x && x < r && a->y <= y && y < b)
86 2917213 return a;
87
88 //it's too far away, no need check it;
89
4/4
✓ Branch 0 taken 12904288 times.
✓ Branch 1 taken 19541269 times.
✓ Branch 2 taken 687510 times.
✓ Branch 3 taken 12216778 times.
32445557 if (x >= r && y >= b)
90 687510 break;
91 }
92 750261 return NULL;
93 }
94
95 1164315 int ff_vvc_get_top_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
96 {
97 1164315 const VVCFrameContext *fc = lc->fc;
98 1164315 const VVCSPS *sps = fc->ps.sps;
99 1164315 const int hs = sps->hshift[c_idx];
100 1164315 const int vs = sps->vshift[c_idx];
101 1164315 const int log2_ctb_size_v = sps->ctb_log2_size_y - vs;
102 1164315 const int end_of_ctb_x = ((lc->cu->x0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
103 1164315 const int y0b = av_zero_extend(y, log2_ctb_size_v);
104 1164315 const int max_x = FFMIN(fc->ps.pps->width, end_of_ctb_x) >> hs;
105 const ReconstructedArea *a;
106 1164315 int px = x;
107
108
2/2
✓ Branch 0 taken 118451 times.
✓ Branch 1 taken 1045864 times.
1164315 if (!y0b) {
109
2/2
✓ Branch 0 taken 28297 times.
✓ Branch 1 taken 90154 times.
118451 if (!lc->ctb_up_flag)
110 28297 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 1045864 target_size = FFMAX(0, FFMIN(target_size, max_x - x));
118
4/4
✓ Branch 0 taken 1838423 times.
✓ Branch 1 taken 672408 times.
✓ Branch 3 taken 1464967 times.
✓ Branch 4 taken 373456 times.
2510831 while (target_size > 0 && (a = get_reconstructed_area(lc, px, y - 1, c_idx))) {
119 1464967 const int sz = FFMIN(target_size, a->x + a->w - px);
120 1464967 px += sz;
121 1464967 target_size -= sz;
122 }
123 1045864 return px - x;
124 }
125
126 1162603 int ff_vvc_get_left_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
127 {
128 1162603 const VVCFrameContext *fc = lc->fc;
129 1162603 const VVCSPS *sps = fc->ps.sps;
130 1162603 const int hs = sps->hshift[c_idx];
131 1162603 const int vs = sps->vshift[c_idx];
132 1162603 const int log2_ctb_size_h = sps->ctb_log2_size_y - hs;
133 1162603 const int x0b = av_zero_extend(x, log2_ctb_size_h);
134 1162603 const int end_of_ctb_y = ((lc->cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
135 1162603 const int max_y = FFMIN(fc->ps.pps->height, end_of_ctb_y) >> vs;
136 const ReconstructedArea *a;
137 1162603 int py = y;
138
139
4/4
✓ Branch 0 taken 154568 times.
✓ Branch 1 taken 1008035 times.
✓ Branch 2 taken 29412 times.
✓ Branch 3 taken 125156 times.
1162603 if (!x0b && !lc->ctb_left_flag)
140 29412 return 0;
141
142 1133191 target_size = FFMAX(0, FFMIN(target_size, max_y - y));
143
2/2
✓ Branch 0 taken 125156 times.
✓ Branch 1 taken 1008035 times.
1133191 if (!x0b)
144 125156 return target_size;
145
146
4/4
✓ Branch 0 taken 1829051 times.
✓ Branch 1 taken 631230 times.
✓ Branch 3 taken 1452246 times.
✓ Branch 4 taken 376805 times.
2460281 while (target_size > 0 && (a = get_reconstructed_area(lc, x - 1, py, c_idx))) {
147 1452246 const int sz = FFMIN(target_size, a->y + a->h - py);
148 1452246 py += sz;
149 1452246 target_size -= sz;
150 }
151 1008035 return py - y;
152 }
153
154 3475604 static int less(const void *a, const void *b)
155 {
156 3475604 return *(const int*)a - *(const int*)b;
157 }
158
159 931612 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 931612 return bsearch(&mode, modes, FF_ARRAY_ELEMS(modes), sizeof(int), less) != NULL;
163 }
164
165 1089866 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 1089866 int sign = 1, idx, intra_pred_angle;
172
2/2
✓ Branch 0 taken 553370 times.
✓ Branch 1 taken 536496 times.
1089866 if (pred_mode > INTRA_DIAG) {
173 553370 idx = pred_mode - INTRA_VERT;
174
2/2
✓ Branch 0 taken 486342 times.
✓ Branch 1 taken 50154 times.
536496 } else if (pred_mode > 0) {
175 486342 idx = INTRA_HORZ - pred_mode;
176 } else {
177 50154 idx = INTRA_HORZ - 2 - pred_mode;
178 }
179
2/2
✓ Branch 0 taken 400950 times.
✓ Branch 1 taken 688916 times.
1089866 if (idx < 0) {
180 400950 idx = -idx;
181 400950 sign = -1;
182 }
183 1089866 intra_pred_angle = sign * angles[idx];
184 1089866 return intra_pred_angle;
185 }
186
187 780782 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 580307 times.
✓ Branch 1 taken 200475 times.
780782 if (intra_pred_angle > 0)
191 580307 return ROUNDED_DIV(32*512, intra_pred_angle);
192 else
193 200475 return -ROUNDED_DIV(32*512, -intra_pred_angle);
194 }
195
196 //8.4.5.2.7 Wide angle intra prediction mode mapping proces
197 1211596 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 229918 times.
✓ Branch 1 taken 981678 times.
✓ Branch 2 taken 7810 times.
✓ Branch 3 taken 222108 times.
1211596 if (cu->isp_split_type == ISP_NO_SPLIT || c_idx) {
203 989488 nw = tb_width;
204 989488 nh = tb_height;
205 } else {
206 222108 nw = cu->cb_width;
207 222108 nh = cu->cb_height;
208 }
209 1211596 wh_ratio = FFABS(ff_log2(nw) - ff_log2(nh));
210
2/2
✓ Branch 0 taken 284002 times.
✓ Branch 1 taken 927594 times.
1211596 max = (wh_ratio > 1) ? (8 + 2 * wh_ratio) : 8;
211
2/2
✓ Branch 0 taken 284002 times.
✓ Branch 1 taken 927594 times.
1211596 min = (wh_ratio > 1) ? (60 - 2 * wh_ratio) : 60;
212
213
6/6
✓ Branch 0 taken 484609 times.
✓ Branch 1 taken 726987 times.
✓ Branch 2 taken 261641 times.
✓ Branch 3 taken 222968 times.
✓ Branch 4 taken 43994 times.
✓ Branch 5 taken 217647 times.
1211596 if (nw > nh && pred_mode_intra >=2 && pred_mode_intra < max)
214 43994 pred_mode_intra += 65;
215
5/6
✓ Branch 0 taken 313061 times.
✓ Branch 1 taken 854541 times.
✓ Branch 2 taken 313061 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15712 times.
✓ Branch 5 taken 297349 times.
1167602 else if (nh > nw && pred_mode_intra <= 66 && pred_mode_intra > min)
216 15712 pred_mode_intra -= 67;
217 1211596 return pred_mode_intra;
218 }
219