FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/ps.c
Date: 2026-09-11 02:21:26
Exec Total Coverage
Lines: 822 932 88.2%
Functions: 75 76 98.7%
Branches: 416 546 76.2%

Line Branch Exec Source
1 /*
2 * VVC parameter set parser
3 *
4 * Copyright (C) 2023 Nuo Mi
5 * Copyright (C) 2022 Xu Mu
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23 #include <limits.h>
24 #include <stdbool.h>
25
26 #include "libavcodec/cbs_h266.h"
27 #include "libavcodec/decode.h"
28 #include "libavcodec/h2645data.h"
29 #include "libavutil/mem.h"
30 #include "libavutil/pixdesc.h"
31 #include "libavutil/refstruct.h"
32 #include "data.h"
33 #include "ps.h"
34 #include "dec.h"
35
36 107 static int sps_map_pixel_format(VVCSPS *sps, void *log_ctx)
37 {
38 107 const H266RawSPS *r = sps->r;
39 const AVPixFmtDescriptor *desc;
40
41
2/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
107 switch (sps->bit_depth) {
42 12 case 8:
43
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (r->sps_chroma_format_idc == 0) sps->pix_fmt = AV_PIX_FMT_GRAY8;
44
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (r->sps_chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P;
45
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (r->sps_chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P;
46
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (r->sps_chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P;
47 12 break;
48 95 case 10:
49
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 92 times.
95 if (r->sps_chroma_format_idc == 0) sps->pix_fmt = AV_PIX_FMT_GRAY10;
50
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 12 times.
95 if (r->sps_chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P10;
51
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 91 times.
95 if (r->sps_chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P10;
52
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 90 times.
95 if (r->sps_chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P10;
53 95 break;
54 case 12:
55 if (r->sps_chroma_format_idc == 0) sps->pix_fmt = AV_PIX_FMT_GRAY12;
56 if (r->sps_chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P12;
57 if (r->sps_chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P12;
58 if (r->sps_chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P12;
59 break;
60 default:
61 av_log(log_ctx, AV_LOG_ERROR,
62 "The following bit-depths are currently specified: 8, 10, 12 bits, "
63 "chroma_format_idc is %d, depth is %d\n",
64 r->sps_chroma_format_idc, sps->bit_depth);
65 return AVERROR_INVALIDDATA;
66 }
67
68 107 desc = av_pix_fmt_desc_get(sps->pix_fmt);
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (!desc)
70 return AVERROR(EINVAL);
71
72 107 sps->hshift[0] = sps->vshift[0] = 0;
73 107 sps->hshift[2] = sps->hshift[1] = desc->log2_chroma_w;
74 107 sps->vshift[2] = sps->vshift[1] = desc->log2_chroma_h;
75
76 107 sps->pixel_shift = sps->bit_depth > 8;
77
78 107 return 0;
79 }
80
81 107 static int sps_bit_depth(VVCSPS *sps, void *log_ctx)
82 {
83 107 const H266RawSPS *r = sps->r;
84
85 107 sps->bit_depth = r->sps_bitdepth_minus8 + 8;
86 107 sps->qp_bd_offset = 6 * (sps->bit_depth - 8);
87 107 sps->log2_transform_range =
88
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
107 r->sps_extended_precision_flag ? FFMAX(15, FFMIN(20, sps->bit_depth + 6)) : 15;
89 107 return sps_map_pixel_format(sps, log_ctx);
90 }
91
92 104 static int sps_chroma_qp_table(VVCSPS *sps)
93 {
94 104 const H266RawSPS *r = sps->r;
95 208 const int num_qp_tables = r->sps_same_qp_table_for_chroma_flag ?
96
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 101 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
104 1 : (r->sps_joint_cbcr_enabled_flag ? 3 : 2);
97
98
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 104 times.
214 for (int i = 0; i < num_qp_tables; i++) {
99 int num_points_in_qp_table;
100 int8_t qp_in[VVC_MAX_POINTS_IN_QP_TABLE], qp_out[VVC_MAX_POINTS_IN_QP_TABLE];
101 unsigned int delta_qp_in[VVC_MAX_POINTS_IN_QP_TABLE];
102 110 int off = sps->qp_bd_offset;
103
104 110 num_points_in_qp_table = r->sps_num_points_in_qp_table_minus1[i] + 1;
105
106 110 qp_out[0] = qp_in[0] = r->sps_qp_table_start_minus26[i] + 26;
107
2/2
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 110 times.
434 for (int j = 0; j < num_points_in_qp_table; j++ ) {
108 324 const uint8_t delta_qp_out = (r->sps_delta_qp_in_val_minus1[i][j] ^ r->sps_delta_qp_diff_val[i][j]);
109 324 delta_qp_in[j] = r->sps_delta_qp_in_val_minus1[i][j] + 1;
110 // Note: we cannot check qp_{in,out}[j+1] here as qp_*[j] + delta_qp_*
111 // may not fit in an 8-bit signed integer.
112
2/4
✓ Branch 0 taken 324 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 324 times.
324 if (qp_in[j] + delta_qp_in[j] > 63 || qp_out[j] + delta_qp_out > 63)
113 return AVERROR(EINVAL);
114 324 qp_in[j+1] = qp_in[j] + delta_qp_in[j];
115 324 qp_out[j+1] = qp_out[j] + delta_qp_out;
116 }
117 110 sps->chroma_qp_table[i][qp_in[0] + off] = qp_out[0];
118
2/2
✓ Branch 0 taken 3214 times.
✓ Branch 1 taken 110 times.
3324 for (int k = qp_in[0] - 1 + off; k >= 0; k--)
119 3214 sps->chroma_qp_table[i][k] = av_clip(sps->chroma_qp_table[i][k+1]-1, -off, 63);
120
121
2/2
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 110 times.
434 for (int j = 0; j < num_points_in_qp_table; j++) {
122 324 int sh = delta_qp_in[j] >> 1;
123
2/2
✓ Branch 0 taken 2539 times.
✓ Branch 1 taken 324 times.
2863 for (int k = qp_in[j] + 1 + off, m = 1; k <= qp_in[j+1] + off; k++, m++) {
124 2539 sps->chroma_qp_table[i][k] = sps->chroma_qp_table[i][qp_in[j] + off] +
125 2539 ((qp_out[j+1] - qp_out[j]) * m + sh) / delta_qp_in[j];
126 }
127 }
128
2/2
✓ Branch 0 taken 2353 times.
✓ Branch 1 taken 110 times.
2463 for (int k = qp_in[num_points_in_qp_table] + 1 + off; k <= 63 + off; k++)
129 2353 sps->chroma_qp_table[i][k] = av_clip(sps->chroma_qp_table[i][k-1] + 1, -sps->qp_bd_offset, 63);
130 }
131
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 3 times.
104 if (r->sps_same_qp_table_for_chroma_flag) {
132 101 memcpy(&sps->chroma_qp_table[1], &sps->chroma_qp_table[0], sizeof(sps->chroma_qp_table[0]));
133 101 memcpy(&sps->chroma_qp_table[2], &sps->chroma_qp_table[0], sizeof(sps->chroma_qp_table[0]));
134 }
135
136 104 return 0;
137 }
138
139 107 static void sps_poc(VVCSPS *sps)
140 {
141 107 sps->max_pic_order_cnt_lsb = 1 << (sps->r->sps_log2_max_pic_order_cnt_lsb_minus4 + 4);
142 107 }
143
144 107 static void sps_inter(VVCSPS *sps)
145 {
146 107 const H266RawSPS *r = sps->r;
147
148 107 sps->max_num_merge_cand = 6 - r->sps_six_minus_max_num_merge_cand;
149 107 sps->max_num_ibc_merge_cand = 6 - r->sps_six_minus_max_num_ibc_merge_cand;
150
151
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 21 times.
107 if (sps->r->sps_gpm_enabled_flag) {
152 86 sps->max_num_gpm_merge_cand = 2;
153
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 if (sps->max_num_merge_cand >= 3)
154 86 sps->max_num_gpm_merge_cand = sps->max_num_merge_cand - r->sps_max_num_merge_cand_minus_max_num_gpm_cand;
155 }
156
157 107 sps->log2_parallel_merge_level = r->sps_log2_parallel_merge_level_minus2 + 2;
158 107 }
159
160 107 static void sps_partition_constraints(VVCSPS* sps)
161 {
162 107 const H266RawSPS *r = sps->r;
163
164 107 sps->ctb_log2_size_y = r->sps_log2_ctu_size_minus5 + 5;
165 107 sps->ctb_size_y = 1 << sps->ctb_log2_size_y;
166 107 sps->min_cb_log2_size_y = r->sps_log2_min_luma_coding_block_size_minus2 + 2;
167 107 sps->min_cb_size_y = 1 << sps->min_cb_log2_size_y;
168
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 12 times.
107 sps->max_tb_size_y = 1 << (r->sps_max_luma_transform_size_64_flag ? 6 : 5);
169 107 sps->max_ts_size = 1 << (r->sps_log2_transform_skip_max_size_minus2 + 2);
170 107 }
171
172 107 static void sps_ladf(VVCSPS* sps)
173 {
174 107 const H266RawSPS *r = sps->r;
175
176
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 105 times.
107 if (r->sps_ladf_enabled_flag) {
177 2 sps->num_ladf_intervals = r->sps_num_ladf_intervals_minus2 + 2;
178 2 sps->ladf_interval_lower_bound[0] = 0;
179
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int i = 0; i < sps->num_ladf_intervals - 1; i++) {
180 4 sps->ladf_interval_lower_bound[i + 1] =
181 4 sps->ladf_interval_lower_bound[i] + r->sps_ladf_delta_threshold_minus1[i] + 1;
182 }
183 }
184 107 }
185
186 #define EXTENDED_SAR 255
187 9 static void sps_vui(AVCodecContext *c, const H266RawVUI *vui)
188 {
189 9 AVRational sar = (AVRational){ 0, 1 };
190
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (vui->vui_aspect_ratio_info_present_flag) {
191
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (vui->vui_aspect_ratio_idc < FF_ARRAY_ELEMS(ff_h2645_pixel_aspect))
192 2 sar = ff_h2645_pixel_aspect[vui->vui_aspect_ratio_idc];
193 else if (vui->vui_aspect_ratio_idc == EXTENDED_SAR) {
194 sar = (AVRational){ vui->vui_sar_width, vui->vui_sar_height };
195 } else {
196 av_log(c, AV_LOG_WARNING, "Unknown SAR index: %u.\n", vui->vui_aspect_ratio_idc);
197 }
198 }
199 9 ff_set_sar(c, sar);
200
201
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (vui->vui_colour_description_present_flag) {
202 2 c->color_primaries = vui->vui_colour_primaries;
203 2 c->color_trc = vui->vui_transfer_characteristics;
204 2 c->colorspace = vui->vui_matrix_coeffs;
205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 c->color_range = vui->vui_full_range_flag ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
206
207 // Set invalid values to "unspecified"
208
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!av_color_primaries_name(c->color_primaries))
209 c->color_primaries = AVCOL_PRI_UNSPECIFIED;
210
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!av_color_transfer_name(c->color_trc))
211 c->color_trc = AVCOL_TRC_UNSPECIFIED;
212
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!av_color_space_name(c->colorspace))
213 c->colorspace = AVCOL_SPC_UNSPECIFIED;
214 } else {
215 7 c->color_primaries = AVCOL_PRI_UNSPECIFIED;
216 7 c->color_trc = AVCOL_TRC_UNSPECIFIED;
217 7 c->colorspace = AVCOL_SPC_UNSPECIFIED;
218 7 c->color_range = AVCOL_RANGE_MPEG;
219 }
220 9 }
221
222
223 107 static void sps_export_stream_params(AVCodecContext *c, const VVCSPS *sps)
224 {
225 107 const H266RawSPS *r = sps->r;
226
227 107 c->has_b_frames = !!r->sps_dpb_params.dpb_max_num_reorder_pics[r->sps_max_sublayers_minus1];
228
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 98 times.
107 if (r->sps_vui_parameters_present_flag)
229 9 sps_vui(c, &r->vui);
230 107 }
231
232 107 static int sps_derive(VVCSPS *sps, AVCodecContext *c)
233 {
234 int ret;
235 107 const H266RawSPS *r = sps->r;
236
237 107 ret = sps_bit_depth(sps, c);
238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (ret < 0)
239 return ret;
240 107 sps_poc(sps);
241 107 sps_inter(sps);
242 107 sps_partition_constraints(sps);
243 107 sps_ladf(sps);
244
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 3 times.
107 if (r->sps_chroma_format_idc != 0) {
245 104 ret = sps_chroma_qp_table(sps);
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 104 times.
104 if (ret < 0)
247 return ret;
248 }
249 107 sps_export_stream_params(c, sps);
250
251 107 return 0;
252 }
253
254 107 static void sps_free(AVRefStructOpaque opaque, void *obj)
255 {
256 107 VVCSPS *sps = obj;
257 107 av_refstruct_unref(&sps->r);
258 107 }
259
260 107 static const VVCSPS *sps_alloc(const H266RawSPS *rsps, AVCodecContext *c)
261 {
262 int ret;
263 107 VVCSPS *sps = av_refstruct_alloc_ext(sizeof(*sps), 0, NULL, sps_free);
264
265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (!sps)
266 return NULL;
267
268 107 av_refstruct_replace(&sps->r, rsps);
269
270 107 ret = sps_derive(sps, c);
271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (ret < 0)
272 goto fail;
273
274 107 return sps;
275
276 fail:
277 av_refstruct_unref(&sps);
278 return NULL;
279 }
280
281 1102 static int decode_sps(VVCParamSets *ps, AVCodecContext *c, const H266RawSPS *rsps, int is_clvss)
282 {
283 1102 VVCContext *s = c->priv_data;
284 1102 const int sps_id = rsps->sps_seq_parameter_set_id;
285 1102 const VVCSPS *old_sps = ps->sps_list[sps_id];
286 const VVCSPS *sps;
287
288
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 986 times.
1102 if (is_clvss) {
289 116 ps->sps_id_used = 0;
290 116 s->seq_decode = (s->seq_decode + 1) & 0xff;
291 }
292
293
2/2
✓ Branch 0 taken 1000 times.
✓ Branch 1 taken 102 times.
1102 if (old_sps) {
294
4/4
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 698 times.
✓ Branch 2 taken 297 times.
✓ Branch 3 taken 5 times.
1000 if (old_sps->r == rsps || !memcmp(old_sps->r, rsps, sizeof(*old_sps->r))) {
295 995 ps->sps_id_used |= (1 << sps_id);
296 995 return 0;
297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 } else if (ps->sps_id_used & (1 << sps_id))
298 return AVERROR_INVALIDDATA;
299 }
300
301 107 sps = sps_alloc(rsps, c);
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (!sps)
303 return AVERROR(ENOMEM);
304
305 107 av_refstruct_unref(&ps->sps_list[sps_id]);
306 107 ps->sps_list[sps_id] = sps;
307 107 ps->sps_id_used |= (1 << sps_id);
308
309 107 return 0;
310 }
311
312 206 static void pps_chroma_qp_offset(VVCPPS *pps)
313 {
314 206 pps->chroma_qp_offset[CB - 1] = pps->r->pps_cb_qp_offset;
315 206 pps->chroma_qp_offset[CR - 1] = pps->r->pps_cr_qp_offset;
316 206 pps->chroma_qp_offset[JCBCR - 1]= pps->r->pps_joint_cbcr_qp_offset_value;
317
2/2
✓ Branch 0 taken 1236 times.
✓ Branch 1 taken 206 times.
1442 for (int i = 0; i < 6; i++) {
318 1236 pps->chroma_qp_offset_list[i][CB - 1] = pps->r->pps_cb_qp_offset_list[i];
319 1236 pps->chroma_qp_offset_list[i][CR - 1] = pps->r->pps_cr_qp_offset_list[i];
320 1236 pps->chroma_qp_offset_list[i][JCBCR - 1]= pps->r->pps_joint_cbcr_qp_offset_list[i];
321 }
322 206 }
323
324 206 static void pps_width_height(VVCPPS *pps, const VVCSPS *sps)
325 {
326 206 const H266RawPPS *r = pps->r;
327
328 206 pps->width = r->pps_pic_width_in_luma_samples;
329 206 pps->height = r->pps_pic_height_in_luma_samples;
330
331 206 pps->ctb_width = AV_CEIL_RSHIFT(pps->width, sps->ctb_log2_size_y);
332 206 pps->ctb_height = AV_CEIL_RSHIFT(pps->height, sps->ctb_log2_size_y);
333 206 pps->ctb_count = pps->ctb_width * pps->ctb_height;
334
335 206 pps->min_cb_width = pps->width >> sps->min_cb_log2_size_y;
336 206 pps->min_cb_height = pps->height >> sps->min_cb_log2_size_y;
337
338 206 pps->min_pu_width = pps->width >> MIN_PU_LOG2;
339 206 pps->min_pu_height = pps->height >> MIN_PU_LOG2;
340 206 pps->min_tu_width = pps->width >> MIN_TU_LOG2;
341 206 pps->min_tu_height = pps->height >> MIN_TU_LOG2;
342
343 206 pps->width32 = AV_CEIL_RSHIFT(pps->width, 5);
344 206 pps->height32 = AV_CEIL_RSHIFT(pps->height, 5);
345 206 pps->width64 = AV_CEIL_RSHIFT(pps->width, 6);
346 206 pps->height64 = AV_CEIL_RSHIFT(pps->height, 6);
347 206 }
348
349 206 static int pps_bd(VVCPPS *pps)
350 {
351 206 const H266RawPPS *r = pps->r;
352
353 206 pps->col_bd = av_calloc(r->num_tile_columns + 1, sizeof(*pps->col_bd));
354 206 pps->row_bd = av_calloc(r->num_tile_rows + 1, sizeof(*pps->row_bd));
355 206 pps->ctb_to_col_bd = av_calloc(pps->ctb_width + 1, sizeof(*pps->ctb_to_col_bd));
356 206 pps->ctb_to_row_bd = av_calloc(pps->ctb_height + 1, sizeof(*pps->ctb_to_col_bd));
357
4/8
✓ Branch 0 taken 206 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 206 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 206 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 206 times.
206 if (!pps->col_bd || !pps->row_bd || !pps->ctb_to_col_bd || !pps->ctb_to_row_bd)
358 return AVERROR(ENOMEM);
359
360
2/2
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 206 times.
530 for (int i = 0, j = 0; i < r->num_tile_columns; i++) {
361 324 pps->col_bd[i] = j;
362 324 j += r->col_width_val[i];
363
2/2
✓ Branch 0 taken 1439 times.
✓ Branch 1 taken 324 times.
1763 for (int k = pps->col_bd[i]; k < j; k++)
364 1439 pps->ctb_to_col_bd[k] = pps->col_bd[i];
365 }
366 206 pps->col_bd[r->num_tile_columns] = pps->ctb_to_col_bd[pps->ctb_width] = pps->ctb_width;
367
368
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 206 times.
515 for (int i = 0, j = 0; i < r->num_tile_rows; i++) {
369 309 pps->row_bd[i] = j;
370 309 j += r->row_height_val[i];
371
2/2
✓ Branch 0 taken 873 times.
✓ Branch 1 taken 309 times.
1182 for (int k = pps->row_bd[i]; k < j; k++)
372 873 pps->ctb_to_row_bd[k] = pps->row_bd[i];
373 }
374 206 pps->row_bd[r->num_tile_rows] = pps->ctb_to_row_bd[pps->ctb_height] = pps->ctb_height;
375
376 206 return 0;
377 }
378
379
380 163 static int next_tile_idx(int tile_idx, const int i, const H266RawPPS *r)
381 {
382
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 102 times.
163 if (r->pps_tile_idx_delta_present_flag) {
383 61 tile_idx += r->pps_tile_idx_delta_val[i];
384 } else {
385 102 tile_idx += r->pps_slice_width_in_tiles_minus1[i] + 1;
386
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 45 times.
102 if (tile_idx % r->num_tile_columns == 0)
387 57 tile_idx += (r->pps_slice_height_in_tiles_minus1[i]) * r->num_tile_columns;
388 }
389 163 return tile_idx;
390 }
391
392 163 static void tile_xy(int *tile_x, int *tile_y, const int tile_idx, const VVCPPS *pps)
393 {
394 163 *tile_x = tile_idx % pps->r->num_tile_columns;
395 163 *tile_y = tile_idx / pps->r->num_tile_columns;
396 163 }
397
398 732 static void ctu_xy(int *rx, int *ry, const int tile_x, const int tile_y, const VVCPPS *pps)
399 {
400 732 *rx = pps->col_bd[tile_x];
401 732 *ry = pps->row_bd[tile_y];
402 732 }
403
404 8463 static int ctu_rs(const int rx, const int ry, const VVCPPS *pps)
405 {
406 8463 return pps->ctb_width * ry + rx;
407 }
408
409 788 static int pps_add_ctus(VVCPPS *pps, int *off, const int rx, const int ry,
410 const int w, const int h)
411 {
412 788 int start = *off;
413
2/2
✓ Branch 0 taken 1738 times.
✓ Branch 1 taken 788 times.
2526 for (int y = 0; y < h; y++) {
414
2/2
✓ Branch 0 taken 8463 times.
✓ Branch 1 taken 1738 times.
10201 for (int x = 0; x < w; x++) {
415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8463 times.
8463 if (*off >= pps->ctb_count)
416 return AVERROR_INVALIDDATA;
417 8463 pps->ctb_addr_in_slice[*off] = ctu_rs(rx + x, ry + y, pps);
418 8463 (*off)++;
419 }
420 }
421 788 return *off - start;
422 }
423
424 2 static int pps_single_slice_picture(VVCPPS *pps, int *off)
425 {
426 2 pps->num_ctus_in_slice[0] = 0;
427
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (int j = 0; j < pps->r->num_tile_rows; j++) {
428
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (int i = 0; i < pps->r->num_tile_columns; i++) {
429 8 const int ret = pps_add_ctus(pps, off,
430 8 pps->col_bd[i], pps->row_bd[j],
431 8 pps->r->col_width_val[i], pps->r->row_height_val[j]);
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
433 return ret;
434 8 pps->num_ctus_in_slice[0] += ret;
435 }
436 }
437
438 2 return 0;
439 }
440
441 16 static void subpic_tiles(int *tile_x, int *tile_y, int *tile_x_end, int *tile_y_end,
442 const VVCSPS *sps, const VVCPPS *pps, const int i)
443 {
444 16 const int rx = sps->r->sps_subpic_ctu_top_left_x[i];
445 16 const int ry = sps->r->sps_subpic_ctu_top_left_y[i];
446
447 16 *tile_x = *tile_y = 0;
448
449
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 16 times.
40 while (pps->col_bd[*tile_x] < rx)
450 24 (*tile_x)++;
451
452
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 16 times.
24 while (pps->row_bd[*tile_y] < ry)
453 8 (*tile_y)++;
454
455 16 *tile_x_end = (*tile_x);
456 16 *tile_y_end = (*tile_y);
457
458
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 while (pps->col_bd[*tile_x_end] < rx + sps->r->sps_subpic_width_minus1[i] + 1)
459 16 (*tile_x_end)++;
460
461
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 while (pps->row_bd[*tile_y_end] < ry + sps->r->sps_subpic_height_minus1[i] + 1)
462 16 (*tile_y_end)++;
463 16 }
464
465 static int pps_subpic_less_than_one_tile_slice(VVCPPS *pps, const VVCSPS *sps, const int i, const int tx, const int ty, int *off)
466 {
467 const int ret = pps_add_ctus(pps, off,
468 sps->r->sps_subpic_ctu_top_left_x[i], sps->r->sps_subpic_ctu_top_left_y[i],
469 sps->r->sps_subpic_width_minus1[i] + 1, sps->r->sps_subpic_height_minus1[i] + 1);
470 if (ret < 0)
471 return ret;
472
473 pps->num_ctus_in_slice[i] = ret;
474 return 0;
475 }
476
477 16 static int pps_subpic_one_or_more_tiles_slice(VVCPPS *pps, const int tile_x, const int tile_y, const int x_end, const int y_end,
478 const int i, int *off)
479 {
480
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 for (int ty = tile_y; ty < y_end; ty++) {
481
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 for (int tx = tile_x; tx < x_end; tx++) {
482 16 const int ret = pps_add_ctus(pps, off,
483 16 pps->col_bd[tx], pps->row_bd[ty],
484 16 pps->r->col_width_val[tx], pps->r->row_height_val[ty]);
485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
486 return ret;
487
488 16 pps->num_ctus_in_slice[i] += ret;
489 }
490 }
491 16 return 0;
492 }
493
494 16 static int pps_subpic_slice(VVCPPS *pps, const VVCSPS *sps, const int i, int *off)
495 {
496 int tx, ty, x_end, y_end;
497
498 16 pps->slice_start_offset[i] = *off;
499 16 pps->num_ctus_in_slice[i] = 0;
500
501 16 subpic_tiles(&tx, &ty, &x_end, &y_end, sps, pps, i);
502
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 if (ty + 1 == y_end && sps->r->sps_subpic_height_minus1[i] + 1 < pps->r->row_height_val[ty])
503 return pps_subpic_less_than_one_tile_slice(pps, sps, i, tx, ty, off);
504 else
505 16 return pps_subpic_one_or_more_tiles_slice(pps, tx, ty, x_end, y_end, i, off);
506 }
507
508 4 static int pps_single_slice_per_subpic(VVCPPS *pps, const VVCSPS *sps, int *off)
509 {
510 int ret;
511
512
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!sps->r->sps_subpic_info_present_flag) {
513 2 ret = pps_single_slice_picture(pps, off);
514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
515 return ret;
516 } else {
517
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 for (int i = 0; i < pps->r->pps_num_slices_in_pic_minus1 + 1; i++) {
518 16 const int ret = pps_subpic_slice(pps, sps, i, off);
519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
520 return ret;
521 }
522 }
523 4 return 0;
524 }
525
526 95 static int pps_one_tile_slices(VVCPPS *pps, const int tile_idx, int i, int *off)
527 {
528 95 const H266RawPPS *r = pps->r;
529 int rx, ry, ctu_y_end, tile_x, tile_y;
530
531 95 tile_xy(&tile_x, &tile_y, tile_idx, pps);
532 95 ctu_xy(&rx, &ry, tile_x, tile_y, pps);
533 95 ctu_y_end = ry + r->row_height_val[tile_y];
534
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 95 times.
222 while (ry < ctu_y_end) {
535 int ret;
536 127 pps->slice_start_offset[i] = *off;
537 127 ret = pps_add_ctus(pps, off, rx, ry,
538 127 r->col_width_val[tile_x], r->slice_height_in_ctus[i]);
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 127 times.
127 if (ret < 0)
540 return ret;
541 127 pps->num_ctus_in_slice[i] = ret;
542 127 ry += r->slice_height_in_ctus[i++];
543 }
544 95 i--;
545 95 return i;
546 }
547
548 68 static int pps_multi_tiles_slice(VVCPPS *pps, const int tile_idx, const int i, int *off, bool *tile_in_slice)
549 {
550 68 const H266RawPPS *r = pps->r;
551 int rx, ry, tile_x, tile_y;
552
553 68 tile_xy(&tile_x, &tile_y, tile_idx, pps);
554 68 pps->slice_start_offset[i] = *off;
555 68 pps->num_ctus_in_slice[i] = 0;
556
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 68 times.
196 for (int ty = tile_y; ty <= tile_y + r->pps_slice_height_in_tiles_minus1[i]; ty++) {
557
2/2
✓ Branch 0 taken 424 times.
✓ Branch 1 taken 128 times.
552 for (int tx = tile_x; tx <= tile_x + r->pps_slice_width_in_tiles_minus1[i]; tx++) {
558 int ret;
559 424 const int idx = ty * r->num_tile_columns + tx;
560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 424 times.
424 if (tile_in_slice[idx])
561 return AVERROR_INVALIDDATA;
562 424 tile_in_slice[idx] = true;
563 424 ctu_xy(&rx, &ry, tx, ty, pps);
564 424 ret = pps_add_ctus(pps, off, rx, ry,
565 424 r->col_width_val[tx], r->row_height_val[ty]);
566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 424 times.
424 if (ret < 0)
567 return ret;
568 424 pps->num_ctus_in_slice[i] += ret;
569 }
570 }
571
572 68 return 0;
573 }
574
575 41 static int pps_rect_slice(VVCPPS *pps, const VVCSPS *sps)
576 {
577 41 const H266RawPPS *r = pps->r;
578 41 bool tile_in_slice[VVC_MAX_TILES_PER_AU] = {false};
579 41 int tile_idx = 0, off = 0, ret;
580
581
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 37 times.
41 if (r->pps_single_slice_per_subpic_flag) {
582 4 return pps_single_slice_per_subpic(pps, sps, &off);
583 }
584
585
2/2
✓ Branch 0 taken 163 times.
✓ Branch 1 taken 37 times.
200 for (int i = 0; i < r->pps_num_slices_in_pic_minus1 + 1; i++) {
586
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 62 times.
163 if (!r->pps_slice_width_in_tiles_minus1[i] &&
587
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 6 times.
101 !r->pps_slice_height_in_tiles_minus1[i]) {
588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 if (tile_in_slice[tile_idx])
589 return AVERROR_INVALIDDATA;
590 95 tile_in_slice[tile_idx] = true;
591 95 ret = pps_one_tile_slices(pps, tile_idx, i, &off);
592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 if (ret < 0)
593 return ret;
594 95 i = ret;
595 } else {
596 68 ret = pps_multi_tiles_slice(pps, tile_idx, i, &off, tile_in_slice);
597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (ret < 0)
598 return ret;
599 }
600 163 tile_idx = next_tile_idx(tile_idx, i, r);
601 }
602
603
2/2
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 37 times.
556 for (int i = 0; i < r->num_tiles_in_pic; i++) {
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 519 times.
519 if (!tile_in_slice[i])
605 return AVERROR_INVALIDDATA;
606 }
607
608 37 return 0;
609 }
610
611 165 static int pps_no_rect_slice(VVCPPS* pps)
612 {
613 165 const H266RawPPS* r = pps->r;
614 165 int rx, ry, off = 0;
615
616
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 165 times.
338 for (int tile_y = 0; tile_y < r->num_tile_rows; tile_y++) {
617
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 173 times.
386 for (int tile_x = 0; tile_x < r->num_tile_columns; tile_x++) {
618 int ret;
619 213 ctu_xy(&rx, &ry, tile_x, tile_y, pps);
620 213 ret = pps_add_ctus(pps, &off, rx, ry, r->col_width_val[tile_x], r->row_height_val[tile_y]);
621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 213 times.
213 if (ret < 0)
622 return ret;
623 }
624 }
625
626 165 return 0;
627 }
628
629 206 static int pps_slice_map(VVCPPS *pps, const VVCSPS *sps)
630 {
631 int ret;
632
633 206 pps->ctb_addr_in_slice = av_calloc(pps->ctb_count, sizeof(*pps->ctb_addr_in_slice));
634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 206 times.
206 if (!pps->ctb_addr_in_slice)
635 return AVERROR(ENOMEM);
636
637
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 165 times.
206 if (pps->r->pps_rect_slice_flag)
638 41 return pps_rect_slice(pps, sps);
639
640 165 ret = pps_no_rect_slice(pps);
641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165 times.
165 if (ret < 0)
642 return ret;
643
644 165 return 0;
645 }
646
647 206 static void pps_ref_wraparound_offset(VVCPPS *pps, const VVCSPS *sps)
648 {
649 206 const H266RawPPS *r = pps->r;
650
651
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 203 times.
206 if (r->pps_ref_wraparound_enabled_flag)
652 3 pps->ref_wraparound_offset = (pps->width / sps->min_cb_size_y) - r->pps_pic_width_minus_wraparound_offset;
653 206 }
654
655 206 static void pps_subpic(VVCPPS *pps, const VVCSPS *sps)
656 {
657 206 const H266RawSPS *rsps = sps->r;
658
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 206 times.
492 for (int i = 0; i < rsps->sps_num_subpics_minus1 + 1; i++) {
659
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 177 times.
286 if (rsps->sps_subpic_treated_as_pic_flag[i]) {
660 109 pps->subpic_x[i] = rsps->sps_subpic_ctu_top_left_x[i] << sps->ctb_log2_size_y;
661 109 pps->subpic_y[i] = rsps->sps_subpic_ctu_top_left_y[i] << sps->ctb_log2_size_y;
662 109 pps->subpic_width[i] = FFMIN(pps->width - pps->subpic_x[i], (rsps->sps_subpic_width_minus1[i] + 1) << sps->ctb_log2_size_y);
663 109 pps->subpic_height[i] = FFMIN(pps->height - pps->subpic_y[i], (rsps->sps_subpic_height_minus1[i] + 1) << sps->ctb_log2_size_y);
664 } else {
665 177 pps->subpic_x[i] = 0;
666 177 pps->subpic_y[i] = 0;
667 177 pps->subpic_width[i] = pps->width;
668 177 pps->subpic_height[i] = pps->height;
669 }
670 }
671 206 }
672
673 206 static int pps_derive(VVCPPS *pps, const VVCSPS *sps)
674 {
675 int ret;
676
677 206 pps_chroma_qp_offset(pps);
678 206 pps_width_height(pps, sps);
679
680 206 ret = pps_bd(pps);
681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 206 times.
206 if (ret < 0)
682 return ret;
683
684 206 ret = pps_slice_map(pps, sps);
685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 206 times.
206 if (ret < 0)
686 return ret;
687
688 206 pps_ref_wraparound_offset(pps, sps);
689 206 pps_subpic(pps, sps);
690
691 206 return 0;
692 }
693
694 206 static void pps_free(AVRefStructOpaque opaque, void *obj)
695 {
696 206 VVCPPS *pps = obj;
697
698 206 av_refstruct_unref(&pps->r);
699
700 206 av_freep(&pps->col_bd);
701 206 av_freep(&pps->row_bd);
702 206 av_freep(&pps->ctb_to_col_bd);
703 206 av_freep(&pps->ctb_to_row_bd);
704 206 av_freep(&pps->ctb_addr_in_slice);
705 206 }
706
707 206 static const VVCPPS *pps_alloc(const H266RawPPS *rpps, const VVCSPS *sps)
708 {
709 int ret;
710 206 VVCPPS *pps = av_refstruct_alloc_ext(sizeof(*pps), 0, NULL, pps_free);
711
712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 206 times.
206 if (!pps)
713 return NULL;
714
715 206 av_refstruct_replace(&pps->r, rpps);
716
717 206 ret = pps_derive(pps, sps);
718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 206 times.
206 if (ret < 0)
719 goto fail;
720
721 206 return pps;
722
723 fail:
724 av_refstruct_unref(&pps);
725 return NULL;
726 }
727
728 1102 static int decode_pps(VVCParamSets *ps, const H266RawPPS *rpps)
729 {
730 1102 int ret = 0;
731 1102 const int pps_id = rpps->pps_pic_parameter_set_id;
732 1102 const int sps_id = rpps->pps_seq_parameter_set_id;
733 1102 const VVCPPS *old_pps = ps->pps_list[pps_id];
734 const VVCPPS *pps;
735
736
4/4
✓ Branch 0 taken 978 times.
✓ Branch 1 taken 124 times.
✓ Branch 2 taken 896 times.
✓ Branch 3 taken 82 times.
1102 if (old_pps && old_pps->r == rpps)
737 896 return 0;
738
739 206 pps = pps_alloc(rpps, ps->sps_list[sps_id]);
740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 206 times.
206 if (!pps)
741 return AVERROR(ENOMEM);
742
743 206 av_refstruct_unref(&ps->pps_list[pps_id]);
744 206 ps->pps_list[pps_id] = pps;
745
746 206 return ret;
747 }
748
749 1102 static int decode_ps(VVCParamSets *ps, AVCodecContext *c, const SliceContext *sc, int is_clvss)
750 {
751 1102 const H266RawSlice *sl = sc->ref;
752 1102 const H266RawPPS *rpps = sl->pps;
753 1102 const H266RawSPS *rsps = sl->sps;
754 int ret;
755
756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (!rpps)
757 return AVERROR_INVALIDDATA;
758
759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (!rsps)
760 return AVERROR_INVALIDDATA;
761
762 1102 ret = decode_sps(ps, c, rsps, is_clvss);
763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (ret < 0)
764 return ret;
765
766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (rsps->sps_log2_ctu_size_minus5 > 2) {
767 // CTU > 128 are reserved in vvc spec v3
768 av_log(c, AV_LOG_ERROR, "CTU size > 128. \n");
769 return AVERROR_PATCHWELCOME;
770 }
771
772 1102 ret = decode_pps(ps, rpps);
773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (ret < 0)
774 return ret;
775
776 1102 return 0;
777 }
778
779 #define WEIGHT_TABLE(x) \
780 w->nb_weights[L##x] = r->num_weights_l##x; \
781 for (int i = 0; i < w->nb_weights[L##x]; i++) { \
782 w->weight_flag[L##x][LUMA][i] = r->luma_weight_l##x##_flag[i]; \
783 w->weight_flag[L##x][CHROMA][i] = r->chroma_weight_l##x##_flag[i]; \
784 w->weight[L##x][LUMA][i] = denom[LUMA] + r->delta_luma_weight_l##x[i]; \
785 w->offset[L##x][LUMA][i] = r->luma_offset_l##x[i]; \
786 for (int j = CB; j <= CR; j++) { \
787 w->weight[L##x][j][i] = denom[CHROMA] + r->delta_chroma_weight_l##x[i][j - 1]; \
788 w->offset[L##x][j][i] = 128 + r->delta_chroma_offset_l##x[i][j - 1]; \
789 w->offset[L##x][j][i] -= (128 * w->weight[L##x][j][i]) >> w->log2_denom[CHROMA]; \
790 w->offset[L##x][j][i] = av_clip_intp2(w->offset[L##x][j][i], 7); \
791 } \
792 } \
793
794 73 static void pred_weight_table(PredWeightTable *w, const H266RawPredWeightTable *r)
795 {
796 int denom[2];
797
798 73 w->log2_denom[LUMA] = r->luma_log2_weight_denom;
799 73 w->log2_denom[CHROMA] = w->log2_denom[LUMA] + r->delta_chroma_log2_weight_denom;
800 73 denom[LUMA] = 1 << w->log2_denom[LUMA];
801 73 denom[CHROMA] = 1 << w->log2_denom[CHROMA];
802
4/4
✓ Branch 0 taken 830 times.
✓ Branch 1 taken 415 times.
✓ Branch 2 taken 415 times.
✓ Branch 3 taken 73 times.
1318 WEIGHT_TABLE(0)
803
4/4
✓ Branch 0 taken 710 times.
✓ Branch 1 taken 355 times.
✓ Branch 2 taken 355 times.
✓ Branch 3 taken 73 times.
1138 WEIGHT_TABLE(1)
804 73 }
805
806 // 8.3.1 Decoding process for picture order count
807 1102 static int ph_compute_poc(const H266RawPictureHeader *ph, const H266RawSPS *sps, const int poc_tid0, const int is_clvss)
808 {
809 1102 const int max_poc_lsb = 1 << (sps->sps_log2_max_pic_order_cnt_lsb_minus4 + 4);
810 1102 const int prev_poc_lsb = poc_tid0 % max_poc_lsb;
811 1102 const int prev_poc_msb = poc_tid0 - prev_poc_lsb;
812 1102 const int poc_lsb = ph->ph_pic_order_cnt_lsb;
813 int poc_msb;
814
815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (ph->ph_poc_msb_cycle_present_flag) {
816 poc_msb = ph->ph_poc_msb_cycle_val * max_poc_lsb;
817
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 986 times.
1102 } else if (is_clvss) {
818 116 poc_msb = 0;
819 } else {
820
3/4
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 374 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 612 times.
986 if (poc_lsb < prev_poc_lsb && prev_poc_lsb - poc_lsb >= max_poc_lsb / 2)
821 poc_msb = prev_poc_msb + max_poc_lsb;
822
3/4
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 612 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 374 times.
986 else if (poc_lsb > prev_poc_lsb && poc_lsb - prev_poc_lsb > max_poc_lsb / 2)
823 poc_msb = prev_poc_msb - max_poc_lsb;
824 else
825 986 poc_msb = prev_poc_msb;
826 }
827
828 1102 return poc_msb + poc_lsb;
829 }
830
831 778240 static av_always_inline uint16_t lmcs_derive_lut_sample(uint16_t sample,
832 uint16_t *pivot1, uint16_t *pivot2, uint16_t *scale_coeff, const int idx, const int max)
833 {
834 778240 const int lut_sample =
835 778240 pivot1[idx] + ((scale_coeff[idx] * (sample - pivot2[idx]) + (1<< 10)) >> 11);
836 778240 return av_clip(lut_sample, 0, max - 1);
837 }
838
839 //8.8.2.2 Inverse mapping process for a luma sample
840 380 static int lmcs_derive_lut(VVCLMCS *lmcs, const H266RawAPS *rlmcs, const H266RawSPS *sps)
841 {
842 380 const int bit_depth = (sps->sps_bitdepth_minus8 + 8);
843 380 const int max = (1 << bit_depth);
844 380 const int org_cw = max / LMCS_MAX_BIN_SIZE;
845 380 const int shift = av_log2(org_cw);
846 380 const int off = 1 << (shift - 1);
847 int cw[LMCS_MAX_BIN_SIZE];
848 uint16_t input_pivot[LMCS_MAX_BIN_SIZE];
849 uint16_t scale_coeff[LMCS_MAX_BIN_SIZE];
850 uint16_t inv_scale_coeff[LMCS_MAX_BIN_SIZE];
851 380 int i, delta_crs, sum_cw = 0;
852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (bit_depth > LMCS_MAX_BIT_DEPTH)
853 return AVERROR_PATCHWELCOME;
854
855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (!rlmcs)
856 return AVERROR_INVALIDDATA;
857
858 380 lmcs->min_bin_idx = rlmcs->lmcs_min_bin_idx;
859 380 lmcs->max_bin_idx = LMCS_MAX_BIN_SIZE - 1 - rlmcs->lmcs_delta_max_bin_idx;
860
861 380 memset(cw, 0, sizeof(cw));
862
2/2
✓ Branch 0 taken 5069 times.
✓ Branch 1 taken 380 times.
5449 for (int i = lmcs->min_bin_idx; i <= lmcs->max_bin_idx; i++) {
863 5069 cw[i] = org_cw + (1 - 2 * rlmcs->lmcs_delta_sign_cw_flag[i]) * rlmcs->lmcs_delta_abs_cw[i];
864 5069 sum_cw += cw[i];
865 }
866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (sum_cw > (1 << bit_depth) - 1)
867 return AVERROR_INVALIDDATA;
868
869 380 delta_crs = (1 - 2 * rlmcs->lmcs_delta_sign_crs_flag) * rlmcs->lmcs_delta_abs_crs;
870
871 380 lmcs->pivot[0] = 0;
872
2/2
✓ Branch 0 taken 6080 times.
✓ Branch 1 taken 380 times.
6460 for (i = 0; i < LMCS_MAX_BIN_SIZE; i++) {
873 6080 input_pivot[i] = i * org_cw;
874 6080 lmcs->pivot[i + 1] = lmcs->pivot[i] + cw[i];
875
4/4
✓ Branch 0 taken 5676 times.
✓ Branch 1 taken 404 times.
✓ Branch 2 taken 5069 times.
✓ Branch 3 taken 607 times.
6080 if (i >= lmcs->min_bin_idx && i <= lmcs->max_bin_idx &&
876
2/2
✓ Branch 0 taken 4484 times.
✓ Branch 1 taken 585 times.
5069 lmcs->pivot[i] % (1 << (bit_depth - 5)) != 0 &&
877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4484 times.
4484 lmcs->pivot[i] >> (bit_depth - 5) == lmcs->pivot[i + 1] >> (bit_depth - 5))
878 return AVERROR_INVALIDDATA;
879 6080 scale_coeff[i] = (cw[i] * (1 << 11) + off) >> shift;
880
2/2
✓ Branch 0 taken 1011 times.
✓ Branch 1 taken 5069 times.
6080 if (cw[i] == 0) {
881 1011 inv_scale_coeff[i] = 0;
882 1011 lmcs->chroma_scale_coeff[i] = (1 << 11);
883 } else {
884 5069 const int cw_plus_d = cw[i] + delta_crs;
885
2/4
✓ Branch 0 taken 5069 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5069 times.
5069 if (cw_plus_d < (org_cw >> 3) || cw_plus_d > ((org_cw << 3) - 1))
886 return AVERROR_INVALIDDATA;
887 5069 inv_scale_coeff[i] = org_cw * (1 << 11) / cw[i];
888 5069 lmcs->chroma_scale_coeff[i] = org_cw * (1 << 11) / cw_plus_d;
889 }
890 }
891
892 //derive lmcs_fwd_lut
893
2/2
✓ Branch 0 taken 389120 times.
✓ Branch 1 taken 380 times.
389500 for (uint16_t sample = 0; sample < max; sample++) {
894 389120 const int idx_y = sample >> shift;
895 389120 const uint16_t fwd_sample = lmcs_derive_lut_sample(sample, lmcs->pivot,
896 input_pivot, scale_coeff, idx_y, max);
897
1/2
✓ Branch 0 taken 389120 times.
✗ Branch 1 not taken.
389120 if (bit_depth > 8)
898 389120 lmcs->fwd_lut.u16[sample] = fwd_sample;
899 else
900 lmcs->fwd_lut.u8 [sample] = fwd_sample;
901
902 }
903
904 //derive lmcs_inv_lut
905 380 i = lmcs->min_bin_idx;
906
2/2
✓ Branch 0 taken 389120 times.
✓ Branch 1 taken 380 times.
389500 for (uint16_t sample = 0; sample < max; sample++) {
907 uint16_t inv_sample;
908
4/4
✓ Branch 0 taken 377976 times.
✓ Branch 1 taken 16213 times.
✓ Branch 2 taken 5069 times.
✓ Branch 3 taken 372907 times.
394189 while (i <= lmcs->max_bin_idx && sample >= lmcs->pivot[i + 1])
909 5069 i++;
910 389120 i = FFMIN(i, LMCS_MAX_BIN_SIZE - 1);
911
912 389120 inv_sample = lmcs_derive_lut_sample(sample, input_pivot, lmcs->pivot,
913 inv_scale_coeff, i, max);
914
915
1/2
✓ Branch 0 taken 389120 times.
✗ Branch 1 not taken.
389120 if (bit_depth > 8)
916 389120 lmcs->inv_lut.u16[sample] = inv_sample;
917 else
918 lmcs->inv_lut.u8 [sample] = inv_sample;
919 }
920
921 380 return 0;
922 }
923
924 1102 static int ph_max_num_subblock_merge_cand(const H266RawSPS *sps, const H266RawPictureHeader *ph)
925 {
926
2/2
✓ Branch 0 taken 1063 times.
✓ Branch 1 taken 39 times.
1102 if (sps->sps_affine_enabled_flag)
927 1063 return 5 - sps->sps_five_minus_max_num_subblock_merge_cand;
928
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
39 return sps->sps_sbtmvp_enabled_flag && ph->ph_temporal_mvp_enabled_flag;
929 }
930
931 42 static int ph_vb_pos(uint16_t *vbs, uint8_t *num_vbs, const uint16_t *pos_minus_1, const uint8_t num_pos, uint16_t max, const int ctb_size_y)
932 {
933 42 max = FF_CEIL_RSHIFT(max, 3) - 2;
934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 for (int i = 0; i < num_pos; i++) {
935 if (pos_minus_1[i] > max)
936 return AVERROR_INVALIDDATA;
937
938 vbs[i] = (pos_minus_1[i] + 1) << 3;
939
940 // The distance between any two vertical virtual boundaries shall be greater than or equal to CtbSizeY luma samples
941 if (i && vbs[i] < vbs[i - 1] + ctb_size_y)
942 return AVERROR_INVALIDDATA;
943 }
944 42 *num_vbs = num_pos;
945
946 42 return 0;
947 }
948
949 #define VBF(f) (sps->sps_virtual_boundaries_present_flag ? sps->sps_##f : ph->r->ph_##f)
950 #define VBFS(c, d) VBF(virtual_boundary_pos_##c##_minus1), VBF(num_##d##_virtual_boundaries)
951
952 1102 static int ph_vb(VVCPH *ph, const H266RawSPS *sps, const H266RawPPS *pps)
953 {
954 1102 const int ctb_size_y = 1 << (sps->sps_log2_ctu_size_minus5 + 5);
955 int ret;
956
957
2/2
✓ Branch 0 taken 1081 times.
✓ Branch 1 taken 21 times.
1102 if (!sps->sps_virtual_boundaries_enabled_flag)
958 1081 return 0;
959
960
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 ret = ph_vb_pos(ph->vb_pos_x, &ph->num_ver_vbs, VBFS(x, ver), pps->pps_pic_width_in_luma_samples, ctb_size_y);
961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (ret < 0)
962 return ret;
963
964
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 ret = ph_vb_pos(ph->vb_pos_y, &ph->num_hor_vbs, VBFS(y, hor), pps->pps_pic_height_in_luma_samples, ctb_size_y);
965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (ret < 0)
966 return ret;
967
968 21 return 0;
969 }
970
971 1102 static int ph_derive(VVCPH *ph, const H266RawSPS *sps, const H266RawPPS *pps, const int poc_tid0, const int is_clvss)
972 {
973 int ret;
974 1102 ph->max_num_subblock_merge_cand = ph_max_num_subblock_merge_cand(sps, ph->r);
975
976 1102 ph->poc = ph_compute_poc(ph->r, sps, poc_tid0, is_clvss);
977
978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (pps->pps_wp_info_in_ph_flag)
979 pred_weight_table(&ph->pwt, &ph->r->ph_pred_weight_table);
980
981 1102 ret = ph_vb(ph, sps, pps);
982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (ret < 0)
983 return ret;
984
985 1102 return 0;
986 }
987
988 1102 static int decode_ph(VVCFrameParamSets *fps, const H266RawPictureHeader *rph, void *rph_ref,
989 const int poc_tid0, const int is_clvss)
990 {
991 int ret;
992 1102 VVCPH *ph = &fps->ph;
993 1102 const H266RawSPS *sps = fps->sps->r;
994 1102 const H266RawPPS *pps = fps->pps->r;
995
996 1102 ph->r = rph;
997 1102 av_refstruct_replace(&ph->rref, rph_ref);
998 1102 ret = ph_derive(ph, sps, pps, poc_tid0, is_clvss);
999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (ret < 0)
1000 return ret;
1001
1002 1102 return 0;
1003 }
1004
1005 1102 static int decode_frame_ps(VVCFrameParamSets *fps, const VVCParamSets *ps,
1006 const SliceContext *sc, const int poc_tid0, const int is_clvss, const VVCContext *s)
1007 {
1008 1102 const H266RawSlice *sl = sc->ref;
1009 1102 const H266RawPictureHeader *ph = sl->ph;
1010 1102 const H266RawPPS *rpps = sl->pps;
1011 int ret;
1012
1013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (!ph)
1014 return AVERROR_INVALIDDATA;
1015
1016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (!rpps)
1017 return AVERROR_INVALIDDATA;
1018
1019 1102 av_refstruct_replace(&fps->sps, ps->sps_list[rpps->pps_seq_parameter_set_id]);
1020 1102 av_refstruct_replace(&fps->pps, ps->pps_list[rpps->pps_pic_parameter_set_id]);
1021
1022 1102 ret = decode_ph(fps, ph, sl->ph_ref, poc_tid0, is_clvss);
1023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (ret < 0)
1024 return ret;
1025
1026
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 965 times.
1102 if (ph->ph_explicit_scaling_list_enabled_flag)
1027 137 av_refstruct_replace(&fps->sl, ps->scaling_list[ph->ph_scaling_list_aps_id]);
1028
1029
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 722 times.
1102 if (ph->ph_lmcs_enabled_flag) {
1030 380 ret = lmcs_derive_lut(&fps->lmcs, ps->lmcs_list[ph->ph_lmcs_aps_id], fps->sps->r);
1031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 if (ret < 0)
1032 return ret;
1033 }
1034
1035
2/2
✓ Branch 0 taken 8816 times.
✓ Branch 1 taken 1102 times.
9918 for (int i = 0; i < FF_ARRAY_ELEMS(fps->alf_list); i++)
1036 8816 av_refstruct_replace(&fps->alf_list[i], ps->alf_list[i]);
1037
1038 1102 return 0;
1039 }
1040
1041 1102 static void decode_recovery_flag(VVCContext *s)
1042 {
1043
4/4
✓ Branch 0 taken 1095 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 103 times.
✓ Branch 3 taken 992 times.
1102 if (IS_IDR(s))
1044 110 s->no_output_before_recovery_flag = 1;
1045
4/4
✓ Branch 0 taken 980 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 977 times.
992 else if (IS_CRA(s) || IS_GDR(s))
1046 15 s->no_output_before_recovery_flag = s->last_eos;
1047 1102 }
1048
1049 1102 static int decode_recovery_poc(VVCContext *s, const VVCFrameParamSets *fps)
1050 {
1051 1102 const VVCPH *ph = &fps->ph;
1052
1053
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1099 times.
1102 if (IS_GDR(s)) {
1054 3 const uint32_t recovery_poc_cnt = ph->r->ph_recovery_poc_cnt;
1055 3 const uint32_t max_recovery_poc_cnt = fps->sps->max_pic_order_cnt_lsb - 1;
1056
1057 3 const int64_t recovery_poc = (int64_t)ph->poc + recovery_poc_cnt;
1058
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (recovery_poc < INT_MIN || recovery_poc > INT_MAX) {
1059 av_log(s->avctx, AV_LOG_ERROR, "Recovery point POC out of range: %"PRId64".\n", recovery_poc);
1060 return AVERROR_INVALIDDATA;
1061 }
1062
1063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (recovery_poc_cnt > max_recovery_poc_cnt) {
1064 const int strict = s->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT;
1065 av_log(s->avctx, strict ? AV_LOG_ERROR : AV_LOG_WARNING,
1066 "ph_recovery_poc_cnt out of range: %"PRIu32
1067 ", expected [0, %"PRIu32"].\n", recovery_poc_cnt, max_recovery_poc_cnt);
1068 if (strict)
1069 return AVERROR_INVALIDDATA;
1070 }
1071
1072
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (s->no_output_before_recovery_flag)
1073 3 s->gdr_recovery_point_poc = recovery_poc;
1074 }
1075
1076
2/2
✓ Branch 0 taken 901 times.
✓ Branch 1 taken 201 times.
1102 if (s->no_output_before_recovery_flag) {
1077
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 898 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
901 if (!GDR_IS_RECOVERED(s) && s->gdr_recovery_point_poc <= ph->poc)
1078 3 GDR_SET_RECOVERED(s);
1079 }
1080
1081 1102 return 0;
1082 }
1083
1084 1102 int ff_vvc_decode_frame_ps(struct VVCFrameContext *fc, struct VVCContext *s)
1085 {
1086 1102 int ret = 0;
1087 1102 VVCFrameParamSets *fps = &fc->ps;
1088 1102 VVCParamSets *ps = &s->ps;
1089 1102 const SliceContext *sc = fc->slices[0];
1090 int is_clvss;
1091
1092 1102 decode_recovery_flag(s);
1093
10/10
✓ Branch 0 taken 1095 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 992 times.
✓ Branch 3 taken 103 times.
✓ Branch 4 taken 980 times.
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 977 times.
✓ Branch 8 taken 116 times.
✓ Branch 9 taken 9 times.
1102 is_clvss = IS_CLVSS(s);
1094
1095 1102 ret = decode_ps(ps, s->avctx, sc, is_clvss);
1096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (ret < 0)
1097 return ret;
1098
1099 1102 ret = decode_frame_ps(fps, ps, sc, s->poc_tid0, is_clvss, s);
1100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
1102 if (ret < 0)
1101 return ret;
1102
1103 1102 return decode_recovery_poc(s, fps);
1104 }
1105
1106 816 void ff_vvc_frame_ps_free(VVCFrameParamSets *fps)
1107 {
1108 816 av_refstruct_unref(&fps->sps);
1109 816 av_refstruct_unref(&fps->pps);
1110 816 av_refstruct_unref(&fps->ph.rref);
1111 816 av_refstruct_unref(&fps->sl);
1112
2/2
✓ Branch 0 taken 6528 times.
✓ Branch 1 taken 816 times.
7344 for (int i = 0; i < FF_ARRAY_ELEMS(fps->alf_list); i++)
1113 6528 av_refstruct_unref(&fps->alf_list[i]);
1114 816 }
1115
1116 102 void ff_vvc_ps_uninit(VVCParamSets *ps)
1117 {
1118
2/2
✓ Branch 0 taken 816 times.
✓ Branch 1 taken 102 times.
918 for (int i = 0; i < FF_ARRAY_ELEMS(ps->scaling_list); i++)
1119 816 av_refstruct_unref(&ps->scaling_list[i]);
1120
2/2
✓ Branch 0 taken 408 times.
✓ Branch 1 taken 102 times.
510 for (int i = 0; i < FF_ARRAY_ELEMS(ps->lmcs_list); i++)
1121 408 av_refstruct_unref(&ps->lmcs_list[i]);
1122
2/2
✓ Branch 0 taken 816 times.
✓ Branch 1 taken 102 times.
918 for (int i = 0; i < FF_ARRAY_ELEMS(ps->alf_list); i++)
1123 816 av_refstruct_unref(&ps->alf_list[i]);
1124
2/2
✓ Branch 0 taken 1632 times.
✓ Branch 1 taken 102 times.
1734 for (int i = 0; i < FF_ARRAY_ELEMS(ps->sps_list); i++)
1125 1632 av_refstruct_unref(&ps->sps_list[i]);
1126
2/2
✓ Branch 0 taken 6528 times.
✓ Branch 1 taken 102 times.
6630 for (int i = 0; i < FF_ARRAY_ELEMS(ps->pps_list); i++)
1127 6528 av_refstruct_unref(&ps->pps_list[i]);
1128 102 }
1129
1130 7665 static void alf_coeff(int16_t *coeff,
1131 const uint8_t *abs, const uint8_t *sign, const int size)
1132 {
1133
2/2
✓ Branch 0 taken 87540 times.
✓ Branch 1 taken 7665 times.
95205 for (int i = 0; i < size; i++)
1134 87540 coeff[i] = (1 - 2 * sign[i]) * abs[i];
1135 7665 }
1136
1137 830 static void alf_coeff_cc(int16_t *coeff,
1138 const uint8_t *mapped_abs, const uint8_t *sign)
1139 {
1140
2/2
✓ Branch 0 taken 5810 times.
✓ Branch 1 taken 830 times.
6640 for (int i = 0; i < ALF_NUM_COEFF_CC; i++) {
1141 5810 int c = mapped_abs[i];
1142
2/2
✓ Branch 0 taken 4996 times.
✓ Branch 1 taken 814 times.
5810 if (c)
1143 4996 c = (1 - 2 * sign[i]) * (1 << (c - 1));
1144 5810 coeff[i] = c;
1145 }
1146 830 }
1147
1148 328 static void alf_luma(VVCALF *alf, const H266RawAPS *aps)
1149 {
1150
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 277 times.
328 if (!aps->alf_luma_filter_signal_flag)
1151 51 return;
1152
1153
2/2
✓ Branch 0 taken 6925 times.
✓ Branch 1 taken 277 times.
7202 for (int i = 0; i < ALF_NUM_FILTERS_LUMA; i++) {
1154 6925 const int ref = aps->alf_luma_coeff_delta_idx[i];
1155 6925 const uint8_t *abs = aps->alf_luma_coeff_abs[ref];
1156 6925 const uint8_t *sign = aps->alf_luma_coeff_sign[ref];
1157
1158 6925 alf_coeff(alf->luma_coeff[i], abs, sign, ALF_NUM_COEFF_LUMA);
1159 6925 memcpy(alf->luma_clip_idx[i], aps->alf_luma_clip_idx[ref],
1160 sizeof(alf->luma_clip_idx[i]));
1161 }
1162 }
1163
1164 328 static void alf_chroma(VVCALF *alf, const H266RawAPS *aps)
1165 {
1166
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 238 times.
328 if (!aps->alf_chroma_filter_signal_flag)
1167 90 return;
1168
1169 238 alf->num_chroma_filters = aps->alf_chroma_num_alt_filters_minus1 + 1;
1170
2/2
✓ Branch 0 taken 740 times.
✓ Branch 1 taken 238 times.
978 for (int i = 0; i < alf->num_chroma_filters; i++) {
1171 740 const uint8_t *abs = aps->alf_chroma_coeff_abs[i];
1172 740 const uint8_t *sign = aps->alf_chroma_coeff_sign[i];
1173
1174 740 alf_coeff(alf->chroma_coeff[i], abs, sign, ALF_NUM_COEFF_CHROMA);
1175 740 memcpy(alf->chroma_clip_idx[i], aps->alf_chroma_clip_idx[i],
1176 sizeof(alf->chroma_clip_idx[i]));
1177 }
1178 }
1179
1180 328 static void alf_cc(VVCALF *alf, const H266RawAPS *aps)
1181 {
1182 328 const uint8_t (*abs[])[ALF_NUM_COEFF_CC] =
1183 328 { aps->alf_cc_cb_mapped_coeff_abs, aps->alf_cc_cr_mapped_coeff_abs };
1184 328 const uint8_t (*sign[])[ALF_NUM_COEFF_CC] =
1185 328 {aps->alf_cc_cb_coeff_sign, aps->alf_cc_cr_coeff_sign };
1186 328 const int signaled[] = { aps->alf_cc_cb_filter_signal_flag, aps->alf_cc_cr_filter_signal_flag};
1187
1188 328 alf->num_cc_filters[0] = aps->alf_cc_cb_filters_signalled_minus1 + 1;
1189 328 alf->num_cc_filters[1] = aps->alf_cc_cr_filters_signalled_minus1 + 1;
1190
1191
2/2
✓ Branch 0 taken 656 times.
✓ Branch 1 taken 328 times.
984 for (int idx = 0; idx < 2; idx++) {
1192
2/2
✓ Branch 0 taken 276 times.
✓ Branch 1 taken 380 times.
656 if (signaled[idx]) {
1193
2/2
✓ Branch 0 taken 830 times.
✓ Branch 1 taken 276 times.
1106 for (int i = 0; i < alf->num_cc_filters[idx]; i++)
1194 830 alf_coeff_cc(alf->cc_coeff[idx][i], abs[idx][i], sign[idx][i]);
1195 }
1196 }
1197 328 }
1198
1199 328 static void alf_derive(VVCALF *alf, const H266RawAPS *aps)
1200 {
1201 328 alf_luma(alf, aps);
1202 328 alf_chroma(alf, aps);
1203 328 alf_cc(alf, aps);
1204 328 }
1205
1206 328 static void alf_free(AVRefStructOpaque unused, void *obj)
1207 {
1208 328 VVCALF *alf = obj;
1209
1210 328 av_refstruct_unref(&alf->r);
1211 328 }
1212
1213 328 static int aps_decode_alf(const VVCALF **alf, const H266RawAPS *aps)
1214 {
1215 328 VVCALF *a = av_refstruct_alloc_ext(sizeof(*a), 0, NULL, alf_free);
1216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 328 times.
328 if (!a)
1217 return AVERROR(ENOMEM);
1218
1219 328 alf_derive(a, aps);
1220 328 av_refstruct_replace(&a->r, aps);
1221 328 av_refstruct_replace(alf, a);
1222 328 av_refstruct_unref(&a);
1223
1224 328 return 0;
1225 }
1226
1227 280 static int is_luma_list(const int id)
1228 {
1229
4/4
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 180 times.
280 return id % VVC_MAX_SAMPLE_ARRAYS == SL_START_4x4 || id == SL_START_64x64 + 1;
1230 }
1231
1232 448 static int derive_matrix_size(const int id)
1233 {
1234
4/4
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 320 times.
448 return id < SL_START_4x4 ? 2 : (id < SL_START_8x8 ? 4 : 8);
1235 }
1236
1237 // 7.4.3.20 Scaling list data semantics
1238 16 static void scaling_derive(VVCScalingList *sl, const H266RawAPS *aps)
1239 {
1240
2/2
✓ Branch 0 taken 448 times.
✓ Branch 1 taken 16 times.
464 for (int id = 0; id < SL_MAX_ID; id++) {
1241 448 const int matrix_size = derive_matrix_size(id);
1242 448 const int log2_size = av_log2(matrix_size);
1243 448 const int list_size = matrix_size * matrix_size;
1244 int coeff[SL_MAX_MATRIX_SIZE * SL_MAX_MATRIX_SIZE];
1245 const uint8_t *pred;
1246 const int *scaling_list;
1247 448 int dc = 0;
1248
1249
4/4
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 168 times.
✓ Branch 3 taken 100 times.
✓ Branch 4 taken 180 times.
448 if (aps->aps_chroma_present_flag || is_luma_list(id)) {
1250
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 146 times.
268 if (!aps->scaling_list_copy_mode_flag[id]) {
1251 122 int next_coef = 0;
1252
1253
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 86 times.
122 if (id >= SL_START_16x16)
1254 36 dc = next_coef = aps->scaling_list_dc_coef[id - SL_START_16x16];
1255
1256
2/2
✓ Branch 0 taken 5504 times.
✓ Branch 1 taken 122 times.
5626 for (int i = 0; i < list_size; i++) {
1257 5504 const int x = ff_vvc_diag_scan_x[3][3][i];
1258 5504 const int y = ff_vvc_diag_scan_y[3][3][i];
1259
1260
6/6
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 5120 times.
✓ Branch 2 taken 192 times.
✓ Branch 3 taken 192 times.
✓ Branch 4 taken 96 times.
✓ Branch 5 taken 96 times.
5504 if (!(id >= SL_START_64x64 && x >= 4 && y >= 4))
1261 5408 next_coef += aps->scaling_list_delta_coef[id][i];
1262 5504 coeff[i] = next_coef;
1263 }
1264 }
1265 }
1266
1267 //dc
1268
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 224 times.
448 if (id >= SL_START_16x16) {
1269
4/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 32 times.
224 if (!aps->scaling_list_copy_mode_flag[id] && !aps->scaling_list_pred_mode_flag[id]) {
1270 4 dc += 8;
1271
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 140 times.
220 } else if (!aps->scaling_list_pred_id_delta[id]) {
1272 80 dc += 16;
1273 } else {
1274 140 const int ref_id = id - aps->scaling_list_pred_id_delta[id];
1275
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 46 times.
140 if (ref_id >= SL_START_16x16)
1276 94 dc += sl->scaling_matrix_dc_rec[ref_id - SL_START_16x16];
1277 else
1278 46 dc += sl->scaling_matrix_rec[ref_id][0];
1279 }
1280 224 sl->scaling_matrix_dc_rec[id - SL_START_16x16] = dc & 255;
1281 }
1282
1283 //ac
1284
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 326 times.
448 scaling_list = aps->scaling_list_copy_mode_flag[id] ? ff_vvc_scaling_list0 : coeff;
1285
4/4
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 326 times.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 76 times.
448 if (!aps->scaling_list_copy_mode_flag[id] && !aps->scaling_list_pred_mode_flag[id])
1286 46 pred = ff_vvc_scaling_pred_8;
1287
2/2
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 208 times.
402 else if (!aps->scaling_list_pred_id_delta[id])
1288 194 pred = ff_vvc_scaling_pred_16;
1289 else
1290 208 pred = sl->scaling_matrix_rec[id - aps->scaling_list_pred_id_delta[id]];
1291
2/2
✓ Branch 0 taken 22144 times.
✓ Branch 1 taken 448 times.
22592 for (int i = 0; i < list_size; i++) {
1292 22144 const int x = ff_vvc_diag_scan_x[log2_size][log2_size][i];
1293 22144 const int y = ff_vvc_diag_scan_y[log2_size][log2_size][i];
1294 22144 const int off = y * matrix_size + x;
1295 22144 sl->scaling_matrix_rec[id][off] = (pred[off] + scaling_list[i]) & 255;
1296 }
1297 }
1298 16 }
1299
1300 16 static int aps_decode_scaling(const VVCScalingList **scaling, const H266RawAPS *aps)
1301 {
1302 16 VVCScalingList *sl = av_refstruct_allocz(sizeof(*sl));
1303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!sl)
1304 return AVERROR(ENOMEM);
1305
1306 16 scaling_derive(sl, aps);
1307 16 av_refstruct_replace(scaling, sl);
1308 16 av_refstruct_unref(&sl);
1309
1310 16 return 0;
1311 }
1312
1313 431 int ff_vvc_decode_aps(VVCParamSets *ps, const CodedBitstreamUnit *unit)
1314 {
1315 431 const H266RawAPS *aps = unit->content_ref;
1316 431 int ret = 0;
1317
1318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 431 times.
431 if (!aps)
1319 return AVERROR_INVALIDDATA;
1320
1321
3/4
✓ Branch 0 taken 328 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
431 switch (aps->aps_params_type) {
1322 328 case VVC_ASP_TYPE_ALF:
1323 328 ret = aps_decode_alf(&ps->alf_list[aps->aps_adaptation_parameter_set_id], aps);
1324 328 break;
1325 87 case VVC_ASP_TYPE_LMCS:
1326 87 av_refstruct_replace(&ps->lmcs_list[aps->aps_adaptation_parameter_set_id], aps);
1327 87 break;
1328 16 case VVC_ASP_TYPE_SCALING:
1329 16 ret = aps_decode_scaling(&ps->scaling_list[aps->aps_adaptation_parameter_set_id], aps);
1330 16 break;
1331 }
1332
1333 431 return ret;
1334 }
1335
1336 1867 static int sh_alf_aps(const VVCSH *sh, const VVCFrameParamSets *fps)
1337 {
1338
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 1411 times.
1867 if (!sh->r->sh_alf_enabled_flag)
1339 456 return 0;
1340
1341
2/2
✓ Branch 0 taken 1737 times.
✓ Branch 1 taken 1411 times.
3148 for (int i = 0; i < sh->r->sh_num_alf_aps_ids_luma; i++) {
1342 1737 const VVCALF *alf_aps_luma = fps->alf_list[sh->r->sh_alf_aps_id_luma[i]];
1343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1737 times.
1737 if (!alf_aps_luma)
1344 return AVERROR_INVALIDDATA;
1345 }
1346
1347
4/4
✓ Branch 0 taken 753 times.
✓ Branch 1 taken 658 times.
✓ Branch 2 taken 152 times.
✓ Branch 3 taken 601 times.
1411 if (sh->r->sh_alf_cb_enabled_flag || sh->r->sh_alf_cr_enabled_flag) {
1348 810 const VVCALF *alf_aps_chroma = fps->alf_list[sh->r->sh_alf_aps_id_chroma];
1349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 810 times.
810 if (!alf_aps_chroma)
1350 return AVERROR_INVALIDDATA;
1351 }
1352
1353
2/2
✓ Branch 0 taken 1352 times.
✓ Branch 1 taken 59 times.
1411 if (fps->sps->r->sps_ccalf_enabled_flag) {
1354
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 1136 times.
1352 if (sh->r->sh_alf_cc_cb_enabled_flag) {
1355 216 const VVCALF *alf_aps_cc_cr = fps->alf_list[sh->r->sh_alf_cc_cb_aps_id];
1356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
216 if (!alf_aps_cc_cr)
1357 return AVERROR_INVALIDDATA;
1358 }
1359
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 1164 times.
1352 if (sh->r->sh_alf_cc_cr_enabled_flag) {
1360 188 const VVCALF *alf_aps_cc_cr = fps->alf_list[sh->r->sh_alf_cc_cr_aps_id];
1361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
188 if (!alf_aps_cc_cr)
1362 return AVERROR_INVALIDDATA;
1363 }
1364 }
1365
1366 1411 return 0;
1367 }
1368
1369 1867 static int sh_slice_address(VVCSH *sh, const H266RawSPS *sps, const VVCPPS *pps)
1370 {
1371 1867 const int slice_address = sh->r->sh_slice_address;
1372
1373
2/2
✓ Branch 0 taken 718 times.
✓ Branch 1 taken 1149 times.
1867 if (pps->r->pps_rect_slice_flag) {
1374 718 int pic_level_slice_idx = slice_address;
1375
2/2
✓ Branch 0 taken 1047 times.
✓ Branch 1 taken 718 times.
1765 for (int j = 0; j < sh->r->curr_subpic_idx; j++)
1376 1047 pic_level_slice_idx += pps->r->num_slices_in_subpic[j];
1377 718 sh->ctb_addr_in_curr_slice = pps->ctb_addr_in_slice + pps->slice_start_offset[pic_level_slice_idx];
1378 718 sh->num_ctus_in_curr_slice = pps->num_ctus_in_slice[pic_level_slice_idx];
1379 } else {
1380 1149 int tile_x = slice_address % pps->r->num_tile_columns;
1381 1149 int tile_y = slice_address / pps->r->num_tile_columns;
1382 1149 const int slice_start_ctb = pps->row_bd[tile_y] * pps->ctb_width + pps->col_bd[tile_x] * pps->r->row_height_val[tile_y];
1383
1384 1149 sh->ctb_addr_in_curr_slice = pps->ctb_addr_in_slice + slice_start_ctb;
1385
1386 1149 sh->num_ctus_in_curr_slice = 0;
1387
2/2
✓ Branch 0 taken 1229 times.
✓ Branch 1 taken 1149 times.
2378 for (int tile_idx = slice_address; tile_idx <= slice_address + sh->r->sh_num_tiles_in_slice_minus1; tile_idx++) {
1388 1229 tile_x = tile_idx % pps->r->num_tile_columns;
1389 1229 tile_y = tile_idx / pps->r->num_tile_columns;
1390 1229 sh->num_ctus_in_curr_slice += pps->r->row_height_val[tile_y] * pps->r->col_width_val[tile_x];
1391 }
1392 }
1393
1394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1867 times.
1867 if (!sh->num_ctus_in_curr_slice)
1395 return AVERROR_INVALIDDATA;
1396
1397 1867 return 0;
1398 }
1399
1400 1867 static void sh_qp_y(VVCSH *sh, const H266RawPPS *pps, const H266RawPictureHeader *ph)
1401 {
1402 1867 const int init_qp = pps->pps_init_qp_minus26 + 26;
1403
1404
2/2
✓ Branch 0 taken 1597 times.
✓ Branch 1 taken 270 times.
1867 if (!pps->pps_qp_delta_info_in_ph_flag)
1405 1597 sh->slice_qp_y = init_qp + sh->r->sh_qp_delta;
1406 else
1407 270 sh->slice_qp_y = init_qp + ph->ph_qp_delta;
1408 1867 }
1409
1410 1867 static void sh_inter(VVCSH *sh, const H266RawSPS *sps, const H266RawPPS *pps)
1411 {
1412 1867 const H266RawSliceHeader *rsh = sh->r;
1413
1414
1/2
✓ Branch 0 taken 1867 times.
✗ Branch 1 not taken.
1867 if (!pps->pps_wp_info_in_ph_flag &&
1415
4/4
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 1785 times.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 12 times.
1867 ((pps->pps_weighted_pred_flag && IS_P(rsh)) ||
1416
4/4
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 1785 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 9 times.
1855 (pps->pps_weighted_bipred_flag && IS_B(rsh))))
1417 73 pred_weight_table(&sh->pwt, &rsh->sh_pred_weight_table);
1418 1867 }
1419
1420 1867 static void sh_deblock_offsets(VVCSH *sh)
1421 {
1422 1867 const H266RawSliceHeader *r = sh->r;
1423
1424
2/2
✓ Branch 0 taken 1854 times.
✓ Branch 1 taken 13 times.
1867 if (!r->sh_deblocking_filter_disabled_flag) {
1425 1854 sh->deblock.beta_offset[LUMA] = r->sh_luma_beta_offset_div2 * 2;
1426 1854 sh->deblock.tc_offset[LUMA] = r->sh_luma_tc_offset_div2 * 2;
1427 1854 sh->deblock.beta_offset[CB] = r->sh_cb_beta_offset_div2 * 2;
1428 1854 sh->deblock.tc_offset[CB] = r->sh_cb_tc_offset_div2 * 2;
1429 1854 sh->deblock.beta_offset[CR] = r->sh_cr_beta_offset_div2 * 2;
1430 1854 sh->deblock.tc_offset[CR] = r->sh_cr_tc_offset_div2 * 2;
1431 }
1432 1867 }
1433
1434 1867 static void sh_partition_constraints(VVCSH *sh, const H266RawSPS *sps, const H266RawPictureHeader *ph)
1435 {
1436 1867 const int min_cb_log2_size_y = sps->sps_log2_min_luma_coding_block_size_minus2 + 2;
1437 int min_qt_log2_size_y[2];
1438
1439
2/2
✓ Branch 0 taken 291 times.
✓ Branch 1 taken 1576 times.
1867 if (IS_I(sh->r)) {
1440 291 min_qt_log2_size_y[LUMA] = (min_cb_log2_size_y + ph->ph_log2_diff_min_qt_min_cb_intra_slice_luma);
1441 291 min_qt_log2_size_y[CHROMA] = (min_cb_log2_size_y + ph->ph_log2_diff_min_qt_min_cb_intra_slice_chroma);
1442
1443 291 sh->max_bt_size[LUMA] = 1 << (min_qt_log2_size_y[LUMA] + ph->ph_log2_diff_max_bt_min_qt_intra_slice_luma);
1444 291 sh->max_bt_size[CHROMA] = 1 << (min_qt_log2_size_y[CHROMA]+ ph->ph_log2_diff_max_bt_min_qt_intra_slice_chroma);
1445
1446 291 sh->max_tt_size[LUMA] = 1 << (min_qt_log2_size_y[LUMA] + ph->ph_log2_diff_max_tt_min_qt_intra_slice_luma);
1447 291 sh->max_tt_size[CHROMA] = 1 << (min_qt_log2_size_y[CHROMA]+ ph->ph_log2_diff_max_tt_min_qt_intra_slice_chroma);
1448
1449 291 sh->max_mtt_depth[LUMA] = ph->ph_max_mtt_hierarchy_depth_intra_slice_luma;
1450 291 sh->max_mtt_depth[CHROMA] = ph->ph_max_mtt_hierarchy_depth_intra_slice_chroma;
1451
1452 291 sh->cu_qp_delta_subdiv = ph->ph_cu_qp_delta_subdiv_intra_slice;
1453 291 sh->cu_chroma_qp_offset_subdiv = ph->ph_cu_chroma_qp_offset_subdiv_intra_slice;
1454 } else {
1455
2/2
✓ Branch 0 taken 3152 times.
✓ Branch 1 taken 1576 times.
4728 for (int i = LUMA; i <= CHROMA; i++) {
1456 3152 min_qt_log2_size_y[i] = (min_cb_log2_size_y + ph->ph_log2_diff_min_qt_min_cb_inter_slice);
1457 3152 sh->max_bt_size[i] = 1 << (min_qt_log2_size_y[i] + ph->ph_log2_diff_max_bt_min_qt_inter_slice);
1458 3152 sh->max_tt_size[i] = 1 << (min_qt_log2_size_y[i] + ph->ph_log2_diff_max_tt_min_qt_inter_slice);
1459 3152 sh->max_mtt_depth[i] = ph->ph_max_mtt_hierarchy_depth_inter_slice;
1460 }
1461
1462 1576 sh->cu_qp_delta_subdiv = ph->ph_cu_qp_delta_subdiv_inter_slice;
1463 1576 sh->cu_chroma_qp_offset_subdiv = ph->ph_cu_chroma_qp_offset_subdiv_inter_slice;
1464 }
1465
1466 1867 sh->min_qt_size[LUMA] = 1 << min_qt_log2_size_y[LUMA];
1467 1867 sh->min_qt_size[CHROMA] = 1 << min_qt_log2_size_y[CHROMA];
1468 1867 }
1469
1470 1867 static void sh_entry_points(VVCSH *sh, const H266RawSPS *sps, const VVCPPS *pps)
1471 {
1472
2/2
✓ Branch 0 taken 1773 times.
✓ Branch 1 taken 94 times.
1867 if (sps->sps_entry_point_offsets_present_flag) {
1473
2/2
✓ Branch 0 taken 51743 times.
✓ Branch 1 taken 1773 times.
53516 for (int i = 1, j = 0; i < sh->num_ctus_in_curr_slice; i++) {
1474 51743 const int pre_ctb_addr_x = sh->ctb_addr_in_curr_slice[i - 1] % pps->ctb_width;
1475 51743 const int pre_ctb_addr_y = sh->ctb_addr_in_curr_slice[i - 1] / pps->ctb_width;
1476 51743 const int ctb_addr_x = sh->ctb_addr_in_curr_slice[i] % pps->ctb_width;
1477 51743 const int ctb_addr_y = sh->ctb_addr_in_curr_slice[i] / pps->ctb_width;
1478
2/2
✓ Branch 0 taken 51700 times.
✓ Branch 1 taken 43 times.
51743 if (pps->ctb_to_row_bd[ctb_addr_y] != pps->ctb_to_row_bd[pre_ctb_addr_y] ||
1479
4/4
✓ Branch 0 taken 51489 times.
✓ Branch 1 taken 211 times.
✓ Branch 2 taken 4119 times.
✓ Branch 3 taken 47370 times.
51700 pps->ctb_to_col_bd[ctb_addr_x] != pps->ctb_to_col_bd[pre_ctb_addr_x] ||
1480
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 3966 times.
4119 (ctb_addr_y != pre_ctb_addr_y && sps->sps_entropy_coding_sync_enabled_flag)) {
1481 407 sh->entry_point_start_ctu[j++] = i;
1482 }
1483 }
1484 }
1485 1867 }
1486
1487 1867 static int sh_derive(VVCSH *sh, const VVCFrameParamSets *fps)
1488 {
1489 1867 const H266RawSPS *sps = fps->sps->r;
1490 1867 const H266RawPPS *pps = fps->pps->r;
1491 1867 const H266RawPictureHeader *ph = fps->ph.r;
1492 int ret;
1493
1494 1867 ret = sh_slice_address(sh, sps, fps->pps);
1495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1867 times.
1867 if (ret < 0)
1496 return ret;
1497 1867 ret = sh_alf_aps(sh, fps);
1498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1867 times.
1867 if (ret < 0)
1499 return ret;
1500 1867 sh_inter(sh, sps, pps);
1501 1867 sh_qp_y(sh, pps, ph);
1502 1867 sh_deblock_offsets(sh);
1503 1867 sh_partition_constraints(sh, sps, ph);
1504 1867 sh_entry_points(sh, sps, fps->pps);
1505
1506 1867 return 0;
1507 }
1508
1509 1867 int ff_vvc_decode_sh(VVCSH *sh, const VVCFrameParamSets *fps, const CodedBitstreamUnit *unit)
1510 {
1511 int ret;
1512
1513
2/4
✓ Branch 0 taken 1867 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1867 times.
1867 if (!fps->sps || !fps->pps)
1514 return AVERROR_INVALIDDATA;
1515
1516 1867 av_refstruct_replace(&sh->r, unit->content_ref);
1517
1518 1867 ret = sh_derive(sh, fps);
1519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1867 times.
1867 if (ret < 0)
1520 return ret;
1521
1522 1867 return 0;
1523 }
1524