FFmpeg
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 
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 {
42  uint8_t has_lock;
43  uint8_t has_cond;
45 
47 {
48  /* frame->frame can be NULL if context init failed */
49  if (!frame->frame || !frame->frame->buf[0])
50  return;
51 
52  frame->flags &= ~flags;
53  if (!frame->flags) {
54  av_frame_unref(frame->frame);
57  ff_refstruct_unref(&frame->progress);
58 
59  ff_refstruct_unref(&frame->tab_dmvr_mvf);
60 
62  frame->nb_rpl_elems = 0;
63  ff_refstruct_unref(&frame->rpl_tab);
64 
65  frame->collocated_ref = NULL;
66  }
67 }
68 
69 const RefPicList *ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
70 {
71  const int x_cb = x0 >> fc->ps.sps->ctb_log2_size_y;
72  const int y_cb = y0 >> fc->ps.sps->ctb_log2_size_y;
73  const int pic_width_cb = fc->ps.pps->ctb_width;
74  const int ctb_addr_rs = y_cb * pic_width_cb + x_cb;
75 
76  return (const RefPicList *)ref->rpl_tab[ctb_addr_rs];
77 }
78 
80 {
81  for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
82  ff_vvc_unref_frame(fc, &fc->DPB[i],
84 }
85 
87 {
88  for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
89  ff_vvc_unref_frame(fc, &fc->DPB[i], ~0);
90 }
91 
92 static void free_progress(FFRefStructOpaque unused, void *obj)
93 {
94  FrameProgress *p = (FrameProgress *)obj;
95 
96  if (p->has_cond)
97  ff_cond_destroy(&p->cond);
98  if (p->has_lock)
100 }
101 
103 {
105 
106  if (p) {
107  p->has_lock = !ff_mutex_init(&p->lock, NULL);
108  p->has_cond = !ff_cond_init(&p->cond, NULL);
109  if (!p->has_lock || !p->has_cond)
110  ff_refstruct_unref(&p);
111  }
112  return p;
113 }
114 
116 {
117  const VVCSPS *sps = fc->ps.sps;
118  const VVCPPS *pps = fc->ps.pps;
119  for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
120  int ret;
121  VVCFrame *frame = &fc->DPB[i];
122  VVCWindow *win = &frame->scaling_win;
123  if (frame->frame->buf[0])
124  continue;
125 
126  frame->sps = ff_refstruct_ref_c(fc->ps.sps);
127  frame->pps = ff_refstruct_ref_c(fc->ps.pps);
128 
130  if (ret < 0)
131  return NULL;
132 
133  frame->rpl = ff_refstruct_allocz(s->current_frame.nb_units * sizeof(RefPicListTab));
134  if (!frame->rpl)
135  goto fail;
136  frame->nb_rpl_elems = s->current_frame.nb_units;
137 
138  frame->tab_dmvr_mvf = ff_refstruct_pool_get(fc->tab_dmvr_mvf_pool);
139  if (!frame->tab_dmvr_mvf)
140  goto fail;
141 
142  frame->rpl_tab = ff_refstruct_pool_get(fc->rpl_tab_pool);
143  if (!frame->rpl_tab)
144  goto fail;
145  frame->ctb_count = pps->ctb_width * pps->ctb_height;
146  for (int j = 0; j < frame->ctb_count; j++)
147  frame->rpl_tab[j] = frame->rpl;
148 
149  win->left_offset = pps->r->pps_scaling_win_left_offset << sps->hshift[CHROMA];
150  win->right_offset = pps->r->pps_scaling_win_right_offset << sps->hshift[CHROMA];
151  win->top_offset = pps->r->pps_scaling_win_top_offset << sps->vshift[CHROMA];
152  win->bottom_offset = pps->r->pps_scaling_win_bottom_offset << sps->vshift[CHROMA];
153  frame->ref_width = pps->r->pps_pic_width_in_luma_samples - win->left_offset - win->right_offset;
154  frame->ref_height = pps->r->pps_pic_height_in_luma_samples - win->bottom_offset - win->top_offset;
155 
156  frame->progress = alloc_progress();
157  if (!frame->progress)
158  goto fail;
159 
160  return frame;
161 fail:
163  return NULL;
164  }
165  av_log(s->avctx, AV_LOG_ERROR, "Error allocating frame, DPB full.\n");
166  return NULL;
167 }
168 
170 {
171  const VVCPH *ph= &fc->ps.ph;
172  const int poc = ph->poc;
173  VVCFrame *ref;
174 
175  /* check that this POC doesn't already exist */
176  for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
177  VVCFrame *frame = &fc->DPB[i];
178 
179  if (frame->frame->buf[0] && frame->sequence == s->seq_decode &&
180  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  ref = alloc_frame(s, fc);
187  if (!ref)
188  return AVERROR(ENOMEM);
189 
190  *frame = ref->frame;
191  fc->ref = ref;
192 
193  if (s->no_output_before_recovery_flag && (IS_RASL(s) || !GDR_IS_RECOVERED(s)))
194  ref->flags = VVC_FRAME_FLAG_SHORT_REF;
195  else if (ph->r->ph_pic_output_flag)
197 
198  if (!ph->r->ph_non_ref_pic_flag)
199  ref->flags |= VVC_FRAME_FLAG_SHORT_REF;
200 
201  ref->poc = poc;
202  ref->sequence = s->seq_decode;
203  ref->frame->crop_left = fc->ps.pps->r->pps_conf_win_left_offset << fc->ps.sps->hshift[CHROMA];
204  ref->frame->crop_right = fc->ps.pps->r->pps_conf_win_right_offset << fc->ps.sps->hshift[CHROMA];
205  ref->frame->crop_top = fc->ps.pps->r->pps_conf_win_top_offset << fc->ps.sps->vshift[CHROMA];
206  ref->frame->crop_bottom = fc->ps.pps->r->pps_conf_win_bottom_offset << fc->ps.sps->vshift[CHROMA];
207 
208  return 0;
209 }
210 
211 int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush)
212 {
213  const VVCSPS *sps = fc->ps.sps;
214  do {
215  int nb_output = 0;
216  int min_poc = INT_MAX;
217  int min_idx, ret;
218 
219  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) {
225  }
226  }
227  }
228 
229  for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
230  VVCFrame *frame = &fc->DPB[i];
231  if ((frame->flags & VVC_FRAME_FLAG_OUTPUT) &&
232  frame->sequence == s->seq_output) {
233  nb_output++;
234  if (frame->poc < min_poc || nb_output == 1) {
235  min_poc = frame->poc;
236  min_idx = i;
237  }
238  }
239  }
240 
241  /* wait for more frames before output */
242  if (!flush && s->seq_output == s->seq_decode && sps &&
243  nb_output <= sps->r->sps_dpb_params.dpb_max_num_reorder_pics[sps->r->sps_max_sublayers_minus1])
244  return 0;
245 
246  if (nb_output) {
247  VVCFrame *frame = &fc->DPB[min_idx];
248 
249  ret = av_frame_ref(out, frame->frame);
250  if (frame->flags & VVC_FRAME_FLAG_BUMPING)
252  else
254  if (ret < 0)
255  return ret;
256 
257  av_log(s->avctx, AV_LOG_DEBUG,
258  "Output frame with POC %d.\n", frame->poc);
259  return 1;
260  }
261 
262  if (s->seq_output != s->seq_decode)
263  s->seq_output = (s->seq_output + 1) & 0xff;
264  else
265  break;
266  } while (1);
267  return 0;
268 }
269 
271 {
272  const VVCSPS *sps = fc->ps.sps;
273  const int poc = fc->ps.ph.poc;
274  int dpb = 0;
275  int min_poc = INT_MAX;
276 
277  for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
278  VVCFrame *frame = &fc->DPB[i];
279  if ((frame->flags) &&
280  frame->sequence == s->seq_output &&
281  frame->poc != poc) {
282  dpb++;
283  }
284  }
285 
286  if (sps && dpb >= sps->r->sps_dpb_params.dpb_max_dec_pic_buffering_minus1[sps->r->sps_max_sublayers_minus1] + 1) {
287  for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
288  VVCFrame *frame = &fc->DPB[i];
289  if ((frame->flags) &&
290  frame->sequence == s->seq_output &&
291  frame->poc != poc) {
292  if (frame->flags == VVC_FRAME_FLAG_OUTPUT && frame->poc < min_poc) {
293  min_poc = frame->poc;
294  }
295  }
296  }
297 
298  for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
299  VVCFrame *frame = &fc->DPB[i];
300  if (frame->flags & VVC_FRAME_FLAG_OUTPUT &&
301  frame->sequence == s->seq_output &&
302  frame->poc <= min_poc) {
303  frame->flags |= VVC_FRAME_FLAG_BUMPING;
304  }
305  }
306 
307  dpb--;
308  }
309 }
310 
311 static VVCFrame *find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb)
312 {
313  const unsigned mask = use_msb ? ~0 : fc->ps.sps->max_pic_order_cnt_lsb - 1;
314 
315  for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
316  VVCFrame *ref = &fc->DPB[i];
317  if (ref->frame->buf[0] && ref->sequence == s->seq_decode) {
318  if ((ref->poc & mask) == poc)
319  return ref;
320  }
321  }
322  return NULL;
323 }
324 
325 static void mark_ref(VVCFrame *frame, int flag)
326 {
328  frame->flags |= flag;
329 }
330 
332 {
333  const VVCSPS *sps = fc->ps.sps;
334  const VVCPPS *pps = fc->ps.pps;
335  VVCFrame *frame;
336 
337  frame = alloc_frame(s, fc);
338  if (!frame)
339  return NULL;
340 
341  if (!s->avctx->hwaccel) {
342  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  for (int i = 0; frame->frame->data[i]; i++)
348  for (int y = 0; y < (pps->height >> sps->vshift[i]); y++) {
349  uint8_t *dst = frame->frame->data[i] + y * frame->frame->linesize[i];
350  AV_WN16(dst, 1 << (sps->bit_depth - 1));
351  av_memcpy_backptr(dst + 2, 2, 2*(pps->width >> sps->hshift[i]) - 2);
352  }
353  }
354  }
355 
356  frame->poc = poc;
357  frame->sequence = s->seq_decode;
358  frame->flags = 0;
359 
361 
362  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 static int check_candidate_ref(const VVCFrame *frame, const VVCRefPic *refp)
368 {
369  const VVCFrame *ref = refp->ref;
370 
371  if (refp->is_scaled) {
372  const int max = FFMAX(8, frame->sps->min_cb_size_y);
373  return frame->ref_width * 2 >= ref->ref_width &&
374  frame->ref_height * 2 >= ref->ref_height &&
375  frame->ref_width <= ref->ref_width * 8 &&
376  frame->ref_height <= ref->ref_height * 8 &&
378  }
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 */
385  int poc, int ref_flag, uint8_t use_msb)
386 {
387  VVCFrame *ref = find_ref_idx(s, fc, poc, use_msb);
388  VVCRefPic *refp = &list->refs[list->nb_refs];
389 
390  if (ref == fc->ref || list->nb_refs >= VVC_MAX_REF_ENTRIES)
391  return AVERROR_INVALIDDATA;
392 
393  if (!ref) {
394  ref = generate_missing_ref(s, fc, poc);
395  if (!ref)
396  return AVERROR(ENOMEM);
397  }
398 
399  refp->poc = poc;
400  refp->ref = ref;
401  refp->is_lt = ref_flag & VVC_FRAME_FLAG_LONG_REF;
402  refp->is_scaled = ref->sps->r->sps_num_subpics_minus1 != fc->ref->sps->r->sps_num_subpics_minus1||
403  memcmp(&ref->scaling_win, &fc->ref->scaling_win, sizeof(ref->scaling_win)) ||
404  ref->pps->r->pps_pic_width_in_luma_samples != fc->ref->pps->r->pps_pic_width_in_luma_samples ||
405  ref->pps->r->pps_pic_height_in_luma_samples != fc->ref->pps->r->pps_pic_height_in_luma_samples;
406 
407  if (!check_candidate_ref(fc->ref, refp))
408  return AVERROR_INVALIDDATA;
409 
410  if (refp->is_scaled) {
411  refp->scale[0] = RPR_SCALE(ref_width);
412  refp->scale[1] = RPR_SCALE(ref_height);
413  }
414  list->nb_refs++;
415 
416  mark_ref(ref, ref_flag);
417  return 0;
418 }
419 
421 {
422  VVCFrame *frame = fc->ref;
423  const VVCSH *sh = &sc->sh;
424 
425  if (sc->slice_idx >= frame->nb_rpl_elems)
426  return AVERROR_INVALIDDATA;
427 
428  for (int i = 0; i < sh->num_ctus_in_curr_slice; i++) {
429  const int rs = sh->ctb_addr_in_curr_slice[i];
430  frame->rpl_tab[rs] = frame->rpl + sc->slice_idx;
431  }
432 
433  sc->rpl = frame->rpl_tab[sh->ctb_addr_in_curr_slice[0]]->refPicList;
434 
435  return 0;
436 }
437 
438 static int delta_poc_st(const H266RefPicListStruct *rpls,
439  const int lx, const int i, const VVCSPS *sps)
440 {
441  int abs_delta_poc_st = rpls->abs_delta_poc_st[i];
442  if (!((sps->r->sps_weighted_pred_flag ||
443  sps->r->sps_weighted_bipred_flag) && i != 0))
444  abs_delta_poc_st++;
445  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 
463 {
464  const VVCSPS *sps = fc->ps.sps;
465  const H266RawPPS *pps = fc->ps.pps->r;
466  const VVCPH *ph = &fc->ps.ph;
467  const H266RawSliceHeader *rsh = sc->sh.r;
468  const int max_poc_lsb = sps->max_pic_order_cnt_lsb;
469  const H266RefPicLists *ref_lists =
470  pps->pps_rpl_info_in_ph_flag ? &ph->r->ph_ref_pic_lists : &rsh->sh_ref_pic_lists;
471  int ret = 0;
472 
473  ret = init_slice_rpl(fc, sc);
474  if (ret < 0)
475  return ret;
476 
477  for (int lx = L0; lx <= L1; lx++) {
478  const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx;
479  RefPicList *rpl = sc->rpl + lx;
480  int poc_base = ph->poc;
481  int prev_delta_poc_msb = 0;
482 
483  rpl->nb_refs = 0;
484  for (int i = 0, j = 0; i < rpls->num_ref_entries; i++) {
485  int poc;
486  if (!rpls->inter_layer_ref_pic_flag[i]) {
487  int use_msb = 1;
488  int ref_flag;
489  if (rpls->st_ref_pic_flag[i]) {
490  poc = poc_base + delta_poc_st(rpls, lx, i, sps);
491  poc_base = poc;
492  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  ret = add_candidate_ref(s, fc, rpl, poc, ref_flag, use_msb);
500  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");
506  return ret;
507  }
508  }
509  if (ph->r->ph_temporal_mvp_enabled_flag &&
510  (!rsh->sh_collocated_from_l0_flag) == lx &&
511  rsh->sh_collocated_ref_idx < rpl->nb_refs) {
512  const VVCRefPic *refp = rpl->refs + rsh->sh_collocated_ref_idx;
513  if (refp->is_scaled || refp->ref->sps->ctb_log2_size_y != sps->ctb_log2_size_y)
514  return AVERROR_INVALIDDATA;
515  fc->ref->collocated_ref = refp->ref;
516  }
517  }
518  return 0;
519 }
520 
522 {
523  int ret = 0;
524 
525  /* clear the reference flags on all frames except the current one */
526  for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) {
527  VVCFrame *frame = &fc->DPB[i];
528 
529  if (frame == fc->ref)
530  continue;
531 
532  mark_ref(frame, 0);
533  }
534 
535  if ((ret = ff_vvc_slice_rpl(s, fc, sc)) < 0)
536  goto fail;
537 
538 fail:
539  /* release any frames that are now unused */
540  for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++)
541  ff_vvc_unref_frame(fc, &fc->DPB[i], 0);
542  return ret;
543 }
544 
546 {
549 }
550 
551 static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l)
552 {
553  return p->progress[l->vp] > l->y;
554 }
555 
557 {
558  l->next = *prev;
559  *prev = l;
560 }
561 
563 {
564  *prev = l->next;
565  l->next = NULL;
566  return l;
567 }
568 
570 {
572  VVCProgressListener **prev = &p->listener[vp];
573 
574  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  return list;
583 }
584 
585 void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y)
586 {
587  FrameProgress *p = frame->progress;
589 
590  ff_mutex_lock(&p->lock);
591  if (p->progress[vp] < y) {
592  // Due to the nature of thread scheduling, later progress may reach this point before earlier progress.
593  // Therefore, we only update the progress when p->progress[vp] < y.
594  p->progress[vp] = y;
595  l = get_done_listener(p, vp);
596  ff_cond_signal(&p->cond);
597  }
598  ff_mutex_unlock(&p->lock);
599 
600  while (l) {
601  l->progress_done(l);
602  l = l->next;
603  }
604 }
605 
607 {
608  FrameProgress *p = frame->progress;
609 
610  ff_mutex_lock(&p->lock);
611 
612  if (is_progress_done(p, l)) {
613  ff_mutex_unlock(&p->lock);
614  l->progress_done(l);
615  } else {
616  add_listener(p->listener + l->vp, l);
617  ff_mutex_unlock(&p->lock);
618  }
619 }
VVCSPS
Definition: ps.h:58
L1
F H1 F F H1 F F F F H1<-F-------F-------F v v v H2 H3 H2 ^ ^ ^ F-------F-------F-> H1<-F-------F-------F|||||||||F H1 F|||||||||F H1 Funavailable fullpel samples(outside the picture for example) shall be equalto the closest available fullpel sampleSmaller pel interpolation:--------------------------if diag_mc is set then points which lie on a line between 2 vertically, horizontally or diagonally adjacent halfpel points shall be interpolatedlinearly with rounding to nearest and halfway values rounded up.points which lie on 2 diagonals at the same time should only use the onediagonal not containing the fullpel point F--> O q O<--h1-> O q O<--F v \/v \/v O O O O O O O|/|\|q q q q q|/|\|O O O O O O O ^/\ ^/\ ^ h2--> O q O<--h3-> O q O<--h2 v \/v \/v O O O O O O O|\|/|q q q q q|\|/|O O O O O O O ^/\ ^/\ ^ F--> O q O<--h1-> O q O<--Fthe remaining points shall be bilinearly interpolated from theup to 4 surrounding halfpel and fullpel points, again rounding should be tonearest and halfway values rounded upcompliant Snow decoders MUST support 1-1/8 pel luma and 1/2-1/16 pel chromainterpolation at leastOverlapped block motion compensation:-------------------------------------FIXMELL band prediction:===================Each sample in the LL0 subband is predicted by the median of the left, top andleft+top-topleft samples, samples outside the subband shall be considered tobe 0. To reverse this prediction in the decoder apply the following.for(y=0;y< height;y++){ for(x=0;x< width;x++){ sample[y][x]+=median(sample[y-1][x], sample[y][x-1], sample[y-1][x]+sample[y][x-1]-sample[y-1][x-1]);}}sample[-1][ *]=sample[ *][-1]=0;width, height here are the width and height of the LL0 subband not of the finalvideoDequantization:===============FIXMEWavelet Transform:==================Snow supports 2 wavelet transforms, the symmetric biorthogonal 5/3 integertransform and an integer approximation of the symmetric biorthogonal 9/7daubechies wavelet.2D IDWT(inverse discrete wavelet transform) --------------------------------------------The 2D IDWT applies a 2D filter recursively, each time combining the4 lowest frequency subbands into a single subband until only 1 subbandremains.The 2D filter is done by first applying a 1D filter in the vertical directionand then applying it in the horizontal one. --------------- --------------- --------------- ---------------|LL0|HL0|||||||||||||---+---|HL1||L0|H0|HL1||LL1|HL1|||||LH0|HH0|||||||||||||-------+-------|-> L1 H1 LH1 HH1 LH1 HH1 LH1 HH1 L1
Definition: snow.txt:554
H266RefPicLists::poc_lsb_lt
uint16_t poc_lsb_lt[2][VVC_MAX_REF_ENTRIES]
Definition: cbs_h266.h:175
VVCSH::num_ctus_in_curr_slice
uint32_t num_ctus_in_curr_slice
NumCtusInCurrSlice.
Definition: ps.h:242
VVCPH
Definition: ps.h:147
ff_mutex_init
static int ff_mutex_init(AVMutex *mutex, const void *attr)
Definition: thread.h:187
VVCPPS
Definition: ps.h:92
add_candidate_ref
static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *list, int poc, int ref_flag, uint8_t use_msb)
Definition: refs.c:384
VVC_PROGRESS_PIXEL
@ VVC_PROGRESS_PIXEL
Definition: refs.h:40
r
const char * r
Definition: vf_curves.c:127
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
out
FILE * out
Definition: movenc.c:55
FrameProgress::has_cond
uint8_t has_cond
Definition: refs.c:43
thread.h
ff_vvc_report_frame_finished
void ff_vvc_report_frame_finished(VVCFrame *frame)
Definition: refs.c:545
VVCProgressListener::vp
VVCProgress vp
Definition: refs.h:48
ff_refstruct_alloc_ext
static void * ff_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(FFRefStructOpaque opaque, void *obj))
A wrapper around ff_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
Definition: refstruct.h:94
is_progress_done
static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l)
Definition: refs.c:551
mask
int mask
Definition: mediacodecdec_common.c:154
ph
static int FUNC() ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
Definition: cbs_h266_syntax_template.c:3034
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
VVCRefPic
Definition: dec.h:45
atomic_int
intptr_t atomic_int
Definition: stdatomic.h:55
VVCSH::r
const H266RawSliceHeader * r
RefStruct reference.
Definition: ps.h:238
H266RefPicListStruct::st_ref_pic_flag
uint8_t st_ref_pic_flag[VVC_MAX_REF_ENTRIES]
Definition: cbs_h266.h:164
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:472
H266RefPicListStruct::ltrp_in_header_flag
uint8_t ltrp_in_header_flag
Definition: cbs_h266.h:162
free_progress
static void free_progress(FFRefStructOpaque unused, void *obj)
Definition: refs.c:92
max
#define max(a, b)
Definition: cuda_runtime.h:33
FFRefStructOpaque
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition: refstruct.h:58
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
FrameProgress::cond
AVCond cond
Definition: refs.c:41
ff_vvc_slice_rpl
int ff_vvc_slice_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
Definition: refs.c:462
H266RefPicListStruct::num_ref_entries
uint8_t num_ref_entries
Definition: cbs_h266.h:161
RefPicList
Definition: hevcdec.h:192
ff_vvc_report_progress
void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y)
Definition: refs.c:585
thread.h
VVCProgress
VVCProgress
Definition: refs.h:38
VVC_FRAME_FLAG_LONG_REF
#define VVC_FRAME_FLAG_LONG_REF
Definition: refs.c:34
VVCRefPic::ref
struct VVCFrame * ref
Definition: dec.h:46
win
static float win(SuperEqualizerContext *s, float n, int N)
Definition: af_superequalizer.c:119
ff_mutex_unlock
static int ff_mutex_unlock(AVMutex *mutex)
Definition: thread.h:189
H266RefPicListStruct::inter_layer_ref_pic_flag
uint8_t inter_layer_ref_pic_flag[VVC_MAX_REF_ENTRIES]
Definition: cbs_h266.h:163
fail
#define fail()
Definition: checkasm.h:188
H266RefPicLists::rpl_ref_list
H266RefPicListStruct rpl_ref_list[2]
Definition: cbs_h266.h:174
CHECK_SAMPLES
#define CHECK_SAMPLES(d)
Definition: refs.c:366
FrameProgress::listener
VVCProgressListener * listener[VVC_PROGRESS_LAST]
Definition: refs.c:39
SliceContext::rpl
RefPicList * rpl
Definition: dec.h:111
RefPicList::nb_refs
int nb_refs
Definition: hevcdec.h:196
refstruct.h
H266RefPicLists::delta_poc_msb_cycle_present_flag
uint8_t delta_poc_msb_cycle_present_flag[2][VVC_MAX_REF_ENTRIES]
Definition: cbs_h266.h:176
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
ff_refstruct_ref_c
const void * ff_refstruct_ref_c(const void *obj)
Analog of ff_refstruct_ref(), but for constant objects.
Definition: refstruct.c:149
RefPicList::refs
VVCRefPic refs[VVC_MAX_REF_ENTRIES]
Definition: dec.h:56
AVMutex
#define AVMutex
Definition: thread.h:184
av_memcpy_backptr
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition: mem.c:447
ff_vvc_unref_frame
void ff_vvc_unref_frame(VVCFrameContext *fc, VVCFrame *frame, int flags)
Definition: refs.c:46
RPR_SCALE
#define RPR_SCALE(f)
Definition: refs.c:382
s
#define s(width, name)
Definition: cbs_vp9.c:198
SliceContext::slice_idx
int slice_idx
Definition: dec.h:107
AV_GET_BUFFER_FLAG_REF
#define AV_GET_BUFFER_FLAG_REF
The decoder will keep a reference to the frame and may reuse it later.
Definition: avcodec.h:431
generate_missing_ref
static VVCFrame * generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int poc)
Definition: refs.c:331
ff_thread_get_buffer
int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags)
Wrapper around get_buffer() for frame-multithreaded codecs.
Definition: pthread_frame.c:1049
delta_poc_st
static int delta_poc_st(const H266RefPicListStruct *rpls, const int lx, const int i, const VVCSPS *sps)
Definition: refs.c:438
VVCSH
Definition: ps.h:237
ff_vvc_clear_refs
void ff_vvc_clear_refs(VVCFrameContext *fc)
Definition: refs.c:79
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
H266RefPicLists
Definition: cbs_h266.h:171
add_listener
static void add_listener(VVCProgressListener **prev, VVCProgressListener *l)
Definition: refs.c:556
AVCond
#define AVCond
Definition: thread.h:192
VVCWindow
Definition: dec.h:64
VVC_MAX_REF_ENTRIES
@ VVC_MAX_REF_ENTRIES
Definition: vvc.h:115
H266RefPicListStruct::abs_delta_poc_st
uint8_t abs_delta_poc_st[VVC_MAX_REF_ENTRIES]
Definition: cbs_h266.h:165
H266RawPPS
Definition: cbs_h266.h:496
VVCSPS::ctb_log2_size_y
uint8_t ctb_log2_size_y
CtbLog2SizeY.
Definition: ps.h:71
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
H266RefPicListStruct::strp_entry_sign_flag
uint8_t strp_entry_sign_flag[VVC_MAX_REF_ENTRIES]
Definition: cbs_h266.h:166
find_ref_idx
static VVCFrame * find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb)
Definition: refs.c:311
L0
#define L0
Definition: hevcdec.h:58
list
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining list
Definition: filter_design.txt:25
flush
void(* flush)(AVBSFContext *ctx)
Definition: dts2pts.c:370
ff_refstruct_allocz
static void * ff_refstruct_allocz(size_t size)
Equivalent to ff_refstruct_alloc_ext(size, 0, NULL, NULL)
Definition: refstruct.h:105
H266RefPicListStruct::rpls_poc_lsb_lt
uint8_t rpls_poc_lsb_lt[VVC_MAX_REF_ENTRIES]
Definition: cbs_h266.h:167
RefPicListTab
Definition: hevcdec.h:199
init_slice_rpl
static int init_slice_rpl(const VVCFrameContext *fc, SliceContext *sc)
Definition: refs.c:420
VVCRefPic::is_scaled
int is_scaled
RprConstraintsActiveFlag.
Definition: dec.h:51
VVCRefPic::is_lt
int is_lt
Definition: dec.h:48
H266RawSliceHeader::sh_collocated_ref_idx
uint8_t sh_collocated_ref_idx
Definition: cbs_h266.h:801
IS_RASL
#define IS_RASL(s)
Definition: ps.h:35
SliceContext
Definition: mss12.h:70
ff_mutex_destroy
static int ff_mutex_destroy(AVMutex *mutex)
Definition: thread.h:190
ff_vvc_flush_dpb
void ff_vvc_flush_dpb(VVCFrameContext *fc)
Definition: refs.c:86
H266RawSliceHeader::sh_collocated_from_l0_flag
uint8_t sh_collocated_from_l0_flag
Definition: cbs_h266.h:800
height
#define height
Definition: dsp.h:85
av_frame_ref
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:388
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
poc_lt
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:448
VVCProgressListener::y
int y
Definition: refs.h:49
H266RefPicListStruct
Definition: cbs_h266.h:160
mark_ref
static void mark_ref(VVCFrame *frame, int flag)
Definition: refs.c:325
avpriv_report_missing_feature
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
VVCRefPic::poc
int poc
Definition: dec.h:47
refs.h
CHECK_MAX
#define CHECK_MAX(d)
Definition: refs.c:365
VVC_PROGRESS_LAST
@ VVC_PROGRESS_LAST
Definition: refs.h:41
VVCFrame
Definition: dec.h:71
VVCSH::ctb_addr_in_curr_slice
const uint32_t * ctb_addr_in_curr_slice
CtbAddrInCurrSlice.
Definition: ps.h:243
ff_mutex_lock
static int ff_mutex_lock(AVMutex *mutex)
Definition: thread.h:188
ff_vvc_output_frame
int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush)
Definition: refs.c:211
VVC_PROGRESS_MV
@ VVC_PROGRESS_MV
Definition: refs.h:39
H266RawSliceHeader
Definition: cbs_h266.h:769
flag
#define flag(name)
Definition: cbs_av1.c:474
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
VVC_FRAME_FLAG_OUTPUT
#define VVC_FRAME_FLAG_OUTPUT
Definition: refs.c:32
alloc_progress
static FrameProgress * alloc_progress(void)
Definition: refs.c:102
delta
float delta
Definition: vorbis_enc_data.h:430
FrameProgress::progress
atomic_int progress[VVC_PROGRESS_LAST]
Definition: refs.c:38
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:610
VVCProgressListener::next
VVCProgressListener * next
Definition: refs.h:51
VVC_FRAME_FLAG_SHORT_REF
#define VVC_FRAME_FLAG_SHORT_REF
Definition: refs.c:33
GDR_IS_RECOVERED
#define GDR_IS_RECOVERED(s)
Definition: ps.h:43
H266RefPicLists::delta_poc_msb_cycle_lt
uint16_t delta_poc_msb_cycle_lt[2][VVC_MAX_REF_ENTRIES]
Definition: cbs_h266.h:177
ret
ret
Definition: filter_design.txt:187
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
CHROMA
@ CHROMA
Definition: vf_waveform.c:49
sps
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
Definition: cbs_h264_syntax_template.c:260
check_candidate_ref
static int check_candidate_ref(const VVCFrame *frame, const VVCRefPic *refp)
Definition: refs.c:367
VVCProgressListener
Definition: refs.h:47
remove_listener
static VVCProgressListener * remove_listener(VVCProgressListener **prev, VVCProgressListener *l)
Definition: refs.c:562
FrameProgress::lock
AVMutex lock
Definition: refs.c:40
VVC_FRAME_FLAG_BUMPING
#define VVC_FRAME_FLAG_BUMPING
Definition: refs.c:35
FrameProgress
Definition: refs.c:37
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:112
ff_cond_signal
static int ff_cond_signal(AVCond *cond)
Definition: thread.h:196
pps
uint64_t pps
Definition: dovi_rpuenc.c:35
ff_vvc_set_new_ref
int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, AVFrame **frame)
Definition: refs.c:169
ff_vvc_get_ref_list
const RefPicList * ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
Definition: refs.c:69
FrameProgress::has_lock
uint8_t has_lock
Definition: refs.c:42
ff_vvc_frame_rpl
int ff_vvc_frame_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
Definition: refs.c:521
mem.h
alloc_frame
static VVCFrame * alloc_frame(VVCContext *s, VVCFrameContext *fc)
Definition: refs.c:115
get_done_listener
static VVCProgressListener * get_done_listener(FrameProgress *p, const VVCProgress vp)
Definition: refs.c:569
ff_cond_destroy
static int ff_cond_destroy(AVCond *cond)
Definition: thread.h:195
VVCProgressListener::progress_done
progress_done_fn progress_done
Definition: refs.h:50
SliceContext::sh
VVCSH sh
Definition: dec.h:108
VVCFrameContext
Definition: dec.h:115
H266RawSliceHeader::sh_ref_pic_lists
H266RefPicLists sh_ref_pic_lists
Definition: cbs_h266.h:795
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
ff_cond_init
static int ff_cond_init(AVCond *cond, const void *attr)
Definition: thread.h:194
width
#define width
Definition: dsp.h:85
ff_refstruct_unref
void ff_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition: refstruct.c:120
ff_vvc_add_progress_listener
void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l)
Definition: refs.c:606
VVCFrame::sps
const VVCSPS * sps
RefStruct reference.
Definition: dec.h:74
ff_vvc_bump_frame
void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc)
Definition: refs.c:270
ff_refstruct_pool_get
void * ff_refstruct_pool_get(FFRefStructPool *pool)
Get an object from the pool, reusing an old one from the pool when available.
Definition: refstruct.c:297
VVCRefPic::scale
int scale[2]
RefPicScale[].
Definition: dec.h:52
VVCContext
Definition: dec.h:214
AV_WN16
#define AV_WN16(p, v)
Definition: intreadwrite.h:368