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