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