| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * VVC reference management | ||
| 3 | * | ||
| 4 | * Copyright (C) 2023 Nuo Mi | ||
| 5 | * | ||
| 6 | * This file is part of FFmpeg. | ||
| 7 | * | ||
| 8 | * FFmpeg is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU Lesser General Public | ||
| 10 | * License as published by the Free Software Foundation; either | ||
| 11 | * version 2.1 of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | * Lesser General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU Lesser General Public | ||
| 19 | * License along with FFmpeg; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <stdatomic.h> | ||
| 24 | #include <stdbool.h> | ||
| 25 | |||
| 26 | #include "libavutil/mem.h" | ||
| 27 | #include "libavutil/thread.h" | ||
| 28 | #include "libavutil/refstruct.h" | ||
| 29 | #include "libavcodec/thread.h" | ||
| 30 | #include "libavcodec/decode.h" | ||
| 31 | |||
| 32 | #include "refs.h" | ||
| 33 | |||
| 34 | |||
| 35 | typedef struct FrameProgress { | ||
| 36 | atomic_int progress[VVC_PROGRESS_LAST]; | ||
| 37 | VVCProgressListener *listener[VVC_PROGRESS_LAST]; | ||
| 38 | AVMutex lock; | ||
| 39 | AVCond cond; | ||
| 40 | uint8_t has_lock; | ||
| 41 | uint8_t has_cond; | ||
| 42 | } FrameProgress; | ||
| 43 | |||
| 44 | 55655 | void ff_vvc_unref_frame(VVCFrameContext *fc, VVCFrame *frame, int flags) | |
| 45 | { | ||
| 46 | /* frame->frame can be NULL if context init failed */ | ||
| 47 |
3/4✓ Branch 0 taken 55655 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42978 times.
✓ Branch 3 taken 12677 times.
|
55655 | if (!frame->frame || !frame->frame->buf[0]) |
| 48 | 42978 | return; | |
| 49 | |||
| 50 | 12677 | frame->flags &= ~flags; | |
| 51 |
2/2✓ Branch 0 taken 6401 times.
✓ Branch 1 taken 6276 times.
|
12677 | if (!(frame->flags & ~VVC_FRAME_FLAG_CORRUPT)) |
| 52 | 6401 | frame->flags = 0; | |
| 53 |
2/2✓ Branch 0 taken 6401 times.
✓ Branch 1 taken 6276 times.
|
12677 | if (!frame->flags) { |
| 54 | 6401 | av_frame_unref(frame->frame); | |
| 55 | |||
| 56 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6401 times.
|
6401 | if (frame->needs_fg) { |
| 57 | ✗ | av_frame_unref(frame->frame_grain); | |
| 58 | ✗ | frame->needs_fg = 0; | |
| 59 | } | ||
| 60 | |||
| 61 | 6401 | av_refstruct_unref(&frame->sps); | |
| 62 | 6401 | av_refstruct_unref(&frame->pps); | |
| 63 | 6401 | av_refstruct_unref(&frame->progress); | |
| 64 | |||
| 65 | 6401 | av_refstruct_unref(&frame->tab_dmvr_mvf); | |
| 66 | |||
| 67 | 6401 | av_refstruct_unref(&frame->rpl); | |
| 68 | 6401 | frame->nb_rpl_elems = 0; | |
| 69 | 6401 | av_refstruct_unref(&frame->rpl_tab); | |
| 70 | |||
| 71 | 6401 | frame->collocated_ref = NULL; | |
| 72 | 6401 | av_refstruct_unref(&frame->hwaccel_picture_private); | |
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | 3060628 | const RefPicList *ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0) | |
| 77 | { | ||
| 78 | 3060628 | const int x_cb = x0 >> fc->ps.sps->ctb_log2_size_y; | |
| 79 | 3060628 | const int y_cb = y0 >> fc->ps.sps->ctb_log2_size_y; | |
| 80 | 3060628 | const int pic_width_cb = fc->ps.pps->ctb_width; | |
| 81 | 3060628 | const int ctb_addr_rs = y_cb * pic_width_cb + x_cb; | |
| 82 | |||
| 83 | 3060628 | return (const RefPicList *)ref->rpl_tab[ctb_addr_rs]; | |
| 84 | } | ||
| 85 | |||
| 86 | 112 | void ff_vvc_clear_refs(VVCFrameContext *fc) | |
| 87 | { | ||
| 88 |
2/2✓ Branch 0 taken 1904 times.
✓ Branch 1 taken 112 times.
|
2016 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
| 89 | 1904 | ff_vvc_unref_frame(fc, &fc->DPB[i], | |
| 90 | VVC_FRAME_FLAG_SHORT_REF | VVC_FRAME_FLAG_LONG_REF); | ||
| 91 | 112 | } | |
| 92 | |||
| 93 | 104 | void ff_vvc_flush_dpb(VVCFrameContext *fc) | |
| 94 | { | ||
| 95 |
2/2✓ Branch 0 taken 1768 times.
✓ Branch 1 taken 104 times.
|
1872 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
| 96 | 1768 | ff_vvc_unref_frame(fc, &fc->DPB[i], ~0); | |
| 97 | 104 | } | |
| 98 | |||
| 99 | 1150 | static void free_progress(AVRefStructOpaque unused, void *obj) | |
| 100 | { | ||
| 101 | 1150 | FrameProgress *p = (FrameProgress *)obj; | |
| 102 | |||
| 103 |
1/2✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
|
1150 | if (p->has_cond) |
| 104 | 1150 | ff_cond_destroy(&p->cond); | |
| 105 |
1/2✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
|
1150 | if (p->has_lock) |
| 106 | 1150 | ff_mutex_destroy(&p->lock); | |
| 107 | 1150 | } | |
| 108 | |||
| 109 | 1150 | static FrameProgress *alloc_progress(void) | |
| 110 | { | ||
| 111 | 1150 | FrameProgress *p = av_refstruct_alloc_ext(sizeof(*p), 0, NULL, free_progress); | |
| 112 | |||
| 113 |
1/2✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
|
1150 | if (p) { |
| 114 | 1150 | p->has_lock = !ff_mutex_init(&p->lock, NULL); | |
| 115 | 1150 | p->has_cond = !ff_cond_init(&p->cond, NULL); | |
| 116 |
2/4✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1150 times.
|
1150 | if (!p->has_lock || !p->has_cond) |
| 117 | ✗ | av_refstruct_unref(&p); | |
| 118 | } | ||
| 119 | 1150 | return p; | |
| 120 | } | ||
| 121 | |||
| 122 | 1150 | static VVCFrame *alloc_frame(VVCContext *s, VVCFrameContext *fc) | |
| 123 | { | ||
| 124 | 1150 | const VVCSPS *sps = fc->ps.sps; | |
| 125 | 1150 | const VVCPPS *pps = fc->ps.pps; | |
| 126 |
1/2✓ Branch 0 taken 4587 times.
✗ Branch 1 not taken.
|
4587 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 127 | int ret; | ||
| 128 | 4587 | VVCFrame *frame = &fc->DPB[i]; | |
| 129 | 4587 | VVCWindow *win = &frame->scaling_win; | |
| 130 |
2/2✓ Branch 0 taken 3437 times.
✓ Branch 1 taken 1150 times.
|
4587 | if (frame->frame->buf[0]) |
| 131 | 3437 | continue; | |
| 132 | |||
| 133 | 1150 | frame->sps = av_refstruct_ref_c(fc->ps.sps); | |
| 134 | 1150 | frame->pps = av_refstruct_ref_c(fc->ps.pps); | |
| 135 | |||
| 136 | // Add LCEVC SEI metadata here, as it's needed in get_buffer() | ||
| 137 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1118 times.
|
1150 | if (fc->sei.common.itut_t35.lcevc) { |
| 138 | 32 | ret = ff_frame_new_side_data_from_buf(s->avctx, frame->frame, | |
| 139 | AV_FRAME_DATA_LCEVC, &fc->sei.common.itut_t35.lcevc); | ||
| 140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if (ret < 0) |
| 141 | ✗ | goto fail; | |
| 142 | } | ||
| 143 | |||
| 144 | 1150 | ret = ff_thread_get_buffer(s->avctx, frame->frame, AV_GET_BUFFER_FLAG_REF); | |
| 145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
|
1150 | if (ret < 0) |
| 146 | ✗ | return NULL; | |
| 147 | |||
| 148 | 1150 | frame->rpl = av_refstruct_allocz(s->current_frame.nb_units * sizeof(RefPicListTab)); | |
| 149 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
|
1150 | if (!frame->rpl) |
| 150 | ✗ | goto fail; | |
| 151 | 1150 | frame->nb_rpl_elems = s->current_frame.nb_units; | |
| 152 | |||
| 153 | 1150 | frame->tab_dmvr_mvf = av_refstruct_pool_get(fc->tab_dmvr_mvf_pool); | |
| 154 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
|
1150 | if (!frame->tab_dmvr_mvf) |
| 155 | ✗ | goto fail; | |
| 156 | |||
| 157 | 1150 | frame->rpl_tab = av_refstruct_pool_get(fc->rpl_tab_pool); | |
| 158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
|
1150 | if (!frame->rpl_tab) |
| 159 | ✗ | goto fail; | |
| 160 | 1150 | frame->ctb_count = pps->ctb_width * pps->ctb_height; | |
| 161 |
2/2✓ Branch 0 taken 56034 times.
✓ Branch 1 taken 1150 times.
|
57184 | for (int j = 0; j < frame->ctb_count; j++) |
| 162 | 56034 | frame->rpl_tab[j] = frame->rpl; | |
| 163 | |||
| 164 | 1150 | win->left_offset = pps->r->pps_scaling_win_left_offset * (1 << sps->hshift[CHROMA]); | |
| 165 | 1150 | win->right_offset = pps->r->pps_scaling_win_right_offset * (1 << sps->hshift[CHROMA]); | |
| 166 | 1150 | win->top_offset = pps->r->pps_scaling_win_top_offset * (1 << sps->vshift[CHROMA]); | |
| 167 | 1150 | win->bottom_offset = pps->r->pps_scaling_win_bottom_offset * (1 << sps->vshift[CHROMA]); | |
| 168 | 1150 | frame->ref_width = pps->r->pps_pic_width_in_luma_samples - win->left_offset - win->right_offset; | |
| 169 | 1150 | frame->ref_height = pps->r->pps_pic_height_in_luma_samples - win->bottom_offset - win->top_offset; | |
| 170 | |||
| 171 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1129 times.
|
1150 | if (fc->sei.frame_field_info.present) { |
| 172 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 10 times.
|
21 | if (fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD) |
| 173 | 11 | frame->frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; | |
| 174 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 11 times.
|
21 | if (fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD || |
| 175 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_BOTTOM_FIELD) |
| 176 | 21 | frame->frame->flags |= AV_FRAME_FLAG_INTERLACED; | |
| 177 | } | ||
| 178 | |||
| 179 | 1150 | frame->progress = alloc_progress(); | |
| 180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
|
1150 | if (!frame->progress) |
| 181 | ✗ | goto fail; | |
| 182 | |||
| 183 | 1150 | ret = ff_hwaccel_frame_priv_alloc(s->avctx, &frame->hwaccel_picture_private); | |
| 184 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
|
1150 | if (ret < 0) |
| 185 | ✗ | goto fail; | |
| 186 | |||
| 187 | 1150 | return frame; | |
| 188 | ✗ | fail: | |
| 189 | ✗ | ff_vvc_unref_frame(fc, frame, ~0); | |
| 190 | ✗ | return NULL; | |
| 191 | } | ||
| 192 | ✗ | av_log(s->avctx, AV_LOG_ERROR, "Error allocating frame, DPB full.\n"); | |
| 193 | ✗ | return NULL; | |
| 194 | } | ||
| 195 | |||
| 196 | 1133 | static void set_pict_type(AVFrame *frame, const VVCContext *s, const VVCFrameContext *fc) | |
| 197 | { | ||
| 198 | 1133 | bool has_b = false, has_inter = false; | |
| 199 | |||
| 200 |
6/6✓ Branch 0 taken 1126 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1021 times.
✓ Branch 3 taken 105 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 1009 times.
|
1133 | if (IS_IRAP(s)) { |
| 201 | 124 | frame->pict_type = AV_PICTURE_TYPE_I; | |
| 202 | 124 | frame->flags |= AV_FRAME_FLAG_KEY; | |
| 203 | 124 | return; | |
| 204 | } | ||
| 205 | |||
| 206 |
2/2✓ Branch 0 taken 1006 times.
✓ Branch 1 taken 3 times.
|
1009 | 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 | 1006 | const CodedBitstreamFragment *current = &s->current_frame; | |
| 209 |
4/4✓ Branch 0 taken 2457 times.
✓ Branch 1 taken 108 times.
✓ Branch 2 taken 1559 times.
✓ Branch 3 taken 898 times.
|
2565 | for (int i = 0; i < current->nb_units && !has_b; i++) { |
| 210 | 1559 | const CodedBitstreamUnit *unit = current->units + i; | |
| 211 |
3/4✓ Branch 0 taken 1559 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1006 times.
✓ Branch 3 taken 553 times.
|
1559 | if (unit->content_ref && unit->type <= VVC_RSV_IRAP_11) { |
| 212 | 1006 | const H266RawSliceHeader *rsh = unit->content_ref; | |
| 213 | 1006 | has_inter |= !IS_I(rsh); | |
| 214 | 1006 | has_b |= IS_B(rsh); | |
| 215 | } | ||
| 216 | } | ||
| 217 | } | ||
| 218 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1006 times.
|
1009 | if (!has_inter) |
| 219 | 3 | frame->pict_type = AV_PICTURE_TYPE_I; | |
| 220 |
2/2✓ Branch 0 taken 951 times.
✓ Branch 1 taken 55 times.
|
1006 | else if (has_b) |
| 221 | 951 | frame->pict_type = AV_PICTURE_TYPE_B; | |
| 222 | else | ||
| 223 | 55 | frame->pict_type = AV_PICTURE_TYPE_P; | |
| 224 | } | ||
| 225 | |||
| 226 | 1133 | int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, AVFrame **frame) | |
| 227 | { | ||
| 228 | 1133 | const VVCPH *ph= &fc->ps.ph; | |
| 229 | 1133 | const int poc = ph->poc; | |
| 230 | VVCFrame *ref; | ||
| 231 | |||
| 232 | /* check that this POC doesn't already exist */ | ||
| 233 |
2/2✓ Branch 0 taken 19261 times.
✓ Branch 1 taken 1133 times.
|
20394 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 234 | 19261 | VVCFrame *frame = &fc->DPB[i]; | |
| 235 | |||
| 236 |
4/4✓ Branch 0 taken 5226 times.
✓ Branch 1 taken 14035 times.
✓ Branch 2 taken 5117 times.
✓ Branch 3 taken 109 times.
|
19261 | if (frame->frame->buf[0] && frame->sequence == s->seq_decode && |
| 237 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5117 times.
|
5117 | 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 | 1133 | ref = alloc_frame(s, fc); | |
| 244 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1133 times.
|
1133 | if (!ref) |
| 245 | ✗ | return AVERROR(ENOMEM); | |
| 246 | |||
| 247 | 1133 | set_pict_type(ref->frame, s, fc); | |
| 248 | 1133 | *frame = ref->frame; | |
| 249 | 1133 | fc->ref = ref; | |
| 250 | |||
| 251 |
5/6✓ Branch 0 taken 932 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 917 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 917 times.
|
1133 | if (s->no_output_before_recovery_flag && (IS_RASL(s) || !GDR_IS_RECOVERED(s))) |
| 252 | 15 | ref->flags = VVC_FRAME_FLAG_SHORT_REF; | |
| 253 |
1/2✓ Branch 0 taken 1118 times.
✗ Branch 1 not taken.
|
1118 | else if (ph->r->ph_pic_output_flag) |
| 254 | 1118 | ref->flags = VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_SHORT_REF; | |
| 255 | |||
| 256 |
2/2✓ Branch 0 taken 1121 times.
✓ Branch 1 taken 12 times.
|
1133 | if (!ph->r->ph_non_ref_pic_flag) |
| 257 | 1121 | ref->flags |= VVC_FRAME_FLAG_SHORT_REF; | |
| 258 | |||
| 259 | 1133 | ref->poc = poc; | |
| 260 | 1133 | ref->sequence = s->seq_decode; | |
| 261 | 1133 | ref->frame->crop_left = fc->ps.pps->r->pps_conf_win_left_offset << fc->ps.sps->hshift[CHROMA]; | |
| 262 | 1133 | ref->frame->crop_right = fc->ps.pps->r->pps_conf_win_right_offset << fc->ps.sps->hshift[CHROMA]; | |
| 263 | 1133 | ref->frame->crop_top = fc->ps.pps->r->pps_conf_win_top_offset << fc->ps.sps->vshift[CHROMA]; | |
| 264 | 1133 | ref->frame->crop_bottom = fc->ps.pps->r->pps_conf_win_bottom_offset << fc->ps.sps->vshift[CHROMA]; | |
| 265 | |||
| 266 | 1133 | return 0; | |
| 267 | } | ||
| 268 | |||
| 269 | 1269 | int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush) | |
| 270 | { | ||
| 271 | 1269 | const VVCSPS *sps = fc->ps.sps; | |
| 272 | 118 | do { | |
| 273 | 1387 | int nb_output = 0; | |
| 274 | 1387 | int min_poc = INT_MAX; | |
| 275 | int min_idx, ret; | ||
| 276 | |||
| 277 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1387 times.
|
1387 | 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) { | |
| 282 | ✗ | ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT); | |
| 283 | } | ||
| 284 | } | ||
| 285 | } | ||
| 286 | |||
| 287 |
2/2✓ Branch 0 taken 23579 times.
✓ Branch 1 taken 1387 times.
|
24966 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 288 | 23579 | VVCFrame *frame = &fc->DPB[i]; | |
| 289 |
2/2✓ Branch 0 taken 5212 times.
✓ Branch 1 taken 18367 times.
|
23579 | if ((frame->flags & VVC_FRAME_FLAG_OUTPUT) && |
| 290 |
2/2✓ Branch 0 taken 4944 times.
✓ Branch 1 taken 268 times.
|
5212 | frame->sequence == s->seq_output) { |
| 291 | 4944 | nb_output++; | |
| 292 |
3/4✓ Branch 0 taken 2409 times.
✓ Branch 1 taken 2535 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2409 times.
|
4944 | if (frame->poc < min_poc || nb_output == 1) { |
| 293 | 2535 | min_poc = frame->poc; | |
| 294 | 2535 | min_idx = i; | |
| 295 | } | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | /* wait for more frames before output */ | ||
| 300 |
5/6✓ Branch 0 taken 1249 times.
✓ Branch 1 taken 138 times.
✓ Branch 2 taken 1090 times.
✓ Branch 3 taken 159 times.
✓ Branch 4 taken 1090 times.
✗ Branch 5 not taken.
|
1387 | if (!flush && s->seq_output == s->seq_decode && sps && |
| 301 |
2/2✓ Branch 0 taken 167 times.
✓ Branch 1 taken 923 times.
|
1090 | nb_output <= sps->r->sps_dpb_params.dpb_max_num_reorder_pics[sps->r->sps_max_sublayers_minus1]) |
| 302 | 167 | return 0; | |
| 303 | |||
| 304 |
2/2✓ Branch 0 taken 1068 times.
✓ Branch 1 taken 152 times.
|
1220 | if (nb_output) { |
| 305 | 1068 | VVCFrame *frame = &fc->DPB[min_idx]; | |
| 306 | |||
| 307 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
|
1068 | if (frame->flags & VVC_FRAME_FLAG_CORRUPT) |
| 308 | ✗ | frame->frame->flags |= AV_FRAME_FLAG_CORRUPT; | |
| 309 | |||
| 310 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
|
1068 | ret = av_frame_ref(out, frame->needs_fg ? frame->frame_grain : frame->frame); |
| 311 | |||
| 312 |
2/4✓ Branch 0 taken 1068 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1068 times.
✗ Branch 3 not taken.
|
1068 | if (!ret && !(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN)) |
| 313 | 1068 | av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS); | |
| 314 | |||
| 315 |
2/2✓ Branch 0 taken 716 times.
✓ Branch 1 taken 352 times.
|
1068 | if (frame->flags & VVC_FRAME_FLAG_BUMPING) |
| 316 | 716 | ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_BUMPING); | |
| 317 | else | ||
| 318 | 352 | ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT); | |
| 319 | |||
| 320 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
|
1068 | if (ret < 0) |
| 321 | ✗ | return ret; | |
| 322 | |||
| 323 | 1068 | av_log(s->avctx, AV_LOG_DEBUG, | |
| 324 | "Output frame with POC %d.\n", frame->poc); | ||
| 325 | 1068 | return 1; | |
| 326 | } | ||
| 327 | |||
| 328 |
2/2✓ Branch 0 taken 118 times.
✓ Branch 1 taken 34 times.
|
152 | if (s->seq_output != s->seq_decode) |
| 329 | 118 | s->seq_output = (s->seq_output + 1) & 0xff; | |
| 330 | else | ||
| 331 | 34 | break; | |
| 332 | } while (1); | ||
| 333 | 34 | return 0; | |
| 334 | } | ||
| 335 | |||
| 336 | 1021 | void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc) | |
| 337 | { | ||
| 338 | 1021 | const VVCSPS *sps = fc->ps.sps; | |
| 339 | 1021 | const int poc = fc->ps.ph.poc; | |
| 340 | 1021 | int dpb = 0; | |
| 341 | 1021 | int min_poc = INT_MAX; | |
| 342 | |||
| 343 |
2/2✓ Branch 0 taken 17357 times.
✓ Branch 1 taken 1021 times.
|
18378 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 344 | 17357 | VVCFrame *frame = &fc->DPB[i]; | |
| 345 |
2/2✓ Branch 0 taken 6204 times.
✓ Branch 1 taken 11153 times.
|
17357 | if ((frame->flags) && |
| 346 |
2/2✓ Branch 0 taken 6076 times.
✓ Branch 1 taken 128 times.
|
6204 | frame->sequence == s->seq_output && |
| 347 |
2/2✓ Branch 0 taken 5089 times.
✓ Branch 1 taken 987 times.
|
6076 | frame->poc != poc) { |
| 348 | 5089 | dpb++; | |
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 |
3/4✓ Branch 0 taken 1021 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 501 times.
✓ Branch 3 taken 520 times.
|
1021 | if (sps && dpb >= sps->r->sps_dpb_params.dpb_max_dec_pic_buffering_minus1[sps->r->sps_max_sublayers_minus1] + 1) { |
| 353 |
2/2✓ Branch 0 taken 8517 times.
✓ Branch 1 taken 501 times.
|
9018 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 354 | 8517 | VVCFrame *frame = &fc->DPB[i]; | |
| 355 |
2/2✓ Branch 0 taken 3345 times.
✓ Branch 1 taken 5172 times.
|
8517 | if ((frame->flags) && |
| 356 |
1/2✓ Branch 0 taken 3345 times.
✗ Branch 1 not taken.
|
3345 | frame->sequence == s->seq_output && |
| 357 |
2/2✓ Branch 0 taken 2844 times.
✓ Branch 1 taken 501 times.
|
3345 | frame->poc != poc) { |
| 358 |
4/4✓ Branch 0 taken 60 times.
✓ Branch 1 taken 2784 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 9 times.
|
2844 | if (frame->flags == VVC_FRAME_FLAG_OUTPUT && frame->poc < min_poc) { |
| 359 | 51 | min_poc = frame->poc; | |
| 360 | } | ||
| 361 | } | ||
| 362 | } | ||
| 363 | |||
| 364 |
2/2✓ Branch 0 taken 8517 times.
✓ Branch 1 taken 501 times.
|
9018 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 365 | 8517 | VVCFrame *frame = &fc->DPB[i]; | |
| 366 |
2/2✓ Branch 0 taken 2225 times.
✓ Branch 1 taken 6292 times.
|
8517 | if (frame->flags & VVC_FRAME_FLAG_OUTPUT && |
| 367 |
1/2✓ Branch 0 taken 2225 times.
✗ Branch 1 not taken.
|
2225 | frame->sequence == s->seq_output && |
| 368 |
2/2✓ Branch 0 taken 2021 times.
✓ Branch 1 taken 204 times.
|
2225 | frame->poc <= min_poc) { |
| 369 | 2021 | frame->flags |= VVC_FRAME_FLAG_BUMPING; | |
| 370 | } | ||
| 371 | } | ||
| 372 | |||
| 373 | 501 | dpb--; | |
| 374 | } | ||
| 375 | 1021 | } | |
| 376 | |||
| 377 | 7627 | static VVCFrame *find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb) | |
| 378 | { | ||
| 379 |
2/2✓ Branch 0 taken 395 times.
✓ Branch 1 taken 7232 times.
|
7627 | const unsigned mask = use_msb ? ~0 : fc->ps.sps->max_pic_order_cnt_lsb - 1; |
| 380 | |||
| 381 |
2/2✓ Branch 0 taken 27759 times.
✓ Branch 1 taken 17 times.
|
27776 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 382 | 27759 | VVCFrame *ref = &fc->DPB[i]; | |
| 383 | |||
| 384 | // In the specification, the current frame is not considered part of | ||
| 385 | // the DPB at this stage, therefore we treat it as if it's not there. | ||
| 386 |
2/2✓ Branch 0 taken 2369 times.
✓ Branch 1 taken 25390 times.
|
27759 | if (ref == fc->ref) |
| 387 | 2369 | continue; | |
| 388 | |||
| 389 |
4/4✓ Branch 0 taken 22643 times.
✓ Branch 1 taken 2747 times.
✓ Branch 2 taken 21715 times.
✓ Branch 3 taken 928 times.
|
25390 | if (ref->frame->buf[0] && ref->sequence == s->seq_decode) { |
| 390 |
2/2✓ Branch 0 taken 7610 times.
✓ Branch 1 taken 14105 times.
|
21715 | if ((ref->poc & mask) == poc) |
| 391 | 7610 | return ref; | |
| 392 | } | ||
| 393 | } | ||
| 394 | 17 | return NULL; | |
| 395 | } | ||
| 396 | |||
| 397 | 25755 | static void mark_ref(VVCFrame *frame, int flag) | |
| 398 | { | ||
| 399 | 25755 | frame->flags &= ~(VVC_FRAME_FLAG_LONG_REF | VVC_FRAME_FLAG_SHORT_REF); | |
| 400 | 25755 | frame->flags |= flag; | |
| 401 | 25755 | } | |
| 402 | |||
| 403 | 17 | static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int poc) | |
| 404 | { | ||
| 405 | 17 | const VVCSPS *sps = fc->ps.sps; | |
| 406 | 17 | const VVCPPS *pps = fc->ps.pps; | |
| 407 | VVCFrame *frame; | ||
| 408 | |||
| 409 | 17 | frame = alloc_frame(s, fc); | |
| 410 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!frame) |
| 411 | ✗ | return NULL; | |
| 412 | |||
| 413 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | if (!s->avctx->hwaccel) { |
| 414 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!sps->pixel_shift) { |
| 415 | ✗ | for (int i = 0; frame->frame->buf[i]; i++) | |
| 416 | ✗ | memset(frame->frame->buf[i]->data, 1 << (sps->bit_depth - 1), | |
| 417 | ✗ | frame->frame->buf[i]->size); | |
| 418 | } else { | ||
| 419 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 17 times.
|
68 | for (int i = 0; frame->frame->data[i]; i++) |
| 420 |
2/2✓ Branch 0 taken 10688 times.
✓ Branch 1 taken 51 times.
|
10739 | for (int y = 0; y < (pps->height >> sps->vshift[i]); y++) { |
| 421 | 10688 | uint8_t *dst = frame->frame->data[i] + y * frame->frame->linesize[i]; | |
| 422 | 10688 | AV_WN16(dst, 1 << (sps->bit_depth - 1)); | |
| 423 | 10688 | av_memcpy_backptr(dst + 2, 2, 2*(pps->width >> sps->hshift[i]) - 2); | |
| 424 | } | ||
| 425 | } | ||
| 426 | } | ||
| 427 | |||
| 428 | 17 | frame->poc = poc; | |
| 429 | 17 | frame->sequence = s->seq_decode; | |
| 430 | 17 | frame->flags = VVC_FRAME_FLAG_CORRUPT; | |
| 431 | |||
| 432 | 17 | ff_vvc_report_frame_finished(frame); | |
| 433 | |||
| 434 | 17 | return frame; | |
| 435 | } | ||
| 436 | |||
| 437 | #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)) | ||
| 438 | #define CHECK_SAMPLES(d) (frame->pps->r->pps_pic_##d##_in_luma_samples == ref->pps->r->pps_pic_##d##_in_luma_samples) | ||
| 439 | 7627 | static int check_candidate_ref(const VVCFrame *frame, const VVCRefPic *refp) | |
| 440 | { | ||
| 441 | 7627 | const VVCFrame *ref = refp->ref; | |
| 442 | |||
| 443 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7619 times.
|
7627 | if (refp->is_scaled) { |
| 444 | 8 | const int max = FFMAX(8, frame->sps->min_cb_size_y); | |
| 445 | 16 | return frame->ref_width * 2 >= ref->ref_width && | |
| 446 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | frame->ref_height * 2 >= ref->ref_height && |
| 447 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | frame->ref_width <= ref->ref_width * 8 && |
| 448 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | frame->ref_height <= ref->ref_height * 8 && |
| 449 |
3/6✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
16 | CHECK_MAX(width) && CHECK_MAX(height); |
| 450 | } | ||
| 451 |
2/4✓ Branch 0 taken 7619 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7619 times.
✗ Branch 3 not taken.
|
7619 | return CHECK_SAMPLES(width) && CHECK_SAMPLES(height); |
| 452 | } | ||
| 453 | |||
| 454 | #define RPR_SCALE(f) (((ref->f << 14) + (fc->ref->f >> 1)) / fc->ref->f) | ||
| 455 | /* add a reference with the given poc to the list and mark it as used in DPB */ | ||
| 456 | 7627 | static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *list, | |
| 457 | int poc, int ref_flag, uint8_t use_msb) | ||
| 458 | { | ||
| 459 | 7627 | VVCRefPic *refp = &list->refs[list->nb_refs]; | |
| 460 | VVCFrame *ref; | ||
| 461 | |||
| 462 |
4/6✓ Branch 0 taken 7232 times.
✓ Branch 1 taken 395 times.
✓ Branch 2 taken 7232 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7627 times.
|
7627 | if (use_msb && poc == fc->ref->poc || list->nb_refs >= VVC_MAX_REF_ENTRIES) |
| 463 | ✗ | return AVERROR_INVALIDDATA; | |
| 464 | |||
| 465 | 7627 | ref = find_ref_idx(s, fc, poc, use_msb); | |
| 466 | |||
| 467 |
6/8✓ Branch 0 taken 7627 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7613 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 7567 times.
✓ Branch 5 taken 46 times.
✓ Branch 6 taken 7567 times.
✗ Branch 7 not taken.
|
7627 | if (!IS_CVSS(s)) { |
| 468 |
3/4✓ Branch 0 taken 7567 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 7548 times.
|
7567 | const bool ref_corrupt = !ref || (ref->flags & VVC_FRAME_FLAG_CORRUPT); |
| 469 |
2/2✓ Branch 0 taken 6704 times.
✓ Branch 1 taken 863 times.
|
14271 | const bool recovering = s->no_output_before_recovery_flag && |
| 470 |
3/4✓ Branch 0 taken 6632 times.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6632 times.
|
6704 | (IS_RASL(s) || !GDR_IS_RECOVERED(s)); |
| 471 | |||
| 472 |
3/4✓ Branch 0 taken 19 times.
✓ Branch 1 taken 7548 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
|
7567 | if (ref_corrupt && !recovering) { |
| 473 | ✗ | if (!(s->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) && | |
| 474 | ✗ | !(s->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL)) | |
| 475 | ✗ | return AVERROR_INVALIDDATA; | |
| 476 | |||
| 477 | ✗ | fc->ref->flags |= VVC_FRAME_FLAG_CORRUPT; | |
| 478 | } | ||
| 479 | } | ||
| 480 | |||
| 481 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 7610 times.
|
7627 | if (!ref) { |
| 482 | 17 | ref = generate_missing_ref(s, fc, poc); | |
| 483 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!ref) |
| 484 | ✗ | return AVERROR(ENOMEM); | |
| 485 | } | ||
| 486 | |||
| 487 | 7627 | refp->poc = poc; | |
| 488 | 7627 | refp->ref = ref; | |
| 489 | 7627 | refp->is_lt = ref_flag & VVC_FRAME_FLAG_LONG_REF; | |
| 490 | 22881 | refp->is_scaled = ref->sps->r->sps_num_subpics_minus1 != fc->ref->sps->r->sps_num_subpics_minus1|| | |
| 491 |
1/2✓ Branch 0 taken 7627 times.
✗ Branch 1 not taken.
|
7627 | memcmp(&ref->scaling_win, &fc->ref->scaling_win, sizeof(ref->scaling_win)) || |
| 492 |
3/4✓ Branch 0 taken 7627 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7619 times.
✓ Branch 3 taken 8 times.
|
22873 | ref->pps->r->pps_pic_width_in_luma_samples != fc->ref->pps->r->pps_pic_width_in_luma_samples || |
| 493 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7619 times.
|
7619 | ref->pps->r->pps_pic_height_in_luma_samples != fc->ref->pps->r->pps_pic_height_in_luma_samples; |
| 494 | |||
| 495 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7627 times.
|
7627 | if (!check_candidate_ref(fc->ref, refp)) |
| 496 | ✗ | return AVERROR_INVALIDDATA; | |
| 497 | |||
| 498 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7619 times.
|
7627 | if (refp->is_scaled) { |
| 499 | 8 | refp->scale[0] = RPR_SCALE(ref_width); | |
| 500 | 8 | refp->scale[1] = RPR_SCALE(ref_height); | |
| 501 | } | ||
| 502 | 7627 | list->nb_refs++; | |
| 503 | |||
| 504 | 7627 | mark_ref(ref, ref_flag); | |
| 505 | 7627 | return 0; | |
| 506 | } | ||
| 507 | |||
| 508 | 1732 | static int init_slice_rpl(const VVCFrameContext *fc, SliceContext *sc) | |
| 509 | { | ||
| 510 | 1732 | VVCFrame *frame = fc->ref; | |
| 511 | 1732 | const VVCSH *sh = &sc->sh; | |
| 512 | |||
| 513 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1732 times.
|
1732 | if (sc->slice_idx >= frame->nb_rpl_elems) |
| 514 | ✗ | return AVERROR_INVALIDDATA; | |
| 515 | |||
| 516 |
2/2✓ Branch 0 taken 54141 times.
✓ Branch 1 taken 1732 times.
|
55873 | for (int i = 0; i < sh->num_ctus_in_curr_slice; i++) { |
| 517 | 54141 | const int rs = sh->ctb_addr_in_curr_slice[i]; | |
| 518 | 54141 | frame->rpl_tab[rs] = frame->rpl + sc->slice_idx; | |
| 519 | } | ||
| 520 | |||
| 521 | 1732 | sc->rpl = frame->rpl_tab[sh->ctb_addr_in_curr_slice[0]]->refPicList; | |
| 522 | |||
| 523 | 1732 | return 0; | |
| 524 | } | ||
| 525 | |||
| 526 | 7218 | static int delta_poc_st(const H266RefPicListStruct *rpls, | |
| 527 | const int lx, const int i, const VVCSPS *sps) | ||
| 528 | { | ||
| 529 | 7218 | int abs_delta_poc_st = rpls->abs_delta_poc_st[i]; | |
| 530 |
4/4✓ Branch 0 taken 6699 times.
✓ Branch 1 taken 519 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 447 times.
|
7218 | if (!((sps->r->sps_weighted_pred_flag || |
| 531 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6699 times.
|
6699 | sps->r->sps_weighted_bipred_flag) && i != 0)) |
| 532 | 6771 | abs_delta_poc_st++; | |
| 533 | 7218 | return (1 - 2 * rpls->strp_entry_sign_flag[i]) * abs_delta_poc_st; | |
| 534 | } | ||
| 535 | |||
| 536 | 409 | static int poc_lt(int *prev_delta_poc_msb, const int poc, const H266RefPicLists *ref_lists, | |
| 537 | const int lx, const int j, const int max_poc_lsb) | ||
| 538 | { | ||
| 539 | 409 | const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx; | |
| 540 |
1/2✓ Branch 0 taken 409 times.
✗ Branch 1 not taken.
|
409 | int lt_poc = rpls->ltrp_in_header_flag ? ref_lists->poc_lsb_lt[lx][j] : rpls->rpls_poc_lsb_lt[j]; |
| 541 | |||
| 542 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 395 times.
|
409 | if (ref_lists->delta_poc_msb_cycle_present_flag[lx][j]) { |
| 543 | 14 | const uint32_t delta = ref_lists->delta_poc_msb_cycle_lt[lx][j] + *prev_delta_poc_msb; | |
| 544 | 14 | lt_poc += poc - delta * max_poc_lsb - (poc & (max_poc_lsb - 1)); | |
| 545 | 14 | *prev_delta_poc_msb = delta; | |
| 546 | } | ||
| 547 | 409 | return lt_poc; | |
| 548 | } | ||
| 549 | |||
| 550 | 1732 | int ff_vvc_slice_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc) | |
| 551 | { | ||
| 552 | 1732 | const VVCSPS *sps = fc->ps.sps; | |
| 553 | 1732 | const H266RawPPS *pps = fc->ps.pps->r; | |
| 554 | 1732 | const VVCPH *ph = &fc->ps.ph; | |
| 555 | 1732 | const H266RawSliceHeader *rsh = sc->sh.r; | |
| 556 | 1732 | const int max_poc_lsb = sps->max_pic_order_cnt_lsb; | |
| 557 | 1732 | const H266RefPicLists *ref_lists = | |
| 558 |
2/2✓ Branch 0 taken 253 times.
✓ Branch 1 taken 1479 times.
|
1732 | pps->pps_rpl_info_in_ph_flag ? &ph->r->ph_ref_pic_lists : &rsh->sh_ref_pic_lists; |
| 559 | 1732 | int ret = 0; | |
| 560 | |||
| 561 | 1732 | ret = init_slice_rpl(fc, sc); | |
| 562 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1732 times.
|
1732 | if (ret < 0) |
| 563 | ✗ | return ret; | |
| 564 | |||
| 565 |
2/2✓ Branch 0 taken 3464 times.
✓ Branch 1 taken 1732 times.
|
5196 | for (int lx = L0; lx <= L1; lx++) { |
| 566 | 3464 | const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx; | |
| 567 | 3464 | RefPicList *rpl = sc->rpl + lx; | |
| 568 | 3464 | int poc_base = ph->poc; | |
| 569 | 3464 | int prev_delta_poc_msb = 0; | |
| 570 | |||
| 571 | 3464 | rpl->nb_refs = 0; | |
| 572 |
2/2✓ Branch 0 taken 7627 times.
✓ Branch 1 taken 3464 times.
|
11091 | for (int i = 0, j = 0; i < rpls->num_ref_entries; i++) { |
| 573 | int poc; | ||
| 574 |
1/2✓ Branch 0 taken 7627 times.
✗ Branch 1 not taken.
|
7627 | if (!rpls->inter_layer_ref_pic_flag[i]) { |
| 575 | 7627 | int use_msb = 1; | |
| 576 | int ref_flag; | ||
| 577 |
2/2✓ Branch 0 taken 7218 times.
✓ Branch 1 taken 409 times.
|
7627 | if (rpls->st_ref_pic_flag[i]) { |
| 578 | 7218 | poc = poc_base + delta_poc_st(rpls, lx, i, sps); | |
| 579 | 7218 | poc_base = poc; | |
| 580 | 7218 | ref_flag = VVC_FRAME_FLAG_SHORT_REF; | |
| 581 | } else { | ||
| 582 | 409 | use_msb = ref_lists->delta_poc_msb_cycle_present_flag[lx][j]; | |
| 583 | 409 | poc = poc_lt(&prev_delta_poc_msb, ph->poc, ref_lists, lx, j, max_poc_lsb); | |
| 584 | 409 | ref_flag = VVC_FRAME_FLAG_LONG_REF; | |
| 585 | 409 | j++; | |
| 586 | } | ||
| 587 | 7627 | ret = add_candidate_ref(s, fc, rpl, poc, ref_flag, use_msb); | |
| 588 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7627 times.
|
7627 | if (ret < 0) |
| 589 | ✗ | return ret; | |
| 590 | } else { | ||
| 591 | // OPI_B_3.bit and VPS_A_3.bit should cover this | ||
| 592 | ✗ | avpriv_report_missing_feature(fc->log_ctx, "Inter layer ref"); | |
| 593 | ✗ | ret = AVERROR_PATCHWELCOME; | |
| 594 | ✗ | return ret; | |
| 595 | } | ||
| 596 | } | ||
| 597 |
2/2✓ Branch 0 taken 3182 times.
✓ Branch 1 taken 282 times.
|
3464 | if (ph->r->ph_temporal_mvp_enabled_flag && |
| 598 |
2/2✓ Branch 0 taken 1591 times.
✓ Branch 1 taken 1591 times.
|
3182 | (!rsh->sh_collocated_from_l0_flag) == lx && |
| 599 |
1/2✓ Branch 0 taken 1591 times.
✗ Branch 1 not taken.
|
1591 | rsh->sh_collocated_ref_idx < rpl->nb_refs) { |
| 600 | 1591 | const VVCRefPic *refp = rpl->refs + rsh->sh_collocated_ref_idx; | |
| 601 |
2/4✓ Branch 0 taken 1591 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1591 times.
|
1591 | if (refp->is_scaled || refp->ref->sps->ctb_log2_size_y != sps->ctb_log2_size_y) |
| 602 | ✗ | return AVERROR_INVALIDDATA; | |
| 603 | 1591 | fc->ref->collocated_ref = refp->ref; | |
| 604 | } | ||
| 605 | } | ||
| 606 | 1732 | return 0; | |
| 607 | } | ||
| 608 | |||
| 609 | 1133 | int ff_vvc_frame_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc) | |
| 610 | { | ||
| 611 | 1133 | int ret = 0; | |
| 612 | |||
| 613 | /* clear the reference flags on all frames except the current one */ | ||
| 614 |
2/2✓ Branch 0 taken 19261 times.
✓ Branch 1 taken 1133 times.
|
20394 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 615 | 19261 | VVCFrame *frame = &fc->DPB[i]; | |
| 616 | |||
| 617 |
2/2✓ Branch 0 taken 1133 times.
✓ Branch 1 taken 18128 times.
|
19261 | if (frame == fc->ref) |
| 618 | 1133 | continue; | |
| 619 | |||
| 620 | 18128 | mark_ref(frame, 0); | |
| 621 | } | ||
| 622 | |||
| 623 |
1/2✓ Branch 1 taken 1133 times.
✗ Branch 2 not taken.
|
1133 | if ((ret = ff_vvc_slice_rpl(s, fc, sc)) < 0) |
| 624 | ✗ | goto fail; | |
| 625 | |||
| 626 | 1133 | fail: | |
| 627 | /* release any frames that are now unused */ | ||
| 628 |
2/2✓ Branch 0 taken 19261 times.
✓ Branch 1 taken 1133 times.
|
20394 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
| 629 | 19261 | ff_vvc_unref_frame(fc, &fc->DPB[i], 0); | |
| 630 | 1133 | return ret; | |
| 631 | } | ||
| 632 | |||
| 633 | 1150 | void ff_vvc_report_frame_finished(VVCFrame *frame) | |
| 634 | { | ||
| 635 | 1150 | ff_vvc_report_progress(frame, VVC_PROGRESS_MV, INT_MAX); | |
| 636 | 1150 | ff_vvc_report_progress(frame, VVC_PROGRESS_PIXEL, INT_MAX); | |
| 637 | 1150 | } | |
| 638 | |||
| 639 | 103248 | static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l) | |
| 640 | { | ||
| 641 | 103248 | return p->progress[l->vp] > l->y; | |
| 642 | } | ||
| 643 | |||
| 644 | ✗ | static void add_listener(VVCProgressListener **prev, VVCProgressListener *l) | |
| 645 | { | ||
| 646 | ✗ | l->next = *prev; | |
| 647 | ✗ | *prev = l; | |
| 648 | ✗ | } | |
| 649 | |||
| 650 | ✗ | static VVCProgressListener* remove_listener(VVCProgressListener **prev, VVCProgressListener *l) | |
| 651 | { | ||
| 652 | ✗ | *prev = l->next; | |
| 653 | ✗ | l->next = NULL; | |
| 654 | ✗ | return l; | |
| 655 | } | ||
| 656 | |||
| 657 | 10199 | static VVCProgressListener* get_done_listener(FrameProgress *p, const VVCProgress vp) | |
| 658 | { | ||
| 659 | 10199 | VVCProgressListener *list = NULL; | |
| 660 | 10199 | VVCProgressListener **prev = &p->listener[vp]; | |
| 661 | |||
| 662 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10199 times.
|
10199 | while (*prev) { |
| 663 | ✗ | if (is_progress_done(p, *prev)) { | |
| 664 | ✗ | VVCProgressListener *l = remove_listener(prev, *prev); | |
| 665 | ✗ | add_listener(&list, l); | |
| 666 | } else { | ||
| 667 | ✗ | prev = &(*prev)->next; | |
| 668 | } | ||
| 669 | } | ||
| 670 | 10199 | return list; | |
| 671 | } | ||
| 672 | |||
| 673 | 12465 | void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y) | |
| 674 | { | ||
| 675 | 12465 | FrameProgress *p = frame->progress; | |
| 676 | 12465 | VVCProgressListener *l = NULL; | |
| 677 | |||
| 678 | 12465 | ff_mutex_lock(&p->lock); | |
| 679 |
2/2✓ Branch 0 taken 10199 times.
✓ Branch 1 taken 2266 times.
|
12465 | if (p->progress[vp] < y) { |
| 680 | // Due to the nature of thread scheduling, later progress may reach this point before earlier progress. | ||
| 681 | // Therefore, we only update the progress when p->progress[vp] < y. | ||
| 682 | 10199 | p->progress[vp] = y; | |
| 683 | 10199 | l = get_done_listener(p, vp); | |
| 684 | 10199 | ff_cond_signal(&p->cond); | |
| 685 | } | ||
| 686 | 12465 | ff_mutex_unlock(&p->lock); | |
| 687 | |||
| 688 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12465 times.
|
12465 | while (l) { |
| 689 | ✗ | l->progress_done(l); | |
| 690 | ✗ | l = l->next; | |
| 691 | } | ||
| 692 | 12465 | } | |
| 693 | |||
| 694 | 103248 | void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l) | |
| 695 | { | ||
| 696 | 103248 | FrameProgress *p = frame->progress; | |
| 697 | |||
| 698 | 103248 | ff_mutex_lock(&p->lock); | |
| 699 | |||
| 700 |
1/2✓ Branch 1 taken 103248 times.
✗ Branch 2 not taken.
|
103248 | if (is_progress_done(p, l)) { |
| 701 | 103248 | ff_mutex_unlock(&p->lock); | |
| 702 | 103248 | l->progress_done(l); | |
| 703 | } else { | ||
| 704 | ✗ | add_listener(p->listener + l->vp, l); | |
| 705 | ✗ | ff_mutex_unlock(&p->lock); | |
| 706 | } | ||
| 707 | 103248 | } | |
| 708 |