1 /*
2 * Copyright 2021 Rockchip Electronics Co. LTD
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define MODULE_TAG "avs2d_dpb"
18
19 #include <string.h>
20 #include <stdlib.h>
21
22 #include "mpp_mem.h"
23 #include "mpp_log.h"
24 #include "mpp_debug.h"
25 #include "mpp_compat_impl.h"
26
27 #include "hal_task.h"
28 #include "avs2d_dpb.h"
29
30 #ifndef INT_MAX
31 #define INT_MAX 2147483647 /* maximum (signed) int value */
32 #endif
33
34 /**
35 * @brief Calculate dpb size according to specification
36 * Some bitstream may require larger dpb than declaration, so the largest dpb
37 * size is used for all bitstream. And this function is commented to silence
38 * compiler's unused warnning.
39 */
dpb_get_size(Avs2dCtx_t * p_dec)40 static RK_U32 dpb_get_size(Avs2dCtx_t *p_dec)
41 {
42 RK_U32 mini_size = 8;
43 RK_U32 mini_cu_width, mini_cu_height;
44 RK_U32 pic_size = 0;
45 RK_U32 dpb_size = AVS2_MAX_DPB_SIZE;
46
47 Avs2dSeqHeader_t *vsh = &p_dec->vsh;
48 mini_cu_width = (vsh->horizontal_size + mini_size - 1) / mini_size;
49 if (vsh->progressive_sequence == 0 && vsh->field_coded_sequence == 0) {
50 mini_cu_height = (vsh->vertical_size + 2 * mini_size - 1) / (2 * mini_size);
51 } else {
52 mini_cu_height = (vsh->vertical_size + mini_size - 1) / mini_size;
53 }
54 pic_size = mini_cu_width * mini_size * mini_cu_height * mini_size;
55 avs2d_dbg_dpb("level_id %d, pic_size %d", vsh->level_id, pic_size);
56
57 switch (vsh->level_id) {
58 case 0x10:
59 case 0x12:
60 case 0x14:
61 case 0x20:
62 case 0x22:
63 dpb_size = 15;
64 break;
65 case 0x40:
66 case 0x42:
67 case 0x44:
68 case 0x46:
69 case 0x48:
70 case 0x4A:
71 dpb_size = MPP_MIN(13369344 / pic_size, 16) - 1;
72 break;
73 case 0x50:
74 case 0x52:
75 case 0x54:
76 case 0x56:
77 case 0x58:
78 case 0x5A:
79 dpb_size = MPP_MIN(56623104 / pic_size, 16) - 1;
80 break;
81 case 0x60:
82 case 0x62:
83 case 0x64:
84 case 0x66:
85 case 0x68:
86 case 0x6A:
87 dpb_size = MPP_MIN(213909504 / pic_size, 16) - 1;
88 break;
89 default:
90 AVS2D_DBG(AVS2D_DBG_WARNNING, "invalid level id(%d)", vsh->level_id);
91 break;
92 }
93
94 if (dpb_size < (RK_U32)(vsh->num_of_rps + 1)) {
95 dpb_size = (RK_U32)(vsh->num_of_rps + 1);
96 }
97 dpb_size = MPP_MIN(dpb_size, AVS2_MAX_DPB_SIZE);
98
99 return dpb_size;
100 }
101
new_frame()102 static Avs2dFrame_t *new_frame()
103 {
104 MPP_RET ret = MPP_OK;
105
106 Avs2dFrame_t *f = mpp_calloc(Avs2dFrame_t, 1);
107 MEM_CHECK(ret, f);
108 f->slot_idx = NO_VAL;
109 f->doi = NO_VAL;
110 f->poi = NO_VAL;
111
112 return f;
113 __FAILED:
114 (void)ret;
115 return NULL;
116 }
117
dpb_init_management(Avs2dFrameMgr_t * mgr)118 static void dpb_init_management(Avs2dFrameMgr_t *mgr)
119 {
120 mgr->num_of_ref = 0;
121 mgr->prev_doi = NO_VAL;
122 mgr->output_poi = NO_VAL;
123 mgr->tr_wrap_cnt = 0;
124
125 mgr->scene_ref = NULL;
126 mgr->cur_frm = NULL;
127 mgr->used_size = 0;
128 memset(mgr->refs, 0, sizeof(mgr->refs));
129 memset(&mgr->cur_rps, 0, sizeof(Avs2dRps_t));
130 }
131
avs2d_dpb_create(Avs2dCtx_t * p_dec)132 MPP_RET avs2d_dpb_create(Avs2dCtx_t *p_dec)
133 {
134 MPP_RET ret = MPP_OK;
135 RK_U32 i;
136 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
137
138 AVS2D_PARSE_TRACE("In.");
139 mgr->dpb_specific_size = dpb_get_size(p_dec);
140 mgr->dpb_size = 15;
141 avs2d_dbg_dpb("create dpb, size %d, specific_size %d\n", mgr->dpb_size, mgr->dpb_specific_size);
142 mgr->dpb = mpp_calloc(Avs2dFrame_t*, mgr->dpb_size);
143 for (i = 0; i < mgr->dpb_size; i++) {
144 mgr->dpb[i] = new_frame();
145 MEM_CHECK(ret, mgr->dpb[i]);
146 mpp_frame_init(&mgr->dpb[i]->frame);
147 avs2d_dbg_dpb("DPB[%d], frame %p", i, mgr->dpb[i]->frame);
148 MEM_CHECK(ret, mgr->dpb[i]->frame);
149 }
150
151 dpb_init_management(mgr);
152 mgr->initial_flag = 1;
153 __FAILED:
154 AVS2D_PARSE_TRACE("Out.");
155 return ret;
156 }
157
avs2d_dpb_destroy(Avs2dCtx_t * p_dec)158 MPP_RET avs2d_dpb_destroy(Avs2dCtx_t *p_dec)
159 {
160 MPP_RET ret = MPP_OK;
161 RK_U32 i;
162 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
163
164 AVS2D_PARSE_TRACE("In.");
165 for (i = 0; i < mgr->dpb_size; i++) {
166 mpp_frame_deinit(&mgr->dpb[i]->frame);
167 MPP_FREE(mgr->dpb[i]);
168 }
169
170 MPP_FREE(mgr->dpb);
171 mgr->initial_flag = 0;
172
173 AVS2D_PARSE_TRACE("Out.");
174 return ret;
175 }
176
recompute_cycle_order_index(Avs2dFrameMgr_t * mgr,Avs2dPicHeader_t * ph)177 static void recompute_cycle_order_index(Avs2dFrameMgr_t *mgr, Avs2dPicHeader_t *ph)
178 {
179 RK_U32 i;
180 RK_S32 wrap_oi;
181 Avs2dFrame_t *p;
182
183 if (ph->doi < (INT_MAX - 2 * AVS2_DOI_CYCLE)) {
184 return;
185 }
186
187 wrap_oi = (mgr->tr_wrap_cnt - 1) * AVS2_DOI_CYCLE;
188 for (i = 0; i < mgr->dpb_size; i++) {
189 p = mgr->dpb[i];
190 if (p->slot_idx == NO_VAL) {
191 continue;
192 }
193 p->doi -= wrap_oi;
194 p->poi -= wrap_oi;
195 }
196
197 ph->doi -= wrap_oi;
198 if (mgr->output_poi != NO_VAL) {
199 mgr->output_poi -= wrap_oi;
200 }
201 }
202
compute_frame_order_index(Avs2dCtx_t * p_dec)203 static void compute_frame_order_index(Avs2dCtx_t *p_dec)
204 {
205 Avs2dSeqHeader_t *vsh = &p_dec->vsh;
206 Avs2dPicHeader_t *ph = &p_dec->ph;
207 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
208 RK_U32 i = 0;
209 Avs2dFrame_t *p;
210
211 //!< DOI should be a periodically-repeated value from 0 to 255
212 if (mgr->output_poi != -1 &&
213 ph->doi != (mgr->prev_doi + 1) % AVS2_DOI_CYCLE) {
214 AVS2D_DBG(AVS2D_DBG_WARNNING, "discontinuous DOI (prev: %d --> curr: %d).", mgr->prev_doi, ph->doi);
215 for (i = 0; i < mgr->dpb_size; i++) {
216 p = mgr->dpb[i];
217 if (p->slot_idx == NO_VAL) {
218 continue;
219 }
220
221 if (MPP_ABS(ph->doi - (p->doi % AVS2_DOI_CYCLE)) > 1) {
222 p->refered_by_others = 0;
223 p->refered_by_scene = 0;
224 }
225 }
226 }
227
228 //!< update DOI
229 if (ph->doi < mgr->prev_doi) {
230 mgr->tr_wrap_cnt++;
231 }
232
233 mgr->prev_doi = ph->doi;
234 ph->doi += mgr->tr_wrap_cnt * AVS2_DOI_CYCLE;
235 recompute_cycle_order_index(mgr, ph);
236
237 avs2d_dbg_dpb("low_delay %d, reorder_delay %d\n", vsh->low_delay, vsh->picture_reorder_delay);
238 if (vsh->low_delay == 0) {
239 ph->poi = ph->doi + ph->picture_output_delay - vsh->picture_reorder_delay;
240 } else {
241 ph->poi = ph->doi;
242 }
243
244 mpp_assert(ph->doi >= 0 && ph->poi >= 0);
245
246 if (mgr->output_poi == NO_VAL && ph->picture_type == I_PICTURE) {
247 mgr->output_poi = ph->poi;
248 }
249
250 avs2d_dbg_dpb("picuture DOI %d, POI %d, out_delay %d, output_poi %d\n", ph->doi, ph->poi, ph->picture_output_delay, mgr->output_poi);
251 }
252
is_outputable_frame(Avs2dFrame_t * p)253 static RK_S32 is_outputable_frame(Avs2dFrame_t *p)
254 {
255 // if (p && p->slot_idx != NO_VAL && !p->invisible && !p->is_output && p->is_decoded) {
256 if (p && p->slot_idx != NO_VAL && !p->invisible && !p->is_output) {
257 return 1;
258 }
259
260 return 0;
261 }
262
get_outputable_smallest_poi(Avs2dFrameMgr_t * mgr,RK_S32 * poi,RK_S32 * pos)263 static RK_S32 get_outputable_smallest_poi(Avs2dFrameMgr_t *mgr, RK_S32 *poi, RK_S32 *pos)
264 {
265 RK_U32 i = 0;
266 RK_S32 find_flag = 0;
267 RK_S32 min_pos = -1;
268 RK_S32 min_poi = INT_MAX;
269 Avs2dFrame_t *p;
270
271 *pos = -1;
272 *poi = INT_MAX;
273 for (i = 0; i < mgr->dpb_size; i++) {
274 p = mgr->dpb[i];
275 if (!is_outputable_frame(p)) {
276 continue;
277 }
278 if (min_poi > p->poi) {
279 min_poi = p->poi;
280 min_pos = i;
281 }
282 if (*poi > p->poi && !p->is_output) {
283 *poi = p->poi;
284 *pos = i;
285 find_flag = 1;
286 }
287 }
288 if (!find_flag) {
289 *poi = min_poi;
290 *pos = min_pos;
291 }
292
293 return find_flag;
294 }
295
296 /**
297 * @brief Ouput frame to display queue
298 * Mark frame at DPB as output, but still remain at DPB
299 *
300 * @param p_dec
301 * @param p
302 * @return MPP_RET
303 */
output_display_frame(Avs2dCtx_t * p_dec,Avs2dFrame_t * p)304 static MPP_RET output_display_frame(Avs2dCtx_t *p_dec, Avs2dFrame_t *p)
305 {
306 MPP_RET ret = MPP_NOK;
307
308 avs2d_dbg_dpb("In.");
309 mpp_assert(p);
310 // if (p->slot_idx >= 0 && !p->invisible && !p->is_output && p->is_decoded) {
311 if (p->slot_idx >= 0 && !p->invisible && !p->is_output) {
312 ret = MPP_OK;
313 p->is_output = 1;
314 p_dec->frm_mgr.output_poi = p->poi;
315 mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_QUEUE_USE);
316 mpp_buf_slot_enqueue(p_dec->frame_slots, p->slot_idx, QUEUE_DISPLAY);
317 avs2d_dbg_dpb("output display frame poi %d slot_idx %d, pts %lld", p->poi, p->slot_idx,
318 mpp_frame_get_pts(p->frame));
319 }
320
321 avs2d_dbg_dpb("Out. ret = %d", ret);
322 return ret;
323 }
324
325 /**
326 * @brief Remove frame from DPB
327 *
328 * @param p_dec
329 * @param p
330 * @return MPP_RET
331 */
dpb_remove_frame(Avs2dCtx_t * p_dec,Avs2dFrame_t * p)332 static MPP_RET dpb_remove_frame(Avs2dCtx_t *p_dec, Avs2dFrame_t *p)
333 {
334 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
335 MppFrame frame = p->frame;
336
337 avs2d_dbg_dpb("In.");
338
339 if (p->picture_type == GB_PICTURE || p->invisible) {
340 MppBuffer buffer = NULL;
341 mpp_buf_slot_get_prop(p_dec->frame_slots, p->slot_idx, SLOT_BUFFER, &buffer);
342 mpp_buffer_put(buffer);
343 }
344
345 mpp_buf_slot_clr_flag(p_dec->frame_slots, p->slot_idx, SLOT_CODEC_USE);
346 avs2d_dbg_dpb("dpb remove frame slot_idx %d, doi %d poi %d, dpb used %d",
347 p->slot_idx, p->doi, p->poi, mgr->used_size);
348
349 memset(p, 0, sizeof(Avs2dFrame_t));
350 p->frame = frame;
351 p->slot_idx = NO_VAL;
352 p->doi = NO_VAL;
353 p->poi = NO_VAL;
354 mgr->used_size--;
355
356 avs2d_dbg_dpb("Out.");
357 return MPP_OK;
358 }
359
is_refered(Avs2dFrame_t * p)360 static RK_S32 is_refered(Avs2dFrame_t *p)
361 {
362 mpp_assert(p);
363 if (p->refered_by_others || p->refered_by_scene) {
364 return 1;
365 }
366
367 return 0;
368 }
369
unmark_refered(Avs2dFrame_t * p)370 static void unmark_refered(Avs2dFrame_t *p)
371 {
372 mpp_assert(p);
373 p->refered_by_scene = 0;
374 p->refered_by_others = 0;
375 }
376
unmark_other_refered(Avs2dFrame_t * p)377 static void unmark_other_refered(Avs2dFrame_t *p)
378 {
379 p->refered_by_others = 0;
380 }
381
dpb_remove_scene_frame(Avs2dCtx_t * p_dec)382 static MPP_RET dpb_remove_scene_frame(Avs2dCtx_t *p_dec)
383 {
384 MPP_RET ret = MPP_OK;
385 Avs2dFrame_t *p = NULL;
386 Avs2dPicHeader_t *ph = &p_dec->ph;
387 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
388
389 avs2d_dbg_dpb("In.");
390 if (ph->picture_type == G_PICTURE || ph->picture_type == GB_PICTURE) {
391 if (mgr->scene_ref) {
392 p = mgr->scene_ref;
393 p->refered_by_scene = 0;
394 //!< remove GB frame directly
395 if (p->picture_type == GB_PICTURE) {
396 FUN_CHECK(ret = dpb_remove_frame(p_dec, p));
397 }
398 mgr->scene_ref = NULL;
399 }
400 }
401
402 __FAILED:
403 avs2d_dbg_dpb("Out.");
404 return ret;
405 }
406
dpb_remove_unused_frame(Avs2dCtx_t * p_dec)407 MPP_RET dpb_remove_unused_frame(Avs2dCtx_t *p_dec)
408 {
409 RK_U32 i = 0;
410 MPP_RET ret = MPP_OK;
411 Avs2dFrame_t *p = NULL;
412 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
413
414 AVS2D_PARSE_TRACE("In.");
415 for (i = 0; i < mgr->dpb_size; i++) {
416 p = mgr->dpb[i];
417 if (p->slot_idx == NO_VAL) {
418 continue;
419 }
420
421 if ((MPP_ABS(p->poi - p_dec->ph.poi) >= AVS2_MAX_POC_DISTANCE)) {
422 p->refered_by_others = 0;
423 p->refered_by_scene = 0;
424 }
425
426 if ((p->is_output || p->invisible) && !is_refered(p)) {
427 FUN_CHECK(ret = dpb_remove_frame(p_dec, p));
428 }
429 }
430
431 __FAILED:
432 AVS2D_PARSE_TRACE("Out.");
433 return ret;
434 }
435
dpb_get_one_frame(Avs2dFrameMgr_t * mgr,Avs2dSeqHeader_t * vsh,Avs2dPicHeader_t * ph)436 static Avs2dFrame_t *dpb_get_one_frame(Avs2dFrameMgr_t *mgr, Avs2dSeqHeader_t *vsh, Avs2dPicHeader_t *ph)
437 {
438 RK_U32 i;
439 Avs2dFrame_t *p = NULL;
440
441 //!< get paired field frame
442 if (vsh->field_coded_sequence) {
443 for (i = 0; i < mgr->dpb_size; i++) {
444 p = mgr->dpb[i];
445 if (p->slot_idx == NO_VAL) {
446 continue;
447 }
448
449 if (p->poi == ph->poi) {
450 return p;
451 }
452 }
453 }
454
455 //!< get unused frame
456 for (i = 0; i < mgr->dpb_size; i++) {
457 p = mgr->dpb[i];
458 if (p->slot_idx == NO_VAL) {
459 break;
460 }
461 }
462
463 return p;
464 }
465
dpb_alloc_frame(Avs2dCtx_t * p_dec,HalDecTask * task)466 static Avs2dFrame_t *dpb_alloc_frame(Avs2dCtx_t *p_dec, HalDecTask *task)
467 {
468 MPP_RET ret = MPP_OK;
469 MppFrame mframe = NULL;
470 Avs2dFrame_t *frm = NULL;
471 Avs2dSeqHeader_t *vsh = &p_dec->vsh;
472 Avs2dPicHeader_t *ph = &p_dec->ph;
473 Avs2dSeqExtHeader_t *exh = &p_dec->exh;
474 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
475 RK_U32 ctu_size = 1 << (p_dec->vsh.lcu_size);
476 RK_U32 bitdepth = p_dec->vsh.bit_depth;
477 RK_U32 ver_stride = vsh->vertical_size;
478
479 avs2d_dbg_dpb("In.");
480 frm = dpb_get_one_frame(mgr, vsh, ph);
481 if (!frm) {
482 mpp_err("Failed to get dpb buffer.\n");
483 return NULL;
484 }
485
486 mframe = frm->frame;
487 frm->doi = ph->doi;
488 frm->poi = ph->poi;
489 frm->out_delay = ph->picture_output_delay;
490 frm->picture_type = ph->picture_type;
491 frm->invisible = (frm->picture_type == GB_PICTURE);
492 frm->scene_frame_flag = (frm->picture_type == G_PICTURE || frm->picture_type == GB_PICTURE);
493 frm->intra_frame_flag = (frm->scene_frame_flag || frm->picture_type == I_PICTURE);
494 frm->refered_by_scene = frm->scene_frame_flag;
495 frm->refered_by_others = (frm->picture_type != GB_PICTURE && mgr->cur_rps.refered_by_others);
496 avs2d_dbg_dpb("frame picture type %d, ref by others %d\n", frm->picture_type, frm->refered_by_others);
497 if (vsh->chroma_format == CHROMA_420 && vsh->bit_depth == 8) {
498 mpp_frame_set_fmt(mframe, MPP_FMT_YUV420SP);
499 } else if (vsh->chroma_format == CHROMA_420 && vsh->bit_depth == 10) {
500 mpp_frame_set_fmt(mframe, MPP_FMT_YUV420SP_10BIT);
501 }
502
503 if (MPP_FRAME_FMT_IS_FBC(p_dec->init.cfg->base.out_fmt)) {
504 // fbc header alignment
505 RK_U32 fbc_hdr_stride = MPP_ALIGN(vsh->horizontal_size, 64);
506
507 mpp_frame_set_fmt(mframe, mpp_frame_get_fmt(mframe) | (p_dec->init.cfg->base.out_fmt & (MPP_FRAME_FBC_MASK)));
508
509 if (*compat_ext_fbc_hdr_256_odd)
510 fbc_hdr_stride = MPP_ALIGN(vsh->horizontal_size, 256) | 256;
511
512 mpp_frame_set_fbc_hdr_stride(mframe, fbc_hdr_stride);
513 // fbc output frame update
514 mpp_frame_set_offset_y(mframe, 8);
515 ver_stride += 16;
516 }
517
518 if (p_dec->is_hdr)
519 mpp_frame_set_fmt(mframe, mpp_frame_get_fmt(mframe) | MPP_FRAME_HDR);
520
521 if (p_dec->init.cfg->base.enable_thumbnail && p_dec->init.hw_info->cap_down_scale)
522 mpp_frame_set_thumbnail_en(mframe, 1);
523 else
524 mpp_frame_set_thumbnail_en(mframe, 0);
525
526 mpp_frame_set_width(mframe, vsh->horizontal_size);
527 mpp_frame_set_height(mframe, vsh->vertical_size);
528 mpp_frame_set_hor_stride(mframe, (MPP_ALIGN(vsh->horizontal_size, ctu_size) * bitdepth + 7) / 8);
529 mpp_frame_set_ver_stride(mframe, MPP_ALIGN(ver_stride, ctu_size));
530 mpp_frame_set_pts(mframe, mpp_packet_get_pts(task->input_packet));
531 mpp_frame_set_dts(mframe, mpp_packet_get_dts(task->input_packet));
532 mpp_frame_set_errinfo(mframe, 0);
533 mpp_frame_set_discard(mframe, 0);
534 mpp_frame_set_poc(mframe, frm->poi);
535 if (p_dec->got_exh) {
536 mpp_frame_set_color_primaries(mframe, exh->color_primaries);
537 mpp_frame_set_color_trc(mframe, exh->transfer_characteristics);
538 }
539 mpp_frame_set_content_light(mframe, p_dec->content_light);
540 mpp_frame_set_mastering_display(mframe, p_dec->display_meta);
541 if (p_dec->hdr_dynamic_meta && p_dec->hdr_dynamic) {
542 mpp_frame_set_hdr_dynamic_meta(mframe, p_dec->hdr_dynamic_meta);
543 p_dec->hdr_dynamic = 0;
544 }
545 if (vsh->progressive_sequence) {
546 frm->frame_mode = MPP_FRAME_FLAG_FRAME;
547 frm->frame_coding_mode = MPP_FRAME_FLAG_FRAME;
548 } else {
549 frm->frame_mode = MPP_FRAME_FLAG_PAIRED_FIELD;
550 if (vsh->field_coded_sequence) {
551 frm->frame_coding_mode = MPP_FRAME_FLAG_PAIRED_FIELD;
552 if (ph->top_field_first) {
553 frm->frame_mode |= MPP_FRAME_FLAG_TOP_FIRST;
554 frm->frame_coding_mode |= MPP_FRAME_FLAG_TOP_FIRST;
555 } else {
556 frm->frame_mode |= MPP_FRAME_FLAG_BOT_FIRST;
557 frm->frame_coding_mode |= MPP_FRAME_FLAG_BOT_FIRST;
558 }
559 } else {
560 frm->frame_coding_mode = MPP_FRAME_FLAG_FRAME;
561 if (ph->top_field_first) {
562 frm->frame_mode |= MPP_FRAME_FLAG_TOP_FIRST;
563 } else {
564 frm->frame_mode |= MPP_FRAME_FLAG_BOT_FIRST;
565 }
566 }
567 }
568
569 mpp_frame_set_mode(mframe, frm->frame_mode);
570 ret = mpp_buf_slot_get_unused(p_dec->frame_slots, &frm->slot_idx);
571 mpp_assert(ret == MPP_OK);
572 mgr->used_size++;
573 avs2d_dbg_dpb("get unused buf slot %d, DPB used %d \n", frm->slot_idx, mgr->used_size);
574 avs2d_dbg_dpb("Out.");
575 return frm;
576 }
577
dpb_output_next_frame(Avs2dCtx_t * p_dec,RK_S32 continuous)578 static MPP_RET dpb_output_next_frame(Avs2dCtx_t *p_dec, RK_S32 continuous)
579 {
580 MPP_RET ret = MPP_NOK;
581 RK_S32 poi, pos;
582 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
583
584 AVS2D_PARSE_TRACE("In.");
585 if (get_outputable_smallest_poi(mgr, &poi, &pos)) {
586 avs2d_dbg_dpb("smallest poi %d, pos %d, output_poi %d\n",
587 poi, pos, mgr->output_poi);
588
589 if ((poi - mgr->output_poi <= 1) ||
590 (mgr->dpb[pos]->doi + mgr->dpb[pos]->out_delay < mgr->cur_frm->doi) ||
591 !continuous) {
592 FUN_CHECK(ret = output_display_frame(p_dec, mgr->dpb[pos]));
593 if (!is_refered(mgr->dpb[pos])) {
594 FUN_CHECK(ret = dpb_remove_frame(p_dec, mgr->dpb[pos]));
595 }
596 }
597 }
598
599 AVS2D_PARSE_TRACE("Out.");
600 __FAILED:
601 return ret;
602 }
603
find_ref_frame(Avs2dFrameMgr_t * mgr,RK_S32 doi)604 static Avs2dFrame_t *find_ref_frame(Avs2dFrameMgr_t *mgr, RK_S32 doi)
605 {
606 RK_U32 i;
607 Avs2dFrame_t *p = NULL;
608
609 avs2d_dbg_dpb("In.");
610 for (i = 0; i < mgr->dpb_size; i++) {
611 p = mgr->dpb[i];
612
613 if (p->slot_idx == NO_VAL || p->doi == NO_VAL) {
614 continue;
615 }
616
617 if (p->doi >= 0 && doi == p->doi) {
618 if (!is_refered(p)) {
619 // DOI matched but not a referenced frame
620 p->error_flag = 1;
621 AVS2D_DBG(AVS2D_DBG_WARNNING, "invalid reference frame [doi: %d].\n", doi);
622 }
623 avs2d_dbg_dpb("found ref[%d] at slot_idx %d, doi %d", i, p->slot_idx, p->doi);
624 return p;
625 }
626 }
627
628 AVS2D_DBG(AVS2D_DBG_ERROR, "reference frame [doi: %d] missed.\n", doi);
629 avs2d_dbg_dpb("Out.");
630 return NULL;
631 }
632
dpb_update_refs(Avs2dCtx_t * p_dec)633 MPP_RET dpb_update_refs(Avs2dCtx_t *p_dec)
634 {
635 MPP_RET ret = MPP_OK;
636 RK_U32 i;
637 RK_S32 doi_of_remove;
638 Avs2dFrame_t *p;
639 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
640 Avs2dRps_t *p_rps = &mgr->cur_rps;
641 avs2d_dbg_dpb("In.");
642
643 if (!mgr->cur_frm) {
644 ret = MPP_NOK;
645 AVS2D_DBG(AVS2D_DBG_WARNNING, "No current frame to update dpb.\n");
646 goto __FAILED;
647 }
648
649 //!< update scene reference frame
650 if (mgr->cur_frm->refered_by_scene) {
651 mgr->scene_ref = mgr->cur_frm;
652 }
653
654 //!< update reference frame flag
655 for (i = 0; i < p_rps->num_to_remove; i++) {
656 doi_of_remove = mgr->cur_frm->doi - p_rps->remove_pic[i];
657 avs2d_dbg_dpb("current doi %d, remove_pic[%d]=%d", mgr->cur_frm->doi, i, p_rps->remove_pic[i]);
658 p = find_ref_frame(mgr, doi_of_remove);
659 if (p) {
660 unmark_other_refered(p);
661 avs2d_dbg_dpb("unmark picture refered, slot_idx %d, doi %d poi %d",
662 p->slot_idx, p->doi, p->poi);
663 }
664 }
665
666 __FAILED:
667 avs2d_dbg_dpb("Out. ret %d", ret);
668 return ret;
669 }
670
dpb_set_frame_refs(Avs2dCtx_t * p_dec,Avs2dFrameMgr_t * mgr,HalDecTask * task)671 static MPP_RET dpb_set_frame_refs(Avs2dCtx_t *p_dec, Avs2dFrameMgr_t *mgr, HalDecTask *task)
672 {
673 MPP_RET ret = MPP_OK;
674 RK_U32 i = 0;
675 RK_U8 error_flag = 0;
676 RK_U8 num_of_ref;
677 RK_S32 doi_of_ref;
678 Avs2dRps_t *p_rps;
679 Avs2dFrame_t *p_cur, *p;
680 RK_U8 replace_ref_flag = 0;
681
682 (void) task;
683
684 avs2d_dbg_dpb("In.");
685 memset(mgr->refs, 0, sizeof(mgr->refs));
686
687 p_cur = mgr->cur_frm;
688 mgr->num_of_ref = 0;
689 p_rps = &mgr->cur_rps;
690 num_of_ref = p_rps->num_of_ref;
691 task->flags.ref_miss = 0;
692 for (i = 0; i < num_of_ref; i++) {
693 doi_of_ref = p_cur->doi - p_rps->ref_pic[i];
694 p = find_ref_frame(mgr, doi_of_ref);
695 if (!p) {
696 task->flags.ref_miss |= 1 << i;
697 avs2d_dbg_dpb("Missing ref doi %d", doi_of_ref);
698 } else {
699 mgr->refs[mgr->num_of_ref] = p;
700 mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_CODEC_USE);
701 mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_HAL_INPUT);
702 }
703
704 mgr->num_of_ref++;
705 }
706
707 if (mgr->num_of_ref < 1 && !p_cur->intra_frame_flag) {
708 error_flag = 1;
709 } else if (p_cur->picture_type == S_PICTURE) {
710 p_cur->refered_bg_frame = 1;
711 if (!mgr->scene_ref) {
712 error_flag = 1;
713 } else if (mgr->scene_ref != mgr->refs[0] || mgr->num_of_ref > 1) {
714 AVS2D_DBG(AVS2D_DBG_ERROR, "Error reference frame(doi %ld ~ %ld) for S.\n",
715 mgr->scene_ref->doi, mgr->refs[0] ? mgr->refs[0]->doi : -1);
716 replace_ref_flag = 1;
717 p_dec->syntax.refp.scene_ref_replace_pos = 0;
718 }
719 } else if ((p_cur->picture_type == P_PICTURE || p_cur->picture_type == F_PICTURE) &&
720 p_dec->ph.background_reference_flag) {
721 p_cur->refered_bg_frame = 1;
722 if (!mgr->scene_ref) {
723 error_flag = 1;
724 } else {
725 replace_ref_flag = 1;
726 p_dec->syntax.refp.scene_ref_replace_pos = mgr->num_of_ref - 1;
727 }
728 } else if (p_cur->picture_type == B_PICTURE &&
729 (mgr->num_of_ref != 2 || (mgr->refs[0] && mgr->refs[0]->poi <= p_cur->poi) ||
730 (mgr->refs[1] && mgr->refs[1]->poi >= p_cur->poi))) {
731 error_flag = 1;
732 }
733
734 if (replace_ref_flag && mgr->scene_ref) {
735 p_dec->syntax.refp.scene_ref_enable = 1;
736 p_dec->syntax.refp.scene_ref_slot_idx = mgr->scene_ref->slot_idx;
737 } else {
738 p_dec->syntax.refp.scene_ref_enable = 0;
739 }
740
741 if (error_flag) {
742 ret = MPP_NOK;
743 mpp_frame_set_errinfo(p_cur->frame, MPP_FRAME_ERR_UNKNOW);
744 AVS2D_DBG(AVS2D_DBG_ERROR, "Error reference frame for picture(%d).\n", p_cur->picture_type);
745 goto __FAILED;
746 }
747
748 __FAILED:
749 avs2d_dbg_dpb("Out. ret %d", ret);
750 return ret;
751 }
752
avs2d_dpb_insert(Avs2dCtx_t * p_dec,HalDecTask * task)753 MPP_RET avs2d_dpb_insert(Avs2dCtx_t *p_dec, HalDecTask *task)
754 {
755 MPP_RET ret = MPP_OK;
756 RK_U32 i;
757 Avs2dFrame_t *p;
758 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
759
760 AVS2D_PARSE_TRACE("In.");
761
762 compute_frame_order_index(p_dec);
763
764 //!< output frame from dpb
765 dpb_output_next_frame(p_dec, 1);
766
767 //!< remove scene(G/GB) frame(scene dbp has only one G/GB)
768 dpb_remove_scene_frame(p_dec);
769
770 //!< remove unused dpb frame
771 dpb_remove_unused_frame(p_dec);
772
773 //!< set task with new frame
774 p = dpb_alloc_frame(p_dec, task);
775 p_dec->frame_no++;
776 avs2d_dbg_dpb("get unused frame from dpb %d", p->slot_idx);
777 if (!p) {
778 ret = MPP_ERR_NOMEM;
779 mpp_err("Failed to alloc dpb frame.\n");
780 goto __FAILED;
781 }
782
783 mgr->cur_frm = p;
784 mpp_buf_slot_set_prop(p_dec->frame_slots, p->slot_idx, SLOT_FRAME, p->frame);
785 mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_CODEC_USE);
786 mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_HAL_OUTPUT);
787
788 //!< set task output
789 task->output = mgr->cur_frm->slot_idx;
790 avs2d_dbg_dpb("curframe slot_idx %d\n", mgr->cur_frm->slot_idx);
791
792 //!< set task refers
793 ret = dpb_set_frame_refs(p_dec, mgr, task);
794 if (ret)
795 task->flags.ref_err = 0;
796
797 for (i = 0; i < mgr->num_of_ref; i++) {
798 task->refer[i] = mgr->refs[i] ? mgr->refs[i]->slot_idx : -1;
799 if (mgr->refs[i]) {
800 task->refer[i] = mgr->refs[i]->slot_idx;
801 avs2d_dbg_dpb("task refer[%d] slot_idx %d doi %d poi %d", i, task->refer[i], mgr->refs[i]->doi, mgr->refs[i]->poi);
802 } else {
803 task->refer[i] = -1;
804 avs2d_dbg_dpb("task refer[%d] missing ref\n", i);
805 }
806 }
807
808 //!< update dpb by rps
809 dpb_update_refs(p_dec);
810
811 avs2d_dbg_dpb("--------DPB INFO--------");
812 avs2d_dbg_dpb("dpb_idx slt_idx doi poi type out refered\n");
813 Avs2dFrame_t *tmp;
814 for (i = 0; i < mgr->dpb_size; i++) {
815 tmp = mgr->dpb[i];
816 avs2d_dbg_dpb("%02d %02d %02d %02d %c %d %d",
817 i, tmp->slot_idx, tmp->doi, tmp->poi, PICTURE_TYPE_TO_CHAR(tmp->picture_type),
818 tmp->is_output, tmp->refered_by_others | tmp->refered_by_scene);
819 }
820 avs2d_dbg_dpb("------------------------");
821
822 __FAILED:
823 AVS2D_PARSE_TRACE("Out.");
824 return ret;
825 }
826
avs2d_dpb_flush(Avs2dCtx_t * p_dec)827 MPP_RET avs2d_dpb_flush(Avs2dCtx_t *p_dec)
828 {
829 MPP_RET ret = MPP_OK;
830 RK_U32 i;
831 Avs2dFrame_t *p;
832 Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
833
834 AVS2D_PARSE_TRACE("In.");
835 //!< unmark all frames refered flag
836 for (i = 0; i < mgr->dpb_size; i++) {
837 p = mgr->dpb[i];
838 if (p->slot_idx != NO_VAL) {
839 unmark_refered(p);
840 }
841 }
842
843 //!< remove all unused frame
844 dpb_remove_unused_frame(p_dec);
845
846 //!< output frames in POI order
847 while (mgr->used_size) {
848 if ((ret = dpb_output_next_frame(p_dec, 0)) != MPP_OK) {
849 break;
850 }
851 }
852
853 //!< reset dpb management
854 dpb_init_management(mgr);
855
856 AVS2D_PARSE_TRACE("In.");
857 return ret;
858 }
859