FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/intra_utils.c
Date: 2024-07-16 12:46:59
Exec Total Coverage
Lines: 117 118 99.2%
Functions: 11 11 100.0%
Branches: 106 116 91.4%

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 75239 int ff_vvc_get_mip_size_id(const int w, const int h)
34 {
35
4/4
✓ Branch 0 taken 18437 times.
✓ Branch 1 taken 56802 times.
✓ Branch 2 taken 7867 times.
✓ Branch 3 taken 10570 times.
75239 if (w == 4 && h == 4)
36 7867 return 0;
37
8/8
✓ Branch 0 taken 56802 times.
✓ Branch 1 taken 10570 times.
✓ Branch 2 taken 40944 times.
✓ Branch 3 taken 15858 times.
✓ Branch 4 taken 13284 times.
✓ Branch 5 taken 27660 times.
✓ Branch 6 taken 7645 times.
✓ Branch 7 taken 5639 times.
67372 if ((w == 4 || h == 4) || (w == 8 && h == 8))
38 34073 return 1;
39 33299 return 2;
40 }
41
42 214385 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 214385 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 109379 times.
✓ Branch 3 taken 105006 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 109379 times.
214385 av_assert0(mode < INTRA_LT_CCLM && !(mode > INTRA_HORZ && mode < INTRA_VERT));
46
3/6
✓ Branch 0 taken 214385 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 214385 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 214385 times.
✗ Branch 5 not taken.
214385 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
47
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 214385 times.
214385 mode == INTRA_HORZ || mode == INTRA_VERT) {
48 nscale = (av_log2(w) + av_log2(h) - 2) >> 2;
49 } else {
50 214385 const int intra_pred_angle = ff_vvc_intra_pred_angle_derive(mode);
51 214385 const int inv_angle = ff_vvc_intra_inv_angle_derive(intra_pred_angle);
52
2/2
✓ Branch 0 taken 109379 times.
✓ Branch 1 taken 105006 times.
214385 if (mode >= INTRA_VERT)
53 109379 side_size = h;
54
2/2
✓ Branch 0 taken 105006 times.
✓ Branch 1 taken 109379 times.
214385 if (mode <= INTRA_HORZ)
55 105006 side_size = w;
56 214385 nscale = FFMIN(2, av_log2(side_size) - av_log2(3 * inv_angle - 2) + 8);
57 }
58 214385 return nscale;
59 }
60
61 746140 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 746140 times.
746140 av_assert0(mode < INTRA_LT_CCLM);
64
7/8
✓ Branch 0 taken 746140 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 678306 times.
✓ Branch 3 taken 67834 times.
✓ Branch 4 taken 655443 times.
✓ Branch 5 taken 22863 times.
✓ Branch 6 taken 655403 times.
✓ Branch 7 taken 40 times.
746140 if ((w >= 4 && h >= 4) && !ref_idx && !bdpcm_flag) {
65 int nscale;
66
6/6
✓ Branch 0 taken 383747 times.
✓ Branch 1 taken 271656 times.
✓ Branch 2 taken 331329 times.
✓ Branch 3 taken 52418 times.
✓ Branch 4 taken 304169 times.
✓ Branch 5 taken 27160 times.
655403 if (mode == INTRA_PLANAR || mode == INTRA_DC ||
67
2/2
✓ Branch 0 taken 31549 times.
✓ Branch 1 taken 272620 times.
304169 mode == INTRA_HORZ || mode == INTRA_VERT)
68 382783 return 1;
69
4/4
✓ Branch 0 taken 193912 times.
✓ Branch 1 taken 78708 times.
✓ Branch 2 taken 115684 times.
✓ Branch 3 taken 78228 times.
272620 if (mode > INTRA_HORZ && mode < INTRA_VERT)
70 115684 return 0;
71 156936 nscale = ff_vvc_nscale_derive(w, h, mode);
72 156936 return nscale >= 0;
73
74 }
75 90737 return 0;
76 }
77
78 2621763 static const ReconstructedArea* get_reconstructed_area(const VVCLocalContext *lc, const int x, const int y, const int c_idx)
79 {
80 2621763 const int ch_type = c_idx > 0;
81
2/2
✓ Branch 0 taken 25105949 times.
✓ Branch 1 taken 46155 times.
25152104 for (int i = lc->num_ras[ch_type] - 1; i >= 0; i--) {
82 25105949 const ReconstructedArea* a = &lc->ras[ch_type][i];
83 25105949 const int r = (a->x + a->w);
84 25105949 const int b = (a->y + a->h);
85
8/8
✓ Branch 0 taken 13579648 times.
✓ Branch 1 taken 11526301 times.
✓ Branch 2 taken 4464967 times.
✓ Branch 3 taken 9114681 times.
✓ Branch 4 taken 2920167 times.
✓ Branch 5 taken 1544800 times.
✓ Branch 6 taken 2080075 times.
✓ Branch 7 taken 840092 times.
25105949 if (a->x <= x && x < r && a->y <= y && y < b)
86 2080075 return a;
87
88 //it's too far away, no need check it;
89
4/4
✓ Branch 0 taken 9114681 times.
✓ Branch 1 taken 13911193 times.
✓ Branch 2 taken 495533 times.
✓ Branch 3 taken 8619148 times.
23025874 if (x >= r && y >= b)
90 495533 break;
91 }
92 541688 return NULL;
93 }
94
95 829634 int ff_vvc_get_top_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
96 {
97 829634 const VVCFrameContext *fc = lc->fc;
98 829634 const VVCSPS *sps = fc->ps.sps;
99 829634 const int hs = sps->hshift[c_idx];
100 829634 const int vs = sps->vshift[c_idx];
101 829634 const int log2_ctb_size_v = sps->ctb_log2_size_y - vs;
102 829634 const int end_of_ctb_x = ((lc->cu->x0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
103 829634 const int y0b = av_zero_extend(y, log2_ctb_size_v);
104 829634 const int max_x = FFMIN(fc->ps.pps->width, end_of_ctb_x) >> hs;
105 const ReconstructedArea *a;
106 829634 int px = x;
107
108
2/2
✓ Branch 0 taken 87859 times.
✓ Branch 1 taken 741775 times.
829634 if (!y0b) {
109
2/2
✓ Branch 0 taken 19546 times.
✓ Branch 1 taken 68313 times.
87859 if (!lc->ctb_up_flag)
110 19546 return 0;
111 68313 target_size = FFMIN(target_size, (lc->end_of_tiles_x >> hs) - x);
112
2/2
✓ Branch 0 taken 4029 times.
✓ Branch 1 taken 64284 times.
68313 if (sps->r->sps_entropy_coding_sync_enabled_flag)
113 4029 target_size = FFMIN(target_size, (end_of_ctb_x >> hs) - x);
114 68313 return target_size;
115 }
116
117 741775 target_size = FFMAX(0, FFMIN(target_size, max_x - x));
118
4/4
✓ Branch 0 taken 1317000 times.
✓ Branch 1 taken 469651 times.
✓ Branch 3 taken 1044876 times.
✓ Branch 4 taken 272124 times.
1786651 while (target_size > 0 && (a = get_reconstructed_area(lc, px, y - 1, c_idx))) {
119 1044876 const int sz = FFMIN(target_size, a->x + a->w - px);
120 1044876 px += sz;
121 1044876 target_size -= sz;
122 }
123 741775 return px - x;
124 }
125
126 828124 int ff_vvc_get_left_available(const VVCLocalContext *lc, const int x, const int y, int target_size, const int c_idx)
127 {
128 828124 const VVCFrameContext *fc = lc->fc;
129 828124 const VVCSPS *sps = fc->ps.sps;
130 828124 const int hs = sps->hshift[c_idx];
131 828124 const int vs = sps->vshift[c_idx];
132 828124 const int log2_ctb_size_h = sps->ctb_log2_size_y - hs;
133 828124 const int x0b = av_zero_extend(x, log2_ctb_size_h);
134 828124 const int end_of_ctb_y = ((lc->cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y;
135 828124 const int max_y = FFMIN(fc->ps.pps->height, end_of_ctb_y) >> vs;
136 const ReconstructedArea *a;
137 828124 int py = y;
138
139
4/4
✓ Branch 0 taken 115060 times.
✓ Branch 1 taken 713064 times.
✓ Branch 2 taken 19383 times.
✓ Branch 3 taken 95677 times.
828124 if (!x0b && !lc->ctb_left_flag)
140 19383 return 0;
141
142 808741 target_size = FFMAX(0, FFMIN(target_size, max_y - y));
143
2/2
✓ Branch 0 taken 95677 times.
✓ Branch 1 taken 713064 times.
808741 if (!x0b)
144 95677 return target_size;
145
146
4/4
✓ Branch 0 taken 1304763 times.
✓ Branch 1 taken 443500 times.
✓ Branch 3 taken 1035199 times.
✓ Branch 4 taken 269564 times.
1748263 while (target_size > 0 && (a = get_reconstructed_area(lc, x - 1, py, c_idx))) {
147 1035199 const int sz = FFMIN(target_size, a->y + a->h - py);
148 1035199 py += sz;
149 1035199 target_size -= sz;
150 }
151 713064 return py - y;
152 }
153
154 2510877 static int less(const void *a, const void *b)
155 {
156 2510877 return *(const int*)a - *(const int*)b;
157 }
158
159 670901 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 670901 return bsearch(&mode, modes, FF_ARRAY_ELEMS(modes), sizeof(int), less) != NULL;
163 }
164
165 756609 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 756609 int sign = 1, idx, intra_pred_angle;
172
2/2
✓ Branch 0 taken 381573 times.
✓ Branch 1 taken 375036 times.
756609 if (pred_mode > INTRA_DIAG) {
173 381573 idx = pred_mode - INTRA_VERT;
174
2/2
✓ Branch 0 taken 339072 times.
✓ Branch 1 taken 35964 times.
375036 } else if (pred_mode > 0) {
175 339072 idx = INTRA_HORZ - pred_mode;
176 } else {
177 35964 idx = INTRA_HORZ - 2 - pred_mode;
178 }
179
2/2
✓ Branch 0 taken 288822 times.
✓ Branch 1 taken 467787 times.
756609 if (idx < 0) {
180 288822 idx = -idx;
181 288822 sign = -1;
182 }
183 756609 intra_pred_angle = sign * angles[idx];
184 756609 return intra_pred_angle;
185 }
186
187 #define ROUND(f) (int)(f < 0 ? -(-f + 0.5) : (f + 0.5))
188 542946 int ff_vvc_intra_inv_angle_derive(const int intra_pred_angle)
189 {
190 float inv_angle;
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 542946 times.
542946 av_assert0(intra_pred_angle);
192 542946 inv_angle = 32 * 512.0 / intra_pred_angle;
193
2/2
✓ Branch 0 taken 144411 times.
✓ Branch 1 taken 398535 times.
542946 return ROUND(inv_angle);
194 }
195
196 //8.4.5.2.7 Wide angle intra prediction mode mapping proces
197 866103 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 184044 times.
✓ Branch 1 taken 682059 times.
✓ Branch 2 taken 7774 times.
✓ Branch 3 taken 176270 times.
866103 if (cu->isp_split_type == ISP_NO_SPLIT || c_idx) {
203 689833 nw = tb_width;
204 689833 nh = tb_height;
205 } else {
206 176270 nw = cu->cb_width;
207 176270 nh = cu->cb_height;
208 }
209 866103 wh_ratio = FFABS(ff_log2(nw) - ff_log2(nh));
210
2/2
✓ Branch 0 taken 213717 times.
✓ Branch 1 taken 652386 times.
866103 max = (wh_ratio > 1) ? (8 + 2 * wh_ratio) : 8;
211
2/2
✓ Branch 0 taken 213717 times.
✓ Branch 1 taken 652386 times.
866103 min = (wh_ratio > 1) ? (60 - 2 * wh_ratio) : 60;
212
213
6/6
✓ Branch 0 taken 362763 times.
✓ Branch 1 taken 503340 times.
✓ Branch 2 taken 191248 times.
✓ Branch 3 taken 171515 times.
✓ Branch 4 taken 31668 times.
✓ Branch 5 taken 159580 times.
866103 if (nw > nh && pred_mode_intra >=2 && pred_mode_intra < max)
214 31668 pred_mode_intra += 65;
215
5/6
✓ Branch 0 taken 236198 times.
✓ Branch 1 taken 598237 times.
✓ Branch 2 taken 236198 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11316 times.
✓ Branch 5 taken 224882 times.
834435 else if (nh > nw && pred_mode_intra <= 66 && pred_mode_intra > min)
216 11316 pred_mode_intra -= 67;
217 866103 return pred_mode_intra;
218 }
219