| 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 | 54264 | 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 54264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41796 times.
✓ Branch 3 taken 12468 times.
|
54264 | if (!frame->frame || !frame->frame->buf[0]) |
| 48 | 41796 | return; | |
| 49 | |||
| 50 | 12468 | frame->flags &= ~flags; | |
| 51 |
2/2✓ Branch 0 taken 6298 times.
✓ Branch 1 taken 6170 times.
|
12468 | if (!(frame->flags & ~VVC_FRAME_FLAG_CORRUPT)) |
| 52 | 6298 | frame->flags = 0; | |
| 53 |
2/2✓ Branch 0 taken 6298 times.
✓ Branch 1 taken 6170 times.
|
12468 | if (!frame->flags) { |
| 54 | 6298 | av_frame_unref(frame->frame); | |
| 55 | |||
| 56 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6298 times.
|
6298 | if (frame->needs_fg) { |
| 57 | ✗ | av_frame_unref(frame->frame_grain); | |
| 58 | ✗ | frame->needs_fg = 0; | |
| 59 | } | ||
| 60 | |||
| 61 | 6298 | av_refstruct_unref(&frame->sps); | |
| 62 | 6298 | av_refstruct_unref(&frame->pps); | |
| 63 | 6298 | av_refstruct_unref(&frame->progress); | |
| 64 | |||
| 65 | 6298 | av_refstruct_unref(&frame->tab_dmvr_mvf); | |
| 66 | |||
| 67 | 6298 | av_refstruct_unref(&frame->rpl); | |
| 68 | 6298 | frame->nb_rpl_elems = 0; | |
| 69 | 6298 | av_refstruct_unref(&frame->rpl_tab); | |
| 70 | |||
| 71 | 6298 | frame->collocated_ref = NULL; | |
| 72 | 6298 | av_refstruct_unref(&frame->hwaccel_picture_private); | |
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | 3060599 | const RefPicList *ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0) | |
| 77 | { | ||
| 78 | 3060599 | const int x_cb = x0 >> fc->ps.sps->ctb_log2_size_y; | |
| 79 | 3060599 | const int y_cb = y0 >> fc->ps.sps->ctb_log2_size_y; | |
| 80 | 3060599 | const int pic_width_cb = fc->ps.pps->ctb_width; | |
| 81 | 3060599 | const int ctb_addr_rs = y_cb * pic_width_cb + x_cb; | |
| 82 | |||
| 83 | 3060599 | return (const RefPicList *)ref->rpl_tab[ctb_addr_rs]; | |
| 84 | } | ||
| 85 | |||
| 86 | 110 | void ff_vvc_clear_refs(VVCFrameContext *fc) | |
| 87 | { | ||
| 88 |
2/2✓ Branch 0 taken 1870 times.
✓ Branch 1 taken 110 times.
|
1980 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
| 89 | 1870 | ff_vvc_unref_frame(fc, &fc->DPB[i], | |
| 90 | VVC_FRAME_FLAG_SHORT_REF | VVC_FRAME_FLAG_LONG_REF); | ||
| 91 | 110 | } | |
| 92 | |||
| 93 | 102 | void ff_vvc_flush_dpb(VVCFrameContext *fc) | |
| 94 | { | ||
| 95 |
2/2✓ Branch 0 taken 1734 times.
✓ Branch 1 taken 102 times.
|
1836 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
| 96 | 1734 | ff_vvc_unref_frame(fc, &fc->DPB[i], ~0); | |
| 97 | 102 | } | |
| 98 | |||
| 99 | 1119 | static void free_progress(AVRefStructOpaque unused, void *obj) | |
| 100 | { | ||
| 101 | 1119 | FrameProgress *p = (FrameProgress *)obj; | |
| 102 | |||
| 103 |
1/2✓ Branch 0 taken 1119 times.
✗ Branch 1 not taken.
|
1119 | if (p->has_cond) |
| 104 | 1119 | ff_cond_destroy(&p->cond); | |
| 105 |
1/2✓ Branch 0 taken 1119 times.
✗ Branch 1 not taken.
|
1119 | if (p->has_lock) |
| 106 | 1119 | ff_mutex_destroy(&p->lock); | |
| 107 | 1119 | } | |
| 108 | |||
| 109 | 1119 | static FrameProgress *alloc_progress(void) | |
| 110 | { | ||
| 111 | 1119 | FrameProgress *p = av_refstruct_alloc_ext(sizeof(*p), 0, NULL, free_progress); | |
| 112 | |||
| 113 |
1/2✓ Branch 0 taken 1119 times.
✗ Branch 1 not taken.
|
1119 | if (p) { |
| 114 | 1119 | p->has_lock = !ff_mutex_init(&p->lock, NULL); | |
| 115 | 1119 | p->has_cond = !ff_cond_init(&p->cond, NULL); | |
| 116 |
2/4✓ Branch 0 taken 1119 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1119 times.
|
1119 | if (!p->has_lock || !p->has_cond) |
| 117 | ✗ | av_refstruct_unref(&p); | |
| 118 | } | ||
| 119 | 1119 | return p; | |
| 120 | } | ||
| 121 | |||
| 122 | 1119 | static VVCFrame *alloc_frame(VVCContext *s, VVCFrameContext *fc) | |
| 123 | { | ||
| 124 | 1119 | const VVCSPS *sps = fc->ps.sps; | |
| 125 | 1119 | const VVCPPS *pps = fc->ps.pps; | |
| 126 |
1/2✓ Branch 0 taken 4521 times.
✗ Branch 1 not taken.
|
4521 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 127 | int ret; | ||
| 128 | 4521 | VVCFrame *frame = &fc->DPB[i]; | |
| 129 | 4521 | VVCWindow *win = &frame->scaling_win; | |
| 130 |
2/2✓ Branch 0 taken 3402 times.
✓ Branch 1 taken 1119 times.
|
4521 | if (frame->frame->buf[0]) |
| 131 | 3402 | continue; | |
| 132 | |||
| 133 | 1119 | frame->sps = av_refstruct_ref_c(fc->ps.sps); | |
| 134 | 1119 | 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 1087 times.
|
1119 | 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 | 1119 | ret = ff_thread_get_buffer(s->avctx, frame->frame, AV_GET_BUFFER_FLAG_REF); | |
| 145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1119 times.
|
1119 | if (ret < 0) |
| 146 | ✗ | return NULL; | |
| 147 | |||
| 148 | 1119 | frame->rpl = av_refstruct_allocz(s->current_frame.nb_units * sizeof(RefPicListTab)); | |
| 149 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1119 times.
|
1119 | if (!frame->rpl) |
| 150 | ✗ | goto fail; | |
| 151 | 1119 | frame->nb_rpl_elems = s->current_frame.nb_units; | |
| 152 | |||
| 153 | 1119 | frame->tab_dmvr_mvf = av_refstruct_pool_get(fc->tab_dmvr_mvf_pool); | |
| 154 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1119 times.
|
1119 | if (!frame->tab_dmvr_mvf) |
| 155 | ✗ | goto fail; | |
| 156 | |||
| 157 | 1119 | frame->rpl_tab = av_refstruct_pool_get(fc->rpl_tab_pool); | |
| 158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1119 times.
|
1119 | if (!frame->rpl_tab) |
| 159 | ✗ | goto fail; | |
| 160 | 1119 | frame->ctb_count = pps->ctb_width * pps->ctb_height; | |
| 161 |
2/2✓ Branch 0 taken 56003 times.
✓ Branch 1 taken 1119 times.
|
57122 | for (int j = 0; j < frame->ctb_count; j++) |
| 162 | 56003 | frame->rpl_tab[j] = frame->rpl; | |
| 163 | |||
| 164 | 1119 | win->left_offset = pps->r->pps_scaling_win_left_offset * (1 << sps->hshift[CHROMA]); | |
| 165 | 1119 | win->right_offset = pps->r->pps_scaling_win_right_offset * (1 << sps->hshift[CHROMA]); | |
| 166 | 1119 | win->top_offset = pps->r->pps_scaling_win_top_offset * (1 << sps->vshift[CHROMA]); | |
| 167 | 1119 | win->bottom_offset = pps->r->pps_scaling_win_bottom_offset * (1 << sps->vshift[CHROMA]); | |
| 168 | 1119 | frame->ref_width = pps->r->pps_pic_width_in_luma_samples - win->left_offset - win->right_offset; | |
| 169 | 1119 | 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 1098 times.
|
1119 | 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 | 1119 | frame->progress = alloc_progress(); | |
| 180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1119 times.
|
1119 | if (!frame->progress) |
| 181 | ✗ | goto fail; | |
| 182 | |||
| 183 | 1119 | ret = ff_hwaccel_frame_priv_alloc(s->avctx, &frame->hwaccel_picture_private); | |
| 184 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1119 times.
|
1119 | if (ret < 0) |
| 185 | ✗ | goto fail; | |
| 186 | |||
| 187 | 1119 | 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 | 1102 | static void set_pict_type(AVFrame *frame, const VVCContext *s, const VVCFrameContext *fc) | |
| 197 | { | ||
| 198 | 1102 | bool has_b = false, has_inter = false; | |
| 199 | |||
| 200 |
6/6✓ Branch 0 taken 1095 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 992 times.
✓ Branch 3 taken 103 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 980 times.
|
1102 | if (IS_IRAP(s)) { |
| 201 | 122 | frame->pict_type = AV_PICTURE_TYPE_I; | |
| 202 | 122 | frame->flags |= AV_FRAME_FLAG_KEY; | |
| 203 | 122 | return; | |
| 204 | } | ||
| 205 | |||
| 206 |
2/2✓ Branch 0 taken 977 times.
✓ Branch 1 taken 3 times.
|
980 | 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 | 977 | const CodedBitstreamFragment *current = &s->current_frame; | |
| 209 |
4/4✓ Branch 0 taken 2428 times.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 1530 times.
✓ Branch 3 taken 898 times.
|
2507 | for (int i = 0; i < current->nb_units && !has_b; i++) { |
| 210 | 1530 | const CodedBitstreamUnit *unit = current->units + i; | |
| 211 |
3/4✓ Branch 0 taken 1530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 977 times.
✓ Branch 3 taken 553 times.
|
1530 | if (unit->content_ref && unit->type <= VVC_RSV_IRAP_11) { |
| 212 | 977 | const H266RawSliceHeader *rsh = unit->content_ref; | |
| 213 | 977 | has_inter |= !IS_I(rsh); | |
| 214 | 977 | has_b |= IS_B(rsh); | |
| 215 | } | ||
| 216 | } | ||
| 217 | } | ||
| 218 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 977 times.
|
980 | if (!has_inter) |
| 219 | 3 | frame->pict_type = AV_PICTURE_TYPE_I; | |
| 220 |
2/2✓ Branch 0 taken 951 times.
✓ Branch 1 taken 26 times.
|
977 | else if (has_b) |
| 221 | 951 | frame->pict_type = AV_PICTURE_TYPE_B; | |
| 222 | else | ||
| 223 | 26 | frame->pict_type = AV_PICTURE_TYPE_P; | |
| 224 | } | ||
| 225 | |||
| 226 | 1102 | int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, AVFrame **frame) | |
| 227 | { | ||
| 228 | 1102 | const VVCPH *ph= &fc->ps.ph; | |
| 229 | 1102 | const int poc = ph->poc; | |
| 230 | VVCFrame *ref; | ||
| 231 | |||
| 232 | /* check that this POC doesn't already exist */ | ||
| 233 |
2/2✓ Branch 0 taken 18734 times.
✓ Branch 1 taken 1102 times.
|
19836 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 234 | 18734 | VVCFrame *frame = &fc->DPB[i]; | |
| 235 | |||
| 236 |
4/4✓ Branch 0 taken 5154 times.
✓ Branch 1 taken 13580 times.
✓ Branch 2 taken 5045 times.
✓ Branch 3 taken 109 times.
|
18734 | if (frame->frame->buf[0] && frame->sequence == s->seq_decode && |
| 237 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5045 times.
|
5045 | 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 | 1102 | ref = alloc_frame(s, fc); | |
| 244 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1102 times.
|
1102 | if (!ref) |
| 245 | ✗ | return AVERROR(ENOMEM); | |
| 246 | |||
| 247 | 1102 | set_pict_type(ref->frame, s, fc); | |
| 248 | 1102 | *frame = ref->frame; | |
| 249 | 1102 | fc->ref = ref; | |
| 250 | |||
| 251 |
5/6✓ Branch 0 taken 901 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 886 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 886 times.
|
1102 | 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 1087 times.
✗ Branch 1 not taken.
|
1087 | else if (ph->r->ph_pic_output_flag) |
| 254 | 1087 | ref->flags = VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_SHORT_REF; | |
| 255 | |||
| 256 |
2/2✓ Branch 0 taken 1090 times.
✓ Branch 1 taken 12 times.
|
1102 | if (!ph->r->ph_non_ref_pic_flag) |
| 257 | 1090 | ref->flags |= VVC_FRAME_FLAG_SHORT_REF; | |
| 258 | |||
| 259 | 1102 | ref->poc = poc; | |
| 260 | 1102 | ref->sequence = s->seq_decode; | |
| 261 | 1102 | ref->frame->crop_left = fc->ps.pps->r->pps_conf_win_left_offset << fc->ps.sps->hshift[CHROMA]; | |
| 262 | 1102 | ref->frame->crop_right = fc->ps.pps->r->pps_conf_win_right_offset << fc->ps.sps->hshift[CHROMA]; | |
| 263 | 1102 | ref->frame->crop_top = fc->ps.pps->r->pps_conf_win_top_offset << fc->ps.sps->vshift[CHROMA]; | |
| 264 | 1102 | ref->frame->crop_bottom = fc->ps.pps->r->pps_conf_win_bottom_offset << fc->ps.sps->vshift[CHROMA]; | |
| 265 | |||
| 266 | 1102 | return 0; | |
| 267 | } | ||
| 268 | |||
| 269 | 1237 | int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush) | |
| 270 | { | ||
| 271 | 1237 | const VVCSPS *sps = fc->ps.sps; | |
| 272 | 116 | do { | |
| 273 | 1353 | int nb_output = 0; | |
| 274 | 1353 | int min_poc = INT_MAX; | |
| 275 | int min_idx, ret; | ||
| 276 | |||
| 277 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1353 times.
|
1353 | 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 23001 times.
✓ Branch 1 taken 1353 times.
|
24354 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 288 | 23001 | VVCFrame *frame = &fc->DPB[i]; | |
| 289 |
2/2✓ Branch 0 taken 5179 times.
✓ Branch 1 taken 17822 times.
|
23001 | if ((frame->flags & VVC_FRAME_FLAG_OUTPUT) && |
| 290 |
2/2✓ Branch 0 taken 4913 times.
✓ Branch 1 taken 266 times.
|
5179 | frame->sequence == s->seq_output) { |
| 291 | 4913 | nb_output++; | |
| 292 |
3/4✓ Branch 0 taken 2409 times.
✓ Branch 1 taken 2504 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2409 times.
|
4913 | if (frame->poc < min_poc || nb_output == 1) { |
| 293 | 2504 | min_poc = frame->poc; | |
| 294 | 2504 | min_idx = i; | |
| 295 | } | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | /* wait for more frames before output */ | ||
| 300 |
5/6✓ Branch 0 taken 1216 times.
✓ Branch 1 taken 137 times.
✓ Branch 2 taken 1059 times.
✓ Branch 3 taken 157 times.
✓ Branch 4 taken 1059 times.
✗ Branch 5 not taken.
|
1353 | if (!flush && s->seq_output == s->seq_decode && sps && |
| 301 |
2/2✓ Branch 0 taken 167 times.
✓ Branch 1 taken 892 times.
|
1059 | 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 1037 times.
✓ Branch 1 taken 149 times.
|
1186 | if (nb_output) { |
| 305 | 1037 | VVCFrame *frame = &fc->DPB[min_idx]; | |
| 306 | |||
| 307 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1037 times.
|
1037 | 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 1037 times.
|
1037 | ret = av_frame_ref(out, frame->needs_fg ? frame->frame_grain : frame->frame); |
| 311 | |||
| 312 |
2/4✓ Branch 0 taken 1037 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1037 times.
✗ Branch 3 not taken.
|
1037 | if (!ret && !(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN)) |
| 313 | 1037 | av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS); | |
| 314 | |||
| 315 |
2/2✓ Branch 0 taken 688 times.
✓ Branch 1 taken 349 times.
|
1037 | if (frame->flags & VVC_FRAME_FLAG_BUMPING) |
| 316 | 688 | ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_BUMPING); | |
| 317 | else | ||
| 318 | 349 | ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT); | |
| 319 | |||
| 320 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1037 times.
|
1037 | if (ret < 0) |
| 321 | ✗ | return ret; | |
| 322 | |||
| 323 | 1037 | av_log(s->avctx, AV_LOG_DEBUG, | |
| 324 | "Output frame with POC %d.\n", frame->poc); | ||
| 325 | 1037 | return 1; | |
| 326 | } | ||
| 327 | |||
| 328 |
2/2✓ Branch 0 taken 116 times.
✓ Branch 1 taken 33 times.
|
149 | if (s->seq_output != s->seq_decode) |
| 329 | 116 | s->seq_output = (s->seq_output + 1) & 0xff; | |
| 330 | else | ||
| 331 | 33 | break; | |
| 332 | } while (1); | ||
| 333 | 33 | return 0; | |
| 334 | } | ||
| 335 | |||
| 336 | 992 | void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc) | |
| 337 | { | ||
| 338 | 992 | const VVCSPS *sps = fc->ps.sps; | |
| 339 | 992 | const int poc = fc->ps.ph.poc; | |
| 340 | 992 | int dpb = 0; | |
| 341 | 992 | int min_poc = INT_MAX; | |
| 342 | |||
| 343 |
2/2✓ Branch 0 taken 16864 times.
✓ Branch 1 taken 992 times.
|
17856 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 344 | 16864 | VVCFrame *frame = &fc->DPB[i]; | |
| 345 |
2/2✓ Branch 0 taken 6103 times.
✓ Branch 1 taken 10761 times.
|
16864 | if ((frame->flags) && |
| 346 |
2/2✓ Branch 0 taken 5975 times.
✓ Branch 1 taken 128 times.
|
6103 | frame->sequence == s->seq_output && |
| 347 |
2/2✓ Branch 0 taken 5017 times.
✓ Branch 1 taken 958 times.
|
5975 | frame->poc != poc) { |
| 348 | 5017 | dpb++; | |
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 |
3/4✓ Branch 0 taken 992 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 473 times.
✓ Branch 3 taken 519 times.
|
992 | 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 8041 times.
✓ Branch 1 taken 473 times.
|
8514 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 354 | 8041 | VVCFrame *frame = &fc->DPB[i]; | |
| 355 |
2/2✓ Branch 0 taken 3246 times.
✓ Branch 1 taken 4795 times.
|
8041 | if ((frame->flags) && |
| 356 |
1/2✓ Branch 0 taken 3246 times.
✗ Branch 1 not taken.
|
3246 | frame->sequence == s->seq_output && |
| 357 |
2/2✓ Branch 0 taken 2773 times.
✓ Branch 1 taken 473 times.
|
3246 | frame->poc != poc) { |
| 358 |
4/4✓ Branch 0 taken 60 times.
✓ Branch 1 taken 2713 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 9 times.
|
2773 | 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 8041 times.
✓ Branch 1 taken 473 times.
|
8514 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 365 | 8041 | VVCFrame *frame = &fc->DPB[i]; | |
| 366 |
2/2✓ Branch 0 taken 2197 times.
✓ Branch 1 taken 5844 times.
|
8041 | if (frame->flags & VVC_FRAME_FLAG_OUTPUT && |
| 367 |
1/2✓ Branch 0 taken 2197 times.
✗ Branch 1 not taken.
|
2197 | frame->sequence == s->seq_output && |
| 368 |
2/2✓ Branch 0 taken 1993 times.
✓ Branch 1 taken 204 times.
|
2197 | frame->poc <= min_poc) { |
| 369 | 1993 | frame->flags |= VVC_FRAME_FLAG_BUMPING; | |
| 370 | } | ||
| 371 | } | ||
| 372 | |||
| 373 | 473 | dpb--; | |
| 374 | } | ||
| 375 | 992 | } | |
| 376 | |||
| 377 | 7583 | static VVCFrame *find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb) | |
| 378 | { | ||
| 379 |
2/2✓ Branch 0 taken 394 times.
✓ Branch 1 taken 7189 times.
|
7583 | const unsigned mask = use_msb ? ~0 : fc->ps.sps->max_pic_order_cnt_lsb - 1; |
| 380 | |||
| 381 |
2/2✓ Branch 0 taken 27652 times.
✓ Branch 1 taken 17 times.
|
27669 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 382 | 27652 | VVCFrame *ref = &fc->DPB[i]; | |
| 383 |
4/4✓ Branch 0 taken 24905 times.
✓ Branch 1 taken 2747 times.
✓ Branch 2 taken 23977 times.
✓ Branch 3 taken 928 times.
|
27652 | if (ref->frame->buf[0] && ref->sequence == s->seq_decode) { |
| 384 |
2/2✓ Branch 0 taken 7566 times.
✓ Branch 1 taken 16411 times.
|
23977 | if ((ref->poc & mask) == poc) |
| 385 | 7566 | return ref; | |
| 386 | } | ||
| 387 | } | ||
| 388 | 17 | return NULL; | |
| 389 | } | ||
| 390 | |||
| 391 | 25215 | static void mark_ref(VVCFrame *frame, int flag) | |
| 392 | { | ||
| 393 | 25215 | frame->flags &= ~(VVC_FRAME_FLAG_LONG_REF | VVC_FRAME_FLAG_SHORT_REF); | |
| 394 | 25215 | frame->flags |= flag; | |
| 395 | 25215 | } | |
| 396 | |||
| 397 | 17 | static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int poc) | |
| 398 | { | ||
| 399 | 17 | const VVCSPS *sps = fc->ps.sps; | |
| 400 | 17 | const VVCPPS *pps = fc->ps.pps; | |
| 401 | VVCFrame *frame; | ||
| 402 | |||
| 403 | 17 | frame = alloc_frame(s, fc); | |
| 404 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!frame) |
| 405 | ✗ | return NULL; | |
| 406 | |||
| 407 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | if (!s->avctx->hwaccel) { |
| 408 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!sps->pixel_shift) { |
| 409 | ✗ | for (int i = 0; frame->frame->buf[i]; i++) | |
| 410 | ✗ | memset(frame->frame->buf[i]->data, 1 << (sps->bit_depth - 1), | |
| 411 | ✗ | frame->frame->buf[i]->size); | |
| 412 | } else { | ||
| 413 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 17 times.
|
68 | for (int i = 0; frame->frame->data[i]; i++) |
| 414 |
2/2✓ Branch 0 taken 10688 times.
✓ Branch 1 taken 51 times.
|
10739 | for (int y = 0; y < (pps->height >> sps->vshift[i]); y++) { |
| 415 | 10688 | uint8_t *dst = frame->frame->data[i] + y * frame->frame->linesize[i]; | |
| 416 | 10688 | AV_WN16(dst, 1 << (sps->bit_depth - 1)); | |
| 417 | 10688 | av_memcpy_backptr(dst + 2, 2, 2*(pps->width >> sps->hshift[i]) - 2); | |
| 418 | } | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 422 | 17 | frame->poc = poc; | |
| 423 | 17 | frame->sequence = s->seq_decode; | |
| 424 | 17 | frame->flags = VVC_FRAME_FLAG_CORRUPT; | |
| 425 | |||
| 426 | 17 | ff_vvc_report_frame_finished(frame); | |
| 427 | |||
| 428 | 17 | return frame; | |
| 429 | } | ||
| 430 | |||
| 431 | #define CHECK_MAX(d) (frame->ref_##d * frame->sps->r->sps_pic_##d##_max_in_luma_samples >= ref->ref_##d * (frame->pps->r->pps_pic_##d##_in_luma_samples - max)) | ||
| 432 | #define CHECK_SAMPLES(d) (frame->pps->r->pps_pic_##d##_in_luma_samples == ref->pps->r->pps_pic_##d##_in_luma_samples) | ||
| 433 | 7583 | static int check_candidate_ref(const VVCFrame *frame, const VVCRefPic *refp) | |
| 434 | { | ||
| 435 | 7583 | const VVCFrame *ref = refp->ref; | |
| 436 | |||
| 437 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7575 times.
|
7583 | if (refp->is_scaled) { |
| 438 | 8 | const int max = FFMAX(8, frame->sps->min_cb_size_y); | |
| 439 | 16 | return frame->ref_width * 2 >= ref->ref_width && | |
| 440 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | frame->ref_height * 2 >= ref->ref_height && |
| 441 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | frame->ref_width <= ref->ref_width * 8 && |
| 442 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | frame->ref_height <= ref->ref_height * 8 && |
| 443 |
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); |
| 444 | } | ||
| 445 |
2/4✓ Branch 0 taken 7575 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7575 times.
✗ Branch 3 not taken.
|
7575 | return CHECK_SAMPLES(width) && CHECK_SAMPLES(height); |
| 446 | } | ||
| 447 | |||
| 448 | #define RPR_SCALE(f) (((ref->f << 14) + (fc->ref->f >> 1)) / fc->ref->f) | ||
| 449 | /* add a reference with the given poc to the list and mark it as used in DPB */ | ||
| 450 | 7583 | static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *list, | |
| 451 | int poc, int ref_flag, uint8_t use_msb) | ||
| 452 | { | ||
| 453 | 7583 | VVCFrame *ref = find_ref_idx(s, fc, poc, use_msb); | |
| 454 | 7583 | VVCRefPic *refp = &list->refs[list->nb_refs]; | |
| 455 | |||
| 456 |
2/4✓ Branch 0 taken 7583 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7583 times.
|
7583 | if (ref == fc->ref || list->nb_refs >= VVC_MAX_REF_ENTRIES) |
| 457 | ✗ | return AVERROR_INVALIDDATA; | |
| 458 | |||
| 459 |
6/8✓ Branch 0 taken 7583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7569 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 7523 times.
✓ Branch 5 taken 46 times.
✓ Branch 6 taken 7523 times.
✗ Branch 7 not taken.
|
7583 | if (!IS_CVSS(s)) { |
| 460 |
3/4✓ Branch 0 taken 7523 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 7504 times.
|
7523 | const bool ref_corrupt = !ref || (ref->flags & VVC_FRAME_FLAG_CORRUPT); |
| 461 |
2/2✓ Branch 0 taken 6660 times.
✓ Branch 1 taken 863 times.
|
14183 | const bool recovering = s->no_output_before_recovery_flag && |
| 462 |
3/4✓ Branch 0 taken 6588 times.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6588 times.
|
6660 | (IS_RASL(s) || !GDR_IS_RECOVERED(s)); |
| 463 | |||
| 464 |
3/4✓ Branch 0 taken 19 times.
✓ Branch 1 taken 7504 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
|
7523 | if (ref_corrupt && !recovering) { |
| 465 | ✗ | if (!(s->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) && | |
| 466 | ✗ | !(s->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL)) | |
| 467 | ✗ | return AVERROR_INVALIDDATA; | |
| 468 | |||
| 469 | ✗ | fc->ref->flags |= VVC_FRAME_FLAG_CORRUPT; | |
| 470 | } | ||
| 471 | } | ||
| 472 | |||
| 473 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 7566 times.
|
7583 | if (!ref) { |
| 474 | 17 | ref = generate_missing_ref(s, fc, poc); | |
| 475 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!ref) |
| 476 | ✗ | return AVERROR(ENOMEM); | |
| 477 | } | ||
| 478 | |||
| 479 | 7583 | refp->poc = poc; | |
| 480 | 7583 | refp->ref = ref; | |
| 481 | 7583 | refp->is_lt = ref_flag & VVC_FRAME_FLAG_LONG_REF; | |
| 482 | 22749 | refp->is_scaled = ref->sps->r->sps_num_subpics_minus1 != fc->ref->sps->r->sps_num_subpics_minus1|| | |
| 483 |
1/2✓ Branch 0 taken 7583 times.
✗ Branch 1 not taken.
|
7583 | memcmp(&ref->scaling_win, &fc->ref->scaling_win, sizeof(ref->scaling_win)) || |
| 484 |
3/4✓ Branch 0 taken 7583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7575 times.
✓ Branch 3 taken 8 times.
|
22741 | ref->pps->r->pps_pic_width_in_luma_samples != fc->ref->pps->r->pps_pic_width_in_luma_samples || |
| 485 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7575 times.
|
7575 | ref->pps->r->pps_pic_height_in_luma_samples != fc->ref->pps->r->pps_pic_height_in_luma_samples; |
| 486 | |||
| 487 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7583 times.
|
7583 | if (!check_candidate_ref(fc->ref, refp)) |
| 488 | ✗ | return AVERROR_INVALIDDATA; | |
| 489 | |||
| 490 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7575 times.
|
7583 | if (refp->is_scaled) { |
| 491 | 8 | refp->scale[0] = RPR_SCALE(ref_width); | |
| 492 | 8 | refp->scale[1] = RPR_SCALE(ref_height); | |
| 493 | } | ||
| 494 | 7583 | list->nb_refs++; | |
| 495 | |||
| 496 | 7583 | mark_ref(ref, ref_flag); | |
| 497 | 7583 | return 0; | |
| 498 | } | ||
| 499 | |||
| 500 | 1701 | static int init_slice_rpl(const VVCFrameContext *fc, SliceContext *sc) | |
| 501 | { | ||
| 502 | 1701 | VVCFrame *frame = fc->ref; | |
| 503 | 1701 | const VVCSH *sh = &sc->sh; | |
| 504 | |||
| 505 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1701 times.
|
1701 | if (sc->slice_idx >= frame->nb_rpl_elems) |
| 506 | ✗ | return AVERROR_INVALIDDATA; | |
| 507 | |||
| 508 |
2/2✓ Branch 0 taken 54110 times.
✓ Branch 1 taken 1701 times.
|
55811 | for (int i = 0; i < sh->num_ctus_in_curr_slice; i++) { |
| 509 | 54110 | const int rs = sh->ctb_addr_in_curr_slice[i]; | |
| 510 | 54110 | frame->rpl_tab[rs] = frame->rpl + sc->slice_idx; | |
| 511 | } | ||
| 512 | |||
| 513 | 1701 | sc->rpl = frame->rpl_tab[sh->ctb_addr_in_curr_slice[0]]->refPicList; | |
| 514 | |||
| 515 | 1701 | return 0; | |
| 516 | } | ||
| 517 | |||
| 518 | 7189 | static int delta_poc_st(const H266RefPicListStruct *rpls, | |
| 519 | const int lx, const int i, const VVCSPS *sps) | ||
| 520 | { | ||
| 521 | 7189 | int abs_delta_poc_st = rpls->abs_delta_poc_st[i]; | |
| 522 |
4/4✓ Branch 0 taken 6670 times.
✓ Branch 1 taken 519 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 447 times.
|
7189 | if (!((sps->r->sps_weighted_pred_flag || |
| 523 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6670 times.
|
6670 | sps->r->sps_weighted_bipred_flag) && i != 0)) |
| 524 | 6742 | abs_delta_poc_st++; | |
| 525 | 7189 | return (1 - 2 * rpls->strp_entry_sign_flag[i]) * abs_delta_poc_st; | |
| 526 | } | ||
| 527 | |||
| 528 | 394 | static int poc_lt(int *prev_delta_poc_msb, const int poc, const H266RefPicLists *ref_lists, | |
| 529 | const int lx, const int j, const int max_poc_lsb) | ||
| 530 | { | ||
| 531 | 394 | const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx; | |
| 532 |
1/2✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
|
394 | int lt_poc = rpls->ltrp_in_header_flag ? ref_lists->poc_lsb_lt[lx][j] : rpls->rpls_poc_lsb_lt[j]; |
| 533 | |||
| 534 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 394 times.
|
394 | if (ref_lists->delta_poc_msb_cycle_present_flag[lx][j]) { |
| 535 | ✗ | const uint32_t delta = ref_lists->delta_poc_msb_cycle_lt[lx][j] + *prev_delta_poc_msb; | |
| 536 | ✗ | lt_poc += poc - delta * max_poc_lsb - (poc & (max_poc_lsb - 1)); | |
| 537 | ✗ | *prev_delta_poc_msb = delta; | |
| 538 | } | ||
| 539 | 394 | return lt_poc; | |
| 540 | } | ||
| 541 | |||
| 542 | 1701 | int ff_vvc_slice_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc) | |
| 543 | { | ||
| 544 | 1701 | const VVCSPS *sps = fc->ps.sps; | |
| 545 | 1701 | const H266RawPPS *pps = fc->ps.pps->r; | |
| 546 | 1701 | const VVCPH *ph = &fc->ps.ph; | |
| 547 | 1701 | const H266RawSliceHeader *rsh = sc->sh.r; | |
| 548 | 1701 | const int max_poc_lsb = sps->max_pic_order_cnt_lsb; | |
| 549 | 1701 | const H266RefPicLists *ref_lists = | |
| 550 |
2/2✓ Branch 0 taken 253 times.
✓ Branch 1 taken 1448 times.
|
1701 | pps->pps_rpl_info_in_ph_flag ? &ph->r->ph_ref_pic_lists : &rsh->sh_ref_pic_lists; |
| 551 | 1701 | int ret = 0; | |
| 552 | |||
| 553 | 1701 | ret = init_slice_rpl(fc, sc); | |
| 554 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1701 times.
|
1701 | if (ret < 0) |
| 555 | ✗ | return ret; | |
| 556 | |||
| 557 |
2/2✓ Branch 0 taken 3402 times.
✓ Branch 1 taken 1701 times.
|
5103 | for (int lx = L0; lx <= L1; lx++) { |
| 558 | 3402 | const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx; | |
| 559 | 3402 | RefPicList *rpl = sc->rpl + lx; | |
| 560 | 3402 | int poc_base = ph->poc; | |
| 561 | 3402 | int prev_delta_poc_msb = 0; | |
| 562 | |||
| 563 | 3402 | rpl->nb_refs = 0; | |
| 564 |
2/2✓ Branch 0 taken 7583 times.
✓ Branch 1 taken 3402 times.
|
10985 | for (int i = 0, j = 0; i < rpls->num_ref_entries; i++) { |
| 565 | int poc; | ||
| 566 |
1/2✓ Branch 0 taken 7583 times.
✗ Branch 1 not taken.
|
7583 | if (!rpls->inter_layer_ref_pic_flag[i]) { |
| 567 | 7583 | int use_msb = 1; | |
| 568 | int ref_flag; | ||
| 569 |
2/2✓ Branch 0 taken 7189 times.
✓ Branch 1 taken 394 times.
|
7583 | if (rpls->st_ref_pic_flag[i]) { |
| 570 | 7189 | poc = poc_base + delta_poc_st(rpls, lx, i, sps); | |
| 571 | 7189 | poc_base = poc; | |
| 572 | 7189 | ref_flag = VVC_FRAME_FLAG_SHORT_REF; | |
| 573 | } else { | ||
| 574 | 394 | use_msb = ref_lists->delta_poc_msb_cycle_present_flag[lx][j]; | |
| 575 | 394 | poc = poc_lt(&prev_delta_poc_msb, ph->poc, ref_lists, lx, j, max_poc_lsb); | |
| 576 | 394 | ref_flag = VVC_FRAME_FLAG_LONG_REF; | |
| 577 | 394 | j++; | |
| 578 | } | ||
| 579 | 7583 | ret = add_candidate_ref(s, fc, rpl, poc, ref_flag, use_msb); | |
| 580 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7583 times.
|
7583 | if (ret < 0) |
| 581 | ✗ | return ret; | |
| 582 | } else { | ||
| 583 | // OPI_B_3.bit and VPS_A_3.bit should cover this | ||
| 584 | ✗ | avpriv_report_missing_feature(fc->log_ctx, "Inter layer ref"); | |
| 585 | ✗ | ret = AVERROR_PATCHWELCOME; | |
| 586 | ✗ | return ret; | |
| 587 | } | ||
| 588 | } | ||
| 589 |
2/2✓ Branch 0 taken 3124 times.
✓ Branch 1 taken 278 times.
|
3402 | if (ph->r->ph_temporal_mvp_enabled_flag && |
| 590 |
2/2✓ Branch 0 taken 1562 times.
✓ Branch 1 taken 1562 times.
|
3124 | (!rsh->sh_collocated_from_l0_flag) == lx && |
| 591 |
1/2✓ Branch 0 taken 1562 times.
✗ Branch 1 not taken.
|
1562 | rsh->sh_collocated_ref_idx < rpl->nb_refs) { |
| 592 | 1562 | const VVCRefPic *refp = rpl->refs + rsh->sh_collocated_ref_idx; | |
| 593 |
2/4✓ Branch 0 taken 1562 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1562 times.
|
1562 | if (refp->is_scaled || refp->ref->sps->ctb_log2_size_y != sps->ctb_log2_size_y) |
| 594 | ✗ | return AVERROR_INVALIDDATA; | |
| 595 | 1562 | fc->ref->collocated_ref = refp->ref; | |
| 596 | } | ||
| 597 | } | ||
| 598 | 1701 | return 0; | |
| 599 | } | ||
| 600 | |||
| 601 | 1102 | int ff_vvc_frame_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc) | |
| 602 | { | ||
| 603 | 1102 | int ret = 0; | |
| 604 | |||
| 605 | /* clear the reference flags on all frames except the current one */ | ||
| 606 |
2/2✓ Branch 0 taken 18734 times.
✓ Branch 1 taken 1102 times.
|
19836 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 607 | 18734 | VVCFrame *frame = &fc->DPB[i]; | |
| 608 | |||
| 609 |
2/2✓ Branch 0 taken 1102 times.
✓ Branch 1 taken 17632 times.
|
18734 | if (frame == fc->ref) |
| 610 | 1102 | continue; | |
| 611 | |||
| 612 | 17632 | mark_ref(frame, 0); | |
| 613 | } | ||
| 614 | |||
| 615 |
1/2✓ Branch 1 taken 1102 times.
✗ Branch 2 not taken.
|
1102 | if ((ret = ff_vvc_slice_rpl(s, fc, sc)) < 0) |
| 616 | ✗ | goto fail; | |
| 617 | |||
| 618 | 1102 | fail: | |
| 619 | /* release any frames that are now unused */ | ||
| 620 |
2/2✓ Branch 0 taken 18734 times.
✓ Branch 1 taken 1102 times.
|
19836 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
| 621 | 18734 | ff_vvc_unref_frame(fc, &fc->DPB[i], 0); | |
| 622 | 1102 | return ret; | |
| 623 | } | ||
| 624 | |||
| 625 | 1119 | void ff_vvc_report_frame_finished(VVCFrame *frame) | |
| 626 | { | ||
| 627 | 1119 | ff_vvc_report_progress(frame, VVC_PROGRESS_MV, INT_MAX); | |
| 628 | 1119 | ff_vvc_report_progress(frame, VVC_PROGRESS_PIXEL, INT_MAX); | |
| 629 | 1119 | } | |
| 630 | |||
| 631 | 103190 | static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l) | |
| 632 | { | ||
| 633 | 103190 | return p->progress[l->vp] > l->y; | |
| 634 | } | ||
| 635 | |||
| 636 | ✗ | static void add_listener(VVCProgressListener **prev, VVCProgressListener *l) | |
| 637 | { | ||
| 638 | ✗ | l->next = *prev; | |
| 639 | ✗ | *prev = l; | |
| 640 | ✗ | } | |
| 641 | |||
| 642 | ✗ | static VVCProgressListener* remove_listener(VVCProgressListener **prev, VVCProgressListener *l) | |
| 643 | { | ||
| 644 | ✗ | *prev = l->next; | |
| 645 | ✗ | l->next = NULL; | |
| 646 | ✗ | return l; | |
| 647 | } | ||
| 648 | |||
| 649 | 10137 | static VVCProgressListener* get_done_listener(FrameProgress *p, const VVCProgress vp) | |
| 650 | { | ||
| 651 | 10137 | VVCProgressListener *list = NULL; | |
| 652 | 10137 | VVCProgressListener **prev = &p->listener[vp]; | |
| 653 | |||
| 654 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10137 times.
|
10137 | while (*prev) { |
| 655 | ✗ | if (is_progress_done(p, *prev)) { | |
| 656 | ✗ | VVCProgressListener *l = remove_listener(prev, *prev); | |
| 657 | ✗ | add_listener(&list, l); | |
| 658 | } else { | ||
| 659 | ✗ | prev = &(*prev)->next; | |
| 660 | } | ||
| 661 | } | ||
| 662 | 10137 | return list; | |
| 663 | } | ||
| 664 | |||
| 665 | 12341 | void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y) | |
| 666 | { | ||
| 667 | 12341 | FrameProgress *p = frame->progress; | |
| 668 | 12341 | VVCProgressListener *l = NULL; | |
| 669 | |||
| 670 | 12341 | ff_mutex_lock(&p->lock); | |
| 671 |
2/2✓ Branch 0 taken 10137 times.
✓ Branch 1 taken 2204 times.
|
12341 | if (p->progress[vp] < y) { |
| 672 | // Due to the nature of thread scheduling, later progress may reach this point before earlier progress. | ||
| 673 | // Therefore, we only update the progress when p->progress[vp] < y. | ||
| 674 | 10137 | p->progress[vp] = y; | |
| 675 | 10137 | l = get_done_listener(p, vp); | |
| 676 | 10137 | ff_cond_signal(&p->cond); | |
| 677 | } | ||
| 678 | 12341 | ff_mutex_unlock(&p->lock); | |
| 679 | |||
| 680 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12341 times.
|
12341 | while (l) { |
| 681 | ✗ | l->progress_done(l); | |
| 682 | ✗ | l = l->next; | |
| 683 | } | ||
| 684 | 12341 | } | |
| 685 | |||
| 686 | 103190 | void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l) | |
| 687 | { | ||
| 688 | 103190 | FrameProgress *p = frame->progress; | |
| 689 | |||
| 690 | 103190 | ff_mutex_lock(&p->lock); | |
| 691 | |||
| 692 |
1/2✓ Branch 1 taken 103190 times.
✗ Branch 2 not taken.
|
103190 | if (is_progress_done(p, l)) { |
| 693 | 103190 | ff_mutex_unlock(&p->lock); | |
| 694 | 103190 | l->progress_done(l); | |
| 695 | } else { | ||
| 696 | ✗ | add_listener(p->listener + l->vp, l); | |
| 697 | ✗ | ff_mutex_unlock(&p->lock); | |
| 698 | } | ||
| 699 | 103190 | } | |
| 700 |