| 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 | 51786 | 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 51786 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39668 times.
✓ Branch 3 taken 12118 times.
|
51786 | if (!frame->frame || !frame->frame->buf[0]) |
| 48 | 39668 | return; | |
| 49 | |||
| 50 | 12118 | frame->flags &= ~flags; | |
| 51 |
2/2✓ Branch 0 taken 6124 times.
✓ Branch 1 taken 5994 times.
|
12118 | if (!(frame->flags & ~VVC_FRAME_FLAG_CORRUPT)) |
| 52 | 6124 | frame->flags = 0; | |
| 53 |
2/2✓ Branch 0 taken 6124 times.
✓ Branch 1 taken 5994 times.
|
12118 | if (!frame->flags) { |
| 54 | 6124 | av_frame_unref(frame->frame); | |
| 55 | |||
| 56 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6124 times.
|
6124 | if (frame->needs_fg) { |
| 57 | ✗ | av_frame_unref(frame->frame_grain); | |
| 58 | ✗ | frame->needs_fg = 0; | |
| 59 | } | ||
| 60 | |||
| 61 | 6124 | av_refstruct_unref(&frame->sps); | |
| 62 | 6124 | av_refstruct_unref(&frame->pps); | |
| 63 | 6124 | av_refstruct_unref(&frame->progress); | |
| 64 | |||
| 65 | 6124 | av_refstruct_unref(&frame->tab_dmvr_mvf); | |
| 66 | |||
| 67 | 6124 | av_refstruct_unref(&frame->rpl); | |
| 68 | 6124 | frame->nb_rpl_elems = 0; | |
| 69 | 6124 | av_refstruct_unref(&frame->rpl_tab); | |
| 70 | |||
| 71 | 6124 | frame->collocated_ref = NULL; | |
| 72 | 6124 | av_refstruct_unref(&frame->hwaccel_picture_private); | |
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | 3060068 | const RefPicList *ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0) | |
| 77 | { | ||
| 78 | 3060068 | const int x_cb = x0 >> fc->ps.sps->ctb_log2_size_y; | |
| 79 | 3060068 | const int y_cb = y0 >> fc->ps.sps->ctb_log2_size_y; | |
| 80 | 3060068 | const int pic_width_cb = fc->ps.pps->ctb_width; | |
| 81 | 3060068 | const int ctb_addr_rs = y_cb * pic_width_cb + x_cb; | |
| 82 | |||
| 83 | 3060068 | return (const RefPicList *)ref->rpl_tab[ctb_addr_rs]; | |
| 84 | } | ||
| 85 | |||
| 86 | 103 | void ff_vvc_clear_refs(VVCFrameContext *fc) | |
| 87 | { | ||
| 88 |
2/2✓ Branch 0 taken 1751 times.
✓ Branch 1 taken 103 times.
|
1854 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
| 89 | 1751 | ff_vvc_unref_frame(fc, &fc->DPB[i], | |
| 90 | VVC_FRAME_FLAG_SHORT_REF | VVC_FRAME_FLAG_LONG_REF); | ||
| 91 | 103 | } | |
| 92 | |||
| 93 | 94 | void ff_vvc_flush_dpb(VVCFrameContext *fc) | |
| 94 | { | ||
| 95 |
2/2✓ Branch 0 taken 1598 times.
✓ Branch 1 taken 94 times.
|
1692 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
| 96 | 1598 | ff_vvc_unref_frame(fc, &fc->DPB[i], ~0); | |
| 97 | 94 | } | |
| 98 | |||
| 99 | 1083 | static void free_progress(AVRefStructOpaque unused, void *obj) | |
| 100 | { | ||
| 101 | 1083 | FrameProgress *p = (FrameProgress *)obj; | |
| 102 | |||
| 103 |
1/2✓ Branch 0 taken 1083 times.
✗ Branch 1 not taken.
|
1083 | if (p->has_cond) |
| 104 | 1083 | ff_cond_destroy(&p->cond); | |
| 105 |
1/2✓ Branch 0 taken 1083 times.
✗ Branch 1 not taken.
|
1083 | if (p->has_lock) |
| 106 | 1083 | ff_mutex_destroy(&p->lock); | |
| 107 | 1083 | } | |
| 108 | |||
| 109 | 1083 | static FrameProgress *alloc_progress(void) | |
| 110 | { | ||
| 111 | 1083 | FrameProgress *p = av_refstruct_alloc_ext(sizeof(*p), 0, NULL, free_progress); | |
| 112 | |||
| 113 |
1/2✓ Branch 0 taken 1083 times.
✗ Branch 1 not taken.
|
1083 | if (p) { |
| 114 | 1083 | p->has_lock = !ff_mutex_init(&p->lock, NULL); | |
| 115 | 1083 | p->has_cond = !ff_cond_init(&p->cond, NULL); | |
| 116 |
2/4✓ Branch 0 taken 1083 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1083 times.
|
1083 | if (!p->has_lock || !p->has_cond) |
| 117 | ✗ | av_refstruct_unref(&p); | |
| 118 | } | ||
| 119 | 1083 | return p; | |
| 120 | } | ||
| 121 | |||
| 122 | 1083 | static VVCFrame *alloc_frame(VVCContext *s, VVCFrameContext *fc) | |
| 123 | { | ||
| 124 | 1083 | const VVCSPS *sps = fc->ps.sps; | |
| 125 | 1083 | const VVCPPS *pps = fc->ps.pps; | |
| 126 |
1/2✓ Branch 0 taken 4409 times.
✗ Branch 1 not taken.
|
4409 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 127 | int ret; | ||
| 128 | 4409 | VVCFrame *frame = &fc->DPB[i]; | |
| 129 | 4409 | VVCWindow *win = &frame->scaling_win; | |
| 130 |
2/2✓ Branch 0 taken 3326 times.
✓ Branch 1 taken 1083 times.
|
4409 | if (frame->frame->buf[0]) |
| 131 | 3326 | continue; | |
| 132 | |||
| 133 | 1083 | frame->sps = av_refstruct_ref_c(fc->ps.sps); | |
| 134 | 1083 | frame->pps = av_refstruct_ref_c(fc->ps.pps); | |
| 135 | |||
| 136 | // Add LCEVC SEI metadata here, as it's needed in get_buffer() | ||
| 137 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1083 times.
|
1083 | if (fc->sei.common.lcevc.info) { |
| 138 | ✗ | HEVCSEILCEVC *lcevc = &fc->sei.common.lcevc; | |
| 139 | ✗ | ret = ff_frame_new_side_data_from_buf(s->avctx, frame->frame, | |
| 140 | AV_FRAME_DATA_LCEVC, &lcevc->info); | ||
| 141 | ✗ | if (ret < 0) | |
| 142 | ✗ | goto fail; | |
| 143 | } | ||
| 144 | |||
| 145 | 1083 | ret = ff_thread_get_buffer(s->avctx, frame->frame, AV_GET_BUFFER_FLAG_REF); | |
| 146 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1083 times.
|
1083 | if (ret < 0) |
| 147 | ✗ | return NULL; | |
| 148 | |||
| 149 | 1083 | frame->rpl = av_refstruct_allocz(s->current_frame.nb_units * sizeof(RefPicListTab)); | |
| 150 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1083 times.
|
1083 | if (!frame->rpl) |
| 151 | ✗ | goto fail; | |
| 152 | 1083 | frame->nb_rpl_elems = s->current_frame.nb_units; | |
| 153 | |||
| 154 | 1083 | frame->tab_dmvr_mvf = av_refstruct_pool_get(fc->tab_dmvr_mvf_pool); | |
| 155 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1083 times.
|
1083 | if (!frame->tab_dmvr_mvf) |
| 156 | ✗ | goto fail; | |
| 157 | |||
| 158 | 1083 | frame->rpl_tab = av_refstruct_pool_get(fc->rpl_tab_pool); | |
| 159 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1083 times.
|
1083 | if (!frame->rpl_tab) |
| 160 | ✗ | goto fail; | |
| 161 | 1083 | frame->ctb_count = pps->ctb_width * pps->ctb_height; | |
| 162 |
2/2✓ Branch 0 taken 53693 times.
✓ Branch 1 taken 1083 times.
|
54776 | for (int j = 0; j < frame->ctb_count; j++) |
| 163 | 53693 | frame->rpl_tab[j] = frame->rpl; | |
| 164 | |||
| 165 | 1083 | win->left_offset = pps->r->pps_scaling_win_left_offset * (1 << sps->hshift[CHROMA]); | |
| 166 | 1083 | win->right_offset = pps->r->pps_scaling_win_right_offset * (1 << sps->hshift[CHROMA]); | |
| 167 | 1083 | win->top_offset = pps->r->pps_scaling_win_top_offset * (1 << sps->vshift[CHROMA]); | |
| 168 | 1083 | win->bottom_offset = pps->r->pps_scaling_win_bottom_offset * (1 << sps->vshift[CHROMA]); | |
| 169 | 1083 | frame->ref_width = pps->r->pps_pic_width_in_luma_samples - win->left_offset - win->right_offset; | |
| 170 | 1083 | frame->ref_height = pps->r->pps_pic_height_in_luma_samples - win->bottom_offset - win->top_offset; | |
| 171 | |||
| 172 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1063 times.
|
1083 | if (fc->sei.frame_field_info.present) { |
| 173 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
|
20 | if (fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD) |
| 174 | 9 | frame->frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; | |
| 175 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 9 times.
|
20 | if (fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_TOP_FIELD || |
| 176 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | fc->sei.frame_field_info.picture_struct == AV_PICTURE_STRUCTURE_BOTTOM_FIELD) |
| 177 | 20 | frame->frame->flags |= AV_FRAME_FLAG_INTERLACED; | |
| 178 | } | ||
| 179 | |||
| 180 | 1083 | frame->progress = alloc_progress(); | |
| 181 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1083 times.
|
1083 | if (!frame->progress) |
| 182 | ✗ | goto fail; | |
| 183 | |||
| 184 | 1083 | ret = ff_hwaccel_frame_priv_alloc(s->avctx, &frame->hwaccel_picture_private); | |
| 185 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1083 times.
|
1083 | if (ret < 0) |
| 186 | ✗ | goto fail; | |
| 187 | |||
| 188 | 1083 | return frame; | |
| 189 | ✗ | fail: | |
| 190 | ✗ | ff_vvc_unref_frame(fc, frame, ~0); | |
| 191 | ✗ | return NULL; | |
| 192 | } | ||
| 193 | ✗ | av_log(s->avctx, AV_LOG_ERROR, "Error allocating frame, DPB full.\n"); | |
| 194 | ✗ | return NULL; | |
| 195 | } | ||
| 196 | |||
| 197 | 1066 | static void set_pict_type(AVFrame *frame, const VVCContext *s, const VVCFrameContext *fc) | |
| 198 | { | ||
| 199 | 1066 | bool has_b = false, has_inter = false; | |
| 200 | |||
| 201 |
6/6✓ Branch 0 taken 1059 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 963 times.
✓ Branch 3 taken 96 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 951 times.
|
1066 | if (IS_IRAP(s)) { |
| 202 | 115 | frame->pict_type = AV_PICTURE_TYPE_I; | |
| 203 | 115 | frame->flags |= AV_FRAME_FLAG_KEY; | |
| 204 | 115 | return; | |
| 205 | } | ||
| 206 | |||
| 207 |
2/2✓ Branch 0 taken 948 times.
✓ Branch 1 taken 3 times.
|
951 | if (fc->ps.ph.r->ph_inter_slice_allowed_flag) { |
| 208 | // At this point, fc->slices is not fully initialized; we need to inspect the CBS directly. | ||
| 209 | 948 | const CodedBitstreamFragment *current = &s->current_frame; | |
| 210 |
4/4✓ Branch 0 taken 2264 times.
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 1366 times.
✓ Branch 3 taken 898 times.
|
2314 | for (int i = 0; i < current->nb_units && !has_b; i++) { |
| 211 | 1366 | const CodedBitstreamUnit *unit = current->units + i; | |
| 212 |
3/4✓ Branch 0 taken 1366 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 948 times.
✓ Branch 3 taken 418 times.
|
1366 | if (unit->content_ref && unit->type <= VVC_RSV_IRAP_11) { |
| 213 | 948 | const H266RawSliceHeader *rsh = unit->content_ref; | |
| 214 | 948 | has_inter |= !IS_I(rsh); | |
| 215 | 948 | has_b |= IS_B(rsh); | |
| 216 | } | ||
| 217 | } | ||
| 218 | } | ||
| 219 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 948 times.
|
951 | if (!has_inter) |
| 220 | 3 | frame->pict_type = AV_PICTURE_TYPE_I; | |
| 221 |
2/2✓ Branch 0 taken 926 times.
✓ Branch 1 taken 22 times.
|
948 | else if (has_b) |
| 222 | 926 | frame->pict_type = AV_PICTURE_TYPE_B; | |
| 223 | else | ||
| 224 | 22 | frame->pict_type = AV_PICTURE_TYPE_P; | |
| 225 | } | ||
| 226 | |||
| 227 | 1066 | int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, AVFrame **frame) | |
| 228 | { | ||
| 229 | 1066 | const VVCPH *ph= &fc->ps.ph; | |
| 230 | 1066 | const int poc = ph->poc; | |
| 231 | VVCFrame *ref; | ||
| 232 | |||
| 233 | /* check that this POC doesn't already exist */ | ||
| 234 |
2/2✓ Branch 0 taken 18122 times.
✓ Branch 1 taken 1066 times.
|
19188 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 235 | 18122 | VVCFrame *frame = &fc->DPB[i]; | |
| 236 | |||
| 237 |
4/4✓ Branch 0 taken 5016 times.
✓ Branch 1 taken 13106 times.
✓ Branch 2 taken 4907 times.
✓ Branch 3 taken 109 times.
|
18122 | if (frame->frame->buf[0] && frame->sequence == s->seq_decode && |
| 238 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4907 times.
|
4907 | frame->poc == poc) { |
| 239 | ✗ | av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence: %d.\n", poc); | |
| 240 | ✗ | return AVERROR_INVALIDDATA; | |
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | 1066 | ref = alloc_frame(s, fc); | |
| 245 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1066 times.
|
1066 | if (!ref) |
| 246 | ✗ | return AVERROR(ENOMEM); | |
| 247 | |||
| 248 | 1066 | set_pict_type(ref->frame, s, fc); | |
| 249 | 1066 | *frame = ref->frame; | |
| 250 | 1066 | fc->ref = ref; | |
| 251 | |||
| 252 |
5/6✓ Branch 0 taken 865 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 850 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 850 times.
|
1066 | if (s->no_output_before_recovery_flag && (IS_RASL(s) || !GDR_IS_RECOVERED(s))) |
| 253 | 15 | ref->flags = VVC_FRAME_FLAG_SHORT_REF; | |
| 254 |
1/2✓ Branch 0 taken 1051 times.
✗ Branch 1 not taken.
|
1051 | else if (ph->r->ph_pic_output_flag) |
| 255 | 1051 | ref->flags = VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_SHORT_REF; | |
| 256 | |||
| 257 |
2/2✓ Branch 0 taken 1054 times.
✓ Branch 1 taken 12 times.
|
1066 | if (!ph->r->ph_non_ref_pic_flag) |
| 258 | 1054 | ref->flags |= VVC_FRAME_FLAG_SHORT_REF; | |
| 259 | |||
| 260 | 1066 | ref->poc = poc; | |
| 261 | 1066 | ref->sequence = s->seq_decode; | |
| 262 | 1066 | ref->frame->crop_left = fc->ps.pps->r->pps_conf_win_left_offset << fc->ps.sps->hshift[CHROMA]; | |
| 263 | 1066 | ref->frame->crop_right = fc->ps.pps->r->pps_conf_win_right_offset << fc->ps.sps->hshift[CHROMA]; | |
| 264 | 1066 | ref->frame->crop_top = fc->ps.pps->r->pps_conf_win_top_offset << fc->ps.sps->vshift[CHROMA]; | |
| 265 | 1066 | ref->frame->crop_bottom = fc->ps.pps->r->pps_conf_win_bottom_offset << fc->ps.sps->vshift[CHROMA]; | |
| 266 | |||
| 267 | 1066 | return 0; | |
| 268 | } | ||
| 269 | |||
| 270 | 1197 | int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush) | |
| 271 | { | ||
| 272 | 1197 | const VVCSPS *sps = fc->ps.sps; | |
| 273 | 109 | do { | |
| 274 | 1306 | int nb_output = 0; | |
| 275 | 1306 | int min_poc = INT_MAX; | |
| 276 | int min_idx, ret; | ||
| 277 | |||
| 278 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1306 times.
|
1306 | if (no_output_of_prior_pics_flag) { |
| 279 | ✗ | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { | |
| 280 | ✗ | VVCFrame *frame = &fc->DPB[i]; | |
| 281 | ✗ | if (!(frame->flags & VVC_FRAME_FLAG_BUMPING) && frame->poc != fc->ps.ph.poc && | |
| 282 | ✗ | frame->sequence == s->seq_output) { | |
| 283 | ✗ | ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT); | |
| 284 | } | ||
| 285 | } | ||
| 286 | } | ||
| 287 | |||
| 288 |
2/2✓ Branch 0 taken 22202 times.
✓ Branch 1 taken 1306 times.
|
23508 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 289 | 22202 | VVCFrame *frame = &fc->DPB[i]; | |
| 290 |
2/2✓ Branch 0 taken 5046 times.
✓ Branch 1 taken 17156 times.
|
22202 | if ((frame->flags & VVC_FRAME_FLAG_OUTPUT) && |
| 291 |
2/2✓ Branch 0 taken 4787 times.
✓ Branch 1 taken 259 times.
|
5046 | frame->sequence == s->seq_output) { |
| 292 | 4787 | nb_output++; | |
| 293 |
3/4✓ Branch 0 taken 2353 times.
✓ Branch 1 taken 2434 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2353 times.
|
4787 | if (frame->poc < min_poc || nb_output == 1) { |
| 294 | 2434 | min_poc = frame->poc; | |
| 295 | 2434 | min_idx = i; | |
| 296 | } | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | /* wait for more frames before output */ | ||
| 301 |
5/6✓ Branch 0 taken 1173 times.
✓ Branch 1 taken 133 times.
✓ Branch 2 taken 1023 times.
✓ Branch 3 taken 150 times.
✓ Branch 4 taken 1023 times.
✗ Branch 5 not taken.
|
1306 | if (!flush && s->seq_output == s->seq_decode && sps && |
| 302 |
2/2✓ Branch 0 taken 158 times.
✓ Branch 1 taken 865 times.
|
1023 | nb_output <= sps->r->sps_dpb_params.dpb_max_num_reorder_pics[sps->r->sps_max_sublayers_minus1]) |
| 303 | 158 | return 0; | |
| 304 | |||
| 305 |
2/2✓ Branch 0 taken 1007 times.
✓ Branch 1 taken 141 times.
|
1148 | if (nb_output) { |
| 306 | 1007 | VVCFrame *frame = &fc->DPB[min_idx]; | |
| 307 | |||
| 308 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1007 times.
|
1007 | if (frame->flags & VVC_FRAME_FLAG_CORRUPT) |
| 309 | ✗ | frame->frame->flags |= AV_FRAME_FLAG_CORRUPT; | |
| 310 | |||
| 311 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1007 times.
|
1007 | ret = av_frame_ref(out, frame->needs_fg ? frame->frame_grain : frame->frame); |
| 312 | |||
| 313 |
2/4✓ Branch 0 taken 1007 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1007 times.
✗ Branch 3 not taken.
|
1007 | if (!ret && !(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN)) |
| 314 | 1007 | av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS); | |
| 315 | |||
| 316 |
2/2✓ Branch 0 taken 660 times.
✓ Branch 1 taken 347 times.
|
1007 | if (frame->flags & VVC_FRAME_FLAG_BUMPING) |
| 317 | 660 | ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_BUMPING); | |
| 318 | else | ||
| 319 | 347 | ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT); | |
| 320 | |||
| 321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1007 times.
|
1007 | if (ret < 0) |
| 322 | ✗ | return ret; | |
| 323 | |||
| 324 | 1007 | av_log(s->avctx, AV_LOG_DEBUG, | |
| 325 | "Output frame with POC %d.\n", frame->poc); | ||
| 326 | 1007 | return 1; | |
| 327 | } | ||
| 328 | |||
| 329 |
2/2✓ Branch 0 taken 109 times.
✓ Branch 1 taken 32 times.
|
141 | if (s->seq_output != s->seq_decode) |
| 330 | 109 | s->seq_output = (s->seq_output + 1) & 0xff; | |
| 331 | else | ||
| 332 | 32 | break; | |
| 333 | } while (1); | ||
| 334 | 32 | return 0; | |
| 335 | } | ||
| 336 | |||
| 337 | 963 | void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc) | |
| 338 | { | ||
| 339 | 963 | const VVCSPS *sps = fc->ps.sps; | |
| 340 | 963 | const int poc = fc->ps.ph.poc; | |
| 341 | 963 | int dpb = 0; | |
| 342 | 963 | int min_poc = INT_MAX; | |
| 343 | |||
| 344 |
2/2✓ Branch 0 taken 16371 times.
✓ Branch 1 taken 963 times.
|
17334 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 345 | 16371 | VVCFrame *frame = &fc->DPB[i]; | |
| 346 |
2/2✓ Branch 0 taken 5936 times.
✓ Branch 1 taken 10435 times.
|
16371 | if ((frame->flags) && |
| 347 |
2/2✓ Branch 0 taken 5808 times.
✓ Branch 1 taken 128 times.
|
5936 | frame->sequence == s->seq_output && |
| 348 |
2/2✓ Branch 0 taken 4879 times.
✓ Branch 1 taken 929 times.
|
5808 | frame->poc != poc) { |
| 349 | 4879 | dpb++; | |
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 |
3/4✓ Branch 0 taken 963 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 448 times.
✓ Branch 3 taken 515 times.
|
963 | if (sps && dpb >= sps->r->sps_dpb_params.dpb_max_dec_pic_buffering_minus1[sps->r->sps_max_sublayers_minus1] + 1) { |
| 354 |
2/2✓ Branch 0 taken 7616 times.
✓ Branch 1 taken 448 times.
|
8064 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 355 | 7616 | VVCFrame *frame = &fc->DPB[i]; | |
| 356 |
2/2✓ Branch 0 taken 3093 times.
✓ Branch 1 taken 4523 times.
|
7616 | if ((frame->flags) && |
| 357 |
1/2✓ Branch 0 taken 3093 times.
✗ Branch 1 not taken.
|
3093 | frame->sequence == s->seq_output && |
| 358 |
2/2✓ Branch 0 taken 2645 times.
✓ Branch 1 taken 448 times.
|
3093 | frame->poc != poc) { |
| 359 |
4/4✓ Branch 0 taken 60 times.
✓ Branch 1 taken 2585 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 9 times.
|
2645 | if (frame->flags == VVC_FRAME_FLAG_OUTPUT && frame->poc < min_poc) { |
| 360 | 51 | min_poc = frame->poc; | |
| 361 | } | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 |
2/2✓ Branch 0 taken 7616 times.
✓ Branch 1 taken 448 times.
|
8064 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 366 | 7616 | VVCFrame *frame = &fc->DPB[i]; | |
| 367 |
2/2✓ Branch 0 taken 2097 times.
✓ Branch 1 taken 5519 times.
|
7616 | if (frame->flags & VVC_FRAME_FLAG_OUTPUT && |
| 368 |
1/2✓ Branch 0 taken 2097 times.
✗ Branch 1 not taken.
|
2097 | frame->sequence == s->seq_output && |
| 369 |
2/2✓ Branch 0 taken 1893 times.
✓ Branch 1 taken 204 times.
|
2097 | frame->poc <= min_poc) { |
| 370 | 1893 | frame->flags |= VVC_FRAME_FLAG_BUMPING; | |
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | 448 | dpb--; | |
| 375 | } | ||
| 376 | 963 | } | |
| 377 | |||
| 378 | 7473 | static VVCFrame *find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb) | |
| 379 | { | ||
| 380 |
2/2✓ Branch 0 taken 394 times.
✓ Branch 1 taken 7079 times.
|
7473 | const unsigned mask = use_msb ? ~0 : fc->ps.sps->max_pic_order_cnt_lsb - 1; |
| 381 | |||
| 382 |
2/2✓ Branch 0 taken 27251 times.
✓ Branch 1 taken 17 times.
|
27268 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 383 | 27251 | VVCFrame *ref = &fc->DPB[i]; | |
| 384 |
4/4✓ Branch 0 taken 24534 times.
✓ Branch 1 taken 2717 times.
✓ Branch 2 taken 23606 times.
✓ Branch 3 taken 928 times.
|
27251 | if (ref->frame->buf[0] && ref->sequence == s->seq_decode) { |
| 385 |
2/2✓ Branch 0 taken 7456 times.
✓ Branch 1 taken 16150 times.
|
23606 | if ((ref->poc & mask) == poc) |
| 386 | 7456 | return ref; | |
| 387 | } | ||
| 388 | } | ||
| 389 | 17 | return NULL; | |
| 390 | } | ||
| 391 | |||
| 392 | 24529 | static void mark_ref(VVCFrame *frame, int flag) | |
| 393 | { | ||
| 394 | 24529 | frame->flags &= ~(VVC_FRAME_FLAG_LONG_REF | VVC_FRAME_FLAG_SHORT_REF); | |
| 395 | 24529 | frame->flags |= flag; | |
| 396 | 24529 | } | |
| 397 | |||
| 398 | 17 | static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int poc) | |
| 399 | { | ||
| 400 | 17 | const VVCSPS *sps = fc->ps.sps; | |
| 401 | 17 | const VVCPPS *pps = fc->ps.pps; | |
| 402 | VVCFrame *frame; | ||
| 403 | |||
| 404 | 17 | frame = alloc_frame(s, fc); | |
| 405 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!frame) |
| 406 | ✗ | return NULL; | |
| 407 | |||
| 408 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | if (!s->avctx->hwaccel) { |
| 409 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!sps->pixel_shift) { |
| 410 | ✗ | for (int i = 0; frame->frame->buf[i]; i++) | |
| 411 | ✗ | memset(frame->frame->buf[i]->data, 1 << (sps->bit_depth - 1), | |
| 412 | ✗ | frame->frame->buf[i]->size); | |
| 413 | } else { | ||
| 414 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 17 times.
|
68 | for (int i = 0; frame->frame->data[i]; i++) |
| 415 |
2/2✓ Branch 0 taken 10688 times.
✓ Branch 1 taken 51 times.
|
10739 | for (int y = 0; y < (pps->height >> sps->vshift[i]); y++) { |
| 416 | 10688 | uint8_t *dst = frame->frame->data[i] + y * frame->frame->linesize[i]; | |
| 417 | 10688 | AV_WN16(dst, 1 << (sps->bit_depth - 1)); | |
| 418 | 10688 | av_memcpy_backptr(dst + 2, 2, 2*(pps->width >> sps->hshift[i]) - 2); | |
| 419 | } | ||
| 420 | } | ||
| 421 | } | ||
| 422 | |||
| 423 | 17 | frame->poc = poc; | |
| 424 | 17 | frame->sequence = s->seq_decode; | |
| 425 | 17 | frame->flags = VVC_FRAME_FLAG_CORRUPT; | |
| 426 | |||
| 427 | 17 | ff_vvc_report_frame_finished(frame); | |
| 428 | |||
| 429 | 17 | return frame; | |
| 430 | } | ||
| 431 | |||
| 432 | #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)) | ||
| 433 | #define CHECK_SAMPLES(d) (frame->pps->r->pps_pic_##d##_in_luma_samples == ref->pps->r->pps_pic_##d##_in_luma_samples) | ||
| 434 | 7473 | static int check_candidate_ref(const VVCFrame *frame, const VVCRefPic *refp) | |
| 435 | { | ||
| 436 | 7473 | const VVCFrame *ref = refp->ref; | |
| 437 | |||
| 438 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7465 times.
|
7473 | if (refp->is_scaled) { |
| 439 | 8 | const int max = FFMAX(8, frame->sps->min_cb_size_y); | |
| 440 | 16 | return frame->ref_width * 2 >= ref->ref_width && | |
| 441 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | frame->ref_height * 2 >= ref->ref_height && |
| 442 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | frame->ref_width <= ref->ref_width * 8 && |
| 443 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | frame->ref_height <= ref->ref_height * 8 && |
| 444 |
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); |
| 445 | } | ||
| 446 |
2/4✓ Branch 0 taken 7465 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7465 times.
✗ Branch 3 not taken.
|
7465 | return CHECK_SAMPLES(width) && CHECK_SAMPLES(height); |
| 447 | } | ||
| 448 | |||
| 449 | #define RPR_SCALE(f) (((ref->f << 14) + (fc->ref->f >> 1)) / fc->ref->f) | ||
| 450 | /* add a reference with the given poc to the list and mark it as used in DPB */ | ||
| 451 | 7473 | static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *list, | |
| 452 | int poc, int ref_flag, uint8_t use_msb) | ||
| 453 | { | ||
| 454 | 7473 | VVCFrame *ref = find_ref_idx(s, fc, poc, use_msb); | |
| 455 | 7473 | VVCRefPic *refp = &list->refs[list->nb_refs]; | |
| 456 | |||
| 457 |
2/4✓ Branch 0 taken 7473 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7473 times.
|
7473 | if (ref == fc->ref || list->nb_refs >= VVC_MAX_REF_ENTRIES) |
| 458 | ✗ | return AVERROR_INVALIDDATA; | |
| 459 | |||
| 460 |
6/8✓ Branch 0 taken 7473 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7459 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 7413 times.
✓ Branch 5 taken 46 times.
✓ Branch 6 taken 7413 times.
✗ Branch 7 not taken.
|
7473 | if (!IS_CVSS(s)) { |
| 461 |
3/4✓ Branch 0 taken 7413 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 7394 times.
|
7413 | const bool ref_corrupt = !ref || (ref->flags & VVC_FRAME_FLAG_CORRUPT); |
| 462 |
2/2✓ Branch 0 taken 6550 times.
✓ Branch 1 taken 863 times.
|
13963 | const bool recovering = s->no_output_before_recovery_flag && |
| 463 |
3/4✓ Branch 0 taken 6478 times.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6478 times.
|
6550 | (IS_RASL(s) || !GDR_IS_RECOVERED(s)); |
| 464 | |||
| 465 |
3/4✓ Branch 0 taken 19 times.
✓ Branch 1 taken 7394 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
|
7413 | if (ref_corrupt && !recovering) { |
| 466 | ✗ | if (!(s->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) && | |
| 467 | ✗ | !(s->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL)) | |
| 468 | ✗ | return AVERROR_INVALIDDATA; | |
| 469 | |||
| 470 | ✗ | fc->ref->flags |= VVC_FRAME_FLAG_CORRUPT; | |
| 471 | } | ||
| 472 | } | ||
| 473 | |||
| 474 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 7456 times.
|
7473 | if (!ref) { |
| 475 | 17 | ref = generate_missing_ref(s, fc, poc); | |
| 476 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!ref) |
| 477 | ✗ | return AVERROR(ENOMEM); | |
| 478 | } | ||
| 479 | |||
| 480 | 7473 | refp->poc = poc; | |
| 481 | 7473 | refp->ref = ref; | |
| 482 | 7473 | refp->is_lt = ref_flag & VVC_FRAME_FLAG_LONG_REF; | |
| 483 | 22419 | refp->is_scaled = ref->sps->r->sps_num_subpics_minus1 != fc->ref->sps->r->sps_num_subpics_minus1|| | |
| 484 |
1/2✓ Branch 0 taken 7473 times.
✗ Branch 1 not taken.
|
7473 | memcmp(&ref->scaling_win, &fc->ref->scaling_win, sizeof(ref->scaling_win)) || |
| 485 |
3/4✓ Branch 0 taken 7473 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7465 times.
✓ Branch 3 taken 8 times.
|
22411 | ref->pps->r->pps_pic_width_in_luma_samples != fc->ref->pps->r->pps_pic_width_in_luma_samples || |
| 486 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7465 times.
|
7465 | ref->pps->r->pps_pic_height_in_luma_samples != fc->ref->pps->r->pps_pic_height_in_luma_samples; |
| 487 | |||
| 488 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7473 times.
|
7473 | if (!check_candidate_ref(fc->ref, refp)) |
| 489 | ✗ | return AVERROR_INVALIDDATA; | |
| 490 | |||
| 491 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7465 times.
|
7473 | if (refp->is_scaled) { |
| 492 | 8 | refp->scale[0] = RPR_SCALE(ref_width); | |
| 493 | 8 | refp->scale[1] = RPR_SCALE(ref_height); | |
| 494 | } | ||
| 495 | 7473 | list->nb_refs++; | |
| 496 | |||
| 497 | 7473 | mark_ref(ref, ref_flag); | |
| 498 | 7473 | return 0; | |
| 499 | } | ||
| 500 | |||
| 501 | 1665 | static int init_slice_rpl(const VVCFrameContext *fc, SliceContext *sc) | |
| 502 | { | ||
| 503 | 1665 | VVCFrame *frame = fc->ref; | |
| 504 | 1665 | const VVCSH *sh = &sc->sh; | |
| 505 | |||
| 506 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1665 times.
|
1665 | if (sc->slice_idx >= frame->nb_rpl_elems) |
| 507 | ✗ | return AVERROR_INVALIDDATA; | |
| 508 | |||
| 509 |
2/2✓ Branch 0 taken 51800 times.
✓ Branch 1 taken 1665 times.
|
53465 | for (int i = 0; i < sh->num_ctus_in_curr_slice; i++) { |
| 510 | 51800 | const int rs = sh->ctb_addr_in_curr_slice[i]; | |
| 511 | 51800 | frame->rpl_tab[rs] = frame->rpl + sc->slice_idx; | |
| 512 | } | ||
| 513 | |||
| 514 | 1665 | sc->rpl = frame->rpl_tab[sh->ctb_addr_in_curr_slice[0]]->refPicList; | |
| 515 | |||
| 516 | 1665 | return 0; | |
| 517 | } | ||
| 518 | |||
| 519 | 7079 | static int delta_poc_st(const H266RefPicListStruct *rpls, | |
| 520 | const int lx, const int i, const VVCSPS *sps) | ||
| 521 | { | ||
| 522 | 7079 | int abs_delta_poc_st = rpls->abs_delta_poc_st[i]; | |
| 523 |
4/4✓ Branch 0 taken 6560 times.
✓ Branch 1 taken 519 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 447 times.
|
7079 | if (!((sps->r->sps_weighted_pred_flag || |
| 524 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6560 times.
|
6560 | sps->r->sps_weighted_bipred_flag) && i != 0)) |
| 525 | 6632 | abs_delta_poc_st++; | |
| 526 | 7079 | return (1 - 2 * rpls->strp_entry_sign_flag[i]) * abs_delta_poc_st; | |
| 527 | } | ||
| 528 | |||
| 529 | 394 | static int poc_lt(int *prev_delta_poc_msb, const int poc, const H266RefPicLists *ref_lists, | |
| 530 | const int lx, const int j, const int max_poc_lsb) | ||
| 531 | { | ||
| 532 | 394 | const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx; | |
| 533 |
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]; |
| 534 | |||
| 535 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 394 times.
|
394 | if (ref_lists->delta_poc_msb_cycle_present_flag[lx][j]) { |
| 536 | ✗ | const uint32_t delta = ref_lists->delta_poc_msb_cycle_lt[lx][j] + *prev_delta_poc_msb; | |
| 537 | ✗ | lt_poc += poc - delta * max_poc_lsb - (poc & (max_poc_lsb - 1)); | |
| 538 | ✗ | *prev_delta_poc_msb = delta; | |
| 539 | } | ||
| 540 | 394 | return lt_poc; | |
| 541 | } | ||
| 542 | |||
| 543 | 1665 | int ff_vvc_slice_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc) | |
| 544 | { | ||
| 545 | 1665 | const VVCSPS *sps = fc->ps.sps; | |
| 546 | 1665 | const H266RawPPS *pps = fc->ps.pps->r; | |
| 547 | 1665 | const VVCPH *ph = &fc->ps.ph; | |
| 548 | 1665 | const H266RawSliceHeader *rsh = sc->sh.r; | |
| 549 | 1665 | const int max_poc_lsb = sps->max_pic_order_cnt_lsb; | |
| 550 | 1665 | const H266RefPicLists *ref_lists = | |
| 551 |
2/2✓ Branch 0 taken 253 times.
✓ Branch 1 taken 1412 times.
|
1665 | pps->pps_rpl_info_in_ph_flag ? &ph->r->ph_ref_pic_lists : &rsh->sh_ref_pic_lists; |
| 552 | 1665 | int ret = 0; | |
| 553 | |||
| 554 | 1665 | ret = init_slice_rpl(fc, sc); | |
| 555 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1665 times.
|
1665 | if (ret < 0) |
| 556 | ✗ | return ret; | |
| 557 | |||
| 558 |
2/2✓ Branch 0 taken 3330 times.
✓ Branch 1 taken 1665 times.
|
4995 | for (int lx = L0; lx <= L1; lx++) { |
| 559 | 3330 | const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx; | |
| 560 | 3330 | RefPicList *rpl = sc->rpl + lx; | |
| 561 | 3330 | int poc_base = ph->poc; | |
| 562 | 3330 | int prev_delta_poc_msb = 0; | |
| 563 | |||
| 564 | 3330 | rpl->nb_refs = 0; | |
| 565 |
2/2✓ Branch 0 taken 7473 times.
✓ Branch 1 taken 3330 times.
|
10803 | for (int i = 0, j = 0; i < rpls->num_ref_entries; i++) { |
| 566 | int poc; | ||
| 567 |
1/2✓ Branch 0 taken 7473 times.
✗ Branch 1 not taken.
|
7473 | if (!rpls->inter_layer_ref_pic_flag[i]) { |
| 568 | 7473 | int use_msb = 1; | |
| 569 | int ref_flag; | ||
| 570 |
2/2✓ Branch 0 taken 7079 times.
✓ Branch 1 taken 394 times.
|
7473 | if (rpls->st_ref_pic_flag[i]) { |
| 571 | 7079 | poc = poc_base + delta_poc_st(rpls, lx, i, sps); | |
| 572 | 7079 | poc_base = poc; | |
| 573 | 7079 | ref_flag = VVC_FRAME_FLAG_SHORT_REF; | |
| 574 | } else { | ||
| 575 | 394 | use_msb = ref_lists->delta_poc_msb_cycle_present_flag[lx][j]; | |
| 576 | 394 | poc = poc_lt(&prev_delta_poc_msb, ph->poc, ref_lists, lx, j, max_poc_lsb); | |
| 577 | 394 | ref_flag = VVC_FRAME_FLAG_LONG_REF; | |
| 578 | 394 | j++; | |
| 579 | } | ||
| 580 | 7473 | ret = add_candidate_ref(s, fc, rpl, poc, ref_flag, use_msb); | |
| 581 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7473 times.
|
7473 | if (ret < 0) |
| 582 | ✗ | return ret; | |
| 583 | } else { | ||
| 584 | // OPI_B_3.bit and VPS_A_3.bit should cover this | ||
| 585 | ✗ | avpriv_report_missing_feature(fc->log_ctx, "Inter layer ref"); | |
| 586 | ✗ | ret = AVERROR_PATCHWELCOME; | |
| 587 | ✗ | return ret; | |
| 588 | } | ||
| 589 | } | ||
| 590 |
2/2✓ Branch 0 taken 3092 times.
✓ Branch 1 taken 238 times.
|
3330 | if (ph->r->ph_temporal_mvp_enabled_flag && |
| 591 |
2/2✓ Branch 0 taken 1546 times.
✓ Branch 1 taken 1546 times.
|
3092 | (!rsh->sh_collocated_from_l0_flag) == lx && |
| 592 |
1/2✓ Branch 0 taken 1546 times.
✗ Branch 1 not taken.
|
1546 | rsh->sh_collocated_ref_idx < rpl->nb_refs) { |
| 593 | 1546 | const VVCRefPic *refp = rpl->refs + rsh->sh_collocated_ref_idx; | |
| 594 |
2/4✓ Branch 0 taken 1546 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1546 times.
|
1546 | if (refp->is_scaled || refp->ref->sps->ctb_log2_size_y != sps->ctb_log2_size_y) |
| 595 | ✗ | return AVERROR_INVALIDDATA; | |
| 596 | 1546 | fc->ref->collocated_ref = refp->ref; | |
| 597 | } | ||
| 598 | } | ||
| 599 | 1665 | return 0; | |
| 600 | } | ||
| 601 | |||
| 602 | 1066 | int ff_vvc_frame_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc) | |
| 603 | { | ||
| 604 | 1066 | int ret = 0; | |
| 605 | |||
| 606 | /* clear the reference flags on all frames except the current one */ | ||
| 607 |
2/2✓ Branch 0 taken 18122 times.
✓ Branch 1 taken 1066 times.
|
19188 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
| 608 | 18122 | VVCFrame *frame = &fc->DPB[i]; | |
| 609 | |||
| 610 |
2/2✓ Branch 0 taken 1066 times.
✓ Branch 1 taken 17056 times.
|
18122 | if (frame == fc->ref) |
| 611 | 1066 | continue; | |
| 612 | |||
| 613 | 17056 | mark_ref(frame, 0); | |
| 614 | } | ||
| 615 | |||
| 616 |
1/2✓ Branch 1 taken 1066 times.
✗ Branch 2 not taken.
|
1066 | if ((ret = ff_vvc_slice_rpl(s, fc, sc)) < 0) |
| 617 | ✗ | goto fail; | |
| 618 | |||
| 619 | 1066 | fail: | |
| 620 | /* release any frames that are now unused */ | ||
| 621 |
2/2✓ Branch 0 taken 18122 times.
✓ Branch 1 taken 1066 times.
|
19188 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
| 622 | 18122 | ff_vvc_unref_frame(fc, &fc->DPB[i], 0); | |
| 623 | 1066 | return ret; | |
| 624 | } | ||
| 625 | |||
| 626 | 1083 | void ff_vvc_report_frame_finished(VVCFrame *frame) | |
| 627 | { | ||
| 628 | 1083 | ff_vvc_report_progress(frame, VVC_PROGRESS_MV, INT_MAX); | |
| 629 | 1083 | ff_vvc_report_progress(frame, VVC_PROGRESS_PIXEL, INT_MAX); | |
| 630 | 1083 | } | |
| 631 | |||
| 632 | 100574 | static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l) | |
| 633 | { | ||
| 634 | 100574 | return p->progress[l->vp] > l->y; | |
| 635 | } | ||
| 636 | |||
| 637 | ✗ | static void add_listener(VVCProgressListener **prev, VVCProgressListener *l) | |
| 638 | { | ||
| 639 | ✗ | l->next = *prev; | |
| 640 | ✗ | *prev = l; | |
| 641 | ✗ | } | |
| 642 | |||
| 643 | ✗ | static VVCProgressListener* remove_listener(VVCProgressListener **prev, VVCProgressListener *l) | |
| 644 | { | ||
| 645 | ✗ | *prev = l->next; | |
| 646 | ✗ | l->next = NULL; | |
| 647 | ✗ | return l; | |
| 648 | } | ||
| 649 | |||
| 650 | 9693 | static VVCProgressListener* get_done_listener(FrameProgress *p, const VVCProgress vp) | |
| 651 | { | ||
| 652 | 9693 | VVCProgressListener *list = NULL; | |
| 653 | 9693 | VVCProgressListener **prev = &p->listener[vp]; | |
| 654 | |||
| 655 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9693 times.
|
9693 | while (*prev) { |
| 656 | ✗ | if (is_progress_done(p, *prev)) { | |
| 657 | ✗ | VVCProgressListener *l = remove_listener(prev, *prev); | |
| 658 | ✗ | add_listener(&list, l); | |
| 659 | } else { | ||
| 660 | ✗ | prev = &(*prev)->next; | |
| 661 | } | ||
| 662 | } | ||
| 663 | 9693 | return list; | |
| 664 | } | ||
| 665 | |||
| 666 | 11825 | void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y) | |
| 667 | { | ||
| 668 | 11825 | FrameProgress *p = frame->progress; | |
| 669 | 11825 | VVCProgressListener *l = NULL; | |
| 670 | |||
| 671 | 11825 | ff_mutex_lock(&p->lock); | |
| 672 |
2/2✓ Branch 0 taken 9693 times.
✓ Branch 1 taken 2132 times.
|
11825 | if (p->progress[vp] < y) { |
| 673 | // Due to the nature of thread scheduling, later progress may reach this point before earlier progress. | ||
| 674 | // Therefore, we only update the progress when p->progress[vp] < y. | ||
| 675 | 9693 | p->progress[vp] = y; | |
| 676 | 9693 | l = get_done_listener(p, vp); | |
| 677 | 9693 | ff_cond_signal(&p->cond); | |
| 678 | } | ||
| 679 | 11825 | ff_mutex_unlock(&p->lock); | |
| 680 | |||
| 681 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11825 times.
|
11825 | while (l) { |
| 682 | ✗ | l->progress_done(l); | |
| 683 | ✗ | l = l->next; | |
| 684 | } | ||
| 685 | 11825 | } | |
| 686 | |||
| 687 | 100574 | void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l) | |
| 688 | { | ||
| 689 | 100574 | FrameProgress *p = frame->progress; | |
| 690 | |||
| 691 | 100574 | ff_mutex_lock(&p->lock); | |
| 692 | |||
| 693 |
1/2✓ Branch 1 taken 100574 times.
✗ Branch 2 not taken.
|
100574 | if (is_progress_done(p, l)) { |
| 694 | 100574 | ff_mutex_unlock(&p->lock); | |
| 695 | 100574 | l->progress_done(l); | |
| 696 | } else { | ||
| 697 | ✗ | add_listener(p->listener + l->vp, l); | |
| 698 | ✗ | ff_mutex_unlock(&p->lock); | |
| 699 | } | ||
| 700 | 100574 | } | |
| 701 |