FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/refs.c
Date: 2026-01-16 07:34:38
Exec Total Coverage
Lines: 353 419 84.2%
Functions: 26 28 92.9%
Branches: 225 312 72.1%

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