FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/refs.c
Date: 2024-07-16 12:46:59
Exec Total Coverage
Lines: 303 366 82.8%
Functions: 24 27 88.9%
Branches: 169 242 69.8%

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