FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/refs.c
Date: 2026-09-14 12:48:48
Exec Total Coverage
Lines: 360 420 85.7%
Functions: 26 28 92.9%
Branches: 232 316 73.4%

Line Branch Exec Source
1 /*
2 * VVC reference management
3 *
4 * Copyright (C) 2023 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 <stdatomic.h>
24 #include <stdbool.h>
25
26 #include "libavutil/mem.h"
27 #include "libavutil/thread.h"
28 #include "libavutil/refstruct.h"
29 #include "libavcodec/thread.h"
30 #include "libavcodec/decode.h"
31
32 #include "refs.h"
33
34
35 typedef struct FrameProgress {
36 atomic_int progress[VVC_PROGRESS_LAST];
37 VVCProgressListener *listener[VVC_PROGRESS_LAST];
38 AVMutex lock;
39 AVCond cond;
40 uint8_t has_lock;
41 uint8_t has_cond;
42 } FrameProgress;
43
44 55655 void ff_vvc_unref_frame(VVCFrameContext *fc, VVCFrame *frame, int flags)
45 {
46 /* frame->frame can be NULL if context init failed */
47
3/4
✓ Branch 0 taken 55655 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42978 times.
✓ Branch 3 taken 12677 times.
55655 if (!frame->frame || !frame->frame->buf[0])
48 42978 return;
49
50 12677 frame->flags &= ~flags;
51
2/2
✓ Branch 0 taken 6401 times.
✓ Branch 1 taken 6276 times.
12677 if (!(frame->flags & ~VVC_FRAME_FLAG_CORRUPT))
52 6401 frame->flags = 0;
53
2/2
✓ Branch 0 taken 6401 times.
✓ Branch 1 taken 6276 times.
12677 if (!frame->flags) {
54 6401 av_frame_unref(frame->frame);
55
56
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6401 times.
6401 if (frame->needs_fg) {
57 av_frame_unref(frame->frame_grain);
58 frame->needs_fg = 0;
59 }
60
61 6401 av_refstruct_unref(&frame->sps);
62 6401 av_refstruct_unref(&frame->pps);
63 6401 av_refstruct_unref(&frame->progress);
64
65 6401 av_refstruct_unref(&frame->tab_dmvr_mvf);
66
67 6401 av_refstruct_unref(&frame->rpl);
68 6401 frame->nb_rpl_elems = 0;
69 6401 av_refstruct_unref(&frame->rpl_tab);
70
71 6401 frame->collocated_ref = NULL;
72 6401 av_refstruct_unref(&frame->hwaccel_picture_private);
73 }
74 }
75
76 3060628 const RefPicList *ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
77 {
78 3060628 const int x_cb = x0 >> fc->ps.sps->ctb_log2_size_y;
79 3060628 const int y_cb = y0 >> fc->ps.sps->ctb_log2_size_y;
80 3060628 const int pic_width_cb = fc->ps.pps->ctb_width;
81 3060628 const int ctb_addr_rs = y_cb * pic_width_cb + x_cb;
82
83 3060628 return (const RefPicList *)ref->rpl_tab[ctb_addr_rs];
84 }
85
86 112 void ff_vvc_clear_refs(VVCFrameContext *fc)
87 {
88
2/2
✓ Branch 0 taken 1904 times.
✓ Branch 1 taken 112 times.
2016 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
89 1904 ff_vvc_unref_frame(fc, &fc->DPB[i],
90 VVC_FRAME_FLAG_SHORT_REF | VVC_FRAME_FLAG_LONG_REF);
91 112 }
92
93 104 void ff_vvc_flush_dpb(VVCFrameContext *fc)
94 {
95
2/2
✓ Branch 0 taken 1768 times.
✓ Branch 1 taken 104 times.
1872 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
96 1768 ff_vvc_unref_frame(fc, &fc->DPB[i], ~0);
97 104 }
98
99 1150 static void free_progress(AVRefStructOpaque unused, void *obj)
100 {
101 1150 FrameProgress *p = (FrameProgress *)obj;
102
103
1/2
✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
1150 if (p->has_cond)
104 1150 ff_cond_destroy(&p->cond);
105
1/2
✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
1150 if (p->has_lock)
106 1150 ff_mutex_destroy(&p->lock);
107 1150 }
108
109 1150 static FrameProgress *alloc_progress(void)
110 {
111 1150 FrameProgress *p = av_refstruct_alloc_ext(sizeof(*p), 0, NULL, free_progress);
112
113
1/2
✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
1150 if (p) {
114 1150 p->has_lock = !ff_mutex_init(&p->lock, NULL);
115 1150 p->has_cond = !ff_cond_init(&p->cond, NULL);
116
2/4
✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1150 times.
1150 if (!p->has_lock || !p->has_cond)
117 av_refstruct_unref(&p);
118 }
119 1150 return p;
120 }
121
122 1150 static VVCFrame *alloc_frame(VVCContext *s, VVCFrameContext *fc)
123 {
124 1150 const VVCSPS *sps = fc->ps.sps;
125 1150 const VVCPPS *pps = fc->ps.pps;
126
1/2
✓ Branch 0 taken 4587 times.
✗ Branch 1 not taken.
4587 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
127 int ret;
128 4587 VVCFrame *frame = &fc->DPB[i];
129 4587 VVCWindow *win = &frame->scaling_win;
130
2/2
✓ Branch 0 taken 3437 times.
✓ Branch 1 taken 1150 times.
4587 if (frame->frame->buf[0])
131 3437 continue;
132
133 1150 frame->sps = av_refstruct_ref_c(fc->ps.sps);
134 1150 frame->pps = av_refstruct_ref_c(fc->ps.pps);
135
136 // Add LCEVC SEI metadata here, as it's needed in get_buffer()
137
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1118 times.
1150 if (fc->sei.common.itut_t35.lcevc) {
138 32 ret = ff_frame_new_side_data_from_buf(s->avctx, frame->frame,
139 AV_FRAME_DATA_LCEVC, &fc->sei.common.itut_t35.lcevc);
140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (ret < 0)
141 goto fail;
142 }
143
144 1150 ret = ff_thread_get_buffer(s->avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
1150 if (ret < 0)
146 return NULL;
147
148 1150 frame->rpl = av_refstruct_allocz(s->current_frame.nb_units * sizeof(RefPicListTab));
149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
1150 if (!frame->rpl)
150 goto fail;
151 1150 frame->nb_rpl_elems = s->current_frame.nb_units;
152
153 1150 frame->tab_dmvr_mvf = av_refstruct_pool_get(fc->tab_dmvr_mvf_pool);
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
1150 if (!frame->tab_dmvr_mvf)
155 goto fail;
156
157 1150 frame->rpl_tab = av_refstruct_pool_get(fc->rpl_tab_pool);
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
1150 if (!frame->rpl_tab)
159 goto fail;
160 1150 frame->ctb_count = pps->ctb_width * pps->ctb_height;
161
2/2
✓ Branch 0 taken 56034 times.
✓ Branch 1 taken 1150 times.
57184 for (int j = 0; j < frame->ctb_count; j++)
162 56034 frame->rpl_tab[j] = frame->rpl;
163
164 1150 win->left_offset = pps->r->pps_scaling_win_left_offset * (1 << sps->hshift[CHROMA]);
165 1150 win->right_offset = pps->r->pps_scaling_win_right_offset * (1 << sps->hshift[CHROMA]);
166 1150 win->top_offset = pps->r->pps_scaling_win_top_offset * (1 << sps->vshift[CHROMA]);
167 1150 win->bottom_offset = pps->r->pps_scaling_win_bottom_offset * (1 << sps->vshift[CHROMA]);
168 1150 frame->ref_width = pps->r->pps_pic_width_in_luma_samples - win->left_offset - win->right_offset;
169 1150 frame->ref_height = pps->r->pps_pic_height_in_luma_samples - win->bottom_offset - win->top_offset;
170
171
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1129 times.
1150 if (fc->sei.frame_field_info.present) {
172
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 10 times.
21 if (fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD)
173 11 frame->frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST;
174
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 11 times.
21 if (fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD ||
175
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_BOTTOM_FIELD)
176 21 frame->frame->flags |= AV_FRAME_FLAG_INTERLACED;
177 }
178
179 1150 frame->progress = alloc_progress();
180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
1150 if (!frame->progress)
181 goto fail;
182
183 1150 ret = ff_hwaccel_frame_priv_alloc(s->avctx, &frame->hwaccel_picture_private);
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
1150 if (ret < 0)
185 goto fail;
186
187 1150 return frame;
188 fail:
189 ff_vvc_unref_frame(fc, frame, ~0);
190 return NULL;
191 }
192 av_log(s->avctx, AV_LOG_ERROR, "Error allocating frame, DPB full.\n");
193 return NULL;
194 }
195
196 1133 static void set_pict_type(AVFrame *frame, const VVCContext *s, const VVCFrameContext *fc)
197 {
198 1133 bool has_b = false, has_inter = false;
199
200
6/6
✓ Branch 0 taken 1126 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1021 times.
✓ Branch 3 taken 105 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 1009 times.
1133 if (IS_IRAP(s)) {
201 124 frame->pict_type = AV_PICTURE_TYPE_I;
202 124 frame->flags |= AV_FRAME_FLAG_KEY;
203 124 return;
204 }
205
206
2/2
✓ Branch 0 taken 1006 times.
✓ Branch 1 taken 3 times.
1009 if (fc->ps.ph.r->ph_inter_slice_allowed_flag) {
207 // At this point, fc->slices is not fully initialized; we need to inspect the CBS directly.
208 1006 const CodedBitstreamFragment *current = &s->current_frame;
209
4/4
✓ Branch 0 taken 2457 times.
✓ Branch 1 taken 108 times.
✓ Branch 2 taken 1559 times.
✓ Branch 3 taken 898 times.
2565 for (int i = 0; i < current->nb_units && !has_b; i++) {
210 1559 const CodedBitstreamUnit *unit = current->units + i;
211
3/4
✓ Branch 0 taken 1559 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1006 times.
✓ Branch 3 taken 553 times.
1559 if (unit->content_ref && unit->type <= VVC_RSV_IRAP_11) {
212 1006 const H266RawSliceHeader *rsh = unit->content_ref;
213 1006 has_inter |= !IS_I(rsh);
214 1006 has_b |= IS_B(rsh);
215 }
216 }
217 }
218
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1006 times.
1009 if (!has_inter)
219 3 frame->pict_type = AV_PICTURE_TYPE_I;
220
2/2
✓ Branch 0 taken 951 times.
✓ Branch 1 taken 55 times.
1006 else if (has_b)
221 951 frame->pict_type = AV_PICTURE_TYPE_B;
222 else
223 55 frame->pict_type = AV_PICTURE_TYPE_P;
224 }
225
226 1133 int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, AVFrame **frame)
227 {
228 1133 const VVCPH *ph= &fc->ps.ph;
229 1133 const int poc = ph->poc;
230 VVCFrame *ref;
231
232 /* check that this POC doesn't already exist */
233
2/2
✓ Branch 0 taken 19261 times.
✓ Branch 1 taken 1133 times.
20394 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
234 19261 VVCFrame *frame = &fc->DPB[i];
235
236
4/4
✓ Branch 0 taken 5226 times.
✓ Branch 1 taken 14035 times.
✓ Branch 2 taken 5117 times.
✓ Branch 3 taken 109 times.
19261 if (frame->frame->buf[0] && frame->sequence == s->seq_decode &&
237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5117 times.
5117 frame->poc == poc) {
238 av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence: %d.\n", poc);
239 return AVERROR_INVALIDDATA;
240 }
241 }
242
243 1133 ref = alloc_frame(s, fc);
244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1133 times.
1133 if (!ref)
245 return AVERROR(ENOMEM);
246
247 1133 set_pict_type(ref->frame, s, fc);
248 1133 *frame = ref->frame;
249 1133 fc->ref = ref;
250
251
5/6
✓ Branch 0 taken 932 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 917 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 917 times.
1133 if (s->no_output_before_recovery_flag && (IS_RASL(s) || !GDR_IS_RECOVERED(s)))
252 15 ref->flags = VVC_FRAME_FLAG_SHORT_REF;
253
1/2
✓ Branch 0 taken 1118 times.
✗ Branch 1 not taken.
1118 else if (ph->r->ph_pic_output_flag)
254 1118 ref->flags = VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_SHORT_REF;
255
256
2/2
✓ Branch 0 taken 1121 times.
✓ Branch 1 taken 12 times.
1133 if (!ph->r->ph_non_ref_pic_flag)
257 1121 ref->flags |= VVC_FRAME_FLAG_SHORT_REF;
258
259 1133 ref->poc = poc;
260 1133 ref->sequence = s->seq_decode;
261 1133 ref->frame->crop_left = fc->ps.pps->r->pps_conf_win_left_offset << fc->ps.sps->hshift[CHROMA];
262 1133 ref->frame->crop_right = fc->ps.pps->r->pps_conf_win_right_offset << fc->ps.sps->hshift[CHROMA];
263 1133 ref->frame->crop_top = fc->ps.pps->r->pps_conf_win_top_offset << fc->ps.sps->vshift[CHROMA];
264 1133 ref->frame->crop_bottom = fc->ps.pps->r->pps_conf_win_bottom_offset << fc->ps.sps->vshift[CHROMA];
265
266 1133 return 0;
267 }
268
269 1269 int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush)
270 {
271 1269 const VVCSPS *sps = fc->ps.sps;
272 118 do {
273 1387 int nb_output = 0;
274 1387 int min_poc = INT_MAX;
275 int min_idx, ret;
276
277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1387 times.
1387 if (no_output_of_prior_pics_flag) {
278 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
279 VVCFrame *frame = &fc->DPB[i];
280 if (!(frame->flags & VVC_FRAME_FLAG_BUMPING) && frame->poc != fc->ps.ph.poc &&
281 frame->sequence == s->seq_output) {
282 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT);
283 }
284 }
285 }
286
287
2/2
✓ Branch 0 taken 23579 times.
✓ Branch 1 taken 1387 times.
24966 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
288 23579 VVCFrame *frame = &fc->DPB[i];
289
2/2
✓ Branch 0 taken 5212 times.
✓ Branch 1 taken 18367 times.
23579 if ((frame->flags & VVC_FRAME_FLAG_OUTPUT) &&
290
2/2
✓ Branch 0 taken 4944 times.
✓ Branch 1 taken 268 times.
5212 frame->sequence == s->seq_output) {
291 4944 nb_output++;
292
3/4
✓ Branch 0 taken 2409 times.
✓ Branch 1 taken 2535 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2409 times.
4944 if (frame->poc < min_poc || nb_output == 1) {
293 2535 min_poc = frame->poc;
294 2535 min_idx = i;
295 }
296 }
297 }
298
299 /* wait for more frames before output */
300
5/6
✓ Branch 0 taken 1249 times.
✓ Branch 1 taken 138 times.
✓ Branch 2 taken 1090 times.
✓ Branch 3 taken 159 times.
✓ Branch 4 taken 1090 times.
✗ Branch 5 not taken.
1387 if (!flush && s->seq_output == s->seq_decode && sps &&
301
2/2
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 923 times.
1090 nb_output <= sps->r->sps_dpb_params.dpb_max_num_reorder_pics[sps->r->sps_max_sublayers_minus1])
302 167 return 0;
303
304
2/2
✓ Branch 0 taken 1068 times.
✓ Branch 1 taken 152 times.
1220 if (nb_output) {
305 1068 VVCFrame *frame = &fc->DPB[min_idx];
306
307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
1068 if (frame->flags & VVC_FRAME_FLAG_CORRUPT)
308 frame->frame->flags |= AV_FRAME_FLAG_CORRUPT;
309
310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
1068 ret = av_frame_ref(out, frame->needs_fg ? frame->frame_grain : frame->frame);
311
312
2/4
✓ Branch 0 taken 1068 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1068 times.
✗ Branch 3 not taken.
1068 if (!ret && !(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))
313 1068 av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS);
314
315
2/2
✓ Branch 0 taken 716 times.
✓ Branch 1 taken 352 times.
1068 if (frame->flags & VVC_FRAME_FLAG_BUMPING)
316 716 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_BUMPING);
317 else
318 352 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT);
319
320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
1068 if (ret < 0)
321 return ret;
322
323 1068 av_log(s->avctx, AV_LOG_DEBUG,
324 "Output frame with POC %d.\n", frame->poc);
325 1068 return 1;
326 }
327
328
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 34 times.
152 if (s->seq_output != s->seq_decode)
329 118 s->seq_output = (s->seq_output + 1) & 0xff;
330 else
331 34 break;
332 } while (1);
333 34 return 0;
334 }
335
336 1021 void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc)
337 {
338 1021 const VVCSPS *sps = fc->ps.sps;
339 1021 const int poc = fc->ps.ph.poc;
340 1021 int dpb = 0;
341 1021 int min_poc = INT_MAX;
342
343
2/2
✓ Branch 0 taken 17357 times.
✓ Branch 1 taken 1021 times.
18378 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
344 17357 VVCFrame *frame = &fc->DPB[i];
345
2/2
✓ Branch 0 taken 6204 times.
✓ Branch 1 taken 11153 times.
17357 if ((frame->flags) &&
346
2/2
✓ Branch 0 taken 6076 times.
✓ Branch 1 taken 128 times.
6204 frame->sequence == s->seq_output &&
347
2/2
✓ Branch 0 taken 5089 times.
✓ Branch 1 taken 987 times.
6076 frame->poc != poc) {
348 5089 dpb++;
349 }
350 }
351
352
3/4
✓ Branch 0 taken 1021 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 501 times.
✓ Branch 3 taken 520 times.
1021 if (sps && dpb >= sps->r->sps_dpb_params.dpb_max_dec_pic_buffering_minus1[sps->r->sps_max_sublayers_minus1] + 1) {
353
2/2
✓ Branch 0 taken 8517 times.
✓ Branch 1 taken 501 times.
9018 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
354 8517 VVCFrame *frame = &fc->DPB[i];
355
2/2
✓ Branch 0 taken 3345 times.
✓ Branch 1 taken 5172 times.
8517 if ((frame->flags) &&
356
1/2
✓ Branch 0 taken 3345 times.
✗ Branch 1 not taken.
3345 frame->sequence == s->seq_output &&
357
2/2
✓ Branch 0 taken 2844 times.
✓ Branch 1 taken 501 times.
3345 frame->poc != poc) {
358
4/4
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 2784 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 9 times.
2844 if (frame->flags == VVC_FRAME_FLAG_OUTPUT && frame->poc < min_poc) {
359 51 min_poc = frame->poc;
360 }
361 }
362 }
363
364
2/2
✓ Branch 0 taken 8517 times.
✓ Branch 1 taken 501 times.
9018 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
365 8517 VVCFrame *frame = &fc->DPB[i];
366
2/2
✓ Branch 0 taken 2225 times.
✓ Branch 1 taken 6292 times.
8517 if (frame->flags & VVC_FRAME_FLAG_OUTPUT &&
367
1/2
✓ Branch 0 taken 2225 times.
✗ Branch 1 not taken.
2225 frame->sequence == s->seq_output &&
368
2/2
✓ Branch 0 taken 2021 times.
✓ Branch 1 taken 204 times.
2225 frame->poc <= min_poc) {
369 2021 frame->flags |= VVC_FRAME_FLAG_BUMPING;
370 }
371 }
372
373 501 dpb--;
374 }
375 1021 }
376
377 7627 static VVCFrame *find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb)
378 {
379
2/2
✓ Branch 0 taken 395 times.
✓ Branch 1 taken 7232 times.
7627 const unsigned mask = use_msb ? ~0 : fc->ps.sps->max_pic_order_cnt_lsb - 1;
380
381
2/2
✓ Branch 0 taken 27759 times.
✓ Branch 1 taken 17 times.
27776 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
382 27759 VVCFrame *ref = &fc->DPB[i];
383
384 // In the specification, the current frame is not considered part of
385 // the DPB at this stage, therefore we treat it as if it's not there.
386
2/2
✓ Branch 0 taken 2369 times.
✓ Branch 1 taken 25390 times.
27759 if (ref == fc->ref)
387 2369 continue;
388
389
4/4
✓ Branch 0 taken 22643 times.
✓ Branch 1 taken 2747 times.
✓ Branch 2 taken 21715 times.
✓ Branch 3 taken 928 times.
25390 if (ref->frame->buf[0] && ref->sequence == s->seq_decode) {
390
2/2
✓ Branch 0 taken 7610 times.
✓ Branch 1 taken 14105 times.
21715 if ((ref->poc & mask) == poc)
391 7610 return ref;
392 }
393 }
394 17 return NULL;
395 }
396
397 25755 static void mark_ref(VVCFrame *frame, int flag)
398 {
399 25755 frame->flags &= ~(VVC_FRAME_FLAG_LONG_REF | VVC_FRAME_FLAG_SHORT_REF);
400 25755 frame->flags |= flag;
401 25755 }
402
403 17 static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int poc)
404 {
405 17 const VVCSPS *sps = fc->ps.sps;
406 17 const VVCPPS *pps = fc->ps.pps;
407 VVCFrame *frame;
408
409 17 frame = alloc_frame(s, fc);
410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (!frame)
411 return NULL;
412
413
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if (!s->avctx->hwaccel) {
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (!sps->pixel_shift) {
415 for (int i = 0; frame->frame->buf[i]; i++)
416 memset(frame->frame->buf[i]->data, 1 << (sps->bit_depth - 1),
417 frame->frame->buf[i]->size);
418 } else {
419
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 17 times.
68 for (int i = 0; frame->frame->data[i]; i++)
420
2/2
✓ Branch 0 taken 10688 times.
✓ Branch 1 taken 51 times.
10739 for (int y = 0; y < (pps->height >> sps->vshift[i]); y++) {
421 10688 uint8_t *dst = frame->frame->data[i] + y * frame->frame->linesize[i];
422 10688 AV_WN16(dst, 1 << (sps->bit_depth - 1));
423 10688 av_memcpy_backptr(dst + 2, 2, 2*(pps->width >> sps->hshift[i]) - 2);
424 }
425 }
426 }
427
428 17 frame->poc = poc;
429 17 frame->sequence = s->seq_decode;
430 17 frame->flags = VVC_FRAME_FLAG_CORRUPT;
431
432 17 ff_vvc_report_frame_finished(frame);
433
434 17 return frame;
435 }
436
437 #define CHECK_MAX(d) (frame->ref_##d * frame->sps->r->sps_pic_##d##_max_in_luma_samples >= ref->ref_##d * (frame->pps->r->pps_pic_##d##_in_luma_samples - max))
438 #define CHECK_SAMPLES(d) (frame->pps->r->pps_pic_##d##_in_luma_samples == ref->pps->r->pps_pic_##d##_in_luma_samples)
439 7627 static int check_candidate_ref(const VVCFrame *frame, const VVCRefPic *refp)
440 {
441 7627 const VVCFrame *ref = refp->ref;
442
443
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7619 times.
7627 if (refp->is_scaled) {
444 8 const int max = FFMAX(8, frame->sps->min_cb_size_y);
445 16 return frame->ref_width * 2 >= ref->ref_width &&
446
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 frame->ref_height * 2 >= ref->ref_height &&
447
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 frame->ref_width <= ref->ref_width * 8 &&
448
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 frame->ref_height <= ref->ref_height * 8 &&
449
3/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
16 CHECK_MAX(width) && CHECK_MAX(height);
450 }
451
2/4
✓ Branch 0 taken 7619 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7619 times.
✗ Branch 3 not taken.
7619 return CHECK_SAMPLES(width) && CHECK_SAMPLES(height);
452 }
453
454 #define RPR_SCALE(f) (((ref->f << 14) + (fc->ref->f >> 1)) / fc->ref->f)
455 /* add a reference with the given poc to the list and mark it as used in DPB */
456 7627 static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *list,
457 int poc, int ref_flag, uint8_t use_msb)
458 {
459 7627 VVCRefPic *refp = &list->refs[list->nb_refs];
460 VVCFrame *ref;
461
462
4/6
✓ Branch 0 taken 7232 times.
✓ Branch 1 taken 395 times.
✓ Branch 2 taken 7232 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7627 times.
7627 if (use_msb && poc == fc->ref->poc || list->nb_refs >= VVC_MAX_REF_ENTRIES)
463 return AVERROR_INVALIDDATA;
464
465 7627 ref = find_ref_idx(s, fc, poc, use_msb);
466
467
6/8
✓ Branch 0 taken 7627 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7613 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 7567 times.
✓ Branch 5 taken 46 times.
✓ Branch 6 taken 7567 times.
✗ Branch 7 not taken.
7627 if (!IS_CVSS(s)) {
468
3/4
✓ Branch 0 taken 7567 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 7548 times.
7567 const bool ref_corrupt = !ref || (ref->flags & VVC_FRAME_FLAG_CORRUPT);
469
2/2
✓ Branch 0 taken 6704 times.
✓ Branch 1 taken 863 times.
14271 const bool recovering = s->no_output_before_recovery_flag &&
470
3/4
✓ Branch 0 taken 6632 times.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6632 times.
6704 (IS_RASL(s) || !GDR_IS_RECOVERED(s));
471
472
3/4
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 7548 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
7567 if (ref_corrupt && !recovering) {
473 if (!(s->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) &&
474 !(s->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL))
475 return AVERROR_INVALIDDATA;
476
477 fc->ref->flags |= VVC_FRAME_FLAG_CORRUPT;
478 }
479 }
480
481
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 7610 times.
7627 if (!ref) {
482 17 ref = generate_missing_ref(s, fc, poc);
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (!ref)
484 return AVERROR(ENOMEM);
485 }
486
487 7627 refp->poc = poc;
488 7627 refp->ref = ref;
489 7627 refp->is_lt = ref_flag & VVC_FRAME_FLAG_LONG_REF;
490 22881 refp->is_scaled = ref->sps->r->sps_num_subpics_minus1 != fc->ref->sps->r->sps_num_subpics_minus1||
491
1/2
✓ Branch 0 taken 7627 times.
✗ Branch 1 not taken.
7627 memcmp(&ref->scaling_win, &fc->ref->scaling_win, sizeof(ref->scaling_win)) ||
492
3/4
✓ Branch 0 taken 7627 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7619 times.
✓ Branch 3 taken 8 times.
22873 ref->pps->r->pps_pic_width_in_luma_samples != fc->ref->pps->r->pps_pic_width_in_luma_samples ||
493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7619 times.
7619 ref->pps->r->pps_pic_height_in_luma_samples != fc->ref->pps->r->pps_pic_height_in_luma_samples;
494
495
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7627 times.
7627 if (!check_candidate_ref(fc->ref, refp))
496 return AVERROR_INVALIDDATA;
497
498
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7619 times.
7627 if (refp->is_scaled) {
499 8 refp->scale[0] = RPR_SCALE(ref_width);
500 8 refp->scale[1] = RPR_SCALE(ref_height);
501 }
502 7627 list->nb_refs++;
503
504 7627 mark_ref(ref, ref_flag);
505 7627 return 0;
506 }
507
508 1732 static int init_slice_rpl(const VVCFrameContext *fc, SliceContext *sc)
509 {
510 1732 VVCFrame *frame = fc->ref;
511 1732 const VVCSH *sh = &sc->sh;
512
513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1732 times.
1732 if (sc->slice_idx >= frame->nb_rpl_elems)
514 return AVERROR_INVALIDDATA;
515
516
2/2
✓ Branch 0 taken 54141 times.
✓ Branch 1 taken 1732 times.
55873 for (int i = 0; i < sh->num_ctus_in_curr_slice; i++) {
517 54141 const int rs = sh->ctb_addr_in_curr_slice[i];
518 54141 frame->rpl_tab[rs] = frame->rpl + sc->slice_idx;
519 }
520
521 1732 sc->rpl = frame->rpl_tab[sh->ctb_addr_in_curr_slice[0]]->refPicList;
522
523 1732 return 0;
524 }
525
526 7218 static int delta_poc_st(const H266RefPicListStruct *rpls,
527 const int lx, const int i, const VVCSPS *sps)
528 {
529 7218 int abs_delta_poc_st = rpls->abs_delta_poc_st[i];
530
4/4
✓ Branch 0 taken 6699 times.
✓ Branch 1 taken 519 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 447 times.
7218 if (!((sps->r->sps_weighted_pred_flag ||
531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6699 times.
6699 sps->r->sps_weighted_bipred_flag) && i != 0))
532 6771 abs_delta_poc_st++;
533 7218 return (1 - 2 * rpls->strp_entry_sign_flag[i]) * abs_delta_poc_st;
534 }
535
536 409 static int poc_lt(int *prev_delta_poc_msb, const int poc, const H266RefPicLists *ref_lists,
537 const int lx, const int j, const int max_poc_lsb)
538 {
539 409 const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx;
540
1/2
✓ Branch 0 taken 409 times.
✗ Branch 1 not taken.
409 int lt_poc = rpls->ltrp_in_header_flag ? ref_lists->poc_lsb_lt[lx][j] : rpls->rpls_poc_lsb_lt[j];
541
542
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 395 times.
409 if (ref_lists->delta_poc_msb_cycle_present_flag[lx][j]) {
543 14 const uint32_t delta = ref_lists->delta_poc_msb_cycle_lt[lx][j] + *prev_delta_poc_msb;
544 14 lt_poc += poc - delta * max_poc_lsb - (poc & (max_poc_lsb - 1));
545 14 *prev_delta_poc_msb = delta;
546 }
547 409 return lt_poc;
548 }
549
550 1732 int ff_vvc_slice_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
551 {
552 1732 const VVCSPS *sps = fc->ps.sps;
553 1732 const H266RawPPS *pps = fc->ps.pps->r;
554 1732 const VVCPH *ph = &fc->ps.ph;
555 1732 const H266RawSliceHeader *rsh = sc->sh.r;
556 1732 const int max_poc_lsb = sps->max_pic_order_cnt_lsb;
557 1732 const H266RefPicLists *ref_lists =
558
2/2
✓ Branch 0 taken 253 times.
✓ Branch 1 taken 1479 times.
1732 pps->pps_rpl_info_in_ph_flag ? &ph->r->ph_ref_pic_lists : &rsh->sh_ref_pic_lists;
559 1732 int ret = 0;
560
561 1732 ret = init_slice_rpl(fc, sc);
562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1732 times.
1732 if (ret < 0)
563 return ret;
564
565
2/2
✓ Branch 0 taken 3464 times.
✓ Branch 1 taken 1732 times.
5196 for (int lx = L0; lx <= L1; lx++) {
566 3464 const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx;
567 3464 RefPicList *rpl = sc->rpl + lx;
568 3464 int poc_base = ph->poc;
569 3464 int prev_delta_poc_msb = 0;
570
571 3464 rpl->nb_refs = 0;
572
2/2
✓ Branch 0 taken 7627 times.
✓ Branch 1 taken 3464 times.
11091 for (int i = 0, j = 0; i < rpls->num_ref_entries; i++) {
573 int poc;
574
1/2
✓ Branch 0 taken 7627 times.
✗ Branch 1 not taken.
7627 if (!rpls->inter_layer_ref_pic_flag[i]) {
575 7627 int use_msb = 1;
576 int ref_flag;
577
2/2
✓ Branch 0 taken 7218 times.
✓ Branch 1 taken 409 times.
7627 if (rpls->st_ref_pic_flag[i]) {
578 7218 poc = poc_base + delta_poc_st(rpls, lx, i, sps);
579 7218 poc_base = poc;
580 7218 ref_flag = VVC_FRAME_FLAG_SHORT_REF;
581 } else {
582 409 use_msb = ref_lists->delta_poc_msb_cycle_present_flag[lx][j];
583 409 poc = poc_lt(&prev_delta_poc_msb, ph->poc, ref_lists, lx, j, max_poc_lsb);
584 409 ref_flag = VVC_FRAME_FLAG_LONG_REF;
585 409 j++;
586 }
587 7627 ret = add_candidate_ref(s, fc, rpl, poc, ref_flag, use_msb);
588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7627 times.
7627 if (ret < 0)
589 return ret;
590 } else {
591 // OPI_B_3.bit and VPS_A_3.bit should cover this
592 avpriv_report_missing_feature(fc->log_ctx, "Inter layer ref");
593 ret = AVERROR_PATCHWELCOME;
594 return ret;
595 }
596 }
597
2/2
✓ Branch 0 taken 3182 times.
✓ Branch 1 taken 282 times.
3464 if (ph->r->ph_temporal_mvp_enabled_flag &&
598
2/2
✓ Branch 0 taken 1591 times.
✓ Branch 1 taken 1591 times.
3182 (!rsh->sh_collocated_from_l0_flag) == lx &&
599
1/2
✓ Branch 0 taken 1591 times.
✗ Branch 1 not taken.
1591 rsh->sh_collocated_ref_idx < rpl->nb_refs) {
600 1591 const VVCRefPic *refp = rpl->refs + rsh->sh_collocated_ref_idx;
601
2/4
✓ Branch 0 taken 1591 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1591 times.
1591 if (refp->is_scaled || refp->ref->sps->ctb_log2_size_y != sps->ctb_log2_size_y)
602 return AVERROR_INVALIDDATA;
603 1591 fc->ref->collocated_ref = refp->ref;
604 }
605 }
606 1732 return 0;
607 }
608
609 1133 int ff_vvc_frame_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
610 {
611 1133 int ret = 0;
612
613 /* clear the reference flags on all frames except the current one */
614
2/2
✓ Branch 0 taken 19261 times.
✓ Branch 1 taken 1133 times.
20394 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
615 19261 VVCFrame *frame = &fc->DPB[i];
616
617
2/2
✓ Branch 0 taken 1133 times.
✓ Branch 1 taken 18128 times.
19261 if (frame == fc->ref)
618 1133 continue;
619
620 18128 mark_ref(frame, 0);
621 }
622
623
1/2
✓ Branch 1 taken 1133 times.
✗ Branch 2 not taken.
1133 if ((ret = ff_vvc_slice_rpl(s, fc, sc)) < 0)
624 goto fail;
625
626 1133 fail:
627 /* release any frames that are now unused */
628
2/2
✓ Branch 0 taken 19261 times.
✓ Branch 1 taken 1133 times.
20394 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
629 19261 ff_vvc_unref_frame(fc, &fc->DPB[i], 0);
630 1133 return ret;
631 }
632
633 1150 void ff_vvc_report_frame_finished(VVCFrame *frame)
634 {
635 1150 ff_vvc_report_progress(frame, VVC_PROGRESS_MV, INT_MAX);
636 1150 ff_vvc_report_progress(frame, VVC_PROGRESS_PIXEL, INT_MAX);
637 1150 }
638
639 103248 static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l)
640 {
641 103248 return p->progress[l->vp] > l->y;
642 }
643
644 static void add_listener(VVCProgressListener **prev, VVCProgressListener *l)
645 {
646 l->next = *prev;
647 *prev = l;
648 }
649
650 static VVCProgressListener* remove_listener(VVCProgressListener **prev, VVCProgressListener *l)
651 {
652 *prev = l->next;
653 l->next = NULL;
654 return l;
655 }
656
657 10199 static VVCProgressListener* get_done_listener(FrameProgress *p, const VVCProgress vp)
658 {
659 10199 VVCProgressListener *list = NULL;
660 10199 VVCProgressListener **prev = &p->listener[vp];
661
662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10199 times.
10199 while (*prev) {
663 if (is_progress_done(p, *prev)) {
664 VVCProgressListener *l = remove_listener(prev, *prev);
665 add_listener(&list, l);
666 } else {
667 prev = &(*prev)->next;
668 }
669 }
670 10199 return list;
671 }
672
673 12465 void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y)
674 {
675 12465 FrameProgress *p = frame->progress;
676 12465 VVCProgressListener *l = NULL;
677
678 12465 ff_mutex_lock(&p->lock);
679
2/2
✓ Branch 0 taken 10199 times.
✓ Branch 1 taken 2266 times.
12465 if (p->progress[vp] < y) {
680 // Due to the nature of thread scheduling, later progress may reach this point before earlier progress.
681 // Therefore, we only update the progress when p->progress[vp] < y.
682 10199 p->progress[vp] = y;
683 10199 l = get_done_listener(p, vp);
684 10199 ff_cond_signal(&p->cond);
685 }
686 12465 ff_mutex_unlock(&p->lock);
687
688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12465 times.
12465 while (l) {
689 l->progress_done(l);
690 l = l->next;
691 }
692 12465 }
693
694 103248 void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l)
695 {
696 103248 FrameProgress *p = frame->progress;
697
698 103248 ff_mutex_lock(&p->lock);
699
700
1/2
✓ Branch 1 taken 103248 times.
✗ Branch 2 not taken.
103248 if (is_progress_done(p, l)) {
701 103248 ff_mutex_unlock(&p->lock);
702 103248 l->progress_done(l);
703 } else {
704 add_listener(p->listener + l->vp, l);
705 ff_mutex_unlock(&p->lock);
706 }
707 103248 }
708