FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/refs.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 306 370 82.7%
Functions: 24 27 88.9%
Branches: 170 242 70.2%

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
25 #include "libavutil/mem.h"
26 #include "libavutil/thread.h"
27 #include "libavcodec/refstruct.h"
28 #include "libavcodec/thread.h"
29 #include "libavcodec/decode.h"
30
31 #include "refs.h"
32
33
34 typedef struct FrameProgress {
35 atomic_int progress[VVC_PROGRESS_LAST];
36 VVCProgressListener *listener[VVC_PROGRESS_LAST];
37 AVMutex lock;
38 AVCond cond;
39 uint8_t has_lock;
40 uint8_t has_cond;
41 } FrameProgress;
42
43 45404 void ff_vvc_unref_frame(VVCFrameContext *fc, VVCFrame *frame, int flags)
44 {
45 /* frame->frame can be NULL if context init failed */
46
3/4
✓ Branch 0 taken 45404 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34944 times.
✓ Branch 3 taken 10460 times.
45404 if (!frame->frame || !frame->frame->buf[0])
47 34944 return;
48
49 10460 frame->flags &= ~flags;
50
2/2
✓ Branch 0 taken 5294 times.
✓ Branch 1 taken 5166 times.
10460 if (!frame->flags) {
51 5294 av_frame_unref(frame->frame);
52 5294 ff_refstruct_unref(&frame->sps);
53 5294 ff_refstruct_unref(&frame->pps);
54 5294 ff_refstruct_unref(&frame->progress);
55
56 5294 ff_refstruct_unref(&frame->tab_dmvr_mvf);
57
58 5294 ff_refstruct_unref(&frame->rpl);
59 5294 frame->nb_rpl_elems = 0;
60 5294 ff_refstruct_unref(&frame->rpl_tab);
61
62 5294 frame->collocated_ref = NULL;
63 5294 ff_refstruct_unref(&frame->hwaccel_picture_private);
64 }
65 }
66
67 2368637 const RefPicList *ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
68 {
69 2368637 const int x_cb = x0 >> fc->ps.sps->ctb_log2_size_y;
70 2368637 const int y_cb = y0 >> fc->ps.sps->ctb_log2_size_y;
71 2368637 const int pic_width_cb = fc->ps.pps->ctb_width;
72 2368637 const int ctb_addr_rs = y_cb * pic_width_cb + x_cb;
73
74 2368637 return (const RefPicList *)ref->rpl_tab[ctb_addr_rs];
75 }
76
77 91 void ff_vvc_clear_refs(VVCFrameContext *fc)
78 {
79
2/2
✓ Branch 0 taken 1547 times.
✓ Branch 1 taken 91 times.
1638 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
80 1547 ff_vvc_unref_frame(fc, &fc->DPB[i],
81 VVC_FRAME_FLAG_SHORT_REF | VVC_FRAME_FLAG_LONG_REF);
82 91 }
83
84 82 void ff_vvc_flush_dpb(VVCFrameContext *fc)
85 {
86
2/2
✓ Branch 0 taken 1394 times.
✓ Branch 1 taken 82 times.
1476 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
87 1394 ff_vvc_unref_frame(fc, &fc->DPB[i], ~0);
88 82 }
89
90 951 static void free_progress(FFRefStructOpaque unused, void *obj)
91 {
92 951 FrameProgress *p = (FrameProgress *)obj;
93
94
1/2
✓ Branch 0 taken 951 times.
✗ Branch 1 not taken.
951 if (p->has_cond)
95 951 ff_cond_destroy(&p->cond);
96
1/2
✓ Branch 0 taken 951 times.
✗ Branch 1 not taken.
951 if (p->has_lock)
97 951 ff_mutex_destroy(&p->lock);
98 951 }
99
100 951 static FrameProgress *alloc_progress(void)
101 {
102 951 FrameProgress *p = ff_refstruct_alloc_ext(sizeof(*p), 0, NULL, free_progress);
103
104
1/2
✓ Branch 0 taken 951 times.
✗ Branch 1 not taken.
951 if (p) {
105 951 p->has_lock = !ff_mutex_init(&p->lock, NULL);
106 951 p->has_cond = !ff_cond_init(&p->cond, NULL);
107
2/4
✓ Branch 0 taken 951 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 951 times.
951 if (!p->has_lock || !p->has_cond)
108 ff_refstruct_unref(&p);
109 }
110 951 return p;
111 }
112
113 951 static VVCFrame *alloc_frame(VVCContext *s, VVCFrameContext *fc)
114 {
115 951 const VVCSPS *sps = fc->ps.sps;
116 951 const VVCPPS *pps = fc->ps.pps;
117
1/2
✓ Branch 0 taken 3786 times.
✗ Branch 1 not taken.
3786 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
118 int ret;
119 3786 VVCFrame *frame = &fc->DPB[i];
120 3786 VVCWindow *win = &frame->scaling_win;
121
2/2
✓ Branch 0 taken 2835 times.
✓ Branch 1 taken 951 times.
3786 if (frame->frame->buf[0])
122 2835 continue;
123
124 951 frame->sps = ff_refstruct_ref_c(fc->ps.sps);
125 951 frame->pps = ff_refstruct_ref_c(fc->ps.pps);
126
127 951 ret = ff_thread_get_buffer(s->avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 951 times.
951 if (ret < 0)
129 return NULL;
130
131 951 frame->rpl = ff_refstruct_allocz(s->current_frame.nb_units * sizeof(RefPicListTab));
132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 951 times.
951 if (!frame->rpl)
133 goto fail;
134 951 frame->nb_rpl_elems = s->current_frame.nb_units;
135
136 951 frame->tab_dmvr_mvf = ff_refstruct_pool_get(fc->tab_dmvr_mvf_pool);
137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 951 times.
951 if (!frame->tab_dmvr_mvf)
138 goto fail;
139
140 951 frame->rpl_tab = ff_refstruct_pool_get(fc->rpl_tab_pool);
141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 951 times.
951 if (!frame->rpl_tab)
142 goto fail;
143 951 frame->ctb_count = pps->ctb_width * pps->ctb_height;
144
2/2
✓ Branch 0 taken 45912 times.
✓ Branch 1 taken 951 times.
46863 for (int j = 0; j < frame->ctb_count; j++)
145 45912 frame->rpl_tab[j] = frame->rpl;
146
147 951 win->left_offset = pps->r->pps_scaling_win_left_offset << sps->hshift[CHROMA];
148 951 win->right_offset = pps->r->pps_scaling_win_right_offset << sps->hshift[CHROMA];
149 951 win->top_offset = pps->r->pps_scaling_win_top_offset << sps->vshift[CHROMA];
150 951 win->bottom_offset = pps->r->pps_scaling_win_bottom_offset << sps->vshift[CHROMA];
151 951 frame->ref_width = pps->r->pps_pic_width_in_luma_samples - win->left_offset - win->right_offset;
152 951 frame->ref_height = pps->r->pps_pic_height_in_luma_samples - win->bottom_offset - win->top_offset;
153
154 951 frame->progress = alloc_progress();
155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 951 times.
951 if (!frame->progress)
156 goto fail;
157
158 951 ret = ff_hwaccel_frame_priv_alloc(s->avctx, &frame->hwaccel_picture_private);
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 951 times.
951 if (ret < 0)
160 goto fail;
161
162 951 return frame;
163 fail:
164 ff_vvc_unref_frame(fc, frame, ~0);
165 return NULL;
166 }
167 av_log(s->avctx, AV_LOG_ERROR, "Error allocating frame, DPB full.\n");
168 return NULL;
169 }
170
171 936 int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, AVFrame **frame)
172 {
173 936 const VVCPH *ph= &fc->ps.ph;
174 936 const int poc = ph->poc;
175 VVCFrame *ref;
176
177 /* check that this POC doesn't already exist */
178
2/2
✓ Branch 0 taken 15912 times.
✓ Branch 1 taken 936 times.
16848 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
179 15912 VVCFrame *frame = &fc->DPB[i];
180
181
4/4
✓ Branch 0 taken 4318 times.
✓ Branch 1 taken 11594 times.
✓ Branch 2 taken 4209 times.
✓ Branch 3 taken 109 times.
15912 if (frame->frame->buf[0] && frame->sequence == s->seq_decode &&
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4209 times.
4209 frame->poc == poc) {
183 av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence: %d.\n", poc);
184 return AVERROR_INVALIDDATA;
185 }
186 }
187
188 936 ref = alloc_frame(s, fc);
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 936 times.
936 if (!ref)
190 return AVERROR(ENOMEM);
191
192 936 *frame = ref->frame;
193 936 fc->ref = ref;
194
195
5/6
✓ Branch 0 taken 751 times.
✓ Branch 1 taken 185 times.
✓ Branch 2 taken 736 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 736 times.
936 if (s->no_output_before_recovery_flag && (IS_RASL(s) || !GDR_IS_RECOVERED(s)))
196 15 ref->flags = VVC_FRAME_FLAG_SHORT_REF;
197
1/2
✓ Branch 0 taken 921 times.
✗ Branch 1 not taken.
921 else if (ph->r->ph_pic_output_flag)
198 921 ref->flags = VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_SHORT_REF;
199
200
2/2
✓ Branch 0 taken 924 times.
✓ Branch 1 taken 12 times.
936 if (!ph->r->ph_non_ref_pic_flag)
201 924 ref->flags |= VVC_FRAME_FLAG_SHORT_REF;
202
203 936 ref->poc = poc;
204 936 ref->sequence = s->seq_decode;
205 936 ref->frame->crop_left = fc->ps.pps->r->pps_conf_win_left_offset << fc->ps.sps->hshift[CHROMA];
206 936 ref->frame->crop_right = fc->ps.pps->r->pps_conf_win_right_offset << fc->ps.sps->hshift[CHROMA];
207 936 ref->frame->crop_top = fc->ps.pps->r->pps_conf_win_top_offset << fc->ps.sps->vshift[CHROMA];
208 936 ref->frame->crop_bottom = fc->ps.pps->r->pps_conf_win_bottom_offset << fc->ps.sps->vshift[CHROMA];
209
210 936 return 0;
211 }
212
213 1041 int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush)
214 {
215 1041 const VVCSPS *sps = fc->ps.sps;
216 91 do {
217 1132 int nb_output = 0;
218 1132 int min_poc = INT_MAX;
219 int min_idx, ret;
220
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1132 times.
1132 if (no_output_of_prior_pics_flag) {
222 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
223 VVCFrame *frame = &fc->DPB[i];
224 if (!(frame->flags & VVC_FRAME_FLAG_BUMPING) && frame->poc != fc->ps.ph.poc &&
225 frame->sequence == s->seq_output) {
226 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT);
227 }
228 }
229 }
230
231
2/2
✓ Branch 0 taken 19244 times.
✓ Branch 1 taken 1132 times.
20376 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
232 19244 VVCFrame *frame = &fc->DPB[i];
233
2/2
✓ Branch 0 taken 4310 times.
✓ Branch 1 taken 14934 times.
19244 if ((frame->flags & VVC_FRAME_FLAG_OUTPUT) &&
234
2/2
✓ Branch 0 taken 4069 times.
✓ Branch 1 taken 241 times.
4310 frame->sequence == s->seq_output) {
235 4069 nb_output++;
236
3/4
✓ Branch 0 taken 1956 times.
✓ Branch 1 taken 2113 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1956 times.
4069 if (frame->poc < min_poc || nb_output == 1) {
237 2113 min_poc = frame->poc;
238 2113 min_idx = i;
239 }
240 }
241 }
242
243 /* wait for more frames before output */
244
5/6
✓ Branch 0 taken 1025 times.
✓ Branch 1 taken 107 times.
✓ Branch 2 taken 893 times.
✓ Branch 3 taken 132 times.
✓ Branch 4 taken 893 times.
✗ Branch 5 not taken.
1132 if (!flush && s->seq_output == s->seq_decode && sps &&
245
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 760 times.
893 nb_output <= sps->r->sps_dpb_params.dpb_max_num_reorder_pics[sps->r->sps_max_sublayers_minus1])
246 133 return 0;
247
248
2/2
✓ Branch 0 taken 881 times.
✓ Branch 1 taken 118 times.
999 if (nb_output) {
249 881 VVCFrame *frame = &fc->DPB[min_idx];
250
251 881 ret = av_frame_ref(out, frame->frame);
252
2/2
✓ Branch 0 taken 581 times.
✓ Branch 1 taken 300 times.
881 if (frame->flags & VVC_FRAME_FLAG_BUMPING)
253 581 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_BUMPING);
254 else
255 300 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT);
256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 881 times.
881 if (ret < 0)
257 return ret;
258
259 881 av_log(s->avctx, AV_LOG_DEBUG,
260 "Output frame with POC %d.\n", frame->poc);
261 881 return 1;
262 }
263
264
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 27 times.
118 if (s->seq_output != s->seq_decode)
265 91 s->seq_output = (s->seq_output + 1) & 0xff;
266 else
267 27 break;
268 } while (1);
269 27 return 0;
270 }
271
272 845 void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc)
273 {
274 845 const VVCSPS *sps = fc->ps.sps;
275 845 const int poc = fc->ps.ph.poc;
276 845 int dpb = 0;
277 845 int min_poc = INT_MAX;
278
279
2/2
✓ Branch 0 taken 14365 times.
✓ Branch 1 taken 845 times.
15210 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
280 14365 VVCFrame *frame = &fc->DPB[i];
281
2/2
✓ Branch 0 taken 5120 times.
✓ Branch 1 taken 9245 times.
14365 if ((frame->flags) &&
282
2/2
✓ Branch 0 taken 4998 times.
✓ Branch 1 taken 122 times.
5120 frame->sequence == s->seq_output &&
283
2/2
✓ Branch 0 taken 4181 times.
✓ Branch 1 taken 817 times.
4998 frame->poc != poc) {
284 4181 dpb++;
285 }
286 }
287
288
3/4
✓ Branch 0 taken 845 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 398 times.
✓ Branch 3 taken 447 times.
845 if (sps && dpb >= sps->r->sps_dpb_params.dpb_max_dec_pic_buffering_minus1[sps->r->sps_max_sublayers_minus1] + 1) {
289
2/2
✓ Branch 0 taken 6766 times.
✓ Branch 1 taken 398 times.
7164 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
290 6766 VVCFrame *frame = &fc->DPB[i];
291
2/2
✓ Branch 0 taken 2734 times.
✓ Branch 1 taken 4032 times.
6766 if ((frame->flags) &&
292
1/2
✓ Branch 0 taken 2734 times.
✗ Branch 1 not taken.
2734 frame->sequence == s->seq_output &&
293
2/2
✓ Branch 0 taken 2336 times.
✓ Branch 1 taken 398 times.
2734 frame->poc != poc) {
294
4/4
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 2278 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 8 times.
2336 if (frame->flags == VVC_FRAME_FLAG_OUTPUT && frame->poc < min_poc) {
295 50 min_poc = frame->poc;
296 }
297 }
298 }
299
300
2/2
✓ Branch 0 taken 6766 times.
✓ Branch 1 taken 398 times.
7164 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
301 6766 VVCFrame *frame = &fc->DPB[i];
302
2/2
✓ Branch 0 taken 1843 times.
✓ Branch 1 taken 4923 times.
6766 if (frame->flags & VVC_FRAME_FLAG_OUTPUT &&
303
1/2
✓ Branch 0 taken 1843 times.
✗ Branch 1 not taken.
1843 frame->sequence == s->seq_output &&
304
2/2
✓ Branch 0 taken 1647 times.
✓ Branch 1 taken 196 times.
1843 frame->poc <= min_poc) {
305 1647 frame->flags |= VVC_FRAME_FLAG_BUMPING;
306 }
307 }
308
309 398 dpb--;
310 }
311 845 }
312
313 6100 static VVCFrame *find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb)
314 {
315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6100 times.
6100 const unsigned mask = use_msb ? ~0 : fc->ps.sps->max_pic_order_cnt_lsb - 1;
316
317
2/2
✓ Branch 0 taken 21837 times.
✓ Branch 1 taken 15 times.
21852 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
318 21837 VVCFrame *ref = &fc->DPB[i];
319
4/4
✓ Branch 0 taken 19499 times.
✓ Branch 1 taken 2338 times.
✓ Branch 2 taken 18571 times.
✓ Branch 3 taken 928 times.
21837 if (ref->frame->buf[0] && ref->sequence == s->seq_decode) {
320
2/2
✓ Branch 0 taken 6085 times.
✓ Branch 1 taken 12486 times.
18571 if ((ref->poc & mask) == poc)
321 6085 return ref;
322 }
323 }
324 15 return NULL;
325 }
326
327 21076 static void mark_ref(VVCFrame *frame, int flag)
328 {
329 21076 frame->flags &= ~(VVC_FRAME_FLAG_LONG_REF | VVC_FRAME_FLAG_SHORT_REF);
330 21076 frame->flags |= flag;
331 21076 }
332
333 15 static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int poc)
334 {
335 15 const VVCSPS *sps = fc->ps.sps;
336 15 const VVCPPS *pps = fc->ps.pps;
337 VVCFrame *frame;
338
339 15 frame = alloc_frame(s, fc);
340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!frame)
341 return NULL;
342
343
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (!s->avctx->hwaccel) {
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!sps->pixel_shift) {
345 for (int i = 0; frame->frame->buf[i]; i++)
346 memset(frame->frame->buf[i]->data, 1 << (sps->bit_depth - 1),
347 frame->frame->buf[i]->size);
348 } else {
349
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 15 times.
60 for (int i = 0; frame->frame->data[i]; i++)
350
2/2
✓ Branch 0 taken 7200 times.
✓ Branch 1 taken 45 times.
7245 for (int y = 0; y < (pps->height >> sps->vshift[i]); y++) {
351 7200 uint8_t *dst = frame->frame->data[i] + y * frame->frame->linesize[i];
352 7200 AV_WN16(dst, 1 << (sps->bit_depth - 1));
353 7200 av_memcpy_backptr(dst + 2, 2, 2*(pps->width >> sps->hshift[i]) - 2);
354 }
355 }
356 }
357
358 15 frame->poc = poc;
359 15 frame->sequence = s->seq_decode;
360 15 frame->flags = 0;
361
362 15 ff_vvc_report_frame_finished(frame);
363
364 15 return frame;
365 }
366
367 #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))
368 #define CHECK_SAMPLES(d) (frame->pps->r->pps_pic_##d##_in_luma_samples == ref->pps->r->pps_pic_##d##_in_luma_samples)
369 6100 static int check_candidate_ref(const VVCFrame *frame, const VVCRefPic *refp)
370 {
371 6100 const VVCFrame *ref = refp->ref;
372
373
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6092 times.
6100 if (refp->is_scaled) {
374 8 const int max = FFMAX(8, frame->sps->min_cb_size_y);
375 16 return frame->ref_width * 2 >= ref->ref_width &&
376
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 frame->ref_height * 2 >= ref->ref_height &&
377
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 frame->ref_width <= ref->ref_width * 8 &&
378
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 frame->ref_height <= ref->ref_height * 8 &&
379
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);
380 }
381
2/4
✓ Branch 0 taken 6092 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6092 times.
✗ Branch 3 not taken.
6092 return CHECK_SAMPLES(width) && CHECK_SAMPLES(height);
382 }
383
384 #define RPR_SCALE(f) (((ref->f << 14) + (fc->ref->f >> 1)) / fc->ref->f)
385 /* add a reference with the given poc to the list and mark it as used in DPB */
386 6100 static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *list,
387 int poc, int ref_flag, uint8_t use_msb)
388 {
389 6100 VVCFrame *ref = find_ref_idx(s, fc, poc, use_msb);
390 6100 VVCRefPic *refp = &list->refs[list->nb_refs];
391
392
2/4
✓ Branch 0 taken 6100 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6100 times.
6100 if (ref == fc->ref || list->nb_refs >= VVC_MAX_REF_ENTRIES)
393 return AVERROR_INVALIDDATA;
394
395
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 6085 times.
6100 if (!ref) {
396 15 ref = generate_missing_ref(s, fc, poc);
397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!ref)
398 return AVERROR(ENOMEM);
399 }
400
401 6100 refp->poc = poc;
402 6100 refp->ref = ref;
403 6100 refp->is_lt = ref_flag & VVC_FRAME_FLAG_LONG_REF;
404 18300 refp->is_scaled = ref->sps->r->sps_num_subpics_minus1 != fc->ref->sps->r->sps_num_subpics_minus1||
405
1/2
✓ Branch 0 taken 6100 times.
✗ Branch 1 not taken.
6100 memcmp(&ref->scaling_win, &fc->ref->scaling_win, sizeof(ref->scaling_win)) ||
406
3/4
✓ Branch 0 taken 6100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6092 times.
✓ Branch 3 taken 8 times.
18292 ref->pps->r->pps_pic_width_in_luma_samples != fc->ref->pps->r->pps_pic_width_in_luma_samples ||
407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6092 times.
6092 ref->pps->r->pps_pic_height_in_luma_samples != fc->ref->pps->r->pps_pic_height_in_luma_samples;
408
409
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6100 times.
6100 if (!check_candidate_ref(fc->ref, refp))
410 return AVERROR_INVALIDDATA;
411
412
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6092 times.
6100 if (refp->is_scaled) {
413 8 refp->scale[0] = RPR_SCALE(ref_width);
414 8 refp->scale[1] = RPR_SCALE(ref_height);
415 }
416 6100 list->nb_refs++;
417
418 6100 mark_ref(ref, ref_flag);
419 6100 return 0;
420 }
421
422 1497 static int init_slice_rpl(const VVCFrameContext *fc, SliceContext *sc)
423 {
424 1497 VVCFrame *frame = fc->ref;
425 1497 const VVCSH *sh = &sc->sh;
426
427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1497 times.
1497 if (sc->slice_idx >= frame->nb_rpl_elems)
428 return AVERROR_INVALIDDATA;
429
430
2/2
✓ Branch 0 taken 44207 times.
✓ Branch 1 taken 1497 times.
45704 for (int i = 0; i < sh->num_ctus_in_curr_slice; i++) {
431 44207 const int rs = sh->ctb_addr_in_curr_slice[i];
432 44207 frame->rpl_tab[rs] = frame->rpl + sc->slice_idx;
433 }
434
435 1497 sc->rpl = frame->rpl_tab[sh->ctb_addr_in_curr_slice[0]]->refPicList;
436
437 1497 return 0;
438 }
439
440 6100 static int delta_poc_st(const H266RefPicListStruct *rpls,
441 const int lx, const int i, const VVCSPS *sps)
442 {
443 6100 int abs_delta_poc_st = rpls->abs_delta_poc_st[i];
444
4/4
✓ Branch 0 taken 6026 times.
✓ Branch 1 taken 74 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 42 times.
6100 if (!((sps->r->sps_weighted_pred_flag ||
445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6026 times.
6026 sps->r->sps_weighted_bipred_flag) && i != 0))
446 6058 abs_delta_poc_st++;
447 6100 return (1 - 2 * rpls->strp_entry_sign_flag[i]) * abs_delta_poc_st;
448 }
449
450 static int poc_lt(int *prev_delta_poc_msb, const int poc, const H266RefPicLists *ref_lists,
451 const int lx, const int j, const int max_poc_lsb)
452 {
453 const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx;
454 int lt_poc = rpls->ltrp_in_header_flag ? ref_lists->poc_lsb_lt[lx][j] : rpls->rpls_poc_lsb_lt[j];
455
456 if (ref_lists->delta_poc_msb_cycle_present_flag[lx][j]) {
457 const uint32_t delta = ref_lists->delta_poc_msb_cycle_lt[lx][j] + *prev_delta_poc_msb;
458 lt_poc += poc - delta * max_poc_lsb - (poc & (max_poc_lsb - 1));
459 *prev_delta_poc_msb = delta;
460 }
461 return lt_poc;
462 }
463
464 1497 int ff_vvc_slice_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
465 {
466 1497 const VVCSPS *sps = fc->ps.sps;
467 1497 const H266RawPPS *pps = fc->ps.pps->r;
468 1497 const VVCPH *ph = &fc->ps.ph;
469 1497 const H266RawSliceHeader *rsh = sc->sh.r;
470 1497 const int max_poc_lsb = sps->max_pic_order_cnt_lsb;
471 1497 const H266RefPicLists *ref_lists =
472
2/2
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 1247 times.
1497 pps->pps_rpl_info_in_ph_flag ? &ph->r->ph_ref_pic_lists : &rsh->sh_ref_pic_lists;
473 1497 int ret = 0;
474
475 1497 ret = init_slice_rpl(fc, sc);
476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1497 times.
1497 if (ret < 0)
477 return ret;
478
479
2/2
✓ Branch 0 taken 2994 times.
✓ Branch 1 taken 1497 times.
4491 for (int lx = L0; lx <= L1; lx++) {
480 2994 const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx;
481 2994 RefPicList *rpl = sc->rpl + lx;
482 2994 int poc_base = ph->poc;
483 2994 int prev_delta_poc_msb = 0;
484
485 2994 rpl->nb_refs = 0;
486
2/2
✓ Branch 0 taken 6100 times.
✓ Branch 1 taken 2994 times.
9094 for (int i = 0, j = 0; i < rpls->num_ref_entries; i++) {
487 int poc;
488
1/2
✓ Branch 0 taken 6100 times.
✗ Branch 1 not taken.
6100 if (!rpls->inter_layer_ref_pic_flag[i]) {
489 6100 int use_msb = 1;
490 int ref_flag;
491
1/2
✓ Branch 0 taken 6100 times.
✗ Branch 1 not taken.
6100 if (rpls->st_ref_pic_flag[i]) {
492 6100 poc = poc_base + delta_poc_st(rpls, lx, i, sps);
493 6100 poc_base = poc;
494 6100 ref_flag = VVC_FRAME_FLAG_SHORT_REF;
495 } else {
496 use_msb = ref_lists->delta_poc_msb_cycle_present_flag[lx][j];
497 poc = poc_lt(&prev_delta_poc_msb, ph->poc, ref_lists, lx, j, max_poc_lsb);
498 ref_flag = VVC_FRAME_FLAG_LONG_REF;
499 j++;
500 }
501 6100 ret = add_candidate_ref(s, fc, rpl, poc, ref_flag, use_msb);
502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6100 times.
6100 if (ret < 0)
503 return ret;
504 } else {
505 // OPI_B_3.bit and VPS_A_3.bit should cover this
506 avpriv_report_missing_feature(fc->log_ctx, "Inter layer ref");
507 ret = AVERROR_PATCHWELCOME;
508 return ret;
509 }
510 }
511
2/2
✓ Branch 0 taken 2782 times.
✓ Branch 1 taken 212 times.
2994 if (ph->r->ph_temporal_mvp_enabled_flag &&
512
2/2
✓ Branch 0 taken 1391 times.
✓ Branch 1 taken 1391 times.
2782 (!rsh->sh_collocated_from_l0_flag) == lx &&
513
1/2
✓ Branch 0 taken 1391 times.
✗ Branch 1 not taken.
1391 rsh->sh_collocated_ref_idx < rpl->nb_refs) {
514 1391 const VVCRefPic *refp = rpl->refs + rsh->sh_collocated_ref_idx;
515
2/4
✓ Branch 0 taken 1391 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1391 times.
1391 if (refp->is_scaled || refp->ref->sps->ctb_log2_size_y != sps->ctb_log2_size_y)
516 return AVERROR_INVALIDDATA;
517 1391 fc->ref->collocated_ref = refp->ref;
518 }
519 }
520 1497 return 0;
521 }
522
523 936 int ff_vvc_frame_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
524 {
525 936 int ret = 0;
526
527 /* clear the reference flags on all frames except the current one */
528
2/2
✓ Branch 0 taken 15912 times.
✓ Branch 1 taken 936 times.
16848 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
529 15912 VVCFrame *frame = &fc->DPB[i];
530
531
2/2
✓ Branch 0 taken 936 times.
✓ Branch 1 taken 14976 times.
15912 if (frame == fc->ref)
532 936 continue;
533
534 14976 mark_ref(frame, 0);
535 }
536
537
1/2
✓ Branch 1 taken 936 times.
✗ Branch 2 not taken.
936 if ((ret = ff_vvc_slice_rpl(s, fc, sc)) < 0)
538 goto fail;
539
540 936 fail:
541 /* release any frames that are now unused */
542
2/2
✓ Branch 0 taken 15912 times.
✓ Branch 1 taken 936 times.
16848 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
543 15912 ff_vvc_unref_frame(fc, &fc->DPB[i], 0);
544 936 return ret;
545 }
546
547 951 void ff_vvc_report_frame_finished(VVCFrame *frame)
548 {
549 951 ff_vvc_report_progress(frame, VVC_PROGRESS_MV, INT_MAX);
550 951 ff_vvc_report_progress(frame, VVC_PROGRESS_PIXEL, INT_MAX);
551 951 }
552
553 82321 static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l)
554 {
555 82321 return p->progress[l->vp] > l->y;
556 }
557
558 static void add_listener(VVCProgressListener **prev, VVCProgressListener *l)
559 {
560 l->next = *prev;
561 *prev = l;
562 }
563
564 static VVCProgressListener* remove_listener(VVCProgressListener **prev, VVCProgressListener *l)
565 {
566 *prev = l->next;
567 l->next = NULL;
568 return l;
569 }
570
571 8183 static VVCProgressListener* get_done_listener(FrameProgress *p, const VVCProgress vp)
572 {
573 8183 VVCProgressListener *list = NULL;
574 8183 VVCProgressListener **prev = &p->listener[vp];
575
576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8183 times.
8183 while (*prev) {
577 if (is_progress_done(p, *prev)) {
578 VVCProgressListener *l = remove_listener(prev, *prev);
579 add_listener(&list, l);
580 } else {
581 prev = &(*prev)->next;
582 }
583 }
584 8183 return list;
585 }
586
587 10055 void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y)
588 {
589 10055 FrameProgress *p = frame->progress;
590 10055 VVCProgressListener *l = NULL;
591
592 10055 ff_mutex_lock(&p->lock);
593
2/2
✓ Branch 0 taken 8183 times.
✓ Branch 1 taken 1872 times.
10055 if (p->progress[vp] < y) {
594 // Due to the nature of thread scheduling, later progress may reach this point before earlier progress.
595 // Therefore, we only update the progress when p->progress[vp] < y.
596 8183 p->progress[vp] = y;
597 8183 l = get_done_listener(p, vp);
598 8183 ff_cond_signal(&p->cond);
599 }
600 10055 ff_mutex_unlock(&p->lock);
601
602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10055 times.
10055 while (l) {
603 l->progress_done(l);
604 l = l->next;
605 }
606 10055 }
607
608 82321 void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l)
609 {
610 82321 FrameProgress *p = frame->progress;
611
612 82321 ff_mutex_lock(&p->lock);
613
614
1/2
✓ Branch 1 taken 82321 times.
✗ Branch 2 not taken.
82321 if (is_progress_done(p, l)) {
615 82321 ff_mutex_unlock(&p->lock);
616 82321 l->progress_done(l);
617 } else {
618 add_listener(p->listener + l->vp, l);
619 ff_mutex_unlock(&p->lock);
620 }
621 82321 }
622