FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/refs.c
Date: 2025-01-20 09:27:23
Exec Total Coverage
Lines: 347 402 86.3%
Functions: 26 28 92.9%
Branches: 215 288 74.7%

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 46835 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 46835 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36158 times.
✓ Branch 3 taken 10677 times.
46835 if (!frame->frame || !frame->frame->buf[0])
48 36158 return;
49
50 10677 frame->flags &= ~flags;
51
2/2
✓ Branch 0 taken 5417 times.
✓ Branch 1 taken 5260 times.
10677 if (!(frame->flags & ~VVC_FRAME_FLAG_CORRUPT))
52 5417 frame->flags = 0;
53
2/2
✓ Branch 0 taken 5417 times.
✓ Branch 1 taken 5260 times.
10677 if (!frame->flags) {
54 5417 av_frame_unref(frame->frame);
55 5417 av_refstruct_unref(&frame->sps);
56 5417 av_refstruct_unref(&frame->pps);
57 5417 av_refstruct_unref(&frame->progress);
58
59 5417 av_refstruct_unref(&frame->tab_dmvr_mvf);
60
61 5417 av_refstruct_unref(&frame->rpl);
62 5417 frame->nb_rpl_elems = 0;
63 5417 av_refstruct_unref(&frame->rpl_tab);
64
65 5417 frame->collocated_ref = NULL;
66 5417 av_refstruct_unref(&frame->hwaccel_picture_private);
67 }
68 }
69
70 2402201 const RefPicList *ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
71 {
72 2402201 const int x_cb = x0 >> fc->ps.sps->ctb_log2_size_y;
73 2402201 const int y_cb = y0 >> fc->ps.sps->ctb_log2_size_y;
74 2402201 const int pic_width_cb = fc->ps.pps->ctb_width;
75 2402201 const int ctb_addr_rs = y_cb * pic_width_cb + x_cb;
76
77 2402201 return (const RefPicList *)ref->rpl_tab[ctb_addr_rs];
78 }
79
80 95 void ff_vvc_clear_refs(VVCFrameContext *fc)
81 {
82
2/2
✓ Branch 0 taken 1615 times.
✓ Branch 1 taken 95 times.
1710 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
83 1615 ff_vvc_unref_frame(fc, &fc->DPB[i],
84 VVC_FRAME_FLAG_SHORT_REF | VVC_FRAME_FLAG_LONG_REF);
85 95 }
86
87 86 void ff_vvc_flush_dpb(VVCFrameContext *fc)
88 {
89
2/2
✓ Branch 0 taken 1462 times.
✓ Branch 1 taken 86 times.
1548 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
90 1462 ff_vvc_unref_frame(fc, &fc->DPB[i], ~0);
91 86 }
92
93 976 static void free_progress(AVRefStructOpaque unused, void *obj)
94 {
95 976 FrameProgress *p = (FrameProgress *)obj;
96
97
1/2
✓ Branch 0 taken 976 times.
✗ Branch 1 not taken.
976 if (p->has_cond)
98 976 ff_cond_destroy(&p->cond);
99
1/2
✓ Branch 0 taken 976 times.
✗ Branch 1 not taken.
976 if (p->has_lock)
100 976 ff_mutex_destroy(&p->lock);
101 976 }
102
103 976 static FrameProgress *alloc_progress(void)
104 {
105 976 FrameProgress *p = av_refstruct_alloc_ext(sizeof(*p), 0, NULL, free_progress);
106
107
1/2
✓ Branch 0 taken 976 times.
✗ Branch 1 not taken.
976 if (p) {
108 976 p->has_lock = !ff_mutex_init(&p->lock, NULL);
109 976 p->has_cond = !ff_cond_init(&p->cond, NULL);
110
2/4
✓ Branch 0 taken 976 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 976 times.
976 if (!p->has_lock || !p->has_cond)
111 av_refstruct_unref(&p);
112 }
113 976 return p;
114 }
115
116 976 static VVCFrame *alloc_frame(VVCContext *s, VVCFrameContext *fc)
117 {
118 976 const VVCSPS *sps = fc->ps.sps;
119 976 const VVCPPS *pps = fc->ps.pps;
120
1/2
✓ Branch 0 taken 3898 times.
✗ Branch 1 not taken.
3898 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
121 int ret;
122 3898 VVCFrame *frame = &fc->DPB[i];
123 3898 VVCWindow *win = &frame->scaling_win;
124
2/2
✓ Branch 0 taken 2922 times.
✓ Branch 1 taken 976 times.
3898 if (frame->frame->buf[0])
125 2922 continue;
126
127 976 frame->sps = av_refstruct_ref_c(fc->ps.sps);
128 976 frame->pps = av_refstruct_ref_c(fc->ps.pps);
129
130 976 ret = ff_thread_get_buffer(s->avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 976 times.
976 if (ret < 0)
132 return NULL;
133
134 976 frame->rpl = av_refstruct_allocz(s->current_frame.nb_units * sizeof(RefPicListTab));
135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 976 times.
976 if (!frame->rpl)
136 goto fail;
137 976 frame->nb_rpl_elems = s->current_frame.nb_units;
138
139 976 frame->tab_dmvr_mvf = av_refstruct_pool_get(fc->tab_dmvr_mvf_pool);
140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 976 times.
976 if (!frame->tab_dmvr_mvf)
141 goto fail;
142
143 976 frame->rpl_tab = av_refstruct_pool_get(fc->rpl_tab_pool);
144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 976 times.
976 if (!frame->rpl_tab)
145 goto fail;
146 976 frame->ctb_count = pps->ctb_width * pps->ctb_height;
147
2/2
✓ Branch 0 taken 47043 times.
✓ Branch 1 taken 976 times.
48019 for (int j = 0; j < frame->ctb_count; j++)
148 47043 frame->rpl_tab[j] = frame->rpl;
149
150 976 win->left_offset = pps->r->pps_scaling_win_left_offset << sps->hshift[CHROMA];
151 976 win->right_offset = pps->r->pps_scaling_win_right_offset << sps->hshift[CHROMA];
152 976 win->top_offset = pps->r->pps_scaling_win_top_offset << sps->vshift[CHROMA];
153 976 win->bottom_offset = pps->r->pps_scaling_win_bottom_offset << sps->vshift[CHROMA];
154 976 frame->ref_width = pps->r->pps_pic_width_in_luma_samples - win->left_offset - win->right_offset;
155 976 frame->ref_height = pps->r->pps_pic_height_in_luma_samples - win->bottom_offset - win->top_offset;
156
157 976 frame->progress = alloc_progress();
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 976 times.
976 if (!frame->progress)
159 goto fail;
160
161 976 ret = ff_hwaccel_frame_priv_alloc(s->avctx, &frame->hwaccel_picture_private);
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 976 times.
976 if (ret < 0)
163 goto fail;
164
165 976 return frame;
166 fail:
167 ff_vvc_unref_frame(fc, frame, ~0);
168 return NULL;
169 }
170 av_log(s->avctx, AV_LOG_ERROR, "Error allocating frame, DPB full.\n");
171 return NULL;
172 }
173
174 959 static void set_pict_type(AVFrame *frame, const VVCContext *s, const VVCFrameContext *fc)
175 {
176 959 bool has_b = false, has_inter = false;
177
178
6/6
✓ Branch 0 taken 952 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 864 times.
✓ Branch 3 taken 88 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 853 times.
959 if (IS_IRAP(s)) {
179 106 frame->pict_type = AV_PICTURE_TYPE_I;
180 106 frame->flags |= AV_FRAME_FLAG_KEY;
181 106 return;
182 }
183
184
2/2
✓ Branch 0 taken 850 times.
✓ Branch 1 taken 3 times.
853 if (fc->ps.ph.r->ph_inter_slice_allowed_flag) {
185 // At this point, fc->slices is not fully initialized; we need to inspect the CBS directly.
186 850 const CodedBitstreamFragment *current = &s->current_frame;
187
4/4
✓ Branch 0 taken 2053 times.
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 1253 times.
✓ Branch 3 taken 800 times.
2103 for (int i = 0; i < current->nb_units && !has_b; i++) {
188 1253 const CodedBitstreamUnit *unit = current->units + i;
189
2/2
✓ Branch 0 taken 850 times.
✓ Branch 1 taken 403 times.
1253 if (unit->type <= VVC_RSV_IRAP_11) {
190 850 const H266RawSliceHeader *rsh = unit->content_ref;
191 850 has_inter |= !IS_I(rsh);
192 850 has_b |= IS_B(rsh);
193 }
194 }
195 }
196
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 850 times.
853 if (!has_inter)
197 3 frame->pict_type = AV_PICTURE_TYPE_I;
198
2/2
✓ Branch 0 taken 828 times.
✓ Branch 1 taken 22 times.
850 else if (has_b)
199 828 frame->pict_type = AV_PICTURE_TYPE_B;
200 else
201 22 frame->pict_type = AV_PICTURE_TYPE_P;
202 }
203
204 959 int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, AVFrame **frame)
205 {
206 959 const VVCPH *ph= &fc->ps.ph;
207 959 const int poc = ph->poc;
208 VVCFrame *ref;
209
210 /* check that this POC doesn't already exist */
211
2/2
✓ Branch 0 taken 16303 times.
✓ Branch 1 taken 959 times.
17262 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
212 16303 VVCFrame *frame = &fc->DPB[i];
213
214
4/4
✓ Branch 0 taken 4416 times.
✓ Branch 1 taken 11887 times.
✓ Branch 2 taken 4307 times.
✓ Branch 3 taken 109 times.
16303 if (frame->frame->buf[0] && frame->sequence == s->seq_decode &&
215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4307 times.
4307 frame->poc == poc) {
216 av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence: %d.\n", poc);
217 return AVERROR_INVALIDDATA;
218 }
219 }
220
221 959 ref = alloc_frame(s, fc);
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 959 times.
959 if (!ref)
223 return AVERROR(ENOMEM);
224
225 959 set_pict_type(ref->frame, s, fc);
226 959 *frame = ref->frame;
227 959 fc->ref = ref;
228
229
5/6
✓ Branch 0 taken 774 times.
✓ Branch 1 taken 185 times.
✓ Branch 2 taken 759 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 759 times.
959 if (s->no_output_before_recovery_flag && (IS_RASL(s) || !GDR_IS_RECOVERED(s)))
230 15 ref->flags = VVC_FRAME_FLAG_SHORT_REF;
231
1/2
✓ Branch 0 taken 944 times.
✗ Branch 1 not taken.
944 else if (ph->r->ph_pic_output_flag)
232 944 ref->flags = VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_SHORT_REF;
233
234
2/2
✓ Branch 0 taken 947 times.
✓ Branch 1 taken 12 times.
959 if (!ph->r->ph_non_ref_pic_flag)
235 947 ref->flags |= VVC_FRAME_FLAG_SHORT_REF;
236
237 959 ref->poc = poc;
238 959 ref->sequence = s->seq_decode;
239 959 ref->frame->crop_left = fc->ps.pps->r->pps_conf_win_left_offset << fc->ps.sps->hshift[CHROMA];
240 959 ref->frame->crop_right = fc->ps.pps->r->pps_conf_win_right_offset << fc->ps.sps->hshift[CHROMA];
241 959 ref->frame->crop_top = fc->ps.pps->r->pps_conf_win_top_offset << fc->ps.sps->vshift[CHROMA];
242 959 ref->frame->crop_bottom = fc->ps.pps->r->pps_conf_win_bottom_offset << fc->ps.sps->vshift[CHROMA];
243
244 959 return 0;
245 }
246
247 1070 int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush)
248 {
249 1070 const VVCSPS *sps = fc->ps.sps;
250 95 do {
251 1165 int nb_output = 0;
252 1165 int min_poc = INT_MAX;
253 int min_idx, ret;
254
255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1165 times.
1165 if (no_output_of_prior_pics_flag) {
256 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
257 VVCFrame *frame = &fc->DPB[i];
258 if (!(frame->flags & VVC_FRAME_FLAG_BUMPING) && frame->poc != fc->ps.ph.poc &&
259 frame->sequence == s->seq_output) {
260 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT);
261 }
262 }
263 }
264
265
2/2
✓ Branch 0 taken 19805 times.
✓ Branch 1 taken 1165 times.
20970 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
266 19805 VVCFrame *frame = &fc->DPB[i];
267
2/2
✓ Branch 0 taken 4437 times.
✓ Branch 1 taken 15368 times.
19805 if ((frame->flags & VVC_FRAME_FLAG_OUTPUT) &&
268
2/2
✓ Branch 0 taken 4192 times.
✓ Branch 1 taken 245 times.
4437 frame->sequence == s->seq_output) {
269 4192 nb_output++;
270
3/4
✓ Branch 0 taken 2029 times.
✓ Branch 1 taken 2163 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2029 times.
4192 if (frame->poc < min_poc || nb_output == 1) {
271 2163 min_poc = frame->poc;
272 2163 min_idx = i;
273 }
274 }
275 }
276
277 /* wait for more frames before output */
278
5/6
✓ Branch 0 taken 1052 times.
✓ Branch 1 taken 113 times.
✓ Branch 2 taken 916 times.
✓ Branch 3 taken 136 times.
✓ Branch 4 taken 916 times.
✗ Branch 5 not taken.
1165 if (!flush && s->seq_output == s->seq_decode && sps &&
279
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 777 times.
916 nb_output <= sps->r->sps_dpb_params.dpb_max_num_reorder_pics[sps->r->sps_max_sublayers_minus1])
280 139 return 0;
281
282
2/2
✓ Branch 0 taken 903 times.
✓ Branch 1 taken 123 times.
1026 if (nb_output) {
283 903 VVCFrame *frame = &fc->DPB[min_idx];
284
285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 903 times.
903 if (frame->flags & VVC_FRAME_FLAG_CORRUPT)
286 frame->frame->flags |= AV_FRAME_FLAG_CORRUPT;
287
288 903 ret = av_frame_ref(out, frame->frame);
289
2/2
✓ Branch 0 taken 580 times.
✓ Branch 1 taken 323 times.
903 if (frame->flags & VVC_FRAME_FLAG_BUMPING)
290 580 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_BUMPING);
291 else
292 323 ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT);
293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 903 times.
903 if (ret < 0)
294 return ret;
295
296 903 av_log(s->avctx, AV_LOG_DEBUG,
297 "Output frame with POC %d.\n", frame->poc);
298 903 return 1;
299 }
300
301
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 28 times.
123 if (s->seq_output != s->seq_decode)
302 95 s->seq_output = (s->seq_output + 1) & 0xff;
303 else
304 28 break;
305 } while (1);
306 28 return 0;
307 }
308
309 864 void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc)
310 {
311 864 const VVCSPS *sps = fc->ps.sps;
312 864 const int poc = fc->ps.ph.poc;
313 864 int dpb = 0;
314 864 int min_poc = INT_MAX;
315
316
2/2
✓ Branch 0 taken 14688 times.
✓ Branch 1 taken 864 times.
15552 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
317 14688 VVCFrame *frame = &fc->DPB[i];
318
2/2
✓ Branch 0 taken 5237 times.
✓ Branch 1 taken 9451 times.
14688 if ((frame->flags) &&
319
2/2
✓ Branch 0 taken 5115 times.
✓ Branch 1 taken 122 times.
5237 frame->sequence == s->seq_output &&
320
2/2
✓ Branch 0 taken 4279 times.
✓ Branch 1 taken 836 times.
5115 frame->poc != poc) {
321 4279 dpb++;
322 }
323 }
324
325
3/4
✓ Branch 0 taken 864 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 390 times.
✓ Branch 3 taken 474 times.
864 if (sps && dpb >= sps->r->sps_dpb_params.dpb_max_dec_pic_buffering_minus1[sps->r->sps_max_sublayers_minus1] + 1) {
326
2/2
✓ Branch 0 taken 6630 times.
✓ Branch 1 taken 390 times.
7020 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
327 6630 VVCFrame *frame = &fc->DPB[i];
328
2/2
✓ Branch 0 taken 2678 times.
✓ Branch 1 taken 3952 times.
6630 if ((frame->flags) &&
329
1/2
✓ Branch 0 taken 2678 times.
✗ Branch 1 not taken.
2678 frame->sequence == s->seq_output &&
330
2/2
✓ Branch 0 taken 2288 times.
✓ Branch 1 taken 390 times.
2678 frame->poc != poc) {
331
4/4
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 2230 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 8 times.
2288 if (frame->flags == VVC_FRAME_FLAG_OUTPUT && frame->poc < min_poc) {
332 50 min_poc = frame->poc;
333 }
334 }
335 }
336
337
2/2
✓ Branch 0 taken 6630 times.
✓ Branch 1 taken 390 times.
7020 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
338 6630 VVCFrame *frame = &fc->DPB[i];
339
2/2
✓ Branch 0 taken 1835 times.
✓ Branch 1 taken 4795 times.
6630 if (frame->flags & VVC_FRAME_FLAG_OUTPUT &&
340
1/2
✓ Branch 0 taken 1835 times.
✗ Branch 1 not taken.
1835 frame->sequence == s->seq_output &&
341
2/2
✓ Branch 0 taken 1639 times.
✓ Branch 1 taken 196 times.
1835 frame->poc <= min_poc) {
342 1639 frame->flags |= VVC_FRAME_FLAG_BUMPING;
343 }
344 }
345
346 390 dpb--;
347 }
348 864 }
349
350 6882 static VVCFrame *find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb)
351 {
352
2/2
✓ Branch 0 taken 394 times.
✓ Branch 1 taken 6488 times.
6882 const unsigned mask = use_msb ? ~0 : fc->ps.sps->max_pic_order_cnt_lsb - 1;
353
354
2/2
✓ Branch 0 taken 25119 times.
✓ Branch 1 taken 28 times.
25147 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
355 25119 VVCFrame *ref = &fc->DPB[i];
356
4/4
✓ Branch 0 taken 22391 times.
✓ Branch 1 taken 2728 times.
✓ Branch 2 taken 21463 times.
✓ Branch 3 taken 928 times.
25119 if (ref->frame->buf[0] && ref->sequence == s->seq_decode) {
357
2/2
✓ Branch 0 taken 6854 times.
✓ Branch 1 taken 14609 times.
21463 if ((ref->poc & mask) == poc)
358 6854 return ref;
359 }
360 }
361 28 return NULL;
362 }
363
364 22211 static void mark_ref(VVCFrame *frame, int flag)
365 {
366 22211 frame->flags &= ~(VVC_FRAME_FLAG_LONG_REF | VVC_FRAME_FLAG_SHORT_REF);
367 22211 frame->flags |= flag;
368 22211 }
369
370 17 static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int poc)
371 {
372 17 const VVCSPS *sps = fc->ps.sps;
373 17 const VVCPPS *pps = fc->ps.pps;
374 VVCFrame *frame;
375
376 17 frame = alloc_frame(s, fc);
377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (!frame)
378 return NULL;
379
380
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if (!s->avctx->hwaccel) {
381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (!sps->pixel_shift) {
382 for (int i = 0; frame->frame->buf[i]; i++)
383 memset(frame->frame->buf[i]->data, 1 << (sps->bit_depth - 1),
384 frame->frame->buf[i]->size);
385 } else {
386
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 17 times.
68 for (int i = 0; frame->frame->data[i]; i++)
387
2/2
✓ Branch 0 taken 10688 times.
✓ Branch 1 taken 51 times.
10739 for (int y = 0; y < (pps->height >> sps->vshift[i]); y++) {
388 10688 uint8_t *dst = frame->frame->data[i] + y * frame->frame->linesize[i];
389 10688 AV_WN16(dst, 1 << (sps->bit_depth - 1));
390 10688 av_memcpy_backptr(dst + 2, 2, 2*(pps->width >> sps->hshift[i]) - 2);
391 }
392 }
393 }
394
395 17 frame->poc = poc;
396 17 frame->sequence = s->seq_decode;
397 17 frame->flags = VVC_FRAME_FLAG_CORRUPT;
398
399 17 ff_vvc_report_frame_finished(frame);
400
401 17 return frame;
402 }
403
404 #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))
405 #define CHECK_SAMPLES(d) (frame->pps->r->pps_pic_##d##_in_luma_samples == ref->pps->r->pps_pic_##d##_in_luma_samples)
406 6867 static int check_candidate_ref(const VVCFrame *frame, const VVCRefPic *refp)
407 {
408 6867 const VVCFrame *ref = refp->ref;
409
410
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6859 times.
6867 if (refp->is_scaled) {
411 8 const int max = FFMAX(8, frame->sps->min_cb_size_y);
412 16 return frame->ref_width * 2 >= ref->ref_width &&
413
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 frame->ref_height * 2 >= ref->ref_height &&
414
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 frame->ref_width <= ref->ref_width * 8 &&
415
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 frame->ref_height <= ref->ref_height * 8 &&
416
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);
417 }
418
2/4
✓ Branch 0 taken 6859 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6859 times.
✗ Branch 3 not taken.
6859 return CHECK_SAMPLES(width) && CHECK_SAMPLES(height);
419 }
420
421 #define RPR_SCALE(f) (((ref->f << 14) + (fc->ref->f >> 1)) / fc->ref->f)
422 /* add a reference with the given poc to the list and mark it as used in DPB */
423 6882 static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *list,
424 int poc, int ref_flag, uint8_t use_msb)
425 {
426 6882 VVCFrame *ref = find_ref_idx(s, fc, poc, use_msb);
427 6882 VVCRefPic *refp = &list->refs[list->nb_refs];
428
429
2/4
✓ Branch 0 taken 6882 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6882 times.
6882 if (ref == fc->ref || list->nb_refs >= VVC_MAX_REF_ENTRIES)
430 return AVERROR_INVALIDDATA;
431
432
6/8
✓ Branch 0 taken 6882 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6868 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 6827 times.
✓ Branch 5 taken 41 times.
✓ Branch 6 taken 6827 times.
✗ Branch 7 not taken.
6882 if (!IS_CVSS(s)) {
433
4/4
✓ Branch 0 taken 6816 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 6812 times.
6827 const bool ref_corrupt = !ref || (ref->flags & VVC_FRAME_FLAG_CORRUPT);
434
3/4
✓ Branch 0 taken 6036 times.
✓ Branch 1 taken 791 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6036 times.
6827 const bool recovering = s->no_output_before_recovery_flag && !GDR_IS_RECOVERED(s);
435
436
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 6812 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
6827 if (ref_corrupt && !recovering) {
437
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (!(s->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) &&
438
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 !(s->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL))
439 15 return AVERROR_INVALIDDATA;
440
441 fc->ref->flags |= VVC_FRAME_FLAG_CORRUPT;
442 }
443 }
444
445
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 6850 times.
6867 if (!ref) {
446 17 ref = generate_missing_ref(s, fc, poc);
447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (!ref)
448 return AVERROR(ENOMEM);
449 }
450
451 6867 refp->poc = poc;
452 6867 refp->ref = ref;
453 6867 refp->is_lt = ref_flag & VVC_FRAME_FLAG_LONG_REF;
454 20601 refp->is_scaled = ref->sps->r->sps_num_subpics_minus1 != fc->ref->sps->r->sps_num_subpics_minus1||
455
1/2
✓ Branch 0 taken 6867 times.
✗ Branch 1 not taken.
6867 memcmp(&ref->scaling_win, &fc->ref->scaling_win, sizeof(ref->scaling_win)) ||
456
3/4
✓ Branch 0 taken 6867 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6859 times.
✓ Branch 3 taken 8 times.
20593 ref->pps->r->pps_pic_width_in_luma_samples != fc->ref->pps->r->pps_pic_width_in_luma_samples ||
457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6859 times.
6859 ref->pps->r->pps_pic_height_in_luma_samples != fc->ref->pps->r->pps_pic_height_in_luma_samples;
458
459
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6867 times.
6867 if (!check_candidate_ref(fc->ref, refp))
460 return AVERROR_INVALIDDATA;
461
462
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6859 times.
6867 if (refp->is_scaled) {
463 8 refp->scale[0] = RPR_SCALE(ref_width);
464 8 refp->scale[1] = RPR_SCALE(ref_height);
465 }
466 6867 list->nb_refs++;
467
468 6867 mark_ref(ref, ref_flag);
469 6867 return 0;
470 }
471
472 1558 static int init_slice_rpl(const VVCFrameContext *fc, SliceContext *sc)
473 {
474 1558 VVCFrame *frame = fc->ref;
475 1558 const VVCSH *sh = &sc->sh;
476
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1558 times.
1558 if (sc->slice_idx >= frame->nb_rpl_elems)
478 return AVERROR_INVALIDDATA;
479
480
2/2
✓ Branch 0 taken 45150 times.
✓ Branch 1 taken 1558 times.
46708 for (int i = 0; i < sh->num_ctus_in_curr_slice; i++) {
481 45150 const int rs = sh->ctb_addr_in_curr_slice[i];
482 45150 frame->rpl_tab[rs] = frame->rpl + sc->slice_idx;
483 }
484
485 1558 sc->rpl = frame->rpl_tab[sh->ctb_addr_in_curr_slice[0]]->refPicList;
486
487 1558 return 0;
488 }
489
490 6488 static int delta_poc_st(const H266RefPicListStruct *rpls,
491 const int lx, const int i, const VVCSPS *sps)
492 {
493 6488 int abs_delta_poc_st = rpls->abs_delta_poc_st[i];
494
4/4
✓ Branch 0 taken 5969 times.
✓ Branch 1 taken 519 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 447 times.
6488 if (!((sps->r->sps_weighted_pred_flag ||
495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5969 times.
5969 sps->r->sps_weighted_bipred_flag) && i != 0))
496 6041 abs_delta_poc_st++;
497 6488 return (1 - 2 * rpls->strp_entry_sign_flag[i]) * abs_delta_poc_st;
498 }
499
500 394 static int poc_lt(int *prev_delta_poc_msb, const int poc, const H266RefPicLists *ref_lists,
501 const int lx, const int j, const int max_poc_lsb)
502 {
503 394 const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx;
504
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];
505
506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 394 times.
394 if (ref_lists->delta_poc_msb_cycle_present_flag[lx][j]) {
507 const uint32_t delta = ref_lists->delta_poc_msb_cycle_lt[lx][j] + *prev_delta_poc_msb;
508 lt_poc += poc - delta * max_poc_lsb - (poc & (max_poc_lsb - 1));
509 *prev_delta_poc_msb = delta;
510 }
511 394 return lt_poc;
512 }
513
514 1558 int ff_vvc_slice_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
515 {
516 1558 const VVCSPS *sps = fc->ps.sps;
517 1558 const H266RawPPS *pps = fc->ps.pps->r;
518 1558 const VVCPH *ph = &fc->ps.ph;
519 1558 const H266RawSliceHeader *rsh = sc->sh.r;
520 1558 const int max_poc_lsb = sps->max_pic_order_cnt_lsb;
521 1558 const H266RefPicLists *ref_lists =
522
2/2
✓ Branch 0 taken 253 times.
✓ Branch 1 taken 1305 times.
1558 pps->pps_rpl_info_in_ph_flag ? &ph->r->ph_ref_pic_lists : &rsh->sh_ref_pic_lists;
523 1558 int ret = 0;
524
525 1558 ret = init_slice_rpl(fc, sc);
526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1558 times.
1558 if (ret < 0)
527 return ret;
528
529
2/2
✓ Branch 0 taken 3101 times.
✓ Branch 1 taken 1543 times.
4644 for (int lx = L0; lx <= L1; lx++) {
530 3101 const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx;
531 3101 RefPicList *rpl = sc->rpl + lx;
532 3101 int poc_base = ph->poc;
533 3101 int prev_delta_poc_msb = 0;
534
535 3101 rpl->nb_refs = 0;
536
2/2
✓ Branch 0 taken 6882 times.
✓ Branch 1 taken 3086 times.
9968 for (int i = 0, j = 0; i < rpls->num_ref_entries; i++) {
537 int poc;
538
1/2
✓ Branch 0 taken 6882 times.
✗ Branch 1 not taken.
6882 if (!rpls->inter_layer_ref_pic_flag[i]) {
539 6882 int use_msb = 1;
540 int ref_flag;
541
2/2
✓ Branch 0 taken 6488 times.
✓ Branch 1 taken 394 times.
6882 if (rpls->st_ref_pic_flag[i]) {
542 6488 poc = poc_base + delta_poc_st(rpls, lx, i, sps);
543 6488 poc_base = poc;
544 6488 ref_flag = VVC_FRAME_FLAG_SHORT_REF;
545 } else {
546 394 use_msb = ref_lists->delta_poc_msb_cycle_present_flag[lx][j];
547 394 poc = poc_lt(&prev_delta_poc_msb, ph->poc, ref_lists, lx, j, max_poc_lsb);
548 394 ref_flag = VVC_FRAME_FLAG_LONG_REF;
549 394 j++;
550 }
551 6882 ret = add_candidate_ref(s, fc, rpl, poc, ref_flag, use_msb);
552
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 6867 times.
6882 if (ret < 0)
553 15 return ret;
554 } else {
555 // OPI_B_3.bit and VPS_A_3.bit should cover this
556 avpriv_report_missing_feature(fc->log_ctx, "Inter layer ref");
557 ret = AVERROR_PATCHWELCOME;
558 return ret;
559 }
560 }
561
2/2
✓ Branch 0 taken 2866 times.
✓ Branch 1 taken 220 times.
3086 if (ph->r->ph_temporal_mvp_enabled_flag &&
562
2/2
✓ Branch 0 taken 1433 times.
✓ Branch 1 taken 1433 times.
2866 (!rsh->sh_collocated_from_l0_flag) == lx &&
563
1/2
✓ Branch 0 taken 1433 times.
✗ Branch 1 not taken.
1433 rsh->sh_collocated_ref_idx < rpl->nb_refs) {
564 1433 const VVCRefPic *refp = rpl->refs + rsh->sh_collocated_ref_idx;
565
2/4
✓ Branch 0 taken 1433 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1433 times.
1433 if (refp->is_scaled || refp->ref->sps->ctb_log2_size_y != sps->ctb_log2_size_y)
566 return AVERROR_INVALIDDATA;
567 1433 fc->ref->collocated_ref = refp->ref;
568 }
569 }
570 1543 return 0;
571 }
572
573 959 int ff_vvc_frame_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
574 {
575 959 int ret = 0;
576
577 /* clear the reference flags on all frames except the current one */
578
2/2
✓ Branch 0 taken 16303 times.
✓ Branch 1 taken 959 times.
17262 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
579 16303 VVCFrame *frame = &fc->DPB[i];
580
581
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 15344 times.
16303 if (frame == fc->ref)
582 959 continue;
583
584 15344 mark_ref(frame, 0);
585 }
586
587
2/2
✓ Branch 1 taken 944 times.
✓ Branch 2 taken 15 times.
959 if ((ret = ff_vvc_slice_rpl(s, fc, sc)) < 0)
588 15 goto fail;
589
590 944 fail:
591 /* release any frames that are now unused */
592
2/2
✓ Branch 0 taken 16303 times.
✓ Branch 1 taken 959 times.
17262 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
593 16303 ff_vvc_unref_frame(fc, &fc->DPB[i], 0);
594 959 return ret;
595 }
596
597 961 void ff_vvc_report_frame_finished(VVCFrame *frame)
598 {
599 961 ff_vvc_report_progress(frame, VVC_PROGRESS_MV, INT_MAX);
600 961 ff_vvc_report_progress(frame, VVC_PROGRESS_PIXEL, INT_MAX);
601 961 }
602
603 88284 static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l)
604 {
605 88284 return p->progress[l->vp] > l->y;
606 }
607
608 static void add_listener(VVCProgressListener **prev, VVCProgressListener *l)
609 {
610 l->next = *prev;
611 *prev = l;
612 }
613
614 static VVCProgressListener* remove_listener(VVCProgressListener **prev, VVCProgressListener *l)
615 {
616 *prev = l->next;
617 l->next = NULL;
618 return l;
619 }
620
621 8425 static VVCProgressListener* get_done_listener(FrameProgress *p, const VVCProgress vp)
622 {
623 8425 VVCProgressListener *list = NULL;
624 8425 VVCProgressListener **prev = &p->listener[vp];
625
626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8425 times.
8425 while (*prev) {
627 if (is_progress_done(p, *prev)) {
628 VVCProgressListener *l = remove_listener(prev, *prev);
629 add_listener(&list, l);
630 } else {
631 prev = &(*prev)->next;
632 }
633 }
634 8425 return list;
635 }
636
637 10313 void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y)
638 {
639 10313 FrameProgress *p = frame->progress;
640 10313 VVCProgressListener *l = NULL;
641
642 10313 ff_mutex_lock(&p->lock);
643
2/2
✓ Branch 0 taken 8425 times.
✓ Branch 1 taken 1888 times.
10313 if (p->progress[vp] < y) {
644 // Due to the nature of thread scheduling, later progress may reach this point before earlier progress.
645 // Therefore, we only update the progress when p->progress[vp] < y.
646 8425 p->progress[vp] = y;
647 8425 l = get_done_listener(p, vp);
648 8425 ff_cond_signal(&p->cond);
649 }
650 10313 ff_mutex_unlock(&p->lock);
651
652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10313 times.
10313 while (l) {
653 l->progress_done(l);
654 l = l->next;
655 }
656 10313 }
657
658 88284 void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l)
659 {
660 88284 FrameProgress *p = frame->progress;
661
662 88284 ff_mutex_lock(&p->lock);
663
664
1/2
✓ Branch 1 taken 88284 times.
✗ Branch 2 not taken.
88284 if (is_progress_done(p, l)) {
665 88284 ff_mutex_unlock(&p->lock);
666 88284 l->progress_done(l);
667 } else {
668 add_listener(p->listener + l->vp, l);
669 ff_mutex_unlock(&p->lock);
670 }
671 88284 }
672