FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/refs.c
Date: 2024-05-03 15:42:48
Exec Total Coverage
Lines: 285 330 86.4%
Functions: 25 26 96.2%
Branches: 153 206 74.3%

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
30 #include "refs.h"
31
32 #define VVC_FRAME_FLAG_OUTPUT (1 << 0)
33 #define VVC_FRAME_FLAG_SHORT_REF (1 << 1)
34 #define VVC_FRAME_FLAG_LONG_REF (1 << 2)
35 #define VVC_FRAME_FLAG_BUMPING (1 << 3)
36
37 typedef struct FrameProgress {
38 atomic_int progress[VVC_PROGRESS_LAST];
39 VVCProgressListener *listener[VVC_PROGRESS_LAST];
40 AVMutex lock;
41 AVCond cond;
42 uint8_t has_lock;
43 uint8_t has_cond;
44 } FrameProgress;
45
46 38288 void ff_vvc_unref_frame(VVCFrameContext *fc, VVCFrame *frame, int flags)
47 {
48 /* frame->frame can be NULL if context init failed */
49
3/4
✓ Branch 0 taken 38288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28227 times.
✓ Branch 3 taken 10061 times.
38288 if (!frame->frame || !frame->frame->buf[0])
50 28227 return;
51
52 10061 frame->flags &= ~flags;
53
2/2
✓ Branch 0 taken 5104 times.
✓ Branch 1 taken 4957 times.
10061 if (!frame->flags) {
54 5104 av_frame_unref(frame->frame);
55 5104 ff_refstruct_unref(&frame->progress);
56
57 5104 ff_refstruct_unref(&frame->tab_dmvr_mvf);
58
59 5104 ff_refstruct_unref(&frame->rpl);
60 5104 frame->nb_rpl_elems = 0;
61 5104 ff_refstruct_unref(&frame->rpl_tab);
62
63 5104 frame->collocated_ref = NULL;
64 }
65 }
66
67 2353318 const RefPicList *ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
68 {
69 2353318 const int x_cb = x0 >> fc->ps.sps->ctb_log2_size_y;
70 2353318 const int y_cb = y0 >> fc->ps.sps->ctb_log2_size_y;
71 2353318 const int pic_width_cb = fc->ps.pps->ctb_width;
72 2353318 const int ctb_addr_rs = y_cb * pic_width_cb + x_cb;
73
74 2353318 return (const RefPicList *)ref->rpl_tab[ctb_addr_rs];
75 }
76
77 59 void ff_vvc_clear_refs(VVCFrameContext *fc)
78 {
79
2/2
✓ Branch 0 taken 1003 times.
✓ Branch 1 taken 59 times.
1062 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
80 1003 ff_vvc_unref_frame(fc, &fc->DPB[i],
81 VVC_FRAME_FLAG_SHORT_REF | VVC_FRAME_FLAG_LONG_REF);
82 59 }
83
84 50 void ff_vvc_flush_dpb(VVCFrameContext *fc)
85 {
86
2/2
✓ Branch 0 taken 850 times.
✓ Branch 1 taken 50 times.
900 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
87 850 ff_vvc_unref_frame(fc, &fc->DPB[i], ~0);
88 50 }
89
90 884 static void free_progress(FFRefStructOpaque unused, void *obj)
91 {
92 884 FrameProgress *p = (FrameProgress *)obj;
93
94
1/2
✓ Branch 0 taken 884 times.
✗ Branch 1 not taken.
884 if (p->has_cond)
95 884 ff_cond_destroy(&p->cond);
96
1/2
✓ Branch 0 taken 884 times.
✗ Branch 1 not taken.
884 if (p->has_lock)
97 884 ff_mutex_destroy(&p->lock);
98 884 }
99
100 884 static FrameProgress *alloc_progress(void)
101 {
102 884 FrameProgress *p = ff_refstruct_alloc_ext(sizeof(*p), 0, NULL, free_progress);
103
104
1/2
✓ Branch 0 taken 884 times.
✗ Branch 1 not taken.
884 if (p) {
105 884 p->has_lock = !ff_mutex_init(&p->lock, NULL);
106 884 p->has_cond = !ff_cond_init(&p->cond, NULL);
107
2/4
✓ Branch 0 taken 884 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 884 times.
884 if (!p->has_lock || !p->has_cond)
108 ff_refstruct_unref(&p);
109 }
110 884 return p;
111 }
112
113 884 static VVCFrame *alloc_frame(VVCContext *s, VVCFrameContext *fc)
114 {
115 884 const VVCPPS *pps = fc->ps.pps;
116
1/2
✓ Branch 0 taken 3608 times.
✗ Branch 1 not taken.
3608 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
117 int ret;
118 3608 VVCFrame *frame = &fc->DPB[i];
119
2/2
✓ Branch 0 taken 2724 times.
✓ Branch 1 taken 884 times.
3608 if (frame->frame->buf[0])
120 2724 continue;
121
122 884 ret = ff_thread_get_buffer(s->avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 884 times.
884 if (ret < 0)
124 return NULL;
125
126 884 frame->rpl = ff_refstruct_allocz(s->current_frame.nb_units * sizeof(RefPicListTab));
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 884 times.
884 if (!frame->rpl)
128 goto fail;
129 884 frame->nb_rpl_elems = s->current_frame.nb_units;
130
131 884 frame->tab_dmvr_mvf = ff_refstruct_pool_get(fc->tab_dmvr_mvf_pool);
132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 884 times.
884 if (!frame->tab_dmvr_mvf)
133 goto fail;
134
135 884 frame->rpl_tab = ff_refstruct_pool_get(fc->rpl_tab_pool);
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 884 times.
884 if (!frame->rpl_tab)
137 goto fail;
138 884 frame->ctb_count = pps->ctb_width * pps->ctb_height;
139
2/2
✓ Branch 0 taken 42987 times.
✓ Branch 1 taken 884 times.
43871 for (int j = 0; j < frame->ctb_count; j++)
140 42987 frame->rpl_tab[j] = frame->rpl;
141
142 884 frame->progress = alloc_progress();
143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 884 times.
884 if (!frame->progress)
144 goto fail;
145
146 884 return frame;
147 fail:
148 ff_vvc_unref_frame(fc, frame, ~0);
149 return NULL;
150 }
151 av_log(s->avctx, AV_LOG_ERROR, "Error allocating frame, DPB full.\n");
152 return NULL;
153 }
154
155 872 int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, AVFrame **frame)
156 {
157 872 const VVCPH *ph= &fc->ps.ph;
158 872 const int poc = ph->poc;
159 VVCFrame *ref;
160
161 /* check that this POC doesn't already exist */
162
2/2
✓ Branch 0 taken 14824 times.
✓ Branch 1 taken 872 times.
15696 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
163 14824 VVCFrame *frame = &fc->DPB[i];
164
165
4/4
✓ Branch 0 taken 4201 times.
✓ Branch 1 taken 10623 times.
✓ Branch 2 taken 4098 times.
✓ Branch 3 taken 103 times.
14824 if (frame->frame->buf[0] && frame->sequence == s->seq_decode &&
166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4098 times.
4098 frame->poc == poc) {
167 av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence: %d.\n", poc);
168 return AVERROR_INVALIDDATA;
169 }
170 }
171
172 872 ref = alloc_frame(s, fc);
173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 872 times.
872 if (!ref)
174 return AVERROR(ENOMEM);
175
176 872 *frame = ref->frame;
177 872 fc->ref = ref;
178
179
5/6
✓ Branch 0 taken 687 times.
✓ Branch 1 taken 185 times.
✓ Branch 2 taken 672 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 672 times.
872 if (s->no_output_before_recovery_flag && (IS_RASL(s) || !GDR_IS_RECOVERED(s)))
180 15 ref->flags = 0;
181
1/2
✓ Branch 0 taken 857 times.
✗ Branch 1 not taken.
857 else if (ph->r->ph_pic_output_flag)
182 857 ref->flags = VVC_FRAME_FLAG_OUTPUT;
183
184
1/2
✓ Branch 0 taken 872 times.
✗ Branch 1 not taken.
872 if (!ph->r->ph_non_ref_pic_flag)
185 872 ref->flags |= VVC_FRAME_FLAG_SHORT_REF;
186
187 872 ref->poc = poc;
188 872 ref->sequence = s->seq_decode;
189 872 ref->frame->crop_left = fc->ps.pps->r->pps_conf_win_left_offset << fc->ps.sps->hshift[CHROMA];
190 872 ref->frame->crop_right = fc->ps.pps->r->pps_conf_win_right_offset << fc->ps.sps->hshift[CHROMA];
191 872 ref->frame->crop_top = fc->ps.pps->r->pps_conf_win_top_offset << fc->ps.sps->vshift[CHROMA];
192 872 ref->frame->crop_bottom = fc->ps.pps->r->pps_conf_win_bottom_offset << fc->ps.sps->vshift[CHROMA];
193
194 872 return 0;
195 }
196
197 973 int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush)
198 {
199 973 const VVCSPS *sps = fc->ps.sps;
200 59 do {
201 1032 int nb_output = 0;
202 1032 int min_poc = INT_MAX;
203 int min_idx, ret;
204
205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1032 times.
1032 if (no_output_of_prior_pics_flag) {
206 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
207 VVCFrame *frame = &fc->DPB[i];
208 if (!(frame->flags & VVC_FRAME_FLAG_BUMPING) && frame->poc != fc->ps.ph.poc &&
209 frame->sequence == s->seq_output) {
210 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT);
211 }
212 }
213 }
214
215
2/2
✓ Branch 0 taken 17544 times.
✓ Branch 1 taken 1032 times.
18576 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
216 17544 VVCFrame *frame = &fc->DPB[i];
217
2/2
✓ Branch 0 taken 4150 times.
✓ Branch 1 taken 13394 times.
17544 if ((frame->flags & VVC_FRAME_FLAG_OUTPUT) &&
218
2/2
✓ Branch 0 taken 3951 times.
✓ Branch 1 taken 199 times.
4150 frame->sequence == s->seq_output) {
219 3951 nb_output++;
220
3/4
✓ Branch 0 taken 1928 times.
✓ Branch 1 taken 2023 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1928 times.
3951 if (frame->poc < min_poc || nb_output == 1) {
221 2023 min_poc = frame->poc;
222 2023 min_idx = i;
223 }
224 }
225 }
226
227 /* wait for more frames before output */
228
5/6
✓ Branch 0 taken 929 times.
✓ Branch 1 taken 103 times.
✓ Branch 2 taken 833 times.
✓ Branch 3 taken 96 times.
✓ Branch 4 taken 833 times.
✗ Branch 5 not taken.
1032 if (!flush && s->seq_output == s->seq_decode && sps &&
229
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 722 times.
833 nb_output <= sps->r->sps_dpb_params.dpb_max_num_reorder_pics[sps->r->sps_max_sublayers_minus1])
230 111 return 0;
231
232
2/2
✓ Branch 0 taken 837 times.
✓ Branch 1 taken 84 times.
921 if (nb_output) {
233 837 VVCFrame *frame = &fc->DPB[min_idx];
234
235 837 ret = av_frame_ref(out, frame->frame);
236
2/2
✓ Branch 0 taken 581 times.
✓ Branch 1 taken 256 times.
837 if (frame->flags & VVC_FRAME_FLAG_BUMPING)
237 581 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_BUMPING);
238 else
239 256 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT);
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 837 times.
837 if (ret < 0)
241 return ret;
242
243 837 av_log(s->avctx, AV_LOG_DEBUG,
244 "Output frame with POC %d.\n", frame->poc);
245 837 return 1;
246 }
247
248
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 25 times.
84 if (s->seq_output != s->seq_decode)
249 59 s->seq_output = (s->seq_output + 1) & 0xff;
250 else
251 25 break;
252 } while (1);
253 25 return 0;
254 }
255
256 813 void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc)
257 {
258 813 const VVCSPS *sps = fc->ps.sps;
259 813 const int poc = fc->ps.ph.poc;
260 813 int dpb = 0;
261 813 int min_poc = INT_MAX;
262
263
2/2
✓ Branch 0 taken 13821 times.
✓ Branch 1 taken 813 times.
14634 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
264 13821 VVCFrame *frame = &fc->DPB[i];
265
2/2
✓ Branch 0 taken 4975 times.
✓ Branch 1 taken 8846 times.
13821 if ((frame->flags) &&
266
2/2
✓ Branch 0 taken 4863 times.
✓ Branch 1 taken 112 times.
4975 frame->sequence == s->seq_output &&
267
2/2
✓ Branch 0 taken 4074 times.
✓ Branch 1 taken 789 times.
4863 frame->poc != poc) {
268 4074 dpb++;
269 }
270 }
271
272
3/4
✓ Branch 0 taken 813 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 398 times.
✓ Branch 3 taken 415 times.
813 if (sps && dpb >= sps->r->sps_dpb_params.dpb_max_dec_pic_buffering_minus1[sps->r->sps_max_sublayers_minus1] + 1) {
273
2/2
✓ Branch 0 taken 6766 times.
✓ Branch 1 taken 398 times.
7164 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
274 6766 VVCFrame *frame = &fc->DPB[i];
275
2/2
✓ Branch 0 taken 2734 times.
✓ Branch 1 taken 4032 times.
6766 if ((frame->flags) &&
276
1/2
✓ Branch 0 taken 2734 times.
✗ Branch 1 not taken.
2734 frame->sequence == s->seq_output &&
277
2/2
✓ Branch 0 taken 2336 times.
✓ Branch 1 taken 398 times.
2734 frame->poc != poc) {
278
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) {
279 50 min_poc = frame->poc;
280 }
281 }
282 }
283
284
2/2
✓ Branch 0 taken 6766 times.
✓ Branch 1 taken 398 times.
7164 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
285 6766 VVCFrame *frame = &fc->DPB[i];
286
2/2
✓ Branch 0 taken 1843 times.
✓ Branch 1 taken 4923 times.
6766 if (frame->flags & VVC_FRAME_FLAG_OUTPUT &&
287
1/2
✓ Branch 0 taken 1843 times.
✗ Branch 1 not taken.
1843 frame->sequence == s->seq_output &&
288
2/2
✓ Branch 0 taken 1647 times.
✓ Branch 1 taken 196 times.
1843 frame->poc <= min_poc) {
289 1647 frame->flags |= VVC_FRAME_FLAG_BUMPING;
290 }
291 }
292
293 398 dpb--;
294 }
295 813 }
296
297 5903 static VVCFrame *find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb)
298 {
299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5903 times.
5903 const int mask = use_msb ? ~0 : fc->ps.sps->max_pic_order_cnt_lsb - 1;
300
301
2/2
✓ Branch 0 taken 21305 times.
✓ Branch 1 taken 12 times.
21317 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
302 21305 VVCFrame *ref = &fc->DPB[i];
303
4/4
✓ Branch 0 taken 19012 times.
✓ Branch 1 taken 2293 times.
✓ Branch 2 taken 18084 times.
✓ Branch 3 taken 928 times.
21305 if (ref->frame->buf[0] && ref->sequence == s->seq_decode) {
304
2/2
✓ Branch 0 taken 5891 times.
✓ Branch 1 taken 12193 times.
18084 if ((ref->poc & mask) == poc)
305 5891 return ref;
306 }
307 }
308 12 return NULL;
309 }
310
311 19855 static void mark_ref(VVCFrame *frame, int flag)
312 {
313 19855 frame->flags &= ~(VVC_FRAME_FLAG_LONG_REF | VVC_FRAME_FLAG_SHORT_REF);
314 19855 frame->flags |= flag;
315 19855 }
316
317 12 static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int poc)
318 {
319 12 const VVCSPS *sps = fc->ps.sps;
320 12 const VVCPPS *pps = fc->ps.pps;
321 VVCFrame *frame;
322
323 12 frame = alloc_frame(s, fc);
324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!frame)
325 return NULL;
326
327
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (!s->avctx->hwaccel) {
328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!sps->pixel_shift) {
329 for (int i = 0; frame->frame->buf[i]; i++)
330 memset(frame->frame->buf[i]->data, 1 << (sps->bit_depth - 1),
331 frame->frame->buf[i]->size);
332 } else {
333
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 12 times.
48 for (int i = 0; frame->frame->data[i]; i++)
334
2/2
✓ Branch 0 taken 5760 times.
✓ Branch 1 taken 36 times.
5796 for (int y = 0; y < (pps->height >> sps->vshift[i]); y++) {
335 5760 uint8_t *dst = frame->frame->data[i] + y * frame->frame->linesize[i];
336 5760 AV_WN16(dst, 1 << (sps->bit_depth - 1));
337 5760 av_memcpy_backptr(dst + 2, 2, 2*(pps->width >> sps->hshift[i]) - 2);
338 }
339 }
340 }
341
342 12 frame->poc = poc;
343 12 frame->sequence = s->seq_decode;
344 12 frame->flags = 0;
345
346 12 ff_vvc_report_frame_finished(frame);
347
348 12 return frame;
349 }
350
351 /* add a reference with the given poc to the list and mark it as used in DPB */
352 5903 static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *list,
353 int poc, int ref_flag, uint8_t use_msb)
354 {
355 5903 VVCFrame *ref = find_ref_idx(s, fc, poc, use_msb);
356
357
2/4
✓ Branch 0 taken 5903 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5903 times.
5903 if (ref == fc->ref || list->nb_refs >= VVC_MAX_REF_ENTRIES)
358 return AVERROR_INVALIDDATA;
359
360
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 5891 times.
5903 if (!ref) {
361 12 ref = generate_missing_ref(s, fc, poc);
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!ref)
363 return AVERROR(ENOMEM);
364 }
365
366 5903 list->list[list->nb_refs] = poc;
367 5903 list->ref[list->nb_refs] = ref;
368 5903 list->isLongTerm[list->nb_refs] = ref_flag & VVC_FRAME_FLAG_LONG_REF;
369 5903 list->nb_refs++;
370
371 5903 mark_ref(ref, ref_flag);
372 5903 return 0;
373 }
374
375 1433 static int init_slice_rpl(const VVCFrameContext *fc, SliceContext *sc)
376 {
377 1433 VVCFrame *frame = fc->ref;
378 1433 const VVCSH *sh = &sc->sh;
379
380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1433 times.
1433 if (sc->slice_idx >= frame->nb_rpl_elems)
381 return AVERROR_INVALIDDATA;
382
383
2/2
✓ Branch 0 taken 41569 times.
✓ Branch 1 taken 1433 times.
43002 for (int i = 0; i < sh->num_ctus_in_curr_slice; i++) {
384 41569 const int rs = sh->ctb_addr_in_curr_slice[i];
385 41569 frame->rpl_tab[rs] = frame->rpl + sc->slice_idx;
386 }
387
388 1433 sc->rpl = frame->rpl_tab[sh->ctb_addr_in_curr_slice[0]]->refPicList;
389
390 1433 return 0;
391 }
392
393 5903 static int delta_poc_st(const H266RefPicListStruct *rpls,
394 const int lx, const int i, const VVCSPS *sps)
395 {
396 5903 int abs_delta_poc_st = rpls->abs_delta_poc_st[i];
397
4/4
✓ Branch 0 taken 5829 times.
✓ Branch 1 taken 74 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 42 times.
5903 if (!((sps->r->sps_weighted_pred_flag ||
398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5829 times.
5829 sps->r->sps_weighted_bipred_flag) && i != 0))
399 5861 abs_delta_poc_st++;
400 5903 return (1 - 2 * rpls->strp_entry_sign_flag[i]) * abs_delta_poc_st;
401 }
402
403 static int poc_lt(int *prev_delta_poc_msb, const int poc, const H266RefPicLists *ref_lists,
404 const int lx, const int j, const int max_poc_lsb)
405 {
406 const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx;
407 int lt_poc = rpls->ltrp_in_header_flag ? ref_lists->poc_lsb_lt[lx][j] : rpls->rpls_poc_lsb_lt[j];
408
409 if (ref_lists->delta_poc_msb_cycle_present_flag[lx][j]) {
410 const uint32_t delta = ref_lists->delta_poc_msb_cycle_lt[lx][j] + *prev_delta_poc_msb;
411 lt_poc += poc - delta * max_poc_lsb - (poc & (max_poc_lsb - 1));
412 *prev_delta_poc_msb = delta;
413 }
414 return lt_poc;
415 }
416
417 1433 int ff_vvc_slice_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
418 {
419 1433 const VVCSPS *sps = fc->ps.sps;
420 1433 const H266RawPPS *pps = fc->ps.pps->r;
421 1433 const VVCPH *ph = &fc->ps.ph;
422 1433 const H266RawSliceHeader *rsh = sc->sh.r;
423 1433 const int max_poc_lsb = sps->max_pic_order_cnt_lsb;
424 1433 const H266RefPicLists *ref_lists =
425
2/2
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 1183 times.
1433 pps->pps_rpl_info_in_ph_flag ? &ph->r->ph_ref_pic_lists : &rsh->sh_ref_pic_lists;
426 1433 int ret = 0;
427
428 1433 ret = init_slice_rpl(fc, sc);
429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1433 times.
1433 if (ret < 0)
430 return ret;
431
432
2/2
✓ Branch 0 taken 2866 times.
✓ Branch 1 taken 1433 times.
4299 for (int lx = L0; lx <= L1; lx++) {
433 2866 const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx;
434 2866 RefPicList *rpl = sc->rpl + lx;
435 2866 int poc_base = ph->poc;
436 2866 int prev_delta_poc_msb = 0;
437
438 2866 rpl->nb_refs = 0;
439
2/2
✓ Branch 0 taken 5903 times.
✓ Branch 1 taken 2866 times.
8769 for (int i = 0, j = 0; i < rpls->num_ref_entries; i++) {
440 int poc;
441
1/2
✓ Branch 0 taken 5903 times.
✗ Branch 1 not taken.
5903 if (!rpls->inter_layer_ref_pic_flag[i]) {
442 5903 int use_msb = 1;
443 int ref_flag;
444
1/2
✓ Branch 0 taken 5903 times.
✗ Branch 1 not taken.
5903 if (rpls->st_ref_pic_flag[i]) {
445 5903 poc = poc_base + delta_poc_st(rpls, lx, i, sps);
446 5903 poc_base = poc;
447 5903 ref_flag = VVC_FRAME_FLAG_SHORT_REF;
448 } else {
449 use_msb = ref_lists->delta_poc_msb_cycle_present_flag[lx][j];
450 poc = poc_lt(&prev_delta_poc_msb, ph->poc, ref_lists, lx, j, max_poc_lsb);
451 ref_flag = VVC_FRAME_FLAG_LONG_REF;
452 j++;
453 }
454 5903 ret = add_candidate_ref(s, fc, rpl, poc, ref_flag, use_msb);
455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5903 times.
5903 if (ret < 0)
456 return ret;
457 } else {
458 // OPI_B_3.bit and VPS_A_3.bit should cover this
459 avpriv_report_missing_feature(fc->log_ctx, "Inter layer ref");
460 ret = AVERROR_PATCHWELCOME;
461 return ret;
462 }
463 }
464
2/2
✓ Branch 0 taken 1433 times.
✓ Branch 1 taken 1433 times.
2866 if ((!rsh->sh_collocated_from_l0_flag) == lx &&
465
2/2
✓ Branch 0 taken 1373 times.
✓ Branch 1 taken 60 times.
1433 rsh->sh_collocated_ref_idx < rpl->nb_refs)
466 1373 fc->ref->collocated_ref = rpl->ref[rsh->sh_collocated_ref_idx];
467 }
468 1433 return 0;
469 }
470
471 872 int ff_vvc_frame_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
472 {
473 872 int ret = 0;
474
475 /* clear the reference flags on all frames except the current one */
476
2/2
✓ Branch 0 taken 14824 times.
✓ Branch 1 taken 872 times.
15696 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
477 14824 VVCFrame *frame = &fc->DPB[i];
478
479
2/2
✓ Branch 0 taken 872 times.
✓ Branch 1 taken 13952 times.
14824 if (frame == fc->ref)
480 872 continue;
481
482 13952 mark_ref(frame, 0);
483 }
484
485
1/2
✓ Branch 1 taken 872 times.
✗ Branch 2 not taken.
872 if ((ret = ff_vvc_slice_rpl(s, fc, sc)) < 0)
486 goto fail;
487
488 872 fail:
489 /* release any frames that are now unused */
490
2/2
✓ Branch 0 taken 14824 times.
✓ Branch 1 taken 872 times.
15696 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
491 14824 ff_vvc_unref_frame(fc, &fc->DPB[i], 0);
492 872 return ret;
493 }
494
495 884 void ff_vvc_report_frame_finished(VVCFrame *frame)
496 {
497 884 ff_vvc_report_progress(frame, VVC_PROGRESS_MV, INT_MAX);
498 884 ff_vvc_report_progress(frame, VVC_PROGRESS_PIXEL, INT_MAX);
499 884 }
500
501 94541 static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l)
502 {
503 94541 return p->progress[l->vp] > l->y;
504 }
505
506 7754 static void add_listener(VVCProgressListener **prev, VVCProgressListener *l)
507 {
508 7754 l->next = *prev;
509 7754 *prev = l;
510 7754 }
511
512 3877 static VVCProgressListener* remove_listener(VVCProgressListener **prev, VVCProgressListener *l)
513 {
514 3877 *prev = l->next;
515 3877 l->next = NULL;
516 3877 return l;
517 }
518
519 9386 static VVCProgressListener* get_done_listener(FrameProgress *p, const VVCProgress vp)
520 {
521 9386 VVCProgressListener *list = NULL;
522 9386 VVCProgressListener **prev = &p->listener[vp];
523
524
2/2
✓ Branch 0 taken 15010 times.
✓ Branch 1 taken 9386 times.
24396 while (*prev) {
525
2/2
✓ Branch 1 taken 3877 times.
✓ Branch 2 taken 11133 times.
15010 if (is_progress_done(p, *prev)) {
526 3877 VVCProgressListener *l = remove_listener(prev, *prev);
527 3877 add_listener(&list, l);
528 } else {
529 11133 prev = &(*prev)->next;
530 }
531 }
532 9386 return list;
533 }
534
535 9386 void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y)
536 {
537 9386 FrameProgress *p = frame->progress;
538 9386 VVCProgressListener *l = NULL;
539
540 9386 ff_mutex_lock(&p->lock);
541
542
3/4
✓ Branch 0 taken 1744 times.
✓ Branch 1 taken 7642 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1744 times.
9386 av_assert0(p->progress[vp] < y || p->progress[vp] == INT_MAX);
543 9386 p->progress[vp] = y;
544 9386 l = get_done_listener(p, vp);
545 9386 ff_cond_signal(&p->cond);
546
547 9386 ff_mutex_unlock(&p->lock);
548
549
2/2
✓ Branch 0 taken 3877 times.
✓ Branch 1 taken 9386 times.
13263 while (l) {
550 3877 l->progress_done(l);
551 3877 l = l->next;
552 }
553 9386 }
554
555 79531 void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l)
556 {
557 79531 FrameProgress *p = frame->progress;
558
559 79531 ff_mutex_lock(&p->lock);
560
561
2/2
✓ Branch 1 taken 75654 times.
✓ Branch 2 taken 3877 times.
79531 if (is_progress_done(p, l)) {
562 75654 ff_mutex_unlock(&p->lock);
563 75654 l->progress_done(l);
564 } else {
565 3877 add_listener(p->listener + l->vp, l);
566 3877 ff_mutex_unlock(&p->lock);
567 }
568 79531 }
569