FFmpeg
Loading...
Searching...
No Matches
refs.c
Go to the documentation of this file.
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
43
45{
46 /* frame->frame can be NULL if context init failed */
47 if (!frame->frame || !frame->frame->buf[0])
48 return;
49
50 frame->flags &= ~flags;
51 if (!(frame->flags & ~VVC_FRAME_FLAG_CORRUPT))
52 frame->flags = 0;
53 if (!frame->flags) {
54 av_frame_unref(frame->frame);
55
56 if (frame->needs_fg) {
57 av_frame_unref(frame->frame_grain);
58 frame->needs_fg = 0;
59 }
60
63 av_refstruct_unref(&frame->progress);
64
65 av_refstruct_unref(&frame->tab_dmvr_mvf);
66
68 frame->nb_rpl_elems = 0;
69 av_refstruct_unref(&frame->rpl_tab);
70
71 frame->collocated_ref = NULL;
72 av_refstruct_unref(&frame->hwaccel_picture_private);
73 }
74}
75
76const RefPicList *ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
77{
78 const int x_cb = x0 >> fc->ps.sps->ctb_log2_size_y;
79 const int y_cb = y0 >> fc->ps.sps->ctb_log2_size_y;
80 const int pic_width_cb = fc->ps.pps->ctb_width;
81 const int ctb_addr_rs = y_cb * pic_width_cb + x_cb;
82
83 return (const RefPicList *)ref->rpl_tab[ctb_addr_rs];
84}
85
92
94{
95 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
96 ff_vvc_unref_frame(fc, &fc->DPB[i], ~0);
97}
98
99static void free_progress(AVRefStructOpaque unused, void *obj)
100{
101 FrameProgress *p = (FrameProgress *)obj;
102
103 if (p->has_cond)
104 ff_cond_destroy(&p->cond);
105 if (p->has_lock)
106 ff_mutex_destroy(&p->lock);
107}
108
110{
112
113 if (p) {
114 p->has_lock = !ff_mutex_init(&p->lock, NULL);
115 p->has_cond = !ff_cond_init(&p->cond, NULL);
116 if (!p->has_lock || !p->has_cond)
118 }
119 return p;
120}
121
123{
124 const VVCSPS *sps = fc->ps.sps;
125 const VVCPPS *pps = fc->ps.pps;
126 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
127 int ret;
128 VVCFrame *frame = &fc->DPB[i];
129 VVCWindow *win = &frame->scaling_win;
130 if (frame->frame->buf[0])
131 continue;
132
133 frame->sps = av_refstruct_ref_c(fc->ps.sps);
134 frame->pps = av_refstruct_ref_c(fc->ps.pps);
135
136 // Add LCEVC SEI metadata here, as it's needed in get_buffer()
137 if (fc->sei.common.itut_t35.lcevc) {
138 ret = ff_frame_new_side_data_from_buf(s->avctx, frame->frame,
139 AV_FRAME_DATA_LCEVC, &fc->sei.common.itut_t35.lcevc);
140 if (ret < 0)
141 goto fail;
142 }
143
144 ret = ff_thread_get_buffer(s->avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
145 if (ret < 0)
146 return NULL;
147
148 frame->rpl = av_refstruct_allocz(s->current_frame.nb_units * sizeof(RefPicListTab));
149 if (!frame->rpl)
150 goto fail;
151 frame->nb_rpl_elems = s->current_frame.nb_units;
152
153 frame->tab_dmvr_mvf = av_refstruct_pool_get(fc->tab_dmvr_mvf_pool);
154 if (!frame->tab_dmvr_mvf)
155 goto fail;
156
157 frame->rpl_tab = av_refstruct_pool_get(fc->rpl_tab_pool);
158 if (!frame->rpl_tab)
159 goto fail;
160 frame->ctb_count = pps->ctb_width * pps->ctb_height;
161 for (int j = 0; j < frame->ctb_count; j++)
162 frame->rpl_tab[j] = frame->rpl;
163
164 win->left_offset = pps->r->pps_scaling_win_left_offset * (1 << sps->hshift[CHROMA]);
165 win->right_offset = pps->r->pps_scaling_win_right_offset * (1 << sps->hshift[CHROMA]);
166 win->top_offset = pps->r->pps_scaling_win_top_offset * (1 << sps->vshift[CHROMA]);
167 win->bottom_offset = pps->r->pps_scaling_win_bottom_offset * (1 << sps->vshift[CHROMA]);
168 frame->ref_width = pps->r->pps_pic_width_in_luma_samples - win->left_offset - win->right_offset;
169 frame->ref_height = pps->r->pps_pic_height_in_luma_samples - win->bottom_offset - win->top_offset;
170
171 if (fc->sei.frame_field_info.present) {
172 if (fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD)
173 frame->frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST;
174 if (fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD ||
175 fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_BOTTOM_FIELD)
176 frame->frame->flags |= AV_FRAME_FLAG_INTERLACED;
177 }
178
179 frame->progress = alloc_progress();
180 if (!frame->progress)
181 goto fail;
182
183 ret = ff_hwaccel_frame_priv_alloc(s->avctx, &frame->hwaccel_picture_private);
184 if (ret < 0)
185 goto fail;
186
187 return frame;
188fail:
190 return NULL;
191 }
192 av_log(s->avctx, AV_LOG_ERROR, "Error allocating frame, DPB full.\n");
193 return NULL;
194}
195
197{
198 bool has_b = false, has_inter = false;
199
200 if (IS_IRAP(s)) {
201 frame->pict_type = AV_PICTURE_TYPE_I;
202 frame->flags |= AV_FRAME_FLAG_KEY;
203 return;
204 }
205
206 if (fc->ps.ph.r->ph_inter_slice_allowed_flag) {
207 // At this point, fc->slices is not fully initialized; we need to inspect the CBS directly.
208 const CodedBitstreamFragment *current = &s->current_frame;
209 for (int i = 0; i < current->nb_units && !has_b; i++) {
210 const CodedBitstreamUnit *unit = current->units + i;
211 if (unit->content_ref && unit->type <= VVC_RSV_IRAP_11) {
212 const H266RawSliceHeader *rsh = unit->content_ref;
213 has_inter |= !IS_I(rsh);
214 has_b |= IS_B(rsh);
215 }
216 }
217 }
218 if (!has_inter)
219 frame->pict_type = AV_PICTURE_TYPE_I;
220 else if (has_b)
221 frame->pict_type = AV_PICTURE_TYPE_B;
222 else
223 frame->pict_type = AV_PICTURE_TYPE_P;
224}
225
227{
228 const VVCPH *ph= &fc->ps.ph;
229 const int poc = ph->poc;
230 VVCFrame *ref;
231
232 /* check that this POC doesn't already exist */
233 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
234 VVCFrame *frame = &fc->DPB[i];
235
236 if (frame->frame->buf[0] && frame->sequence == s->seq_decode &&
237 frame->poc == poc) {
238 av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence: %d.\n", poc);
239 return AVERROR_INVALIDDATA;
240 }
241 }
242
243 ref = alloc_frame(s, fc);
244 if (!ref)
245 return AVERROR(ENOMEM);
246
247 set_pict_type(ref->frame, s, fc);
248 *frame = ref->frame;
249 fc->ref = ref;
250
251 if (s->no_output_before_recovery_flag && (IS_RASL(s) || !GDR_IS_RECOVERED(s)))
253 else if (ph->r->ph_pic_output_flag)
255
256 if (!ph->r->ph_non_ref_pic_flag)
258
259 ref->poc = poc;
260 ref->sequence = s->seq_decode;
261 ref->frame->crop_left = fc->ps.pps->r->pps_conf_win_left_offset << fc->ps.sps->hshift[CHROMA];
262 ref->frame->crop_right = fc->ps.pps->r->pps_conf_win_right_offset << fc->ps.sps->hshift[CHROMA];
263 ref->frame->crop_top = fc->ps.pps->r->pps_conf_win_top_offset << fc->ps.sps->vshift[CHROMA];
264 ref->frame->crop_bottom = fc->ps.pps->r->pps_conf_win_bottom_offset << fc->ps.sps->vshift[CHROMA];
265
266 return 0;
267}
268
269int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush)
270{
271 const VVCSPS *sps = fc->ps.sps;
272 do {
273 int nb_output = 0;
274 int min_poc = INT_MAX;
275 int min_idx, ret;
276
277 if (no_output_of_prior_pics_flag) {
278 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
279 VVCFrame *frame = &fc->DPB[i];
280 if (!(frame->flags & VVC_FRAME_FLAG_BUMPING) && frame->poc != fc->ps.ph.poc &&
281 frame->sequence == s->seq_output) {
283 }
284 }
285 }
286
287 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
288 VVCFrame *frame = &fc->DPB[i];
289 if ((frame->flags & VVC_FRAME_FLAG_OUTPUT) &&
290 frame->sequence == s->seq_output) {
291 nb_output++;
292 if (frame->poc < min_poc || nb_output == 1) {
293 min_poc = frame->poc;
294 min_idx = i;
295 }
296 }
297 }
298
299 /* wait for more frames before output */
300 if (!flush && s->seq_output == s->seq_decode && sps &&
301 nb_output <= sps->r->sps_dpb_params.dpb_max_num_reorder_pics[sps->r->sps_max_sublayers_minus1])
302 return 0;
303
304 if (nb_output) {
305 VVCFrame *frame = &fc->DPB[min_idx];
306
307 if (frame->flags & VVC_FRAME_FLAG_CORRUPT)
308 frame->frame->flags |= AV_FRAME_FLAG_CORRUPT;
309
310 ret = av_frame_ref(out, frame->needs_fg ? frame->frame_grain : frame->frame);
311
312 if (!ret && !(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))
314
315 if (frame->flags & VVC_FRAME_FLAG_BUMPING)
317 else
319
320 if (ret < 0)
321 return ret;
322
323 av_log(s->avctx, AV_LOG_DEBUG,
324 "Output frame with POC %d.\n", frame->poc);
325 return 1;
326 }
327
328 if (s->seq_output != s->seq_decode)
329 s->seq_output = (s->seq_output + 1) & 0xff;
330 else
331 break;
332 } while (1);
333 return 0;
334}
335
337{
338 const VVCSPS *sps = fc->ps.sps;
339 const int poc = fc->ps.ph.poc;
340 int dpb = 0;
341 int min_poc = INT_MAX;
342
343 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
344 VVCFrame *frame = &fc->DPB[i];
345 if ((frame->flags) &&
346 frame->sequence == s->seq_output &&
347 frame->poc != poc) {
348 dpb++;
349 }
350 }
351
352 if (sps && dpb >= sps->r->sps_dpb_params.dpb_max_dec_pic_buffering_minus1[sps->r->sps_max_sublayers_minus1] + 1) {
353 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
354 VVCFrame *frame = &fc->DPB[i];
355 if ((frame->flags) &&
356 frame->sequence == s->seq_output &&
357 frame->poc != poc) {
358 if (frame->flags == VVC_FRAME_FLAG_OUTPUT && frame->poc < min_poc) {
359 min_poc = frame->poc;
360 }
361 }
362 }
363
364 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
365 VVCFrame *frame = &fc->DPB[i];
366 if (frame->flags & VVC_FRAME_FLAG_OUTPUT &&
367 frame->sequence == s->seq_output &&
368 frame->poc <= min_poc) {
370 }
371 }
372
373 dpb--;
374 }
375}
376
377static VVCFrame *find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb)
378{
379 const unsigned mask = use_msb ? ~0 : fc->ps.sps->max_pic_order_cnt_lsb - 1;
380
381 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
382 VVCFrame *ref = &fc->DPB[i];
383 if (ref->frame->buf[0] && ref->sequence == s->seq_decode) {
384 if ((ref->poc & mask) == poc)
385 return ref;
386 }
387 }
388 return NULL;
389}
390
391static void mark_ref(VVCFrame *frame, int flag)
392{
394 frame->flags |= flag;
395}
396
398{
399 const VVCSPS *sps = fc->ps.sps;
400 const VVCPPS *pps = fc->ps.pps;
402
403 frame = alloc_frame(s, fc);
404 if (!frame)
405 return NULL;
406
407 if (!s->avctx->hwaccel) {
408 if (!sps->pixel_shift) {
409 for (int i = 0; frame->frame->buf[i]; i++)
410 memset(frame->frame->buf[i]->data, 1 << (sps->bit_depth - 1),
411 frame->frame->buf[i]->size);
412 } else {
413 for (int i = 0; frame->frame->data[i]; i++)
414 for (int y = 0; y < (pps->height >> sps->vshift[i]); y++) {
415 uint8_t *dst = frame->frame->data[i] + y * frame->frame->linesize[i];
416 AV_WN16(dst, 1 << (sps->bit_depth - 1));
417 av_memcpy_backptr(dst + 2, 2, 2*(pps->width >> sps->hshift[i]) - 2);
418 }
419 }
420 }
421
422 frame->poc = poc;
423 frame->sequence = s->seq_decode;
425
427
428 return frame;
429}
430
431#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))
432#define CHECK_SAMPLES(d) (frame->pps->r->pps_pic_##d##_in_luma_samples == ref->pps->r->pps_pic_##d##_in_luma_samples)
433static int check_candidate_ref(const VVCFrame *frame, const VVCRefPic *refp)
434{
435 const VVCFrame *ref = refp->ref;
436
437 if (refp->is_scaled) {
438 const int max = FFMAX(8, frame->sps->min_cb_size_y);
439 return frame->ref_width * 2 >= ref->ref_width &&
440 frame->ref_height * 2 >= ref->ref_height &&
441 frame->ref_width <= ref->ref_width * 8 &&
442 frame->ref_height <= ref->ref_height * 8 &&
444 }
446}
447
448#define RPR_SCALE(f) (((ref->f << 14) + (fc->ref->f >> 1)) / fc->ref->f)
449/* add a reference with the given poc to the list and mark it as used in DPB */
451 int poc, int ref_flag, uint8_t use_msb)
452{
453 VVCFrame *ref = find_ref_idx(s, fc, poc, use_msb);
454 VVCRefPic *refp = &list->refs[list->nb_refs];
455
456 if (ref == fc->ref || list->nb_refs >= VVC_MAX_REF_ENTRIES)
457 return AVERROR_INVALIDDATA;
458
459 if (!IS_CVSS(s)) {
460 const bool ref_corrupt = !ref || (ref->flags & VVC_FRAME_FLAG_CORRUPT);
461 const bool recovering = s->no_output_before_recovery_flag &&
462 (IS_RASL(s) || !GDR_IS_RECOVERED(s));
463
464 if (ref_corrupt && !recovering) {
465 if (!(s->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) &&
466 !(s->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL))
467 return AVERROR_INVALIDDATA;
468
469 fc->ref->flags |= VVC_FRAME_FLAG_CORRUPT;
470 }
471 }
472
473 if (!ref) {
474 ref = generate_missing_ref(s, fc, poc);
475 if (!ref)
476 return AVERROR(ENOMEM);
477 }
478
479 refp->poc = poc;
480 refp->ref = ref;
481 refp->is_lt = ref_flag & VVC_FRAME_FLAG_LONG_REF;
482 refp->is_scaled = ref->sps->r->sps_num_subpics_minus1 != fc->ref->sps->r->sps_num_subpics_minus1||
483 memcmp(&ref->scaling_win, &fc->ref->scaling_win, sizeof(ref->scaling_win)) ||
484 ref->pps->r->pps_pic_width_in_luma_samples != fc->ref->pps->r->pps_pic_width_in_luma_samples ||
485 ref->pps->r->pps_pic_height_in_luma_samples != fc->ref->pps->r->pps_pic_height_in_luma_samples;
486
487 if (!check_candidate_ref(fc->ref, refp))
488 return AVERROR_INVALIDDATA;
489
490 if (refp->is_scaled) {
491 refp->scale[0] = RPR_SCALE(ref_width);
492 refp->scale[1] = RPR_SCALE(ref_height);
493 }
494 list->nb_refs++;
495
496 mark_ref(ref, ref_flag);
497 return 0;
498}
499
501{
502 VVCFrame *frame = fc->ref;
503 const VVCSH *sh = &sc->sh;
504
505 if (sc->slice_idx >= frame->nb_rpl_elems)
506 return AVERROR_INVALIDDATA;
507
508 for (int i = 0; i < sh->num_ctus_in_curr_slice; i++) {
509 const int rs = sh->ctb_addr_in_curr_slice[i];
510 frame->rpl_tab[rs] = frame->rpl + sc->slice_idx;
511 }
512
513 sc->rpl = frame->rpl_tab[sh->ctb_addr_in_curr_slice[0]]->refPicList;
514
515 return 0;
516}
517
518static int delta_poc_st(const H266RefPicListStruct *rpls,
519 const int lx, const int i, const VVCSPS *sps)
520{
521 int abs_delta_poc_st = rpls->abs_delta_poc_st[i];
522 if (!((sps->r->sps_weighted_pred_flag ||
523 sps->r->sps_weighted_bipred_flag) && i != 0))
524 abs_delta_poc_st++;
525 return (1 - 2 * rpls->strp_entry_sign_flag[i]) * abs_delta_poc_st;
526}
527
528static int poc_lt(int *prev_delta_poc_msb, const int poc, const H266RefPicLists *ref_lists,
529 const int lx, const int j, const int max_poc_lsb)
530{
531 const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx;
532 int lt_poc = rpls->ltrp_in_header_flag ? ref_lists->poc_lsb_lt[lx][j] : rpls->rpls_poc_lsb_lt[j];
533
534 if (ref_lists->delta_poc_msb_cycle_present_flag[lx][j]) {
535 const uint32_t delta = ref_lists->delta_poc_msb_cycle_lt[lx][j] + *prev_delta_poc_msb;
536 lt_poc += poc - delta * max_poc_lsb - (poc & (max_poc_lsb - 1));
537 *prev_delta_poc_msb = delta;
538 }
539 return lt_poc;
540}
541
543{
544 const VVCSPS *sps = fc->ps.sps;
545 const H266RawPPS *pps = fc->ps.pps->r;
546 const VVCPH *ph = &fc->ps.ph;
547 const H266RawSliceHeader *rsh = sc->sh.r;
548 const int max_poc_lsb = sps->max_pic_order_cnt_lsb;
549 const H266RefPicLists *ref_lists =
550 pps->pps_rpl_info_in_ph_flag ? &ph->r->ph_ref_pic_lists : &rsh->sh_ref_pic_lists;
551 int ret = 0;
552
553 ret = init_slice_rpl(fc, sc);
554 if (ret < 0)
555 return ret;
556
557 for (int lx = L0; lx <= L1; lx++) {
558 const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx;
559 RefPicList *rpl = sc->rpl + lx;
560 int poc_base = ph->poc;
561 int prev_delta_poc_msb = 0;
562
563 rpl->nb_refs = 0;
564 for (int i = 0, j = 0; i < rpls->num_ref_entries; i++) {
565 int poc;
566 if (!rpls->inter_layer_ref_pic_flag[i]) {
567 int use_msb = 1;
568 int ref_flag;
569 if (rpls->st_ref_pic_flag[i]) {
570 poc = poc_base + delta_poc_st(rpls, lx, i, sps);
571 poc_base = poc;
572 ref_flag = VVC_FRAME_FLAG_SHORT_REF;
573 } else {
574 use_msb = ref_lists->delta_poc_msb_cycle_present_flag[lx][j];
575 poc = poc_lt(&prev_delta_poc_msb, ph->poc, ref_lists, lx, j, max_poc_lsb);
576 ref_flag = VVC_FRAME_FLAG_LONG_REF;
577 j++;
578 }
579 ret = add_candidate_ref(s, fc, rpl, poc, ref_flag, use_msb);
580 if (ret < 0)
581 return ret;
582 } else {
583 // OPI_B_3.bit and VPS_A_3.bit should cover this
584 avpriv_report_missing_feature(fc->log_ctx, "Inter layer ref");
586 return ret;
587 }
588 }
589 if (ph->r->ph_temporal_mvp_enabled_flag &&
590 (!rsh->sh_collocated_from_l0_flag) == lx &&
591 rsh->sh_collocated_ref_idx < rpl->nb_refs) {
592 const VVCRefPic *refp = rpl->refs + rsh->sh_collocated_ref_idx;
593 if (refp->is_scaled || refp->ref->sps->ctb_log2_size_y != sps->ctb_log2_size_y)
594 return AVERROR_INVALIDDATA;
595 fc->ref->collocated_ref = refp->ref;
596 }
597 }
598 return 0;
599}
600
602{
603 int ret = 0;
604
605 /* clear the reference flags on all frames except the current one */
606 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
607 VVCFrame *frame = &fc->DPB[i];
608
609 if (frame == fc->ref)
610 continue;
611
612 mark_ref(frame, 0);
613 }
614
615 if ((ret = ff_vvc_slice_rpl(s, fc, sc)) < 0)
616 goto fail;
617
618fail:
619 /* release any frames that are now unused */
620 for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
621 ff_vvc_unref_frame(fc, &fc->DPB[i], 0);
622 return ret;
623}
624
630
632{
633 return p->progress[l->vp] > l->y;
634}
635
637{
638 l->next = *prev;
639 *prev = l;
640}
641
643{
644 *prev = l->next;
645 l->next = NULL;
646 return l;
647}
648
650{
652 VVCProgressListener **prev = &p->listener[vp];
653
654 while (*prev) {
655 if (is_progress_done(p, *prev)) {
656 VVCProgressListener *l = remove_listener(prev, *prev);
657 add_listener(&list, l);
658 } else {
659 prev = &(*prev)->next;
660 }
661 }
662 return list;
663}
664
666{
667 FrameProgress *p = frame->progress;
669
670 ff_mutex_lock(&p->lock);
671 if (p->progress[vp] < y) {
672 // Due to the nature of thread scheduling, later progress may reach this point before earlier progress.
673 // Therefore, we only update the progress when p->progress[vp] < y.
674 p->progress[vp] = y;
675 l = get_done_listener(p, vp);
676 ff_cond_signal(&p->cond);
677 }
678 ff_mutex_unlock(&p->lock);
679
680 while (l) {
681 l->progress_done(l);
682 l = l->next;
683 }
684}
685
687{
688 FrameProgress *p = frame->progress;
689
690 ff_mutex_lock(&p->lock);
691
692 if (is_progress_done(p, l)) {
693 ff_mutex_unlock(&p->lock);
694 l->progress_done(l);
695 } else {
696 add_listener(p->listener + l->vp, l);
697 ff_mutex_unlock(&p->lock);
698 }
699}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static float win(SuperEqualizerContext *s, float n, int N)
#define flag(name)
Definition cbs_h264.c:60
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
static int FUNC sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
static int FUNC ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
#define max(a, b)
static const uint16_t fc[]
Definition dcaenc.h:43
int ff_frame_new_side_data_from_buf(const AVCodecContext *avctx, AVFrame *frame, enum AVFrameSideDataType type, AVBufferRef **buf)
Similar to ff_frame_new_side_data, but using an existing buffer ref.
Definition decode.c:2222
int ff_hwaccel_frame_priv_alloc(AVCodecContext *avctx, void **hwaccel_picture_private)
Allocate a hwaccel frame private data if the provided avctx uses a hwaccel method that needs it.
Definition decode.c:2336
static AVFrame * frame
uint64_t pps
Definition dovi_rpuenc.c:36
void(* flush)(AVBSFContext *ctx)
Definition dts2pts.c:610
intptr_t atomic_int
Definition stdatomic.h:55
static struct @111144215057303131116103221376075045141373005341 current
#define fail
Definition test.h:479
#define AV_CODEC_FLAG2_SHOW_ALL
Show all frames before the first keyframe.
Definition avcodec.h:364
#define AV_GET_BUFFER_FLAG_REF
The decoder will keep a reference to the frame and may reuse it later.
Definition avcodec.h:415
#define AV_CODEC_EXPORT_DATA_FILM_GRAIN
Decoding only.
Definition avcodec.h:404
#define AV_CODEC_FLAG_OUTPUT_CORRUPT
Output even those frames that might be corrupted.
Definition avcodec.h:221
@ AV_PICTURE_STRUCTURE_BOTTOM_FIELD
coded as bottom field
Definition avcodec.h:2613
@ AV_PICTURE_STRUCTURE_TOP_FIELD
coded as top field
Definition avcodec.h:2612
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
Definition frame.h:695
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
Definition frame.h:700
#define AV_FRAME_FLAG_CORRUPT
The frame data may be corrupted, e.g.
Definition frame.h:683
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
Definition frame.h:687
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition frame.c:496
void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
Remove and free all side data instances of the given type.
Definition frame.c:725
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition frame.c:278
@ AV_FRAME_DATA_LCEVC
Raw LCEVC payload data, as a uint8_t array, with NAL emulation bytes intact.
Definition frame.h:236
@ AV_FRAME_DATA_FILM_GRAIN_PARAMS
Film grain parameters for a frame, described by AVFilmGrainParams.
Definition frame.h:188
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition mem.c:445
@ AV_PICTURE_TYPE_I
Intra.
Definition avutil.h:278
@ AV_PICTURE_TYPE_P
Predicted.
Definition avutil.h:279
@ AV_PICTURE_TYPE_B
Bi-dir predicted.
Definition avutil.h:280
#define CHROMA(h)
Definition h264dec.h:88
static HEVCFrame * find_ref_idx(HEVCContext *s, HEVCLayerContext *l, int poc, uint8_t use_msb)
Definition refs.c:439
static int add_candidate_ref(HEVCContext *s, HEVCLayerContext *l, RefPicList *rps, int list_idx, int poc, int ref_flag, uint8_t use_msb)
Definition refs.c:499
static void mark_ref(HEVCFrame *frame, int flag)
Definition refs.c:459
static HEVCFrame * alloc_frame(HEVCContext *s, HEVCLayerContext *l)
Definition refs.c:110
static int init_slice_rpl(HEVCContext *s)
Definition refs.c:327
static HEVCFrame * generate_missing_ref(HEVCContext *s, HEVCLayerContext *l, int poc)
Definition refs.c:465
#define L1
Definition hevcdec.h:57
#define L0
Definition hevcdec.h:56
#define IS_IRAP(s)
Definition hevcdec.h:77
#define r
Definition input.c:42
#define AV_WN16(p, v)
Multithreading API for decoders.
@ VVC_MAX_REF_ENTRIES
Definition vvc.h:115
@ VVC_RSV_IRAP_11
Definition vvc.h:40
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
static int ff_mutex_unlock(AVMutex *mutex)
Definition thread.h:189
static int ff_cond_destroy(AVCond *cond)
Definition thread.h:195
static int ff_mutex_lock(AVMutex *mutex)
Definition thread.h:188
static int ff_mutex_destroy(AVMutex *mutex)
Definition thread.h:190
static int ff_cond_init(AVCond *cond, const void *attr)
Definition thread.h:194
#define AVCond
Definition thread.h:192
static int ff_cond_signal(AVCond *cond)
Definition thread.h:196
#define AVMutex
Definition thread.h:184
static int ff_mutex_init(AVMutex *mutex, const void *attr)
Definition thread.h:187
static const uint16_t mask[17]
Definition lzw.c:38
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags)
Wrapper around get_buffer() for frame-multithreaded codecs.
#define VVC_FRAME_FLAG_OUTPUT
Definition refs.h:28
#define VVC_FRAME_FLAG_BUMPING
Definition refs.h:31
#define VVC_FRAME_FLAG_SHORT_REF
Definition refs.h:29
VVCProgress
Definition refs.h:44
@ VVC_PROGRESS_PIXEL
Definition refs.h:46
@ VVC_PROGRESS_MV
Definition refs.h:45
@ VVC_PROGRESS_LAST
Definition refs.h:47
#define VVC_FRAME_FLAG_CORRUPT
Definition refs.h:32
#define VVC_FRAME_FLAG_LONG_REF
Definition refs.h:30
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition refstruct.c:120
const void * av_refstruct_ref_c(const void *obj)
Analog of av_refstruct_ref(), but for constant objects.
Definition refstruct.c:149
void * av_refstruct_pool_get(AVRefStructPool *pool)
Get an object from the pool, reusing an old one from the pool when available.
Definition refstruct.c:297
static void * av_refstruct_allocz(size_t size)
Equivalent to av_refstruct_alloc_ext(size, 0, NULL, NULL)
Definition refstruct.h:105
static void * av_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(AVRefStructOpaque opaque, void *obj))
A wrapper around av_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
Definition refstruct.h:94
#define FF_ARRAY_ELEMS(a)
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
Coded bitstream fragment structure, combining one or more units.
Definition cbs.h:129
Coded bitstream unit structure.
Definition cbs.h:77
void * content_ref
If content is reference counted, a RefStruct reference backing content.
Definition cbs.h:119
CodedBitstreamUnitType type
Codec-specific type of this unit.
Definition cbs.h:81
AVCond cond
Definition refs.c:39
atomic_int progress[VVC_PROGRESS_LAST]
Definition refs.c:36
uint8_t has_cond
Definition refs.c:41
AVMutex lock
Definition refs.c:38
VVCProgressListener * listener[VVC_PROGRESS_LAST]
Definition refs.c:37
uint8_t has_lock
Definition refs.c:40
uint8_t sh_collocated_ref_idx
Definition cbs_h266.h:803
uint8_t sh_collocated_from_l0_flag
Definition cbs_h266.h:802
H266RefPicLists sh_ref_pic_lists
Definition cbs_h266.h:797
uint8_t abs_delta_poc_st[VVC_MAX_REF_ENTRIES]
Definition cbs_h266.h:165
uint8_t strp_entry_sign_flag[VVC_MAX_REF_ENTRIES]
Definition cbs_h266.h:166
uint8_t num_ref_entries
Definition cbs_h266.h:161
uint8_t inter_layer_ref_pic_flag[VVC_MAX_REF_ENTRIES]
Definition cbs_h266.h:163
uint8_t rpls_poc_lsb_lt[VVC_MAX_REF_ENTRIES]
Definition cbs_h266.h:167
uint8_t st_ref_pic_flag[VVC_MAX_REF_ENTRIES]
Definition cbs_h266.h:164
uint8_t ltrp_in_header_flag
Definition cbs_h266.h:162
uint8_t delta_poc_msb_cycle_present_flag[2][VVC_MAX_REF_ENTRIES]
Definition cbs_h266.h:176
uint16_t delta_poc_msb_cycle_lt[2][VVC_MAX_REF_ENTRIES]
Definition cbs_h266.h:177
H266RefPicListStruct rpl_ref_list[2]
Definition cbs_h266.h:174
uint16_t poc_lsb_lt[2][VVC_MAX_REF_ENTRIES]
Definition cbs_h266.h:175
VVCRefPic refs[VVC_MAX_REF_ENTRIES]
Definition dec.h:58
int nb_refs
Definition hevcdec.h:198
VVCSH sh
Definition dec.h:115
int slice_idx
Definition dec.h:114
RefPicList * rpl
Definition dec.h:118
Definition dec.h:73
const VVCSPS * sps
RefStruct reference.
Definition dec.h:76
Definition ps.h:147
Definition ps.h:92
VVCProgressListener * next
Definition refs.h:57
progress_done_fn progress_done
Definition refs.h:56
VVCProgress vp
Definition refs.h:54
int scale[2]
RefPicScale[].
Definition dec.h:54
int is_lt
Definition dec.h:50
int poc
Definition dec.h:49
int is_scaled
RprConstraintsActiveFlag.
Definition dec.h:53
struct VVCFrame * ref
Definition dec.h:48
Definition ps.h:238
const H266RawSliceHeader * r
RefStruct reference.
Definition ps.h:239
const uint32_t * ctb_addr_in_curr_slice
CtbAddrInCurrSlice.
Definition ps.h:244
uint32_t num_ctus_in_curr_slice
NumCtusInCurrSlice.
Definition ps.h:243
Definition ps.h:58
uint8_t ctb_log2_size_y
CtbLog2SizeY.
Definition ps.h:71
#define av_log(a,...)
static int ref[MAX_W *MAX_W]
static FILE * out
Definition movenc.c:55
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition refstruct.h:58
float delta
#define IS_CVSS(s)
Definition ps.h:33
#define GDR_IS_RECOVERED(s)
Definition ps.h:43
#define IS_RASL(s)
Definition ps.h:35
#define IS_I(rsh)
Definition ps.h:38
#define IS_B(rsh)
Definition ps.h:40
#define CHECK_MAX(d)
Definition refs.c:431
#define RPR_SCALE(f)
Definition refs.c:448
void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l)
Definition refs.c:686
void ff_vvc_clear_refs(VVCFrameContext *fc)
Definition refs.c:86
static FrameProgress * alloc_progress(void)
Definition refs.c:109
const RefPicList * ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
Definition refs.c:76
int ff_vvc_frame_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
Definition refs.c:601
void ff_vvc_unref_frame(VVCFrameContext *fc, VVCFrame *frame, int flags)
Definition refs.c:44
void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc)
Definition refs.c:336
void ff_vvc_report_frame_finished(VVCFrame *frame)
Definition refs.c:625
void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y)
Definition refs.c:665
static void free_progress(AVRefStructOpaque unused, void *obj)
Definition refs.c:99
int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush)
Definition refs.c:269
int ff_vvc_slice_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
Definition refs.c:542
static VVCProgressListener * get_done_listener(FrameProgress *p, const VVCProgress vp)
Definition refs.c:649
int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, AVFrame **frame)
Definition refs.c:226
static int check_candidate_ref(const VVCFrame *frame, const VVCRefPic *refp)
Definition refs.c:433
static void add_listener(VVCProgressListener **prev, VVCProgressListener *l)
Definition refs.c:636
void ff_vvc_flush_dpb(VVCFrameContext *fc)
Definition refs.c:93
static void set_pict_type(AVFrame *frame, const VVCContext *s, const VVCFrameContext *fc)
Definition refs.c:196
#define CHECK_SAMPLES(d)
Definition refs.c:432
static int delta_poc_st(const H266RefPicListStruct *rpls, const int lx, const int i, const VVCSPS *sps)
Definition refs.c:518
static VVCProgressListener * remove_listener(VVCProgressListener **prev, VVCProgressListener *l)
Definition refs.c:642
static int poc_lt(int *prev_delta_poc_msb, const int poc, const H266RefPicLists *ref_lists, const int lx, const int j, const int max_poc_lsb)
Definition refs.c:528
static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l)
Definition refs.c:631