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 | |||
30 | #include "refs.h" | ||
31 | |||
32 | #define VVC_FRAME_FLAG_OUTPUT (1 << 0) | ||
33 | #define VVC_FRAME_FLAG_SHORT_REF (1 << 1) | ||
34 | #define VVC_FRAME_FLAG_LONG_REF (1 << 2) | ||
35 | #define VVC_FRAME_FLAG_BUMPING (1 << 3) | ||
36 | |||
37 | typedef struct FrameProgress { | ||
38 | atomic_int progress[VVC_PROGRESS_LAST]; | ||
39 | VVCProgressListener *listener[VVC_PROGRESS_LAST]; | ||
40 | AVMutex lock; | ||
41 | AVCond cond; | ||
42 | uint8_t has_lock; | ||
43 | uint8_t has_cond; | ||
44 | } FrameProgress; | ||
45 | |||
46 | 38288 | void ff_vvc_unref_frame(VVCFrameContext *fc, VVCFrame *frame, int flags) | |
47 | { | ||
48 | /* frame->frame can be NULL if context init failed */ | ||
49 |
3/4✓ Branch 0 taken 38288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28227 times.
✓ Branch 3 taken 10061 times.
|
38288 | if (!frame->frame || !frame->frame->buf[0]) |
50 | 28227 | return; | |
51 | |||
52 | 10061 | frame->flags &= ~flags; | |
53 |
2/2✓ Branch 0 taken 5104 times.
✓ Branch 1 taken 4957 times.
|
10061 | if (!frame->flags) { |
54 | 5104 | av_frame_unref(frame->frame); | |
55 | 5104 | ff_refstruct_unref(&frame->progress); | |
56 | |||
57 | 5104 | ff_refstruct_unref(&frame->tab_dmvr_mvf); | |
58 | |||
59 | 5104 | ff_refstruct_unref(&frame->rpl); | |
60 | 5104 | frame->nb_rpl_elems = 0; | |
61 | 5104 | ff_refstruct_unref(&frame->rpl_tab); | |
62 | |||
63 | 5104 | frame->collocated_ref = NULL; | |
64 | } | ||
65 | } | ||
66 | |||
67 | 2353318 | const RefPicList *ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0) | |
68 | { | ||
69 | 2353318 | const int x_cb = x0 >> fc->ps.sps->ctb_log2_size_y; | |
70 | 2353318 | const int y_cb = y0 >> fc->ps.sps->ctb_log2_size_y; | |
71 | 2353318 | const int pic_width_cb = fc->ps.pps->ctb_width; | |
72 | 2353318 | const int ctb_addr_rs = y_cb * pic_width_cb + x_cb; | |
73 | |||
74 | 2353318 | return (const RefPicList *)ref->rpl_tab[ctb_addr_rs]; | |
75 | } | ||
76 | |||
77 | 59 | void ff_vvc_clear_refs(VVCFrameContext *fc) | |
78 | { | ||
79 |
2/2✓ Branch 0 taken 1003 times.
✓ Branch 1 taken 59 times.
|
1062 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
80 | 1003 | ff_vvc_unref_frame(fc, &fc->DPB[i], | |
81 | VVC_FRAME_FLAG_SHORT_REF | VVC_FRAME_FLAG_LONG_REF); | ||
82 | 59 | } | |
83 | |||
84 | 50 | void ff_vvc_flush_dpb(VVCFrameContext *fc) | |
85 | { | ||
86 |
2/2✓ Branch 0 taken 850 times.
✓ Branch 1 taken 50 times.
|
900 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
87 | 850 | ff_vvc_unref_frame(fc, &fc->DPB[i], ~0); | |
88 | 50 | } | |
89 | |||
90 | 884 | static void free_progress(FFRefStructOpaque unused, void *obj) | |
91 | { | ||
92 | 884 | FrameProgress *p = (FrameProgress *)obj; | |
93 | |||
94 |
1/2✓ Branch 0 taken 884 times.
✗ Branch 1 not taken.
|
884 | if (p->has_cond) |
95 | 884 | ff_cond_destroy(&p->cond); | |
96 |
1/2✓ Branch 0 taken 884 times.
✗ Branch 1 not taken.
|
884 | if (p->has_lock) |
97 | 884 | ff_mutex_destroy(&p->lock); | |
98 | 884 | } | |
99 | |||
100 | 884 | static FrameProgress *alloc_progress(void) | |
101 | { | ||
102 | 884 | FrameProgress *p = ff_refstruct_alloc_ext(sizeof(*p), 0, NULL, free_progress); | |
103 | |||
104 |
1/2✓ Branch 0 taken 884 times.
✗ Branch 1 not taken.
|
884 | if (p) { |
105 | 884 | p->has_lock = !ff_mutex_init(&p->lock, NULL); | |
106 | 884 | p->has_cond = !ff_cond_init(&p->cond, NULL); | |
107 |
2/4✓ Branch 0 taken 884 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 884 times.
|
884 | if (!p->has_lock || !p->has_cond) |
108 | ✗ | ff_refstruct_unref(&p); | |
109 | } | ||
110 | 884 | return p; | |
111 | } | ||
112 | |||
113 | 884 | static VVCFrame *alloc_frame(VVCContext *s, VVCFrameContext *fc) | |
114 | { | ||
115 | 884 | const VVCPPS *pps = fc->ps.pps; | |
116 |
1/2✓ Branch 0 taken 3608 times.
✗ Branch 1 not taken.
|
3608 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
117 | int ret; | ||
118 | 3608 | VVCFrame *frame = &fc->DPB[i]; | |
119 |
2/2✓ Branch 0 taken 2724 times.
✓ Branch 1 taken 884 times.
|
3608 | if (frame->frame->buf[0]) |
120 | 2724 | continue; | |
121 | |||
122 | 884 | ret = ff_thread_get_buffer(s->avctx, frame->frame, AV_GET_BUFFER_FLAG_REF); | |
123 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 884 times.
|
884 | if (ret < 0) |
124 | ✗ | return NULL; | |
125 | |||
126 | 884 | frame->rpl = ff_refstruct_allocz(s->current_frame.nb_units * sizeof(RefPicListTab)); | |
127 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 884 times.
|
884 | if (!frame->rpl) |
128 | ✗ | goto fail; | |
129 | 884 | frame->nb_rpl_elems = s->current_frame.nb_units; | |
130 | |||
131 | 884 | frame->tab_dmvr_mvf = ff_refstruct_pool_get(fc->tab_dmvr_mvf_pool); | |
132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 884 times.
|
884 | if (!frame->tab_dmvr_mvf) |
133 | ✗ | goto fail; | |
134 | |||
135 | 884 | frame->rpl_tab = ff_refstruct_pool_get(fc->rpl_tab_pool); | |
136 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 884 times.
|
884 | if (!frame->rpl_tab) |
137 | ✗ | goto fail; | |
138 | 884 | frame->ctb_count = pps->ctb_width * pps->ctb_height; | |
139 |
2/2✓ Branch 0 taken 42987 times.
✓ Branch 1 taken 884 times.
|
43871 | for (int j = 0; j < frame->ctb_count; j++) |
140 | 42987 | frame->rpl_tab[j] = frame->rpl; | |
141 | |||
142 | 884 | frame->progress = alloc_progress(); | |
143 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 884 times.
|
884 | if (!frame->progress) |
144 | ✗ | goto fail; | |
145 | |||
146 | 884 | return frame; | |
147 | ✗ | fail: | |
148 | ✗ | ff_vvc_unref_frame(fc, frame, ~0); | |
149 | ✗ | return NULL; | |
150 | } | ||
151 | ✗ | av_log(s->avctx, AV_LOG_ERROR, "Error allocating frame, DPB full.\n"); | |
152 | ✗ | return NULL; | |
153 | } | ||
154 | |||
155 | 872 | int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, AVFrame **frame) | |
156 | { | ||
157 | 872 | const VVCPH *ph= &fc->ps.ph; | |
158 | 872 | const int poc = ph->poc; | |
159 | VVCFrame *ref; | ||
160 | |||
161 | /* check that this POC doesn't already exist */ | ||
162 |
2/2✓ Branch 0 taken 14824 times.
✓ Branch 1 taken 872 times.
|
15696 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
163 | 14824 | VVCFrame *frame = &fc->DPB[i]; | |
164 | |||
165 |
4/4✓ Branch 0 taken 4201 times.
✓ Branch 1 taken 10623 times.
✓ Branch 2 taken 4098 times.
✓ Branch 3 taken 103 times.
|
14824 | if (frame->frame->buf[0] && frame->sequence == s->seq_decode && |
166 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4098 times.
|
4098 | frame->poc == poc) { |
167 | ✗ | av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence: %d.\n", poc); | |
168 | ✗ | return AVERROR_INVALIDDATA; | |
169 | } | ||
170 | } | ||
171 | |||
172 | 872 | ref = alloc_frame(s, fc); | |
173 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 872 times.
|
872 | if (!ref) |
174 | ✗ | return AVERROR(ENOMEM); | |
175 | |||
176 | 872 | *frame = ref->frame; | |
177 | 872 | fc->ref = ref; | |
178 | |||
179 |
5/6✓ Branch 0 taken 687 times.
✓ Branch 1 taken 185 times.
✓ Branch 2 taken 672 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 672 times.
|
872 | if (s->no_output_before_recovery_flag && (IS_RASL(s) || !GDR_IS_RECOVERED(s))) |
180 | 15 | ref->flags = 0; | |
181 |
1/2✓ Branch 0 taken 857 times.
✗ Branch 1 not taken.
|
857 | else if (ph->r->ph_pic_output_flag) |
182 | 857 | ref->flags = VVC_FRAME_FLAG_OUTPUT; | |
183 | |||
184 |
1/2✓ Branch 0 taken 872 times.
✗ Branch 1 not taken.
|
872 | if (!ph->r->ph_non_ref_pic_flag) |
185 | 872 | ref->flags |= VVC_FRAME_FLAG_SHORT_REF; | |
186 | |||
187 | 872 | ref->poc = poc; | |
188 | 872 | ref->sequence = s->seq_decode; | |
189 | 872 | ref->frame->crop_left = fc->ps.pps->r->pps_conf_win_left_offset << fc->ps.sps->hshift[CHROMA]; | |
190 | 872 | ref->frame->crop_right = fc->ps.pps->r->pps_conf_win_right_offset << fc->ps.sps->hshift[CHROMA]; | |
191 | 872 | ref->frame->crop_top = fc->ps.pps->r->pps_conf_win_top_offset << fc->ps.sps->vshift[CHROMA]; | |
192 | 872 | ref->frame->crop_bottom = fc->ps.pps->r->pps_conf_win_bottom_offset << fc->ps.sps->vshift[CHROMA]; | |
193 | |||
194 | 872 | return 0; | |
195 | } | ||
196 | |||
197 | 973 | int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush) | |
198 | { | ||
199 | 973 | const VVCSPS *sps = fc->ps.sps; | |
200 | 59 | do { | |
201 | 1032 | int nb_output = 0; | |
202 | 1032 | int min_poc = INT_MAX; | |
203 | int min_idx, ret; | ||
204 | |||
205 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1032 times.
|
1032 | if (no_output_of_prior_pics_flag) { |
206 | ✗ | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { | |
207 | ✗ | VVCFrame *frame = &fc->DPB[i]; | |
208 | ✗ | if (!(frame->flags & VVC_FRAME_FLAG_BUMPING) && frame->poc != fc->ps.ph.poc && | |
209 | ✗ | frame->sequence == s->seq_output) { | |
210 | ✗ | ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT); | |
211 | } | ||
212 | } | ||
213 | } | ||
214 | |||
215 |
2/2✓ Branch 0 taken 17544 times.
✓ Branch 1 taken 1032 times.
|
18576 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
216 | 17544 | VVCFrame *frame = &fc->DPB[i]; | |
217 |
2/2✓ Branch 0 taken 4150 times.
✓ Branch 1 taken 13394 times.
|
17544 | if ((frame->flags & VVC_FRAME_FLAG_OUTPUT) && |
218 |
2/2✓ Branch 0 taken 3951 times.
✓ Branch 1 taken 199 times.
|
4150 | frame->sequence == s->seq_output) { |
219 | 3951 | nb_output++; | |
220 |
3/4✓ Branch 0 taken 1928 times.
✓ Branch 1 taken 2023 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1928 times.
|
3951 | if (frame->poc < min_poc || nb_output == 1) { |
221 | 2023 | min_poc = frame->poc; | |
222 | 2023 | min_idx = i; | |
223 | } | ||
224 | } | ||
225 | } | ||
226 | |||
227 | /* wait for more frames before output */ | ||
228 |
5/6✓ Branch 0 taken 929 times.
✓ Branch 1 taken 103 times.
✓ Branch 2 taken 833 times.
✓ Branch 3 taken 96 times.
✓ Branch 4 taken 833 times.
✗ Branch 5 not taken.
|
1032 | if (!flush && s->seq_output == s->seq_decode && sps && |
229 |
2/2✓ Branch 0 taken 111 times.
✓ Branch 1 taken 722 times.
|
833 | nb_output <= sps->r->sps_dpb_params.dpb_max_num_reorder_pics[sps->r->sps_max_sublayers_minus1]) |
230 | 111 | return 0; | |
231 | |||
232 |
2/2✓ Branch 0 taken 837 times.
✓ Branch 1 taken 84 times.
|
921 | if (nb_output) { |
233 | 837 | VVCFrame *frame = &fc->DPB[min_idx]; | |
234 | |||
235 | 837 | ret = av_frame_ref(out, frame->frame); | |
236 |
2/2✓ Branch 0 taken 581 times.
✓ Branch 1 taken 256 times.
|
837 | if (frame->flags & VVC_FRAME_FLAG_BUMPING) |
237 | 581 | ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_BUMPING); | |
238 | else | ||
239 | 256 | ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT); | |
240 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 837 times.
|
837 | if (ret < 0) |
241 | ✗ | return ret; | |
242 | |||
243 | 837 | av_log(s->avctx, AV_LOG_DEBUG, | |
244 | "Output frame with POC %d.\n", frame->poc); | ||
245 | 837 | return 1; | |
246 | } | ||
247 | |||
248 |
2/2✓ Branch 0 taken 59 times.
✓ Branch 1 taken 25 times.
|
84 | if (s->seq_output != s->seq_decode) |
249 | 59 | s->seq_output = (s->seq_output + 1) & 0xff; | |
250 | else | ||
251 | 25 | break; | |
252 | } while (1); | ||
253 | 25 | return 0; | |
254 | } | ||
255 | |||
256 | 813 | void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc) | |
257 | { | ||
258 | 813 | const VVCSPS *sps = fc->ps.sps; | |
259 | 813 | const int poc = fc->ps.ph.poc; | |
260 | 813 | int dpb = 0; | |
261 | 813 | int min_poc = INT_MAX; | |
262 | |||
263 |
2/2✓ Branch 0 taken 13821 times.
✓ Branch 1 taken 813 times.
|
14634 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
264 | 13821 | VVCFrame *frame = &fc->DPB[i]; | |
265 |
2/2✓ Branch 0 taken 4975 times.
✓ Branch 1 taken 8846 times.
|
13821 | if ((frame->flags) && |
266 |
2/2✓ Branch 0 taken 4863 times.
✓ Branch 1 taken 112 times.
|
4975 | frame->sequence == s->seq_output && |
267 |
2/2✓ Branch 0 taken 4074 times.
✓ Branch 1 taken 789 times.
|
4863 | frame->poc != poc) { |
268 | 4074 | dpb++; | |
269 | } | ||
270 | } | ||
271 | |||
272 |
3/4✓ Branch 0 taken 813 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 398 times.
✓ Branch 3 taken 415 times.
|
813 | if (sps && dpb >= sps->r->sps_dpb_params.dpb_max_dec_pic_buffering_minus1[sps->r->sps_max_sublayers_minus1] + 1) { |
273 |
2/2✓ Branch 0 taken 6766 times.
✓ Branch 1 taken 398 times.
|
7164 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
274 | 6766 | VVCFrame *frame = &fc->DPB[i]; | |
275 |
2/2✓ Branch 0 taken 2734 times.
✓ Branch 1 taken 4032 times.
|
6766 | if ((frame->flags) && |
276 |
1/2✓ Branch 0 taken 2734 times.
✗ Branch 1 not taken.
|
2734 | frame->sequence == s->seq_output && |
277 |
2/2✓ Branch 0 taken 2336 times.
✓ Branch 1 taken 398 times.
|
2734 | frame->poc != poc) { |
278 |
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) { |
279 | 50 | min_poc = frame->poc; | |
280 | } | ||
281 | } | ||
282 | } | ||
283 | |||
284 |
2/2✓ Branch 0 taken 6766 times.
✓ Branch 1 taken 398 times.
|
7164 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
285 | 6766 | VVCFrame *frame = &fc->DPB[i]; | |
286 |
2/2✓ Branch 0 taken 1843 times.
✓ Branch 1 taken 4923 times.
|
6766 | if (frame->flags & VVC_FRAME_FLAG_OUTPUT && |
287 |
1/2✓ Branch 0 taken 1843 times.
✗ Branch 1 not taken.
|
1843 | frame->sequence == s->seq_output && |
288 |
2/2✓ Branch 0 taken 1647 times.
✓ Branch 1 taken 196 times.
|
1843 | frame->poc <= min_poc) { |
289 | 1647 | frame->flags |= VVC_FRAME_FLAG_BUMPING; | |
290 | } | ||
291 | } | ||
292 | |||
293 | 398 | dpb--; | |
294 | } | ||
295 | 813 | } | |
296 | |||
297 | 5903 | static VVCFrame *find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb) | |
298 | { | ||
299 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5903 times.
|
5903 | const int mask = use_msb ? ~0 : fc->ps.sps->max_pic_order_cnt_lsb - 1; |
300 | |||
301 |
2/2✓ Branch 0 taken 21305 times.
✓ Branch 1 taken 12 times.
|
21317 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
302 | 21305 | VVCFrame *ref = &fc->DPB[i]; | |
303 |
4/4✓ Branch 0 taken 19012 times.
✓ Branch 1 taken 2293 times.
✓ Branch 2 taken 18084 times.
✓ Branch 3 taken 928 times.
|
21305 | if (ref->frame->buf[0] && ref->sequence == s->seq_decode) { |
304 |
2/2✓ Branch 0 taken 5891 times.
✓ Branch 1 taken 12193 times.
|
18084 | if ((ref->poc & mask) == poc) |
305 | 5891 | return ref; | |
306 | } | ||
307 | } | ||
308 | 12 | return NULL; | |
309 | } | ||
310 | |||
311 | 19855 | static void mark_ref(VVCFrame *frame, int flag) | |
312 | { | ||
313 | 19855 | frame->flags &= ~(VVC_FRAME_FLAG_LONG_REF | VVC_FRAME_FLAG_SHORT_REF); | |
314 | 19855 | frame->flags |= flag; | |
315 | 19855 | } | |
316 | |||
317 | 12 | static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int poc) | |
318 | { | ||
319 | 12 | const VVCSPS *sps = fc->ps.sps; | |
320 | 12 | const VVCPPS *pps = fc->ps.pps; | |
321 | VVCFrame *frame; | ||
322 | |||
323 | 12 | frame = alloc_frame(s, fc); | |
324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (!frame) |
325 | ✗ | return NULL; | |
326 | |||
327 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (!s->avctx->hwaccel) { |
328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (!sps->pixel_shift) { |
329 | ✗ | for (int i = 0; frame->frame->buf[i]; i++) | |
330 | ✗ | memset(frame->frame->buf[i]->data, 1 << (sps->bit_depth - 1), | |
331 | ✗ | frame->frame->buf[i]->size); | |
332 | } else { | ||
333 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 12 times.
|
48 | for (int i = 0; frame->frame->data[i]; i++) |
334 |
2/2✓ Branch 0 taken 5760 times.
✓ Branch 1 taken 36 times.
|
5796 | for (int y = 0; y < (pps->height >> sps->vshift[i]); y++) { |
335 | 5760 | uint8_t *dst = frame->frame->data[i] + y * frame->frame->linesize[i]; | |
336 | 5760 | AV_WN16(dst, 1 << (sps->bit_depth - 1)); | |
337 | 5760 | av_memcpy_backptr(dst + 2, 2, 2*(pps->width >> sps->hshift[i]) - 2); | |
338 | } | ||
339 | } | ||
340 | } | ||
341 | |||
342 | 12 | frame->poc = poc; | |
343 | 12 | frame->sequence = s->seq_decode; | |
344 | 12 | frame->flags = 0; | |
345 | |||
346 | 12 | ff_vvc_report_frame_finished(frame); | |
347 | |||
348 | 12 | return frame; | |
349 | } | ||
350 | |||
351 | /* add a reference with the given poc to the list and mark it as used in DPB */ | ||
352 | 5903 | static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *list, | |
353 | int poc, int ref_flag, uint8_t use_msb) | ||
354 | { | ||
355 | 5903 | VVCFrame *ref = find_ref_idx(s, fc, poc, use_msb); | |
356 | |||
357 |
2/4✓ Branch 0 taken 5903 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5903 times.
|
5903 | if (ref == fc->ref || list->nb_refs >= VVC_MAX_REF_ENTRIES) |
358 | ✗ | return AVERROR_INVALIDDATA; | |
359 | |||
360 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 5891 times.
|
5903 | if (!ref) { |
361 | 12 | ref = generate_missing_ref(s, fc, poc); | |
362 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (!ref) |
363 | ✗ | return AVERROR(ENOMEM); | |
364 | } | ||
365 | |||
366 | 5903 | list->list[list->nb_refs] = poc; | |
367 | 5903 | list->ref[list->nb_refs] = ref; | |
368 | 5903 | list->isLongTerm[list->nb_refs] = ref_flag & VVC_FRAME_FLAG_LONG_REF; | |
369 | 5903 | list->nb_refs++; | |
370 | |||
371 | 5903 | mark_ref(ref, ref_flag); | |
372 | 5903 | return 0; | |
373 | } | ||
374 | |||
375 | 1433 | static int init_slice_rpl(const VVCFrameContext *fc, SliceContext *sc) | |
376 | { | ||
377 | 1433 | VVCFrame *frame = fc->ref; | |
378 | 1433 | const VVCSH *sh = &sc->sh; | |
379 | |||
380 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1433 times.
|
1433 | if (sc->slice_idx >= frame->nb_rpl_elems) |
381 | ✗ | return AVERROR_INVALIDDATA; | |
382 | |||
383 |
2/2✓ Branch 0 taken 41569 times.
✓ Branch 1 taken 1433 times.
|
43002 | for (int i = 0; i < sh->num_ctus_in_curr_slice; i++) { |
384 | 41569 | const int rs = sh->ctb_addr_in_curr_slice[i]; | |
385 | 41569 | frame->rpl_tab[rs] = frame->rpl + sc->slice_idx; | |
386 | } | ||
387 | |||
388 | 1433 | sc->rpl = frame->rpl_tab[sh->ctb_addr_in_curr_slice[0]]->refPicList; | |
389 | |||
390 | 1433 | return 0; | |
391 | } | ||
392 | |||
393 | 5903 | static int delta_poc_st(const H266RefPicListStruct *rpls, | |
394 | const int lx, const int i, const VVCSPS *sps) | ||
395 | { | ||
396 | 5903 | int abs_delta_poc_st = rpls->abs_delta_poc_st[i]; | |
397 |
4/4✓ Branch 0 taken 5829 times.
✓ Branch 1 taken 74 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 42 times.
|
5903 | if (!((sps->r->sps_weighted_pred_flag || |
398 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5829 times.
|
5829 | sps->r->sps_weighted_bipred_flag) && i != 0)) |
399 | 5861 | abs_delta_poc_st++; | |
400 | 5903 | return (1 - 2 * rpls->strp_entry_sign_flag[i]) * abs_delta_poc_st; | |
401 | } | ||
402 | |||
403 | ✗ | static int poc_lt(int *prev_delta_poc_msb, const int poc, const H266RefPicLists *ref_lists, | |
404 | const int lx, const int j, const int max_poc_lsb) | ||
405 | { | ||
406 | ✗ | const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx; | |
407 | ✗ | int lt_poc = rpls->ltrp_in_header_flag ? ref_lists->poc_lsb_lt[lx][j] : rpls->rpls_poc_lsb_lt[j]; | |
408 | |||
409 | ✗ | if (ref_lists->delta_poc_msb_cycle_present_flag[lx][j]) { | |
410 | ✗ | const uint32_t delta = ref_lists->delta_poc_msb_cycle_lt[lx][j] + *prev_delta_poc_msb; | |
411 | ✗ | lt_poc += poc - delta * max_poc_lsb - (poc & (max_poc_lsb - 1)); | |
412 | ✗ | *prev_delta_poc_msb = delta; | |
413 | } | ||
414 | ✗ | return lt_poc; | |
415 | } | ||
416 | |||
417 | 1433 | int ff_vvc_slice_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc) | |
418 | { | ||
419 | 1433 | const VVCSPS *sps = fc->ps.sps; | |
420 | 1433 | const H266RawPPS *pps = fc->ps.pps->r; | |
421 | 1433 | const VVCPH *ph = &fc->ps.ph; | |
422 | 1433 | const H266RawSliceHeader *rsh = sc->sh.r; | |
423 | 1433 | const int max_poc_lsb = sps->max_pic_order_cnt_lsb; | |
424 | 1433 | const H266RefPicLists *ref_lists = | |
425 |
2/2✓ Branch 0 taken 250 times.
✓ Branch 1 taken 1183 times.
|
1433 | pps->pps_rpl_info_in_ph_flag ? &ph->r->ph_ref_pic_lists : &rsh->sh_ref_pic_lists; |
426 | 1433 | int ret = 0; | |
427 | |||
428 | 1433 | ret = init_slice_rpl(fc, sc); | |
429 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1433 times.
|
1433 | if (ret < 0) |
430 | ✗ | return ret; | |
431 | |||
432 |
2/2✓ Branch 0 taken 2866 times.
✓ Branch 1 taken 1433 times.
|
4299 | for (int lx = L0; lx <= L1; lx++) { |
433 | 2866 | const H266RefPicListStruct *rpls = ref_lists->rpl_ref_list + lx; | |
434 | 2866 | RefPicList *rpl = sc->rpl + lx; | |
435 | 2866 | int poc_base = ph->poc; | |
436 | 2866 | int prev_delta_poc_msb = 0; | |
437 | |||
438 | 2866 | rpl->nb_refs = 0; | |
439 |
2/2✓ Branch 0 taken 5903 times.
✓ Branch 1 taken 2866 times.
|
8769 | for (int i = 0, j = 0; i < rpls->num_ref_entries; i++) { |
440 | int poc; | ||
441 |
1/2✓ Branch 0 taken 5903 times.
✗ Branch 1 not taken.
|
5903 | if (!rpls->inter_layer_ref_pic_flag[i]) { |
442 | 5903 | int use_msb = 1; | |
443 | int ref_flag; | ||
444 |
1/2✓ Branch 0 taken 5903 times.
✗ Branch 1 not taken.
|
5903 | if (rpls->st_ref_pic_flag[i]) { |
445 | 5903 | poc = poc_base + delta_poc_st(rpls, lx, i, sps); | |
446 | 5903 | poc_base = poc; | |
447 | 5903 | ref_flag = VVC_FRAME_FLAG_SHORT_REF; | |
448 | } else { | ||
449 | ✗ | use_msb = ref_lists->delta_poc_msb_cycle_present_flag[lx][j]; | |
450 | ✗ | poc = poc_lt(&prev_delta_poc_msb, ph->poc, ref_lists, lx, j, max_poc_lsb); | |
451 | ✗ | ref_flag = VVC_FRAME_FLAG_LONG_REF; | |
452 | ✗ | j++; | |
453 | } | ||
454 | 5903 | ret = add_candidate_ref(s, fc, rpl, poc, ref_flag, use_msb); | |
455 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5903 times.
|
5903 | if (ret < 0) |
456 | ✗ | return ret; | |
457 | } else { | ||
458 | // OPI_B_3.bit and VPS_A_3.bit should cover this | ||
459 | ✗ | avpriv_report_missing_feature(fc->log_ctx, "Inter layer ref"); | |
460 | ✗ | ret = AVERROR_PATCHWELCOME; | |
461 | ✗ | return ret; | |
462 | } | ||
463 | } | ||
464 |
2/2✓ Branch 0 taken 1433 times.
✓ Branch 1 taken 1433 times.
|
2866 | if ((!rsh->sh_collocated_from_l0_flag) == lx && |
465 |
2/2✓ Branch 0 taken 1373 times.
✓ Branch 1 taken 60 times.
|
1433 | rsh->sh_collocated_ref_idx < rpl->nb_refs) |
466 | 1373 | fc->ref->collocated_ref = rpl->ref[rsh->sh_collocated_ref_idx]; | |
467 | } | ||
468 | 1433 | return 0; | |
469 | } | ||
470 | |||
471 | 872 | int ff_vvc_frame_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc) | |
472 | { | ||
473 | 872 | int ret = 0; | |
474 | |||
475 | /* clear the reference flags on all frames except the current one */ | ||
476 |
2/2✓ Branch 0 taken 14824 times.
✓ Branch 1 taken 872 times.
|
15696 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) { |
477 | 14824 | VVCFrame *frame = &fc->DPB[i]; | |
478 | |||
479 |
2/2✓ Branch 0 taken 872 times.
✓ Branch 1 taken 13952 times.
|
14824 | if (frame == fc->ref) |
480 | 872 | continue; | |
481 | |||
482 | 13952 | mark_ref(frame, 0); | |
483 | } | ||
484 | |||
485 |
1/2✓ Branch 1 taken 872 times.
✗ Branch 2 not taken.
|
872 | if ((ret = ff_vvc_slice_rpl(s, fc, sc)) < 0) |
486 | ✗ | goto fail; | |
487 | |||
488 | 872 | fail: | |
489 | /* release any frames that are now unused */ | ||
490 |
2/2✓ Branch 0 taken 14824 times.
✓ Branch 1 taken 872 times.
|
15696 | for (int i = 0; i < FF_ARRAY_ELEMS(fc->DPB); i++) |
491 | 14824 | ff_vvc_unref_frame(fc, &fc->DPB[i], 0); | |
492 | 872 | return ret; | |
493 | } | ||
494 | |||
495 | 884 | void ff_vvc_report_frame_finished(VVCFrame *frame) | |
496 | { | ||
497 | 884 | ff_vvc_report_progress(frame, VVC_PROGRESS_MV, INT_MAX); | |
498 | 884 | ff_vvc_report_progress(frame, VVC_PROGRESS_PIXEL, INT_MAX); | |
499 | 884 | } | |
500 | |||
501 | 94541 | static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l) | |
502 | { | ||
503 | 94541 | return p->progress[l->vp] > l->y; | |
504 | } | ||
505 | |||
506 | 7754 | static void add_listener(VVCProgressListener **prev, VVCProgressListener *l) | |
507 | { | ||
508 | 7754 | l->next = *prev; | |
509 | 7754 | *prev = l; | |
510 | 7754 | } | |
511 | |||
512 | 3877 | static VVCProgressListener* remove_listener(VVCProgressListener **prev, VVCProgressListener *l) | |
513 | { | ||
514 | 3877 | *prev = l->next; | |
515 | 3877 | l->next = NULL; | |
516 | 3877 | return l; | |
517 | } | ||
518 | |||
519 | 9386 | static VVCProgressListener* get_done_listener(FrameProgress *p, const VVCProgress vp) | |
520 | { | ||
521 | 9386 | VVCProgressListener *list = NULL; | |
522 | 9386 | VVCProgressListener **prev = &p->listener[vp]; | |
523 | |||
524 |
2/2✓ Branch 0 taken 15010 times.
✓ Branch 1 taken 9386 times.
|
24396 | while (*prev) { |
525 |
2/2✓ Branch 1 taken 3877 times.
✓ Branch 2 taken 11133 times.
|
15010 | if (is_progress_done(p, *prev)) { |
526 | 3877 | VVCProgressListener *l = remove_listener(prev, *prev); | |
527 | 3877 | add_listener(&list, l); | |
528 | } else { | ||
529 | 11133 | prev = &(*prev)->next; | |
530 | } | ||
531 | } | ||
532 | 9386 | return list; | |
533 | } | ||
534 | |||
535 | 9386 | void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y) | |
536 | { | ||
537 | 9386 | FrameProgress *p = frame->progress; | |
538 | 9386 | VVCProgressListener *l = NULL; | |
539 | |||
540 | 9386 | ff_mutex_lock(&p->lock); | |
541 | |||
542 |
3/4✓ Branch 0 taken 1744 times.
✓ Branch 1 taken 7642 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1744 times.
|
9386 | av_assert0(p->progress[vp] < y || p->progress[vp] == INT_MAX); |
543 | 9386 | p->progress[vp] = y; | |
544 | 9386 | l = get_done_listener(p, vp); | |
545 | 9386 | ff_cond_signal(&p->cond); | |
546 | |||
547 | 9386 | ff_mutex_unlock(&p->lock); | |
548 | |||
549 |
2/2✓ Branch 0 taken 3877 times.
✓ Branch 1 taken 9386 times.
|
13263 | while (l) { |
550 | 3877 | l->progress_done(l); | |
551 | 3877 | l = l->next; | |
552 | } | ||
553 | 9386 | } | |
554 | |||
555 | 79531 | void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l) | |
556 | { | ||
557 | 79531 | FrameProgress *p = frame->progress; | |
558 | |||
559 | 79531 | ff_mutex_lock(&p->lock); | |
560 | |||
561 |
2/2✓ Branch 1 taken 75654 times.
✓ Branch 2 taken 3877 times.
|
79531 | if (is_progress_done(p, l)) { |
562 | 75654 | ff_mutex_unlock(&p->lock); | |
563 | 75654 | l->progress_done(l); | |
564 | } else { | ||
565 | 3877 | add_listener(p->listener + l->vp, l); | |
566 | 3877 | ff_mutex_unlock(&p->lock); | |
567 | } | ||
568 | 79531 | } | |
569 |