xref: /rockchip-linux_mpp/mpp/codec/dec/avs2/avs2d_dpb.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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 
476     avs2d_dbg_dpb("In.");
477     frm = dpb_get_one_frame(mgr, vsh, ph);
478     if (!frm) {
479         mpp_err("Failed to get dpb buffer.\n");
480         return NULL;
481     }
482 
483     mframe = frm->frame;
484     frm->doi = ph->doi;
485     frm->poi = ph->poi;
486     frm->out_delay = ph->picture_output_delay;
487     frm->picture_type = ph->picture_type;
488     frm->invisible = (frm->picture_type == GB_PICTURE);
489     frm->scene_frame_flag = (frm->picture_type == G_PICTURE || frm->picture_type == GB_PICTURE);
490     frm->intra_frame_flag = (frm->scene_frame_flag || frm->picture_type == I_PICTURE);
491     frm->refered_by_scene = frm->scene_frame_flag;
492     frm->refered_by_others = (frm->picture_type != GB_PICTURE && mgr->cur_rps.refered_by_others);
493     avs2d_dbg_dpb("frame picture type %d, ref by others %d\n", frm->picture_type, frm->refered_by_others);
494     if (vsh->chroma_format == CHROMA_420 && vsh->bit_depth == 8) {
495         mpp_frame_set_fmt(mframe, MPP_FMT_YUV420SP);
496     } else if (vsh->chroma_format == CHROMA_420 && vsh->bit_depth == 10) {
497         mpp_frame_set_fmt(mframe, MPP_FMT_YUV420SP_10BIT);
498     }
499 
500     if (MPP_FRAME_FMT_IS_FBC(p_dec->init.cfg->base.out_fmt)) {
501         // fbc header alignment
502         RK_U32 fbc_hdr_stride = MPP_ALIGN(vsh->horizontal_size, 64);
503 
504         mpp_frame_set_fmt(mframe, mpp_frame_get_fmt(mframe) | (p_dec->init.cfg->base.out_fmt & (MPP_FRAME_FBC_MASK)));
505 
506         if (*compat_ext_fbc_hdr_256_odd)
507             fbc_hdr_stride = MPP_ALIGN(vsh->horizontal_size, 256) | 256;
508 
509         mpp_frame_set_fbc_hdr_stride(mframe, fbc_hdr_stride);
510 
511         if (mpp_get_soc_type() < ROCKCHIP_SOC_RK3576) {
512             RK_U32 ctu_size = 1 << (p_dec->vsh.lcu_size);
513             // fbc output frame update
514             mpp_frame_set_offset_y(mframe, 8);
515             mpp_frame_set_ver_stride(mframe, MPP_ALIGN(vsh->vertical_size, ctu_size) + 16);
516         }
517     } else if (MPP_FRAME_FMT_IS_TILE(p_dec->init.cfg->base.out_fmt))
518         mpp_frame_set_fmt(mframe, mpp_frame_get_fmt(mframe) | (p_dec->init.cfg->base.out_fmt & (MPP_FRAME_TILE_FLAG)));
519 
520     if (p_dec->is_hdr)
521         mpp_frame_set_fmt(mframe, mpp_frame_get_fmt(mframe) | MPP_FRAME_HDR);
522 
523     if (p_dec->init.cfg->base.enable_thumbnail && p_dec->init.hw_info->cap_down_scale)
524         mpp_frame_set_thumbnail_en(mframe, p_dec->init.cfg->base.enable_thumbnail);
525     else
526         mpp_frame_set_thumbnail_en(mframe, 0);
527 
528     mpp_frame_set_width(mframe, vsh->horizontal_size);
529     mpp_frame_set_height(mframe, vsh->vertical_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         mpp_frame_set_colorspace(mframe, exh->matrix_coefficients);
539     }
540     mpp_frame_set_content_light(mframe, p_dec->content_light);
541     mpp_frame_set_mastering_display(mframe, p_dec->display_meta);
542     if (p_dec->hdr_dynamic_meta && p_dec->hdr_dynamic) {
543         mpp_frame_set_hdr_dynamic_meta(mframe, p_dec->hdr_dynamic_meta);
544         p_dec->hdr_dynamic = 0;
545     }
546     if (vsh->progressive_sequence) {
547         frm->frame_mode = MPP_FRAME_FLAG_FRAME;
548         frm->frame_coding_mode = MPP_FRAME_FLAG_FRAME;
549 
550         if (p_dec->init.cfg->base.enable_vproc & MPP_VPROC_MODE_DETECTION) {
551             frm->frame_mode |= MPP_FRAME_FLAG_DEINTERLACED;
552         }
553     } else {
554         frm->frame_mode = MPP_FRAME_FLAG_PAIRED_FIELD;
555         if (vsh->field_coded_sequence) {
556             frm->frame_coding_mode = MPP_FRAME_FLAG_PAIRED_FIELD;
557             if (ph->top_field_first) {
558                 frm->frame_mode |= MPP_FRAME_FLAG_TOP_FIRST;
559                 frm->frame_coding_mode |= MPP_FRAME_FLAG_TOP_FIRST;
560             } else {
561                 frm->frame_mode |= MPP_FRAME_FLAG_BOT_FIRST;
562                 frm->frame_coding_mode |= MPP_FRAME_FLAG_BOT_FIRST;
563             }
564         } else {
565             frm->frame_coding_mode = MPP_FRAME_FLAG_FRAME;
566             if (ph->top_field_first) {
567                 frm->frame_mode |= MPP_FRAME_FLAG_TOP_FIRST;
568             } else {
569                 frm->frame_mode |= MPP_FRAME_FLAG_BOT_FIRST;
570             }
571         }
572     }
573 
574     mpp_frame_set_mode(mframe, frm->frame_mode);
575     ret = mpp_buf_slot_get_unused(p_dec->frame_slots, &frm->slot_idx);
576     mpp_assert(ret == MPP_OK);
577     mgr->used_size++;
578     avs2d_dbg_dpb("get unused buf slot %d, DPB used %d \n", frm->slot_idx, mgr->used_size);
579     avs2d_dbg_dpb("Out.");
580     return frm;
581 }
582 
dpb_output_next_frame(Avs2dCtx_t * p_dec,RK_S32 continuous)583 static MPP_RET dpb_output_next_frame(Avs2dCtx_t *p_dec, RK_S32 continuous)
584 {
585     MPP_RET ret = MPP_NOK;
586     RK_S32 poi, pos;
587     Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
588 
589     AVS2D_PARSE_TRACE("In.");
590     if (get_outputable_smallest_poi(mgr, &poi, &pos)) {
591         avs2d_dbg_dpb("smallest poi %d, pos %d, output_poi %d\n",
592                       poi, pos, mgr->output_poi);
593 
594         if ((poi - mgr->output_poi <= 1) ||
595             (mgr->dpb[pos]->doi + mgr->dpb[pos]->out_delay < mgr->cur_frm->doi) ||
596             !continuous) {
597             FUN_CHECK(ret = output_display_frame(p_dec, mgr->dpb[pos]));
598             if (!is_refered(mgr->dpb[pos])) {
599                 FUN_CHECK(ret = dpb_remove_frame(p_dec, mgr->dpb[pos]));
600             }
601         }
602     }
603 
604     AVS2D_PARSE_TRACE("Out.");
605 __FAILED:
606     return ret;
607 }
608 
find_ref_frame(Avs2dFrameMgr_t * mgr,RK_S32 doi)609 static Avs2dFrame_t *find_ref_frame(Avs2dFrameMgr_t *mgr, RK_S32 doi)
610 {
611     RK_U32 i;
612     Avs2dFrame_t *p = NULL;
613 
614     avs2d_dbg_dpb("In.");
615     for (i = 0; i < mgr->dpb_size; i++) {
616         p = mgr->dpb[i];
617 
618         if (p->slot_idx == NO_VAL || p->doi == NO_VAL) {
619             continue;
620         }
621 
622         if (p->doi >= 0 && doi == p->doi) {
623             if (!is_refered(p)) {
624                 // DOI matched but not a referenced frame
625                 p->error_flag = 1;
626                 AVS2D_DBG(AVS2D_DBG_WARNNING, "invalid reference frame [doi: %d].\n", doi);
627             }
628             avs2d_dbg_dpb("found ref[%d] at slot_idx %d, doi %d", i, p->slot_idx, p->doi);
629             return p;
630         }
631     }
632 
633     AVS2D_DBG(AVS2D_DBG_ERROR, "reference frame [doi: %d] missed.\n", doi);
634     avs2d_dbg_dpb("Out.");
635     return NULL;
636 }
637 
dpb_update_refs(Avs2dCtx_t * p_dec)638 MPP_RET dpb_update_refs(Avs2dCtx_t *p_dec)
639 {
640     MPP_RET ret = MPP_OK;
641     RK_U32 i;
642     RK_S32 doi_of_remove;
643     Avs2dFrame_t *p;
644     Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
645     Avs2dRps_t *p_rps = &mgr->cur_rps;
646     avs2d_dbg_dpb("In.");
647 
648     if (!mgr->cur_frm) {
649         ret = MPP_NOK;
650         AVS2D_DBG(AVS2D_DBG_WARNNING, "No current frame to update dpb.\n");
651         goto __FAILED;
652     }
653 
654     //!< update scene reference frame
655     if (mgr->cur_frm->refered_by_scene) {
656         mgr->scene_ref = mgr->cur_frm;
657     }
658 
659     //!< update reference frame flag
660     for (i = 0; i < p_rps->num_to_remove; i++) {
661         doi_of_remove = mgr->cur_frm->doi - p_rps->remove_pic[i];
662         avs2d_dbg_dpb("current doi %d, remove_pic[%d]=%d", mgr->cur_frm->doi, i, p_rps->remove_pic[i]);
663         p = find_ref_frame(mgr, doi_of_remove);
664         if (p) {
665             unmark_other_refered(p);
666             avs2d_dbg_dpb("unmark picture refered, slot_idx %d, doi %d poi %d",
667                           p->slot_idx, p->doi, p->poi);
668         }
669     }
670 
671 __FAILED:
672     avs2d_dbg_dpb("Out. ret %d", ret);
673     return ret;
674 }
675 
dpb_set_frame_refs(Avs2dCtx_t * p_dec,Avs2dFrameMgr_t * mgr,HalDecTask * task)676 static MPP_RET dpb_set_frame_refs(Avs2dCtx_t *p_dec, Avs2dFrameMgr_t *mgr, HalDecTask *task)
677 {
678     MPP_RET ret = MPP_OK;
679     RK_U32 i = 0;
680     RK_U8 error_flag = 0;
681     RK_U8 num_of_ref;
682     RK_S32 doi_of_ref;
683     Avs2dRps_t *p_rps;
684     Avs2dFrame_t *p_cur, *p;
685     RK_U8 replace_ref_flag = 0;
686 
687     (void) task;
688 
689     avs2d_dbg_dpb("In.");
690     memset(mgr->refs, 0, sizeof(mgr->refs));
691 
692     p_cur = mgr->cur_frm;
693     mgr->num_of_ref = 0;
694     p_rps = &mgr->cur_rps;
695     num_of_ref = p_rps->num_of_ref;
696     task->flags.ref_miss = 0;
697     for (i = 0; i < num_of_ref; i++) {
698         doi_of_ref = p_cur->doi - p_rps->ref_pic[i];
699         p = find_ref_frame(mgr, doi_of_ref);
700         if (!p) {
701             task->flags.ref_miss |= 1 << i;
702             avs2d_dbg_dpb("Missing ref doi %d", doi_of_ref);
703         } else {
704             mgr->refs[mgr->num_of_ref] = p;
705             mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_CODEC_USE);
706             mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_HAL_INPUT);
707         }
708 
709         mgr->num_of_ref++;
710     }
711 
712     if (mgr->num_of_ref < 1 && !p_cur->intra_frame_flag) {
713         error_flag = 1;
714     } else if (p_cur->picture_type == S_PICTURE) {
715         p_cur->refered_bg_frame = 1;
716         if (!mgr->scene_ref) {
717             error_flag = 1;
718         } else if (mgr->scene_ref != mgr->refs[0] || mgr->num_of_ref > 1) {
719             AVS2D_DBG(AVS2D_DBG_ERROR, "Error reference frame(doi %ld ~ %ld) for S.\n",
720                       mgr->scene_ref->doi, mgr->refs[0] ? mgr->refs[0]->doi : -1);
721             replace_ref_flag = 1;
722             p_dec->syntax.refp.scene_ref_replace_pos = 0;
723         }
724     } else if ((p_cur->picture_type == P_PICTURE || p_cur->picture_type == F_PICTURE) &&
725                p_dec->ph.background_reference_flag) {
726         p_cur->refered_bg_frame = 1;
727         if (!mgr->scene_ref) {
728             error_flag = 1;
729         } else {
730             replace_ref_flag = 1;
731             p_dec->syntax.refp.scene_ref_replace_pos = mgr->num_of_ref - 1;
732         }
733     } else if (p_cur->picture_type == B_PICTURE &&
734                (mgr->num_of_ref != 2 || (mgr->refs[0] && mgr->refs[0]->poi <= p_cur->poi) ||
735                 (mgr->refs[1] && mgr->refs[1]->poi >= p_cur->poi))) {
736         error_flag = 1;
737     }
738 
739     if (replace_ref_flag && mgr->scene_ref) {
740         p_dec->syntax.refp.scene_ref_enable = 1;
741         p_dec->syntax.refp.scene_ref_slot_idx = mgr->scene_ref->slot_idx;
742     } else {
743         p_dec->syntax.refp.scene_ref_enable = 0;
744     }
745 
746     if (error_flag) {
747         ret = MPP_NOK;
748         mpp_frame_set_errinfo(p_cur->frame, MPP_FRAME_ERR_UNKNOW);
749         AVS2D_DBG(AVS2D_DBG_ERROR, "Error reference frame for picture(%d).\n", p_cur->picture_type);
750         goto __FAILED;
751     }
752 
753 __FAILED:
754     avs2d_dbg_dpb("Out. ret %d", ret);
755     return ret;
756 }
757 
avs2d_dpb_insert(Avs2dCtx_t * p_dec,HalDecTask * task)758 MPP_RET avs2d_dpb_insert(Avs2dCtx_t *p_dec, HalDecTask *task)
759 {
760     MPP_RET ret = MPP_OK;
761     RK_U32 i;
762     Avs2dFrame_t *p;
763     Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
764 
765     AVS2D_PARSE_TRACE("In.");
766 
767     compute_frame_order_index(p_dec);
768 
769     //!< output frame from dpb
770     dpb_output_next_frame(p_dec, 1);
771 
772     //!< remove scene(G/GB) frame(scene dbp has only one G/GB)
773     dpb_remove_scene_frame(p_dec);
774 
775     //!< remove unused dpb frame
776     dpb_remove_unused_frame(p_dec);
777 
778     //!< set task with new frame
779     p = dpb_alloc_frame(p_dec, task);
780     p_dec->frame_no++;
781     avs2d_dbg_dpb("get unused frame from dpb %d", p->slot_idx);
782     if (!p) {
783         ret = MPP_ERR_NOMEM;
784         mpp_err("Failed to alloc dpb frame.\n");
785         goto __FAILED;
786     }
787 
788     mgr->cur_frm = p;
789     mpp_buf_slot_set_prop(p_dec->frame_slots, p->slot_idx, SLOT_FRAME, p->frame);
790     mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_CODEC_USE);
791     mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_HAL_OUTPUT);
792 
793     //!< set task output
794     task->output = mgr->cur_frm->slot_idx;
795     avs2d_dbg_dpb("curframe slot_idx %d\n", mgr->cur_frm->slot_idx);
796 
797     //!< set task refers
798     ret = dpb_set_frame_refs(p_dec, mgr, task);
799     if (ret)
800         task->flags.ref_err = 0;
801 
802     for (i = 0; i < mgr->num_of_ref; i++) {
803         task->refer[i] = mgr->refs[i] ? mgr->refs[i]->slot_idx : -1;
804         if (mgr->refs[i]) {
805             task->refer[i] = mgr->refs[i]->slot_idx;
806             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);
807         } else {
808             task->refer[i] = -1;
809             avs2d_dbg_dpb("task refer[%d] missing ref\n", i);
810         }
811     }
812 
813     //!< update dpb by rps
814     dpb_update_refs(p_dec);
815 
816     avs2d_dbg_dpb("--------DPB INFO--------");
817     avs2d_dbg_dpb("dpb_idx slt_idx doi poi type out refered\n");
818     Avs2dFrame_t *tmp;
819     for (i = 0; i < mgr->dpb_size; i++) {
820         tmp = mgr->dpb[i];
821         avs2d_dbg_dpb("%02d      %02d      %02d  %02d  %c    %d   %d",
822                       i, tmp->slot_idx, tmp->doi, tmp->poi, PICTURE_TYPE_TO_CHAR(tmp->picture_type),
823                       tmp->is_output, tmp->refered_by_others | tmp->refered_by_scene);
824     }
825     avs2d_dbg_dpb("------------------------");
826 
827 __FAILED:
828     AVS2D_PARSE_TRACE("Out.");
829     return ret;
830 }
831 
avs2d_dpb_flush(Avs2dCtx_t * p_dec)832 MPP_RET avs2d_dpb_flush(Avs2dCtx_t *p_dec)
833 {
834     MPP_RET ret = MPP_OK;
835     RK_U32 i;
836     Avs2dFrame_t *p;
837     Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr;
838 
839     AVS2D_PARSE_TRACE("In.");
840     //!< unmark all frames refered flag
841     for (i = 0; i < mgr->dpb_size; i++) {
842         p = mgr->dpb[i];
843         if (p->slot_idx != NO_VAL) {
844             unmark_refered(p);
845         }
846     }
847 
848     //!< remove all unused frame
849     dpb_remove_unused_frame(p_dec);
850 
851     //!< output frames in POI order
852     while (mgr->used_size) {
853         if ((ret = dpb_output_next_frame(p_dec, 0)) != MPP_OK) {
854             break;
855         }
856     }
857 
858     //!< reset dpb management
859     dpb_init_management(mgr);
860 
861     AVS2D_PARSE_TRACE("Out.");
862     return ret;
863 }
864