xref: /rockchip-linux_mpp/mpp/codec/dec/h264/h264d_dpb.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1*437bfbebSnyanmisaka /*
2*437bfbebSnyanmisaka  *
3*437bfbebSnyanmisaka  * Copyright 2015 Rockchip Electronics Co. LTD
4*437bfbebSnyanmisaka  *
5*437bfbebSnyanmisaka  * Licensed under the Apache License, Version 2.0 (the "License");
6*437bfbebSnyanmisaka  * you may not use this file except in compliance with the License.
7*437bfbebSnyanmisaka  * You may obtain a copy of the License at
8*437bfbebSnyanmisaka  *
9*437bfbebSnyanmisaka  *      http://www.apache.org/licenses/LICENSE-2.0
10*437bfbebSnyanmisaka  *
11*437bfbebSnyanmisaka  * Unless required by applicable law or agreed to in writing, software
12*437bfbebSnyanmisaka  * distributed under the License is distributed on an "AS IS" BASIS,
13*437bfbebSnyanmisaka  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*437bfbebSnyanmisaka  * See the License for the specific language governing permissions and
15*437bfbebSnyanmisaka  * limitations under the License.
16*437bfbebSnyanmisaka  */
17*437bfbebSnyanmisaka 
18*437bfbebSnyanmisaka #define MODULE_TAG "h264d_dpb"
19*437bfbebSnyanmisaka 
20*437bfbebSnyanmisaka #include <stdio.h>
21*437bfbebSnyanmisaka #include <string.h>
22*437bfbebSnyanmisaka 
23*437bfbebSnyanmisaka #include "mpp_common.h"
24*437bfbebSnyanmisaka #include "mpp_buf_slot.h"
25*437bfbebSnyanmisaka 
26*437bfbebSnyanmisaka #include "h264d_scalist.h"
27*437bfbebSnyanmisaka #include "h264d_dpb.h"
28*437bfbebSnyanmisaka #include "h264d_init.h"
29*437bfbebSnyanmisaka 
30*437bfbebSnyanmisaka #ifndef INT_MIN
31*437bfbebSnyanmisaka #define INT_MIN     (-2147483647 - 1) /* minimum (signed) int value */
32*437bfbebSnyanmisaka #endif
33*437bfbebSnyanmisaka #ifndef INT_MAX
34*437bfbebSnyanmisaka #define INT_MAX       2147483647      /* maximum (signed) int value */
35*437bfbebSnyanmisaka #endif
RoundLog2(RK_S32 iValue)36*437bfbebSnyanmisaka static RK_S32 RoundLog2(RK_S32 iValue)
37*437bfbebSnyanmisaka {
38*437bfbebSnyanmisaka     RK_S32 iRet = 0;
39*437bfbebSnyanmisaka     RK_S32 iValue_square = iValue * iValue;
40*437bfbebSnyanmisaka 
41*437bfbebSnyanmisaka     while ((1 << (iRet + 1)) <= iValue_square) {
42*437bfbebSnyanmisaka         ++iRet;
43*437bfbebSnyanmisaka     }
44*437bfbebSnyanmisaka     iRet = (iRet + 1) >> 1;
45*437bfbebSnyanmisaka 
46*437bfbebSnyanmisaka     return iRet;
47*437bfbebSnyanmisaka }
48*437bfbebSnyanmisaka 
getDpbSize(H264dVideoCtx_t * p_Vid,H264_SPS_t * active_sps)49*437bfbebSnyanmisaka static RK_S32 getDpbSize(H264dVideoCtx_t *p_Vid, H264_SPS_t *active_sps)
50*437bfbebSnyanmisaka {
51*437bfbebSnyanmisaka     RK_S32 size = 0, num_views = 0;
52*437bfbebSnyanmisaka     RK_S32 pic_size = (active_sps->pic_width_in_mbs_minus1 + 1)
53*437bfbebSnyanmisaka                       * (active_sps->pic_height_in_map_units_minus1 + 1) * (active_sps->frame_mbs_only_flag ? 1 : 2) * 384;
54*437bfbebSnyanmisaka 
55*437bfbebSnyanmisaka     switch (active_sps->level_idc) {
56*437bfbebSnyanmisaka     case 9:
57*437bfbebSnyanmisaka         size = 152064;
58*437bfbebSnyanmisaka         break;
59*437bfbebSnyanmisaka     case 10:
60*437bfbebSnyanmisaka         size = 152064;
61*437bfbebSnyanmisaka         break;
62*437bfbebSnyanmisaka     case 11:
63*437bfbebSnyanmisaka         if (!is_prext_profile(active_sps->profile_idc) && (active_sps->constrained_set3_flag == 1))
64*437bfbebSnyanmisaka             size = 152064;
65*437bfbebSnyanmisaka         else
66*437bfbebSnyanmisaka             size = 345600;
67*437bfbebSnyanmisaka         break;
68*437bfbebSnyanmisaka     case 12:
69*437bfbebSnyanmisaka         size = 912384;
70*437bfbebSnyanmisaka         break;
71*437bfbebSnyanmisaka     case 13:
72*437bfbebSnyanmisaka         size = 912384;
73*437bfbebSnyanmisaka         break;
74*437bfbebSnyanmisaka     case 20:
75*437bfbebSnyanmisaka         size = 912384;
76*437bfbebSnyanmisaka         break;
77*437bfbebSnyanmisaka     case 21:
78*437bfbebSnyanmisaka         size = 1824768;
79*437bfbebSnyanmisaka         break;
80*437bfbebSnyanmisaka     case 22:
81*437bfbebSnyanmisaka         size = 3110400;
82*437bfbebSnyanmisaka         break;
83*437bfbebSnyanmisaka     case 30:
84*437bfbebSnyanmisaka         size = 3110400;
85*437bfbebSnyanmisaka         break;
86*437bfbebSnyanmisaka     case 31:
87*437bfbebSnyanmisaka         size = 6912000;
88*437bfbebSnyanmisaka         break;
89*437bfbebSnyanmisaka     case 32:
90*437bfbebSnyanmisaka         size = 7864320;
91*437bfbebSnyanmisaka         break;
92*437bfbebSnyanmisaka     case 40:
93*437bfbebSnyanmisaka         size = 12582912;
94*437bfbebSnyanmisaka         break;
95*437bfbebSnyanmisaka     case 41:
96*437bfbebSnyanmisaka         size = 12582912;
97*437bfbebSnyanmisaka         break;
98*437bfbebSnyanmisaka     case 42:
99*437bfbebSnyanmisaka         size = 13369344;
100*437bfbebSnyanmisaka         break;
101*437bfbebSnyanmisaka     case 50:
102*437bfbebSnyanmisaka         size = 42393600;
103*437bfbebSnyanmisaka         break;
104*437bfbebSnyanmisaka     case 51:
105*437bfbebSnyanmisaka         size = 70778880;
106*437bfbebSnyanmisaka         break;
107*437bfbebSnyanmisaka     case 52:
108*437bfbebSnyanmisaka         size = 70778880;
109*437bfbebSnyanmisaka         break;
110*437bfbebSnyanmisaka     default:
111*437bfbebSnyanmisaka         size = 0;
112*437bfbebSnyanmisaka         break;
113*437bfbebSnyanmisaka     }
114*437bfbebSnyanmisaka     size /= pic_size;
115*437bfbebSnyanmisaka     if (p_Vid->active_mvc_sps_flag &&
116*437bfbebSnyanmisaka         (p_Vid->profile_idc == H264_PROFILE_MVC_HIGH || p_Vid->profile_idc == H264_PROFILE_STEREO_HIGH)) {
117*437bfbebSnyanmisaka         num_views = p_Vid->active_subsps->num_views_minus1 + 1;
118*437bfbebSnyanmisaka         size = MPP_MIN(2 * size, MPP_MAX(1, RoundLog2(num_views)) * 16) / num_views;
119*437bfbebSnyanmisaka     } else {
120*437bfbebSnyanmisaka         size = MPP_MIN(size, 16);
121*437bfbebSnyanmisaka     }
122*437bfbebSnyanmisaka     if (active_sps->vui_parameters_present_flag && active_sps->vui_seq_parameters.bitstream_restriction_flag) {
123*437bfbebSnyanmisaka         RK_S32 size_vui = 0;
124*437bfbebSnyanmisaka         if ((RK_S32)active_sps->vui_seq_parameters.max_dec_frame_buffering > size) {
125*437bfbebSnyanmisaka             H264D_WARNNING("warnnig: max_dec_frame_buffering larger than MaxDpbSize");
126*437bfbebSnyanmisaka         }
127*437bfbebSnyanmisaka         size_vui = MPP_MAX(1, active_sps->vui_seq_parameters.max_dec_frame_buffering);
128*437bfbebSnyanmisaka         if (size_vui < size) {
129*437bfbebSnyanmisaka             H264D_WARNNING("warning: max_dec_frame_buffering(%d) is less than dpb_size(%d) calculated from Profile/Level.\n", size_vui, size);
130*437bfbebSnyanmisaka         }
131*437bfbebSnyanmisaka         size = size_vui;
132*437bfbebSnyanmisaka     }
133*437bfbebSnyanmisaka 
134*437bfbebSnyanmisaka     if (size < active_sps->max_num_ref_frames) {
135*437bfbebSnyanmisaka         H264D_WARNNING("warnning: DPB size is less than max_num_ref_frames, level(%d), pic_size(%d), max_num_ref_frames(%d).\n",
136*437bfbebSnyanmisaka                        active_sps->level_idc, pic_size, active_sps->max_num_ref_frames);
137*437bfbebSnyanmisaka         size = MPP_MIN(active_sps->max_num_ref_frames, 16);
138*437bfbebSnyanmisaka     }
139*437bfbebSnyanmisaka 
140*437bfbebSnyanmisaka     return size;
141*437bfbebSnyanmisaka }
142*437bfbebSnyanmisaka 
get_pic_num_x(H264_StorePic_t * p,RK_S32 difference_of_pic_nums_minus1)143*437bfbebSnyanmisaka static RK_S32 get_pic_num_x(H264_StorePic_t *p, RK_S32 difference_of_pic_nums_minus1)
144*437bfbebSnyanmisaka {
145*437bfbebSnyanmisaka     RK_S32 currPicNum;
146*437bfbebSnyanmisaka 
147*437bfbebSnyanmisaka     if (p->structure == FRAME)
148*437bfbebSnyanmisaka         currPicNum = p->frame_num;
149*437bfbebSnyanmisaka     else
150*437bfbebSnyanmisaka         currPicNum = 2 * p->frame_num + 1;
151*437bfbebSnyanmisaka 
152*437bfbebSnyanmisaka     return currPicNum - (difference_of_pic_nums_minus1 + 1);
153*437bfbebSnyanmisaka }
154*437bfbebSnyanmisaka 
unmark_for_reference(H264_DecCtx_t * p_Dec,H264_FrameStore_t * fs)155*437bfbebSnyanmisaka static void unmark_for_reference(H264_DecCtx_t *p_Dec, H264_FrameStore_t* fs)
156*437bfbebSnyanmisaka {
157*437bfbebSnyanmisaka     H264_StorePic_t *cur_pic = NULL;
158*437bfbebSnyanmisaka     if (fs->is_used & 1) {
159*437bfbebSnyanmisaka         if (fs->top_field) {
160*437bfbebSnyanmisaka             fs->top_field->used_for_reference = 0;
161*437bfbebSnyanmisaka             cur_pic = fs->top_field;
162*437bfbebSnyanmisaka         }
163*437bfbebSnyanmisaka     }
164*437bfbebSnyanmisaka     if (fs->is_used & 2) {
165*437bfbebSnyanmisaka         if (fs->bottom_field) {
166*437bfbebSnyanmisaka             fs->bottom_field->used_for_reference = 0;
167*437bfbebSnyanmisaka             cur_pic = fs->bottom_field;
168*437bfbebSnyanmisaka         }
169*437bfbebSnyanmisaka     }
170*437bfbebSnyanmisaka     if (fs->is_used == 3) {
171*437bfbebSnyanmisaka         if (fs->top_field && fs->bottom_field) {
172*437bfbebSnyanmisaka             fs->top_field->used_for_reference = 0;
173*437bfbebSnyanmisaka             fs->bottom_field->used_for_reference = 0;
174*437bfbebSnyanmisaka         }
175*437bfbebSnyanmisaka         fs->frame->used_for_reference = 0;
176*437bfbebSnyanmisaka         cur_pic = fs->frame;
177*437bfbebSnyanmisaka     }
178*437bfbebSnyanmisaka     fs->is_reference = 0;
179*437bfbebSnyanmisaka     (void)cur_pic;
180*437bfbebSnyanmisaka     (void)p_Dec;
181*437bfbebSnyanmisaka }
182*437bfbebSnyanmisaka 
is_short_term_reference(H264_FrameStore_t * fs)183*437bfbebSnyanmisaka static RK_U32 is_short_term_reference(H264_FrameStore_t* fs)
184*437bfbebSnyanmisaka {
185*437bfbebSnyanmisaka     if (fs->is_used == 3) { // frame
186*437bfbebSnyanmisaka         if ((fs->frame->used_for_reference) && (!fs->frame->is_long_term)) {
187*437bfbebSnyanmisaka             return 1;
188*437bfbebSnyanmisaka         }
189*437bfbebSnyanmisaka     }
190*437bfbebSnyanmisaka 
191*437bfbebSnyanmisaka     if (fs->is_used & 1) { // top field
192*437bfbebSnyanmisaka         if (fs->top_field) {
193*437bfbebSnyanmisaka             if ((fs->top_field->used_for_reference) && (!fs->top_field->is_long_term)) {
194*437bfbebSnyanmisaka                 return 1;
195*437bfbebSnyanmisaka             }
196*437bfbebSnyanmisaka         }
197*437bfbebSnyanmisaka     }
198*437bfbebSnyanmisaka 
199*437bfbebSnyanmisaka     if (fs->is_used & 2) { // bottom field
200*437bfbebSnyanmisaka         if (fs->bottom_field) {
201*437bfbebSnyanmisaka             if ((fs->bottom_field->used_for_reference) && (!fs->bottom_field->is_long_term)) {
202*437bfbebSnyanmisaka                 return 1;
203*437bfbebSnyanmisaka             }
204*437bfbebSnyanmisaka         }
205*437bfbebSnyanmisaka     }
206*437bfbebSnyanmisaka     return 0;
207*437bfbebSnyanmisaka }
208*437bfbebSnyanmisaka 
is_long_term_reference(H264_FrameStore_t * fs)209*437bfbebSnyanmisaka static RK_U32 is_long_term_reference(H264_FrameStore_t* fs)
210*437bfbebSnyanmisaka {
211*437bfbebSnyanmisaka 
212*437bfbebSnyanmisaka     if (fs->is_used == 3) { // frame
213*437bfbebSnyanmisaka         if ((fs->frame->used_for_reference) && (fs->frame->is_long_term)) {
214*437bfbebSnyanmisaka             return 1;
215*437bfbebSnyanmisaka         }
216*437bfbebSnyanmisaka     }
217*437bfbebSnyanmisaka 
218*437bfbebSnyanmisaka     if (fs->is_used & 1) { // top field
219*437bfbebSnyanmisaka         if (fs->top_field) {
220*437bfbebSnyanmisaka             if ((fs->top_field->used_for_reference) && (fs->top_field->is_long_term)) {
221*437bfbebSnyanmisaka                 return 1;
222*437bfbebSnyanmisaka             }
223*437bfbebSnyanmisaka         }
224*437bfbebSnyanmisaka     }
225*437bfbebSnyanmisaka 
226*437bfbebSnyanmisaka     if (fs->is_used & 2) { // bottom field
227*437bfbebSnyanmisaka         if (fs->bottom_field) {
228*437bfbebSnyanmisaka             if ((fs->bottom_field->used_for_reference) && (fs->bottom_field->is_long_term)) {
229*437bfbebSnyanmisaka                 return 1;
230*437bfbebSnyanmisaka             }
231*437bfbebSnyanmisaka         }
232*437bfbebSnyanmisaka     }
233*437bfbebSnyanmisaka     return 0;
234*437bfbebSnyanmisaka }
235*437bfbebSnyanmisaka 
unmark_for_long_term_reference(H264_FrameStore_t * fs)236*437bfbebSnyanmisaka static void unmark_for_long_term_reference(H264_FrameStore_t* fs)
237*437bfbebSnyanmisaka {
238*437bfbebSnyanmisaka     if (fs->is_used & 1) {
239*437bfbebSnyanmisaka         if (fs->top_field) {
240*437bfbebSnyanmisaka             fs->top_field->used_for_reference = 0;
241*437bfbebSnyanmisaka             fs->top_field->is_long_term = 0;
242*437bfbebSnyanmisaka         }
243*437bfbebSnyanmisaka     }
244*437bfbebSnyanmisaka     if (fs->is_used & 2) {
245*437bfbebSnyanmisaka         if (fs->bottom_field) {
246*437bfbebSnyanmisaka             fs->bottom_field->used_for_reference = 0;
247*437bfbebSnyanmisaka             fs->bottom_field->is_long_term = 0;
248*437bfbebSnyanmisaka         }
249*437bfbebSnyanmisaka     }
250*437bfbebSnyanmisaka     if (fs->is_used == 3) {
251*437bfbebSnyanmisaka         if (fs->top_field && fs->bottom_field) {
252*437bfbebSnyanmisaka             fs->top_field->used_for_reference = 0;
253*437bfbebSnyanmisaka             fs->top_field->is_long_term = 0;
254*437bfbebSnyanmisaka             fs->bottom_field->used_for_reference = 0;
255*437bfbebSnyanmisaka             fs->bottom_field->is_long_term = 0;
256*437bfbebSnyanmisaka         }
257*437bfbebSnyanmisaka         fs->frame->used_for_reference = 0;
258*437bfbebSnyanmisaka         fs->frame->is_long_term = 0;
259*437bfbebSnyanmisaka     }
260*437bfbebSnyanmisaka 
261*437bfbebSnyanmisaka     fs->is_reference = 0;
262*437bfbebSnyanmisaka     fs->is_long_term = 0;
263*437bfbebSnyanmisaka }
264*437bfbebSnyanmisaka 
mm_unmark_short_term_for_reference(H264_DpbBuf_t * p_Dpb,H264_StorePic_t * p,RK_S32 difference_of_pic_nums_minus1)265*437bfbebSnyanmisaka static void mm_unmark_short_term_for_reference(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 difference_of_pic_nums_minus1)
266*437bfbebSnyanmisaka {
267*437bfbebSnyanmisaka     RK_S32 picNumX = 0;
268*437bfbebSnyanmisaka     RK_U32 i = 0;
269*437bfbebSnyanmisaka 
270*437bfbebSnyanmisaka     picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1);
271*437bfbebSnyanmisaka 
272*437bfbebSnyanmisaka     for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
273*437bfbebSnyanmisaka         if (p->structure == FRAME) {
274*437bfbebSnyanmisaka             if ((p_Dpb->fs_ref[i]->is_reference == 3) && (p_Dpb->fs_ref[i]->is_long_term == 0)) {
275*437bfbebSnyanmisaka                 if (p_Dpb->fs_ref[i]->frame->pic_num == picNumX) {
276*437bfbebSnyanmisaka                     unmark_for_reference(p_Dpb->p_Vid->p_Dec, p_Dpb->fs_ref[i]);
277*437bfbebSnyanmisaka                     return;
278*437bfbebSnyanmisaka                 }
279*437bfbebSnyanmisaka             }
280*437bfbebSnyanmisaka         } else {
281*437bfbebSnyanmisaka             if ((p_Dpb->fs_ref[i]->is_reference & 1) && (!(p_Dpb->fs_ref[i]->is_long_term & 1))) {
282*437bfbebSnyanmisaka                 if (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX) {
283*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->top_field->used_for_reference = 0;
284*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->is_reference &= 2;
285*437bfbebSnyanmisaka                     if (p_Dpb->fs_ref[i]->is_used == 3) {
286*437bfbebSnyanmisaka                         p_Dpb->fs_ref[i]->frame->used_for_reference = 0;
287*437bfbebSnyanmisaka                     }
288*437bfbebSnyanmisaka                     return;
289*437bfbebSnyanmisaka                 }
290*437bfbebSnyanmisaka             }
291*437bfbebSnyanmisaka             if ((p_Dpb->fs_ref[i]->is_reference & 2) && (!(p_Dpb->fs_ref[i]->is_long_term & 2))) {
292*437bfbebSnyanmisaka                 if (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX) {
293*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->bottom_field->used_for_reference = 0;
294*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->is_reference &= 1;
295*437bfbebSnyanmisaka                     if (p_Dpb->fs_ref[i]->is_used == 3) {
296*437bfbebSnyanmisaka                         p_Dpb->fs_ref[i]->frame->used_for_reference = 0;
297*437bfbebSnyanmisaka                     }
298*437bfbebSnyanmisaka                     return;
299*437bfbebSnyanmisaka                 }
300*437bfbebSnyanmisaka             }
301*437bfbebSnyanmisaka         }
302*437bfbebSnyanmisaka     }
303*437bfbebSnyanmisaka }
304*437bfbebSnyanmisaka 
mm_unmark_long_term_for_reference(H264_DpbBuf_t * p_Dpb,H264_StorePic_t * p,RK_S32 long_term_pic_num)305*437bfbebSnyanmisaka static void mm_unmark_long_term_for_reference(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 long_term_pic_num)
306*437bfbebSnyanmisaka {
307*437bfbebSnyanmisaka     RK_U32 i = 0;
308*437bfbebSnyanmisaka 
309*437bfbebSnyanmisaka     for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
310*437bfbebSnyanmisaka         if (p->structure == FRAME) {
311*437bfbebSnyanmisaka             if ((p_Dpb->fs_ltref[i]->is_reference == 3) && (p_Dpb->fs_ltref[i]->is_long_term == 3)) {
312*437bfbebSnyanmisaka                 if (p_Dpb->fs_ltref[i]->frame->long_term_pic_num == long_term_pic_num) {
313*437bfbebSnyanmisaka                     unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
314*437bfbebSnyanmisaka                 }
315*437bfbebSnyanmisaka             }
316*437bfbebSnyanmisaka         } else {
317*437bfbebSnyanmisaka             if ((p_Dpb->fs_ltref[i]->is_reference & 1) && ((p_Dpb->fs_ltref[i]->is_long_term & 1))) {
318*437bfbebSnyanmisaka                 if (p_Dpb->fs_ltref[i]->top_field->long_term_pic_num == long_term_pic_num) {
319*437bfbebSnyanmisaka                     p_Dpb->fs_ltref[i]->top_field->used_for_reference = 0;
320*437bfbebSnyanmisaka                     p_Dpb->fs_ltref[i]->top_field->is_long_term = 0;
321*437bfbebSnyanmisaka                     p_Dpb->fs_ltref[i]->is_reference &= 2;
322*437bfbebSnyanmisaka                     p_Dpb->fs_ltref[i]->is_long_term &= 2;
323*437bfbebSnyanmisaka                     if (p_Dpb->fs_ltref[i]->is_used == 3) {
324*437bfbebSnyanmisaka                         p_Dpb->fs_ltref[i]->frame->used_for_reference = 0;
325*437bfbebSnyanmisaka                         p_Dpb->fs_ltref[i]->frame->is_long_term = 0;
326*437bfbebSnyanmisaka                     }
327*437bfbebSnyanmisaka                     return;
328*437bfbebSnyanmisaka                 }
329*437bfbebSnyanmisaka             }
330*437bfbebSnyanmisaka             if ((p_Dpb->fs_ltref[i]->is_reference & 2) && ((p_Dpb->fs_ltref[i]->is_long_term & 2))) {
331*437bfbebSnyanmisaka                 if (p_Dpb->fs_ltref[i]->bottom_field->long_term_pic_num == long_term_pic_num) {
332*437bfbebSnyanmisaka                     p_Dpb->fs_ltref[i]->bottom_field->used_for_reference = 0;
333*437bfbebSnyanmisaka                     p_Dpb->fs_ltref[i]->bottom_field->is_long_term = 0;
334*437bfbebSnyanmisaka                     p_Dpb->fs_ltref[i]->is_reference &= 1;
335*437bfbebSnyanmisaka                     p_Dpb->fs_ltref[i]->is_long_term &= 1;
336*437bfbebSnyanmisaka                     if (p_Dpb->fs_ltref[i]->is_used == 3) {
337*437bfbebSnyanmisaka                         p_Dpb->fs_ltref[i]->frame->used_for_reference = 0;
338*437bfbebSnyanmisaka                         p_Dpb->fs_ltref[i]->frame->is_long_term = 0;
339*437bfbebSnyanmisaka                     }
340*437bfbebSnyanmisaka                     return;
341*437bfbebSnyanmisaka                 }
342*437bfbebSnyanmisaka             }
343*437bfbebSnyanmisaka         }
344*437bfbebSnyanmisaka     }
345*437bfbebSnyanmisaka }
346*437bfbebSnyanmisaka 
unmark_long_term_frame_for_reference_by_frame_idx(H264_DpbBuf_t * p_Dpb,RK_S32 long_term_frame_idx)347*437bfbebSnyanmisaka static void unmark_long_term_frame_for_reference_by_frame_idx(H264_DpbBuf_t *p_Dpb, RK_S32 long_term_frame_idx)
348*437bfbebSnyanmisaka {
349*437bfbebSnyanmisaka     RK_U32 i = 0;
350*437bfbebSnyanmisaka     for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
351*437bfbebSnyanmisaka         if (p_Dpb->fs_ltref[i]->long_term_frame_idx == long_term_frame_idx) {
352*437bfbebSnyanmisaka             unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
353*437bfbebSnyanmisaka         }
354*437bfbebSnyanmisaka     }
355*437bfbebSnyanmisaka }
356*437bfbebSnyanmisaka 
unmark_long_term_field_for_reference_by_frame_idx(H264_DpbBuf_t * p_Dpb,RK_S32 structure,RK_S32 long_term_frame_idx,RK_S32 mark_current,RK_U32 curr_frame_num,RK_S32 curr_pic_num)357*437bfbebSnyanmisaka static MPP_RET unmark_long_term_field_for_reference_by_frame_idx(H264_DpbBuf_t *p_Dpb, RK_S32 structure,
358*437bfbebSnyanmisaka                                                                  RK_S32 long_term_frame_idx, RK_S32 mark_current, RK_U32 curr_frame_num, RK_S32 curr_pic_num)
359*437bfbebSnyanmisaka {
360*437bfbebSnyanmisaka     RK_U8 i = 0;
361*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
362*437bfbebSnyanmisaka     H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid;
363*437bfbebSnyanmisaka 
364*437bfbebSnyanmisaka     VAL_CHECK(ret, structure != FRAME);
365*437bfbebSnyanmisaka     if (curr_pic_num < 0)
366*437bfbebSnyanmisaka         curr_pic_num += (2 * p_Vid->max_frame_num);
367*437bfbebSnyanmisaka 
368*437bfbebSnyanmisaka     for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
369*437bfbebSnyanmisaka         if (p_Dpb->fs_ltref[i]->long_term_frame_idx == long_term_frame_idx) {
370*437bfbebSnyanmisaka             if (structure == TOP_FIELD) {
371*437bfbebSnyanmisaka                 if (p_Dpb->fs_ltref[i]->is_long_term == 3) {
372*437bfbebSnyanmisaka                     unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
373*437bfbebSnyanmisaka                 } else {
374*437bfbebSnyanmisaka                     if (p_Dpb->fs_ltref[i]->is_long_term == 1) {
375*437bfbebSnyanmisaka                         unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
376*437bfbebSnyanmisaka                     } else {
377*437bfbebSnyanmisaka                         if (mark_current) {
378*437bfbebSnyanmisaka                             if (p_Dpb->last_picture) {
379*437bfbebSnyanmisaka                                 if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || p_Dpb->last_picture->frame_num != curr_frame_num)
380*437bfbebSnyanmisaka                                     unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
381*437bfbebSnyanmisaka                             } else {
382*437bfbebSnyanmisaka                                 unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
383*437bfbebSnyanmisaka                             }
384*437bfbebSnyanmisaka                         } else {
385*437bfbebSnyanmisaka                             if ((p_Dpb->fs_ltref[i]->frame_num) != (unsigned)(curr_pic_num >> 1)) {
386*437bfbebSnyanmisaka                                 unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
387*437bfbebSnyanmisaka                             }
388*437bfbebSnyanmisaka                         }
389*437bfbebSnyanmisaka                     }
390*437bfbebSnyanmisaka                 }
391*437bfbebSnyanmisaka             }
392*437bfbebSnyanmisaka             if (structure == BOTTOM_FIELD) {
393*437bfbebSnyanmisaka                 if (p_Dpb->fs_ltref[i]->is_long_term == 3) {
394*437bfbebSnyanmisaka                     unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
395*437bfbebSnyanmisaka                 } else {
396*437bfbebSnyanmisaka                     if (p_Dpb->fs_ltref[i]->is_long_term == 2) {
397*437bfbebSnyanmisaka                         unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
398*437bfbebSnyanmisaka                     } else {
399*437bfbebSnyanmisaka                         if (mark_current) {
400*437bfbebSnyanmisaka                             if (p_Dpb->last_picture) {
401*437bfbebSnyanmisaka                                 if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || p_Dpb->last_picture->frame_num != curr_frame_num)
402*437bfbebSnyanmisaka                                     unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
403*437bfbebSnyanmisaka                             } else {
404*437bfbebSnyanmisaka                                 unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
405*437bfbebSnyanmisaka                             }
406*437bfbebSnyanmisaka                         } else {
407*437bfbebSnyanmisaka                             if ((p_Dpb->fs_ltref[i]->frame_num) != (unsigned)(curr_pic_num >> 1)) {
408*437bfbebSnyanmisaka                                 unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
409*437bfbebSnyanmisaka                             }
410*437bfbebSnyanmisaka                         }
411*437bfbebSnyanmisaka                     }
412*437bfbebSnyanmisaka                 }
413*437bfbebSnyanmisaka             }
414*437bfbebSnyanmisaka         }
415*437bfbebSnyanmisaka     }
416*437bfbebSnyanmisaka     return ret = MPP_OK;
417*437bfbebSnyanmisaka __FAILED:
418*437bfbebSnyanmisaka     return ret;
419*437bfbebSnyanmisaka }
420*437bfbebSnyanmisaka 
mark_pic_long_term(H264_DpbBuf_t * p_Dpb,H264_StorePic_t * p,RK_S32 long_term_frame_idx,RK_S32 picNumX)421*437bfbebSnyanmisaka static void mark_pic_long_term(H264_DpbBuf_t *p_Dpb, H264_StorePic_t* p, RK_S32 long_term_frame_idx, RK_S32 picNumX)
422*437bfbebSnyanmisaka {
423*437bfbebSnyanmisaka     RK_U32 i = 0;
424*437bfbebSnyanmisaka     RK_S32 add_top = 0, add_bottom = 0;
425*437bfbebSnyanmisaka 
426*437bfbebSnyanmisaka     if (p->structure == FRAME) {
427*437bfbebSnyanmisaka         for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
428*437bfbebSnyanmisaka             if (p_Dpb->fs_ref[i]->is_reference == 3) {
429*437bfbebSnyanmisaka                 if ((!p_Dpb->fs_ref[i]->frame->is_long_term) && (p_Dpb->fs_ref[i]->frame->pic_num == picNumX)) {
430*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_frame_idx = long_term_frame_idx;
431*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx;
432*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->frame->is_long_term = 1;
433*437bfbebSnyanmisaka 
434*437bfbebSnyanmisaka                     if (p_Dpb->fs_ref[i]->top_field && p_Dpb->fs_ref[i]->bottom_field) {
435*437bfbebSnyanmisaka                         p_Dpb->fs_ref[i]->top_field->long_term_frame_idx = p_Dpb->fs_ref[i]->bottom_field->long_term_frame_idx = long_term_frame_idx;
436*437bfbebSnyanmisaka                         p_Dpb->fs_ref[i]->top_field->long_term_pic_num = long_term_frame_idx;
437*437bfbebSnyanmisaka                         p_Dpb->fs_ref[i]->bottom_field->long_term_pic_num = long_term_frame_idx;
438*437bfbebSnyanmisaka                         p_Dpb->fs_ref[i]->top_field->is_long_term = p_Dpb->fs_ref[i]->bottom_field->is_long_term = 1;
439*437bfbebSnyanmisaka                     }
440*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->is_long_term = 3;
441*437bfbebSnyanmisaka                     return;
442*437bfbebSnyanmisaka                 }
443*437bfbebSnyanmisaka             }
444*437bfbebSnyanmisaka         }
445*437bfbebSnyanmisaka         H264D_WARNNING("reference frame for long term marking not found.");
446*437bfbebSnyanmisaka     } else {
447*437bfbebSnyanmisaka         if (p->structure == TOP_FIELD) {
448*437bfbebSnyanmisaka             add_top = 1;
449*437bfbebSnyanmisaka             add_bottom = 0;
450*437bfbebSnyanmisaka         } else {
451*437bfbebSnyanmisaka             add_top = 0;
452*437bfbebSnyanmisaka             add_bottom = 1;
453*437bfbebSnyanmisaka         }
454*437bfbebSnyanmisaka         for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
455*437bfbebSnyanmisaka             if (p_Dpb->fs_ref[i]->is_reference & 1) {
456*437bfbebSnyanmisaka                 if ((!p_Dpb->fs_ref[i]->top_field->is_long_term) && (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX)) {
457*437bfbebSnyanmisaka                     if ((p_Dpb->fs_ref[i]->is_long_term) && (p_Dpb->fs_ref[i]->long_term_frame_idx != long_term_frame_idx)) {
458*437bfbebSnyanmisaka                         H264D_WARNNING("assigning long_term_frame_idx different from other field.");
459*437bfbebSnyanmisaka                     }
460*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->top_field->long_term_frame_idx = long_term_frame_idx;
461*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->top_field->long_term_pic_num = 2 * long_term_frame_idx + add_top;
462*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->top_field->is_long_term = 1;
463*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->is_long_term |= 1;
464*437bfbebSnyanmisaka                     if (p_Dpb->fs_ref[i]->is_long_term == 3) {
465*437bfbebSnyanmisaka                         p_Dpb->fs_ref[i]->frame->is_long_term = 1;
466*437bfbebSnyanmisaka                         p_Dpb->fs_ref[i]->frame->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx;
467*437bfbebSnyanmisaka                     }
468*437bfbebSnyanmisaka                     return;
469*437bfbebSnyanmisaka                 }
470*437bfbebSnyanmisaka             }
471*437bfbebSnyanmisaka             if (p_Dpb->fs_ref[i]->is_reference & 2) {
472*437bfbebSnyanmisaka                 if ((!p_Dpb->fs_ref[i]->bottom_field->is_long_term) && (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX)) {
473*437bfbebSnyanmisaka                     if ((p_Dpb->fs_ref[i]->is_long_term) && (p_Dpb->fs_ref[i]->long_term_frame_idx != long_term_frame_idx)) {
474*437bfbebSnyanmisaka                         H264D_WARNNING("assigning long_term_frame_idx different from other field.");
475*437bfbebSnyanmisaka                     }
476*437bfbebSnyanmisaka 
477*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->bottom_field->long_term_frame_idx
478*437bfbebSnyanmisaka                                                             = long_term_frame_idx;
479*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->bottom_field->long_term_pic_num = 2 * long_term_frame_idx + add_bottom;
480*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->bottom_field->is_long_term = 1;
481*437bfbebSnyanmisaka                     p_Dpb->fs_ref[i]->is_long_term |= 2;
482*437bfbebSnyanmisaka                     if (p_Dpb->fs_ref[i]->is_long_term == 3) {
483*437bfbebSnyanmisaka                         p_Dpb->fs_ref[i]->frame->is_long_term = 1;
484*437bfbebSnyanmisaka                         p_Dpb->fs_ref[i]->frame->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx;
485*437bfbebSnyanmisaka                     }
486*437bfbebSnyanmisaka                     return;
487*437bfbebSnyanmisaka                 }
488*437bfbebSnyanmisaka             }
489*437bfbebSnyanmisaka         }
490*437bfbebSnyanmisaka         H264D_WARNNING("reference field for long term marking not found.");
491*437bfbebSnyanmisaka     }
492*437bfbebSnyanmisaka }
493*437bfbebSnyanmisaka 
mm_assign_long_term_frame_idx(H264_DpbBuf_t * p_Dpb,H264_StorePic_t * p,RK_S32 difference_of_pic_nums_minus1,RK_S32 long_term_frame_idx)494*437bfbebSnyanmisaka static MPP_RET mm_assign_long_term_frame_idx(H264_DpbBuf_t *p_Dpb, H264_StorePic_t* p, RK_S32 difference_of_pic_nums_minus1, RK_S32 long_term_frame_idx)
495*437bfbebSnyanmisaka {
496*437bfbebSnyanmisaka     RK_S32 picNumX = 0;
497*437bfbebSnyanmisaka     RK_U32 i = 0;
498*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
499*437bfbebSnyanmisaka 
500*437bfbebSnyanmisaka     picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1);
501*437bfbebSnyanmisaka     //!< remove frames/fields with same long_term_frame_idx
502*437bfbebSnyanmisaka     if (p->structure == FRAME) {
503*437bfbebSnyanmisaka         unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, long_term_frame_idx);
504*437bfbebSnyanmisaka     } else {
505*437bfbebSnyanmisaka         PictureStructure structure = FRAME;
506*437bfbebSnyanmisaka 
507*437bfbebSnyanmisaka         for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
508*437bfbebSnyanmisaka             if (p_Dpb->fs_ref[i]->is_reference & 1) {
509*437bfbebSnyanmisaka                 if (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX) {
510*437bfbebSnyanmisaka                     structure = TOP_FIELD;
511*437bfbebSnyanmisaka                     break;
512*437bfbebSnyanmisaka                 }
513*437bfbebSnyanmisaka             }
514*437bfbebSnyanmisaka             if (p_Dpb->fs_ref[i]->is_reference & 2) {
515*437bfbebSnyanmisaka                 if (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX) {
516*437bfbebSnyanmisaka                     structure = BOTTOM_FIELD;
517*437bfbebSnyanmisaka                     break;
518*437bfbebSnyanmisaka                 }
519*437bfbebSnyanmisaka             }
520*437bfbebSnyanmisaka         }
521*437bfbebSnyanmisaka         VAL_CHECK(ret, structure != FRAME);
522*437bfbebSnyanmisaka         FUN_CHECK(ret = unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, structure, long_term_frame_idx, 0, 0, picNumX));
523*437bfbebSnyanmisaka     }
524*437bfbebSnyanmisaka     mark_pic_long_term(p_Dpb, p, long_term_frame_idx, picNumX);
525*437bfbebSnyanmisaka 
526*437bfbebSnyanmisaka     return ret = MPP_OK;
527*437bfbebSnyanmisaka __FAILED:
528*437bfbebSnyanmisaka     return ret;
529*437bfbebSnyanmisaka }
530*437bfbebSnyanmisaka 
mm_update_max_long_term_frame_idx(H264_DpbBuf_t * p_Dpb,RK_S32 max_long_term_frame_idx_plus1)531*437bfbebSnyanmisaka static void mm_update_max_long_term_frame_idx(H264_DpbBuf_t *p_Dpb, RK_S32 max_long_term_frame_idx_plus1)
532*437bfbebSnyanmisaka {
533*437bfbebSnyanmisaka     RK_U32 i = 0;
534*437bfbebSnyanmisaka 
535*437bfbebSnyanmisaka     p_Dpb->max_long_term_pic_idx = max_long_term_frame_idx_plus1 - 1;
536*437bfbebSnyanmisaka 
537*437bfbebSnyanmisaka     // check for invalid frames
538*437bfbebSnyanmisaka     for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
539*437bfbebSnyanmisaka         if (p_Dpb->fs_ltref[i]->long_term_frame_idx > p_Dpb->max_long_term_pic_idx) {
540*437bfbebSnyanmisaka             unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
541*437bfbebSnyanmisaka         }
542*437bfbebSnyanmisaka     }
543*437bfbebSnyanmisaka }
544*437bfbebSnyanmisaka 
mm_unmark_all_short_term_for_reference(H264_DpbBuf_t * p_Dpb)545*437bfbebSnyanmisaka static void mm_unmark_all_short_term_for_reference(H264_DpbBuf_t *p_Dpb)
546*437bfbebSnyanmisaka {
547*437bfbebSnyanmisaka     RK_U32 i = 0;
548*437bfbebSnyanmisaka     for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
549*437bfbebSnyanmisaka         unmark_for_reference(p_Dpb->p_Vid->p_Dec, p_Dpb->fs_ref[i]);
550*437bfbebSnyanmisaka     }
551*437bfbebSnyanmisaka     update_ref_list(p_Dpb);
552*437bfbebSnyanmisaka }
553*437bfbebSnyanmisaka 
mm_unmark_all_long_term_for_reference(H264_DpbBuf_t * p_Dpb)554*437bfbebSnyanmisaka static void mm_unmark_all_long_term_for_reference(H264_DpbBuf_t *p_Dpb)
555*437bfbebSnyanmisaka {
556*437bfbebSnyanmisaka     mm_update_max_long_term_frame_idx(p_Dpb, 0);
557*437bfbebSnyanmisaka }
558*437bfbebSnyanmisaka 
mm_mark_current_picture_long_term(H264_DpbBuf_t * p_Dpb,H264_StorePic_t * p,RK_S32 long_term_frame_idx)559*437bfbebSnyanmisaka static void mm_mark_current_picture_long_term(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 long_term_frame_idx)
560*437bfbebSnyanmisaka {
561*437bfbebSnyanmisaka     // remove long term pictures with same long_term_frame_idx
562*437bfbebSnyanmisaka     if (p->structure == FRAME) {
563*437bfbebSnyanmisaka         unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, long_term_frame_idx);
564*437bfbebSnyanmisaka     } else {
565*437bfbebSnyanmisaka         unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, p->structure, long_term_frame_idx, 1, p->pic_num, 0);
566*437bfbebSnyanmisaka     }
567*437bfbebSnyanmisaka 
568*437bfbebSnyanmisaka     p->is_long_term = 1;
569*437bfbebSnyanmisaka     p->long_term_frame_idx = long_term_frame_idx;
570*437bfbebSnyanmisaka }
571*437bfbebSnyanmisaka 
sliding_window_memory_management(H264_DpbBuf_t * p_Dpb)572*437bfbebSnyanmisaka static void sliding_window_memory_management(H264_DpbBuf_t *p_Dpb)
573*437bfbebSnyanmisaka {
574*437bfbebSnyanmisaka     RK_U32 i = 0;
575*437bfbebSnyanmisaka 
576*437bfbebSnyanmisaka     // if this is a reference pic with sliding window, unmark first ref frame
577*437bfbebSnyanmisaka     if (p_Dpb->ref_frames_in_buffer == MPP_MAX(1, p_Dpb->num_ref_frames) - p_Dpb->ltref_frames_in_buffer) {
578*437bfbebSnyanmisaka         for (i = 0; i < p_Dpb->used_size; i++) {
579*437bfbebSnyanmisaka             if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term))) {
580*437bfbebSnyanmisaka                 unmark_for_reference(p_Dpb->p_Vid->p_Dec, p_Dpb->fs[i]);
581*437bfbebSnyanmisaka                 update_ref_list(p_Dpb);
582*437bfbebSnyanmisaka                 break;
583*437bfbebSnyanmisaka             }
584*437bfbebSnyanmisaka         }
585*437bfbebSnyanmisaka     }
586*437bfbebSnyanmisaka }
587*437bfbebSnyanmisaka 
check_num_ref(H264_DpbBuf_t * p_Dpb)588*437bfbebSnyanmisaka static void check_num_ref(H264_DpbBuf_t *p_Dpb)
589*437bfbebSnyanmisaka {
590*437bfbebSnyanmisaka 
591*437bfbebSnyanmisaka     if ((RK_S32)(p_Dpb->ltref_frames_in_buffer + p_Dpb->ref_frames_in_buffer) > MPP_MAX(1, p_Dpb->num_ref_frames)) {
592*437bfbebSnyanmisaka         sliding_window_memory_management(p_Dpb);
593*437bfbebSnyanmisaka         H264D_WARNNING("Max number of reference frames exceeded");
594*437bfbebSnyanmisaka     }
595*437bfbebSnyanmisaka }
596*437bfbebSnyanmisaka 
is_used_for_reference(H264_FrameStore_t * fs)597*437bfbebSnyanmisaka static RK_U32 is_used_for_reference(H264_FrameStore_t* fs)
598*437bfbebSnyanmisaka {
599*437bfbebSnyanmisaka     RK_U8 is_used_flag = 0;
600*437bfbebSnyanmisaka 
601*437bfbebSnyanmisaka     if (!fs) {
602*437bfbebSnyanmisaka         return 0;
603*437bfbebSnyanmisaka     }
604*437bfbebSnyanmisaka     if (fs->is_reference) {
605*437bfbebSnyanmisaka         return is_used_flag = 1;
606*437bfbebSnyanmisaka     }
607*437bfbebSnyanmisaka 
608*437bfbebSnyanmisaka     if (fs->is_used == 3) { // frame
609*437bfbebSnyanmisaka         if (fs->frame->used_for_reference) {
610*437bfbebSnyanmisaka             return is_used_flag = 1;
611*437bfbebSnyanmisaka         }
612*437bfbebSnyanmisaka     }
613*437bfbebSnyanmisaka 
614*437bfbebSnyanmisaka     if (fs->is_used & 1) { // top field
615*437bfbebSnyanmisaka         if (fs->top_field) {
616*437bfbebSnyanmisaka             if (fs->top_field->used_for_reference) {
617*437bfbebSnyanmisaka                 return is_used_flag = 1;
618*437bfbebSnyanmisaka             }
619*437bfbebSnyanmisaka         }
620*437bfbebSnyanmisaka     }
621*437bfbebSnyanmisaka 
622*437bfbebSnyanmisaka     if (fs->is_used & 2) { // bottom field
623*437bfbebSnyanmisaka         if (fs->bottom_field) {
624*437bfbebSnyanmisaka             if (fs->bottom_field->used_for_reference) {
625*437bfbebSnyanmisaka                 return is_used_flag = 1;
626*437bfbebSnyanmisaka             }
627*437bfbebSnyanmisaka         }
628*437bfbebSnyanmisaka     }
629*437bfbebSnyanmisaka     return is_used_flag = 0;
630*437bfbebSnyanmisaka }
631*437bfbebSnyanmisaka 
free_dpb_mark(H264_DecCtx_t * p_Dec,H264_DpbMark_t * p_mark,RK_S32 structure)632*437bfbebSnyanmisaka static void free_dpb_mark(H264_DecCtx_t *p_Dec, H264_DpbMark_t *p_mark, RK_S32 structure)
633*437bfbebSnyanmisaka {
634*437bfbebSnyanmisaka     if (structure == FRAME) {
635*437bfbebSnyanmisaka         p_mark->top_used = (p_mark->top_used > 0) ? (p_mark->top_used - 1) : 0;
636*437bfbebSnyanmisaka         p_mark->bot_used = (p_mark->bot_used > 0) ? (p_mark->bot_used - 1) : 0;
637*437bfbebSnyanmisaka     } else if (structure == TOP_FIELD) {
638*437bfbebSnyanmisaka         p_mark->top_used = (p_mark->top_used > 0) ? (p_mark->top_used - 1) : 0;
639*437bfbebSnyanmisaka     } else if (structure == BOTTOM_FIELD) {
640*437bfbebSnyanmisaka         p_mark->bot_used = (p_mark->bot_used > 0) ? (p_mark->bot_used - 1) : 0;
641*437bfbebSnyanmisaka     }
642*437bfbebSnyanmisaka     if (p_mark->top_used == 0 && p_mark->bot_used == 0
643*437bfbebSnyanmisaka         && p_mark->out_flag == 0 && (p_mark->slot_idx >= 0)) {
644*437bfbebSnyanmisaka         mpp_buf_slot_clr_flag(p_Dec->frame_slots, p_mark->slot_idx, SLOT_CODEC_USE);
645*437bfbebSnyanmisaka         reset_dpb_mark(p_mark);
646*437bfbebSnyanmisaka     }
647*437bfbebSnyanmisaka }
648*437bfbebSnyanmisaka 
remove_frame_from_dpb(H264_DpbBuf_t * p_Dpb,RK_S32 pos)649*437bfbebSnyanmisaka static MPP_RET remove_frame_from_dpb(H264_DpbBuf_t *p_Dpb, RK_S32 pos)
650*437bfbebSnyanmisaka {
651*437bfbebSnyanmisaka     RK_U32  i = 0;
652*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
653*437bfbebSnyanmisaka     H264_FrameStore_t* tmp = NULL;
654*437bfbebSnyanmisaka     H264_FrameStore_t* fs = NULL;
655*437bfbebSnyanmisaka     H264_DecCtx_t *p_Dec = NULL;
656*437bfbebSnyanmisaka 
657*437bfbebSnyanmisaka     INP_CHECK(ret, !p_Dpb);
658*437bfbebSnyanmisaka     fs = p_Dpb->fs[pos];
659*437bfbebSnyanmisaka     INP_CHECK(ret, !fs);
660*437bfbebSnyanmisaka     INP_CHECK(ret, !p_Dpb->p_Vid);
661*437bfbebSnyanmisaka     p_Dec = p_Dpb->p_Vid->p_Dec;
662*437bfbebSnyanmisaka     INP_CHECK(ret, !p_Dec);
663*437bfbebSnyanmisaka 
664*437bfbebSnyanmisaka     switch (fs->is_used) {
665*437bfbebSnyanmisaka     case 3:
666*437bfbebSnyanmisaka         if (fs->frame)           free_storable_picture(p_Dec, fs->frame);
667*437bfbebSnyanmisaka         if (fs->top_field)       free_storable_picture(p_Dec, fs->top_field);
668*437bfbebSnyanmisaka         if (fs->bottom_field)    free_storable_picture(p_Dec, fs->bottom_field);
669*437bfbebSnyanmisaka         fs->frame = NULL;
670*437bfbebSnyanmisaka         fs->top_field = NULL;
671*437bfbebSnyanmisaka         fs->bottom_field = NULL;
672*437bfbebSnyanmisaka         break;
673*437bfbebSnyanmisaka     case 2:
674*437bfbebSnyanmisaka         if (fs->bottom_field)    free_storable_picture(p_Dec, fs->bottom_field);
675*437bfbebSnyanmisaka         fs->bottom_field = NULL;
676*437bfbebSnyanmisaka         break;
677*437bfbebSnyanmisaka     case 1:
678*437bfbebSnyanmisaka         if (fs->top_field)        free_storable_picture(p_Dec, fs->top_field);
679*437bfbebSnyanmisaka         fs->top_field = NULL;
680*437bfbebSnyanmisaka         break;
681*437bfbebSnyanmisaka     case 0:
682*437bfbebSnyanmisaka         break;
683*437bfbebSnyanmisaka     default:
684*437bfbebSnyanmisaka         H264D_ERR("invalid frame store type.");
685*437bfbebSnyanmisaka         goto __FAILED;
686*437bfbebSnyanmisaka     }
687*437bfbebSnyanmisaka 
688*437bfbebSnyanmisaka     fs->is_used = 0;
689*437bfbebSnyanmisaka     fs->is_long_term = 0;
690*437bfbebSnyanmisaka     fs->is_reference = 0;
691*437bfbebSnyanmisaka     fs->is_orig_reference = 0;
692*437bfbebSnyanmisaka 
693*437bfbebSnyanmisaka     // move empty framestore to end of buffer
694*437bfbebSnyanmisaka     tmp = p_Dpb->fs[pos];
695*437bfbebSnyanmisaka 
696*437bfbebSnyanmisaka     for (i = pos; i < p_Dpb->used_size - 1; i++) {
697*437bfbebSnyanmisaka         p_Dpb->fs[i] = p_Dpb->fs[i + 1];
698*437bfbebSnyanmisaka     }
699*437bfbebSnyanmisaka     p_Dpb->fs[p_Dpb->used_size - 1] = tmp;
700*437bfbebSnyanmisaka     p_Dpb->used_size--;
701*437bfbebSnyanmisaka 
702*437bfbebSnyanmisaka     return ret = MPP_OK;
703*437bfbebSnyanmisaka __RETURN:
704*437bfbebSnyanmisaka     return ret;
705*437bfbebSnyanmisaka __FAILED:
706*437bfbebSnyanmisaka     return ret = MPP_NOK;
707*437bfbebSnyanmisaka 
708*437bfbebSnyanmisaka 
709*437bfbebSnyanmisaka }
710*437bfbebSnyanmisaka 
remove_unused_frame_from_dpb(H264_DpbBuf_t * p_Dpb)711*437bfbebSnyanmisaka static MPP_RET remove_unused_frame_from_dpb(H264_DpbBuf_t *p_Dpb)
712*437bfbebSnyanmisaka {
713*437bfbebSnyanmisaka     RK_U32 i = 0;
714*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
715*437bfbebSnyanmisaka     INP_CHECK(ret, !p_Dpb);
716*437bfbebSnyanmisaka     // check for frames that were already output and no longer used for reference
717*437bfbebSnyanmisaka     for (i = 0; i < p_Dpb->used_size; i++) {
718*437bfbebSnyanmisaka         if (p_Dpb->fs[i]) {
719*437bfbebSnyanmisaka             if (p_Dpb->fs[i]->is_output && (!is_used_for_reference(p_Dpb->fs[i]))) {
720*437bfbebSnyanmisaka                 FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, i));
721*437bfbebSnyanmisaka                 return MPP_OK;
722*437bfbebSnyanmisaka             }
723*437bfbebSnyanmisaka         }
724*437bfbebSnyanmisaka     }
725*437bfbebSnyanmisaka __RETURN:
726*437bfbebSnyanmisaka     return ret;
727*437bfbebSnyanmisaka __FAILED:
728*437bfbebSnyanmisaka     return ret;
729*437bfbebSnyanmisaka }
730*437bfbebSnyanmisaka 
get_smallest_poc(H264_DpbBuf_t * p_Dpb,RK_S32 * poc,RK_S32 * pos)731*437bfbebSnyanmisaka static RK_S32 get_smallest_poc(H264_DpbBuf_t *p_Dpb, RK_S32 *poc, RK_S32 *pos)
732*437bfbebSnyanmisaka {
733*437bfbebSnyanmisaka     RK_U32 i = 0;
734*437bfbebSnyanmisaka     RK_S32 find_flag = 0;
735*437bfbebSnyanmisaka     RK_S32 min_pos = -1;
736*437bfbebSnyanmisaka     RK_S32 min_poc = INT_MAX;
737*437bfbebSnyanmisaka 
738*437bfbebSnyanmisaka     *pos = -1;
739*437bfbebSnyanmisaka     *poc = INT_MAX;
740*437bfbebSnyanmisaka     for (i = 0; i < p_Dpb->used_size; i++) {
741*437bfbebSnyanmisaka         if (min_poc > p_Dpb->fs[i]->poc) {
742*437bfbebSnyanmisaka             min_poc = p_Dpb->fs[i]->poc;
743*437bfbebSnyanmisaka             min_pos = i;
744*437bfbebSnyanmisaka         }
745*437bfbebSnyanmisaka         if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output)) {
746*437bfbebSnyanmisaka             *poc = p_Dpb->fs[i]->poc;
747*437bfbebSnyanmisaka             *pos = i;
748*437bfbebSnyanmisaka             find_flag = 1;
749*437bfbebSnyanmisaka         }
750*437bfbebSnyanmisaka     }
751*437bfbebSnyanmisaka     if (!find_flag) {
752*437bfbebSnyanmisaka         *poc = min_poc;
753*437bfbebSnyanmisaka         *pos = min_pos;
754*437bfbebSnyanmisaka     }
755*437bfbebSnyanmisaka 
756*437bfbebSnyanmisaka     return find_flag;
757*437bfbebSnyanmisaka }
758*437bfbebSnyanmisaka 
alloc_frame_store()759*437bfbebSnyanmisaka static H264_FrameStore_t *alloc_frame_store()
760*437bfbebSnyanmisaka {
761*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
762*437bfbebSnyanmisaka     H264_FrameStore_t *f = mpp_calloc(H264_FrameStore_t, 1);
763*437bfbebSnyanmisaka     MEM_CHECK(ret, f);
764*437bfbebSnyanmisaka 
765*437bfbebSnyanmisaka     f->is_used = 0;
766*437bfbebSnyanmisaka     f->is_reference = 0;
767*437bfbebSnyanmisaka     f->is_long_term = 0;
768*437bfbebSnyanmisaka     f->is_orig_reference = 0;
769*437bfbebSnyanmisaka     f->is_output = 0;
770*437bfbebSnyanmisaka 
771*437bfbebSnyanmisaka     f->frame = NULL;
772*437bfbebSnyanmisaka     f->top_field = NULL;
773*437bfbebSnyanmisaka     f->bottom_field = NULL;
774*437bfbebSnyanmisaka 
775*437bfbebSnyanmisaka     return f;
776*437bfbebSnyanmisaka __FAILED:
777*437bfbebSnyanmisaka     (void)ret;
778*437bfbebSnyanmisaka     return NULL;
779*437bfbebSnyanmisaka }
780*437bfbebSnyanmisaka 
dpb_combine_field_yuv(H264dVideoCtx_t * p_Vid,H264_FrameStore_t * fs,RK_U8 combine_flag)781*437bfbebSnyanmisaka static MPP_RET dpb_combine_field_yuv(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, RK_U8 combine_flag)
782*437bfbebSnyanmisaka {
783*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
784*437bfbebSnyanmisaka 
785*437bfbebSnyanmisaka     if (!fs->frame) {
786*437bfbebSnyanmisaka         fs->frame = alloc_storable_picture(p_Vid, FRAME);
787*437bfbebSnyanmisaka         MEM_CHECK(ret, fs->frame);
788*437bfbebSnyanmisaka         ASSERT(fs->top_field->colmv_no_used_flag == fs->bottom_field->colmv_no_used_flag);
789*437bfbebSnyanmisaka         fs->frame->colmv_no_used_flag = fs->top_field->colmv_no_used_flag;
790*437bfbebSnyanmisaka         if (combine_flag) {
791*437bfbebSnyanmisaka             ASSERT(fs->top_field->mem_mark->mark_idx == fs->bottom_field->mem_mark->mark_idx);
792*437bfbebSnyanmisaka             ASSERT(fs->top_field->mem_mark->slot_idx == fs->bottom_field->mem_mark->slot_idx);
793*437bfbebSnyanmisaka             fs->frame->mem_malloc_type = fs->top_field->mem_malloc_type;
794*437bfbebSnyanmisaka             fs->frame->mem_mark = fs->top_field->mem_mark;
795*437bfbebSnyanmisaka         } else if (fs->is_used == 0x01) { // unpaired, have top
796*437bfbebSnyanmisaka             ASSERT(fs->bottom_field->mem_malloc_type == Mem_UnPaired);
797*437bfbebSnyanmisaka             fs->frame->mem_mark = fs->top_field->mem_mark;
798*437bfbebSnyanmisaka         } else if (fs->is_used == 0x02) { // unpaired, have bottom
799*437bfbebSnyanmisaka             ASSERT(fs->top_field->mem_malloc_type == Mem_UnPaired);
800*437bfbebSnyanmisaka             fs->frame->mem_mark = fs->bottom_field->mem_mark;
801*437bfbebSnyanmisaka         } else {
802*437bfbebSnyanmisaka             ASSERT(fs->is_used == 0x03);
803*437bfbebSnyanmisaka             fs->frame->mem_malloc_type = fs->top_field->mem_malloc_type;
804*437bfbebSnyanmisaka             fs->frame->mem_mark = fs->top_field->mem_mark;
805*437bfbebSnyanmisaka         }
806*437bfbebSnyanmisaka     }
807*437bfbebSnyanmisaka     fs->poc = fs->frame->poc = fs->frame->frame_poc = MPP_MIN(fs->top_field->poc, fs->bottom_field->poc);
808*437bfbebSnyanmisaka     fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc;
809*437bfbebSnyanmisaka     fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc;
810*437bfbebSnyanmisaka     fs->top_field->bottom_poc = fs->frame->bottom_poc = fs->bottom_field->poc;
811*437bfbebSnyanmisaka     fs->frame->used_for_reference = (fs->top_field->used_for_reference && fs->bottom_field->used_for_reference);
812*437bfbebSnyanmisaka     fs->frame->is_long_term = (fs->top_field->is_long_term && fs->bottom_field->is_long_term);
813*437bfbebSnyanmisaka     if (fs->frame->is_long_term) {
814*437bfbebSnyanmisaka         fs->frame->long_term_frame_idx = fs->long_term_frame_idx;
815*437bfbebSnyanmisaka     }
816*437bfbebSnyanmisaka     fs->frame->top_field = fs->top_field;
817*437bfbebSnyanmisaka     fs->frame->bottom_field = fs->bottom_field;
818*437bfbebSnyanmisaka     fs->frame->frame = fs->frame;
819*437bfbebSnyanmisaka     fs->frame->chroma_format_idc = fs->top_field->chroma_format_idc;
820*437bfbebSnyanmisaka 
821*437bfbebSnyanmisaka     fs->frame->frame_cropping_flag = fs->top_field->frame_cropping_flag;
822*437bfbebSnyanmisaka     if (fs->frame->frame_cropping_flag) {
823*437bfbebSnyanmisaka         fs->frame->frame_crop_top_offset = fs->top_field->frame_crop_top_offset;
824*437bfbebSnyanmisaka         fs->frame->frame_crop_bottom_offset = fs->top_field->frame_crop_bottom_offset;
825*437bfbebSnyanmisaka         fs->frame->frame_crop_left_offset = fs->top_field->frame_crop_left_offset;
826*437bfbebSnyanmisaka         fs->frame->frame_crop_right_offset = fs->top_field->frame_crop_right_offset;
827*437bfbebSnyanmisaka     }
828*437bfbebSnyanmisaka     fs->top_field->frame = fs->bottom_field->frame = fs->frame;
829*437bfbebSnyanmisaka     fs->top_field->top_field = fs->top_field;
830*437bfbebSnyanmisaka     fs->top_field->bottom_field = fs->bottom_field;
831*437bfbebSnyanmisaka     fs->bottom_field->top_field = fs->top_field;
832*437bfbebSnyanmisaka     fs->bottom_field->bottom_field = fs->bottom_field;
833*437bfbebSnyanmisaka 
834*437bfbebSnyanmisaka     fs->frame->is_mmco_5 = fs->top_field->is_mmco_5 || fs->bottom_field->is_mmco_5;
835*437bfbebSnyanmisaka     fs->frame->poc_mmco5 = MPP_MIN(fs->top_field->top_poc_mmco5, fs->bottom_field->bot_poc_mmco5);
836*437bfbebSnyanmisaka     fs->frame->top_poc_mmco5 = fs->top_field->top_poc_mmco5;
837*437bfbebSnyanmisaka     fs->frame->bot_poc_mmco5 = fs->top_field->bot_poc_mmco5;
838*437bfbebSnyanmisaka 
839*437bfbebSnyanmisaka     return ret = MPP_OK;
840*437bfbebSnyanmisaka __FAILED:
841*437bfbebSnyanmisaka     return ret ;
842*437bfbebSnyanmisaka }
843*437bfbebSnyanmisaka 
write_picture(H264_StorePic_t * p,H264dVideoCtx_t * p_Vid)844*437bfbebSnyanmisaka static void write_picture(H264_StorePic_t *p, H264dVideoCtx_t *p_Vid)
845*437bfbebSnyanmisaka {
846*437bfbebSnyanmisaka     MppFrame mframe = NULL;
847*437bfbebSnyanmisaka     H264_DpbMark_t *p_mark = NULL;
848*437bfbebSnyanmisaka     H264dErrCtx_t *p_err = &p_Vid->p_Dec->errctx;
849*437bfbebSnyanmisaka 
850*437bfbebSnyanmisaka     p_mark = p->mem_mark;
851*437bfbebSnyanmisaka     if ((p->mem_malloc_type == Mem_Malloc
852*437bfbebSnyanmisaka          || p->mem_malloc_type == Mem_TopOnly
853*437bfbebSnyanmisaka          || p->mem_malloc_type == Mem_BotOnly)
854*437bfbebSnyanmisaka         && p->structure == FRAME && p_mark->out_flag) {
855*437bfbebSnyanmisaka         mpp_buf_slot_get_prop(p_Vid->p_Dec->frame_slots, p_mark->slot_idx, SLOT_FRAME_PTR, &mframe);
856*437bfbebSnyanmisaka 
857*437bfbebSnyanmisaka         //!< discard unpaired
858*437bfbebSnyanmisaka         if (p->mem_malloc_type == Mem_TopOnly || p->mem_malloc_type == Mem_BotOnly) {
859*437bfbebSnyanmisaka             if (p_err->used_ref_flag) {
860*437bfbebSnyanmisaka                 mpp_frame_set_errinfo(mframe, MPP_FRAME_ERR_UNKNOW);
861*437bfbebSnyanmisaka             } else {
862*437bfbebSnyanmisaka                 mpp_frame_set_discard(mframe, MPP_FRAME_ERR_UNKNOW);
863*437bfbebSnyanmisaka             }
864*437bfbebSnyanmisaka         }
865*437bfbebSnyanmisaka         //!<  discard less than first i frame poc
866*437bfbebSnyanmisaka         if ((p_err->i_slice_no < 2) && (p->poc < p_err->first_iframe_poc)) {
867*437bfbebSnyanmisaka             if (p_err->used_ref_flag && p_err->first_iframe_is_output) {
868*437bfbebSnyanmisaka                 if ((p->slice_type % 5) == H264_B_SLICE)
869*437bfbebSnyanmisaka                     mpp_frame_set_discard(mframe, MPP_FRAME_ERR_UNKNOW);
870*437bfbebSnyanmisaka                 else
871*437bfbebSnyanmisaka                     mpp_frame_set_errinfo(mframe, MPP_FRAME_ERR_UNKNOW);
872*437bfbebSnyanmisaka             } else {
873*437bfbebSnyanmisaka                 if (p_Vid->dpb_fast_out)
874*437bfbebSnyanmisaka                     mpp_frame_set_discard(mframe, MPP_FRAME_ERR_UNKNOW);
875*437bfbebSnyanmisaka             }
876*437bfbebSnyanmisaka         }
877*437bfbebSnyanmisaka 
878*437bfbebSnyanmisaka         if (p_Vid->p_Dec->mvc_valid) {
879*437bfbebSnyanmisaka             H264_DpbMark_t *match_mark = NULL;
880*437bfbebSnyanmisaka             H264_DpbMark_t *out_mark_list[2] = {NULL, NULL};
881*437bfbebSnyanmisaka             RK_U32 i = 0;
882*437bfbebSnyanmisaka             RK_S32 match_flag = 0;
883*437bfbebSnyanmisaka             RK_U32 is_base_view = p_mark->pic->layer_id == 0 ? 1 : 0;
884*437bfbebSnyanmisaka 
885*437bfbebSnyanmisaka             // find pic with the same poc at base view
886*437bfbebSnyanmisaka             for (i = 0; i < MAX_MARK_SIZE; i++) {
887*437bfbebSnyanmisaka                 match_mark = &p_Vid->p_Dec->dpb_mark[i];
888*437bfbebSnyanmisaka 
889*437bfbebSnyanmisaka                 if (!match_mark || !match_mark->pic || !match_mark->out_flag || match_mark->slot_idx < 0)
890*437bfbebSnyanmisaka                     continue;
891*437bfbebSnyanmisaka 
892*437bfbebSnyanmisaka                 if (match_mark->pic->layer_id != p_mark->pic->layer_id) {
893*437bfbebSnyanmisaka                     if (match_mark->pic->poc < p_mark->pic->poc) {
894*437bfbebSnyanmisaka                         match_flag = 1;
895*437bfbebSnyanmisaka                         break;
896*437bfbebSnyanmisaka                     } else if (match_mark->pic->poc == p_mark->pic->poc) {
897*437bfbebSnyanmisaka                         match_flag = 2;
898*437bfbebSnyanmisaka                         break;
899*437bfbebSnyanmisaka                     } else {
900*437bfbebSnyanmisaka                         match_flag = 0;
901*437bfbebSnyanmisaka                     }
902*437bfbebSnyanmisaka                 }
903*437bfbebSnyanmisaka             }
904*437bfbebSnyanmisaka 
905*437bfbebSnyanmisaka             if (!match_flag) {
906*437bfbebSnyanmisaka                 H264D_DBG(H264D_DBG_DPB_INFO, "no other view matched with current view_id %d, poc %d",
907*437bfbebSnyanmisaka                           p_mark->pic->layer_id, p_mark->pic->poc);
908*437bfbebSnyanmisaka                 out_mark_list[0] = p_mark;
909*437bfbebSnyanmisaka             } else if (match_flag == 1) {
910*437bfbebSnyanmisaka                 H264D_DBG(H264D_DBG_DPB_INFO, "find match view at %d, slot_idx %d, view_id %d, poc %d",
911*437bfbebSnyanmisaka                           i, match_mark->slot_idx, match_mark->pic->layer_id, match_mark->pic->poc);
912*437bfbebSnyanmisaka                 out_mark_list[0] = match_mark;
913*437bfbebSnyanmisaka                 out_mark_list[1] = p_mark;
914*437bfbebSnyanmisaka             } else if (match_flag == 2) {
915*437bfbebSnyanmisaka                 H264D_DBG(H264D_DBG_DPB_INFO, "find match view at %d, slot_idx %d, view_id %d, poc %d",
916*437bfbebSnyanmisaka                           i, match_mark->slot_idx, match_mark->pic->layer_id, match_mark->pic->poc);
917*437bfbebSnyanmisaka                 if (is_base_view) {
918*437bfbebSnyanmisaka                     out_mark_list[0] = p_mark;
919*437bfbebSnyanmisaka                     out_mark_list[1] = match_mark;
920*437bfbebSnyanmisaka                 } else {
921*437bfbebSnyanmisaka                     out_mark_list[0] = match_mark;
922*437bfbebSnyanmisaka                     out_mark_list[1] = p_mark;
923*437bfbebSnyanmisaka                 }
924*437bfbebSnyanmisaka             }
925*437bfbebSnyanmisaka 
926*437bfbebSnyanmisaka             for (i = 0; i < 2; i++) {
927*437bfbebSnyanmisaka                 if (out_mark_list[i]) {
928*437bfbebSnyanmisaka                     mpp_buf_slot_set_flag(p_Vid->p_Dec->frame_slots, out_mark_list[i]->slot_idx, SLOT_QUEUE_USE);
929*437bfbebSnyanmisaka                     mpp_buf_slot_enqueue(p_Vid->p_Dec->frame_slots, out_mark_list[i]->slot_idx, QUEUE_DISPLAY);
930*437bfbebSnyanmisaka                     out_mark_list[i]->out_flag = 0;
931*437bfbebSnyanmisaka                     p_Vid->p_Dec->last_frame_slot_idx = out_mark_list[i]->slot_idx;
932*437bfbebSnyanmisaka                 }
933*437bfbebSnyanmisaka             }
934*437bfbebSnyanmisaka         } else {
935*437bfbebSnyanmisaka             H264D_DBG(H264D_DBG_DPB_INFO, "display frame view_id %d slot_idx %d poc %d",
936*437bfbebSnyanmisaka                       p_mark->pic->layer_id, p_mark->slot_idx, p_mark->pic->poc);
937*437bfbebSnyanmisaka             mpp_buf_slot_set_flag(p_Vid->p_Dec->frame_slots, p_mark->slot_idx, SLOT_QUEUE_USE);
938*437bfbebSnyanmisaka             mpp_buf_slot_enqueue(p_Vid->p_Dec->frame_slots, p_mark->slot_idx, QUEUE_DISPLAY);
939*437bfbebSnyanmisaka             p_Vid->p_Dec->last_frame_slot_idx = p_mark->slot_idx;
940*437bfbebSnyanmisaka             p_mark->out_flag = 0;
941*437bfbebSnyanmisaka         }
942*437bfbebSnyanmisaka     }
943*437bfbebSnyanmisaka }
944*437bfbebSnyanmisaka 
write_unpaired_field(H264dVideoCtx_t * p_Vid,H264_FrameStore_t * fs)945*437bfbebSnyanmisaka static MPP_RET write_unpaired_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs)
946*437bfbebSnyanmisaka {
947*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
948*437bfbebSnyanmisaka     H264_StorePic_t *p = NULL;
949*437bfbebSnyanmisaka 
950*437bfbebSnyanmisaka     VAL_CHECK(ret, fs->is_used < 3);
951*437bfbebSnyanmisaka     if (fs->is_used & 0x01) { // we have a top field, construct an empty bottom field
952*437bfbebSnyanmisaka         p = fs->top_field;
953*437bfbebSnyanmisaka         fs->bottom_field = alloc_storable_picture(p_Vid, BOTTOM_FIELD);
954*437bfbebSnyanmisaka         MEM_CHECK(ret, fs->bottom_field);
955*437bfbebSnyanmisaka         fs->bottom_field->mem_malloc_type = Mem_UnPaired;
956*437bfbebSnyanmisaka         fs->bottom_field->chroma_format_idc = p->chroma_format_idc;
957*437bfbebSnyanmisaka         FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, 0));
958*437bfbebSnyanmisaka         fs->frame->view_id = fs->view_id;
959*437bfbebSnyanmisaka         fs->frame->mem_malloc_type = Mem_TopOnly;
960*437bfbebSnyanmisaka         H264D_WARNNING("write frame, line %d", __LINE__);
961*437bfbebSnyanmisaka         write_picture(fs->frame, p_Vid);
962*437bfbebSnyanmisaka     }
963*437bfbebSnyanmisaka 
964*437bfbebSnyanmisaka     if (fs->is_used & 0x02) { // we have a bottom field, construct an empty top field
965*437bfbebSnyanmisaka         p = fs->bottom_field;
966*437bfbebSnyanmisaka         fs->top_field = alloc_storable_picture(p_Vid, TOP_FIELD);
967*437bfbebSnyanmisaka         MEM_CHECK(ret, fs->top_field);
968*437bfbebSnyanmisaka         fs->top_field->mem_malloc_type = Mem_UnPaired;
969*437bfbebSnyanmisaka         fs->top_field->chroma_format_idc = p->chroma_format_idc;
970*437bfbebSnyanmisaka         fs->top_field->frame_cropping_flag = fs->bottom_field->frame_cropping_flag;
971*437bfbebSnyanmisaka         if (fs->top_field->frame_cropping_flag) {
972*437bfbebSnyanmisaka             fs->top_field->frame_crop_top_offset = fs->bottom_field->frame_crop_top_offset;
973*437bfbebSnyanmisaka             fs->top_field->frame_crop_bottom_offset = fs->bottom_field->frame_crop_bottom_offset;
974*437bfbebSnyanmisaka             fs->top_field->frame_crop_left_offset = fs->bottom_field->frame_crop_left_offset;
975*437bfbebSnyanmisaka             fs->top_field->frame_crop_right_offset = fs->bottom_field->frame_crop_right_offset;
976*437bfbebSnyanmisaka         }
977*437bfbebSnyanmisaka         FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, 0));
978*437bfbebSnyanmisaka         fs->frame->view_id = fs->view_id;
979*437bfbebSnyanmisaka         fs->frame->mem_malloc_type = Mem_BotOnly;
980*437bfbebSnyanmisaka         H264D_WARNNING("write frame, line %d", __LINE__);
981*437bfbebSnyanmisaka         write_picture(fs->frame, p_Vid);
982*437bfbebSnyanmisaka     }
983*437bfbebSnyanmisaka     fs->is_used = 3;
984*437bfbebSnyanmisaka 
985*437bfbebSnyanmisaka     return ret = MPP_OK;
986*437bfbebSnyanmisaka __FAILED:
987*437bfbebSnyanmisaka     return ret;
988*437bfbebSnyanmisaka }
989*437bfbebSnyanmisaka 
flush_direct_output(H264dVideoCtx_t * p_Vid)990*437bfbebSnyanmisaka static MPP_RET flush_direct_output(H264dVideoCtx_t *p_Vid)
991*437bfbebSnyanmisaka {
992*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
993*437bfbebSnyanmisaka 
994*437bfbebSnyanmisaka     FUN_CHECK(ret = write_unpaired_field(p_Vid, &p_Vid->out_buffer));
995*437bfbebSnyanmisaka     free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.frame);
996*437bfbebSnyanmisaka     p_Vid->out_buffer.frame = NULL;
997*437bfbebSnyanmisaka     free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.top_field);
998*437bfbebSnyanmisaka     p_Vid->out_buffer.top_field = NULL;
999*437bfbebSnyanmisaka     free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.bottom_field);
1000*437bfbebSnyanmisaka     p_Vid->out_buffer.bottom_field = NULL;
1001*437bfbebSnyanmisaka     p_Vid->out_buffer.is_used = 0;
1002*437bfbebSnyanmisaka 
1003*437bfbebSnyanmisaka     return ret = MPP_OK;
1004*437bfbebSnyanmisaka __FAILED:
1005*437bfbebSnyanmisaka     return ret;
1006*437bfbebSnyanmisaka }
1007*437bfbebSnyanmisaka 
write_stored_frame(H264dVideoCtx_t * p_Vid,H264_DpbBuf_t * p_Dpb,H264_FrameStore_t * fs)1008*437bfbebSnyanmisaka static MPP_RET write_stored_frame(H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb, H264_FrameStore_t *fs)
1009*437bfbebSnyanmisaka {
1010*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1011*437bfbebSnyanmisaka     INP_CHECK(ret, !p_Vid);
1012*437bfbebSnyanmisaka     INP_CHECK(ret, !fs);
1013*437bfbebSnyanmisaka     //!< make sure no direct output field is pending
1014*437bfbebSnyanmisaka     FUN_CHECK(ret = flush_direct_output(p_Vid));
1015*437bfbebSnyanmisaka 
1016*437bfbebSnyanmisaka     if (fs->is_used < 3) {
1017*437bfbebSnyanmisaka         FUN_CHECK(ret = write_unpaired_field(p_Vid, fs));
1018*437bfbebSnyanmisaka         if (fs->top_field)       free_storable_picture(p_Vid->p_Dec, fs->top_field);
1019*437bfbebSnyanmisaka         if (fs->bottom_field)    free_storable_picture(p_Vid->p_Dec, fs->bottom_field);
1020*437bfbebSnyanmisaka         fs->top_field = NULL;
1021*437bfbebSnyanmisaka         fs->bottom_field = NULL;
1022*437bfbebSnyanmisaka     } else {
1023*437bfbebSnyanmisaka         H264D_WARNNING("write frame, line %d", __LINE__);
1024*437bfbebSnyanmisaka         write_picture(fs->frame, p_Vid);
1025*437bfbebSnyanmisaka     }
1026*437bfbebSnyanmisaka     p_Dpb->last_output_poc = fs->poc;
1027*437bfbebSnyanmisaka     fs->is_output = 1;
1028*437bfbebSnyanmisaka 
1029*437bfbebSnyanmisaka     return ret = MPP_OK;
1030*437bfbebSnyanmisaka __RETURN:
1031*437bfbebSnyanmisaka     return ret;
1032*437bfbebSnyanmisaka __FAILED:
1033*437bfbebSnyanmisaka     return ret;
1034*437bfbebSnyanmisaka }
1035*437bfbebSnyanmisaka 
output_one_frame_from_dpb(H264_DpbBuf_t * p_Dpb)1036*437bfbebSnyanmisaka static MPP_RET output_one_frame_from_dpb(H264_DpbBuf_t *p_Dpb)
1037*437bfbebSnyanmisaka {
1038*437bfbebSnyanmisaka     RK_S32 poc = 0, pos = 0;
1039*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1040*437bfbebSnyanmisaka     H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid;
1041*437bfbebSnyanmisaka 
1042*437bfbebSnyanmisaka     //!< find smallest POC
1043*437bfbebSnyanmisaka     if (get_smallest_poc(p_Dpb, &poc, &pos)) {
1044*437bfbebSnyanmisaka         //!< JVT-P072 ends
1045*437bfbebSnyanmisaka         H264D_WARNNING("write_stored_frame, line %d", __LINE__);
1046*437bfbebSnyanmisaka         FUN_CHECK(ret = write_stored_frame(p_Vid, p_Dpb, p_Dpb->fs[pos]));
1047*437bfbebSnyanmisaka         //!< free frame store and move empty store to end of buffer
1048*437bfbebSnyanmisaka         if (!is_used_for_reference(p_Dpb->fs[pos])) {
1049*437bfbebSnyanmisaka             FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, pos));
1050*437bfbebSnyanmisaka         }
1051*437bfbebSnyanmisaka     }
1052*437bfbebSnyanmisaka     return ret = MPP_OK;
1053*437bfbebSnyanmisaka __FAILED:
1054*437bfbebSnyanmisaka     return ret;
1055*437bfbebSnyanmisaka }
1056*437bfbebSnyanmisaka 
adaptive_memory_management(H264_DpbBuf_t * p_Dpb,H264_StorePic_t * p)1057*437bfbebSnyanmisaka static MPP_RET adaptive_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p)
1058*437bfbebSnyanmisaka {
1059*437bfbebSnyanmisaka     H264_DRPM_t *tmp_drpm = NULL;
1060*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1061*437bfbebSnyanmisaka     H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid;
1062*437bfbebSnyanmisaka 
1063*437bfbebSnyanmisaka     p_Vid->last_has_mmco_5 = 0;
1064*437bfbebSnyanmisaka     VAL_CHECK(ret, !p->idr_flag && p->adaptive_ref_pic_buffering_flag);
1065*437bfbebSnyanmisaka     while (p->dec_ref_pic_marking_buffer) {
1066*437bfbebSnyanmisaka         tmp_drpm = p->dec_ref_pic_marking_buffer;
1067*437bfbebSnyanmisaka         switch (tmp_drpm->memory_management_control_operation) {
1068*437bfbebSnyanmisaka         case 0:
1069*437bfbebSnyanmisaka             VAL_CHECK(ret, tmp_drpm->Next == NULL);
1070*437bfbebSnyanmisaka             break;
1071*437bfbebSnyanmisaka         case 1:
1072*437bfbebSnyanmisaka             mm_unmark_short_term_for_reference(p_Dpb, p, tmp_drpm->difference_of_pic_nums_minus1);
1073*437bfbebSnyanmisaka             update_ref_list(p_Dpb);
1074*437bfbebSnyanmisaka             break;
1075*437bfbebSnyanmisaka         case 2:
1076*437bfbebSnyanmisaka             mm_unmark_long_term_for_reference(p_Dpb, p, tmp_drpm->long_term_pic_num);
1077*437bfbebSnyanmisaka             update_ltref_list(p_Dpb);
1078*437bfbebSnyanmisaka             break;
1079*437bfbebSnyanmisaka         case 3:
1080*437bfbebSnyanmisaka             mm_assign_long_term_frame_idx(p_Dpb, p, tmp_drpm->difference_of_pic_nums_minus1, tmp_drpm->long_term_frame_idx);
1081*437bfbebSnyanmisaka             update_ref_list(p_Dpb);
1082*437bfbebSnyanmisaka             update_ltref_list(p_Dpb);
1083*437bfbebSnyanmisaka             break;
1084*437bfbebSnyanmisaka         case 4:
1085*437bfbebSnyanmisaka             mm_update_max_long_term_frame_idx(p_Dpb, tmp_drpm->max_long_term_frame_idx_plus1);
1086*437bfbebSnyanmisaka             update_ltref_list(p_Dpb);
1087*437bfbebSnyanmisaka             break;
1088*437bfbebSnyanmisaka         case 5:
1089*437bfbebSnyanmisaka             mm_unmark_all_short_term_for_reference(p_Dpb);
1090*437bfbebSnyanmisaka             mm_unmark_all_long_term_for_reference(p_Dpb);
1091*437bfbebSnyanmisaka             p_Vid->last_has_mmco_5 = 1;
1092*437bfbebSnyanmisaka             break;
1093*437bfbebSnyanmisaka         case 6:
1094*437bfbebSnyanmisaka             //!< conceal max_long_term_frame_idx_plus1
1095*437bfbebSnyanmisaka             if (!tmp_drpm->max_long_term_frame_idx_plus1) {
1096*437bfbebSnyanmisaka                 tmp_drpm->max_long_term_frame_idx_plus1 = p_Dpb->num_ref_frames;
1097*437bfbebSnyanmisaka             }
1098*437bfbebSnyanmisaka             mm_mark_current_picture_long_term(p_Dpb, p, tmp_drpm->long_term_frame_idx);
1099*437bfbebSnyanmisaka             check_num_ref(p_Dpb);
1100*437bfbebSnyanmisaka             break;
1101*437bfbebSnyanmisaka         default:
1102*437bfbebSnyanmisaka             ret = MPP_NOK;
1103*437bfbebSnyanmisaka             goto __FAILED;
1104*437bfbebSnyanmisaka         }
1105*437bfbebSnyanmisaka         p->dec_ref_pic_marking_buffer = tmp_drpm->Next;
1106*437bfbebSnyanmisaka     }
1107*437bfbebSnyanmisaka     if (p_Vid->last_has_mmco_5) { //!< similar IDR frame
1108*437bfbebSnyanmisaka         p->pic_num = p->frame_num = 0;
1109*437bfbebSnyanmisaka         switch (p->structure) {
1110*437bfbebSnyanmisaka         case TOP_FIELD:
1111*437bfbebSnyanmisaka             p->is_mmco_5 = 1;
1112*437bfbebSnyanmisaka             p->top_poc_mmco5 = p->top_poc;
1113*437bfbebSnyanmisaka             p->poc = p->top_poc = 0;
1114*437bfbebSnyanmisaka             break;
1115*437bfbebSnyanmisaka 
1116*437bfbebSnyanmisaka         case BOTTOM_FIELD:
1117*437bfbebSnyanmisaka             p->is_mmco_5 = 1;
1118*437bfbebSnyanmisaka             p->bot_poc_mmco5 = p->bottom_poc;
1119*437bfbebSnyanmisaka             p->poc = p->bottom_poc = 0;
1120*437bfbebSnyanmisaka             break;
1121*437bfbebSnyanmisaka 
1122*437bfbebSnyanmisaka         case FRAME:
1123*437bfbebSnyanmisaka             p->is_mmco_5 = 1;
1124*437bfbebSnyanmisaka             p->top_poc_mmco5 = p->top_poc;
1125*437bfbebSnyanmisaka             p->bot_poc_mmco5 = p->bottom_poc;
1126*437bfbebSnyanmisaka             p->poc_mmco5 = MPP_MIN(p->top_poc, p->bottom_poc);
1127*437bfbebSnyanmisaka             p->top_poc -= p->poc;
1128*437bfbebSnyanmisaka             p->bottom_poc -= p->poc;
1129*437bfbebSnyanmisaka 
1130*437bfbebSnyanmisaka             p->poc = MPP_MIN(p->top_poc, p->bottom_poc);
1131*437bfbebSnyanmisaka             p->frame_poc = p->poc;
1132*437bfbebSnyanmisaka             break;
1133*437bfbebSnyanmisaka 
1134*437bfbebSnyanmisaka         }
1135*437bfbebSnyanmisaka         if (p->layer_id == 0) {
1136*437bfbebSnyanmisaka             FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[0], 1));
1137*437bfbebSnyanmisaka         } else {
1138*437bfbebSnyanmisaka             FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[1], 2));
1139*437bfbebSnyanmisaka         }
1140*437bfbebSnyanmisaka     }
1141*437bfbebSnyanmisaka     return ret = MPP_OK;
1142*437bfbebSnyanmisaka __FAILED:
1143*437bfbebSnyanmisaka     return ret;
1144*437bfbebSnyanmisaka }
1145*437bfbebSnyanmisaka 
dpb_split_field(H264dVideoCtx_t * p_Vid,H264_FrameStore_t * fs)1146*437bfbebSnyanmisaka static MPP_RET dpb_split_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs)
1147*437bfbebSnyanmisaka {
1148*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1149*437bfbebSnyanmisaka     H264_StorePic_t *frame = fs->frame;
1150*437bfbebSnyanmisaka     H264_StorePic_t *fs_top = NULL, *fs_btm = NULL;
1151*437bfbebSnyanmisaka 
1152*437bfbebSnyanmisaka     fs->poc = frame->poc;
1153*437bfbebSnyanmisaka     if (!frame->frame_mbs_only_flag) {
1154*437bfbebSnyanmisaka         fs_top = fs->top_field    = alloc_storable_picture(p_Vid, TOP_FIELD);
1155*437bfbebSnyanmisaka         fs_btm = fs->bottom_field = alloc_storable_picture(p_Vid, BOTTOM_FIELD);
1156*437bfbebSnyanmisaka         MEM_CHECK(ret, fs_top && fs_btm);
1157*437bfbebSnyanmisaka         fs_top->colmv_no_used_flag = frame->colmv_no_used_flag;
1158*437bfbebSnyanmisaka         fs_btm->colmv_no_used_flag = frame->colmv_no_used_flag;
1159*437bfbebSnyanmisaka 
1160*437bfbebSnyanmisaka         if (frame->mem_malloc_type == Mem_Malloc || frame->mem_malloc_type == Mem_Clone) {
1161*437bfbebSnyanmisaka             fs_top->mem_mark = frame->mem_mark;
1162*437bfbebSnyanmisaka             fs_btm->mem_mark = frame->mem_mark;
1163*437bfbebSnyanmisaka             fs_top->mem_malloc_type = frame->mem_malloc_type;
1164*437bfbebSnyanmisaka             fs_btm->mem_malloc_type = frame->mem_malloc_type;
1165*437bfbebSnyanmisaka             frame->mem_mark->bot_used += 1;    // picture memory add 1
1166*437bfbebSnyanmisaka             frame->mem_mark->top_used += 1;
1167*437bfbebSnyanmisaka         }
1168*437bfbebSnyanmisaka         fs_top->poc = frame->top_poc;
1169*437bfbebSnyanmisaka         fs_btm->poc = frame->bottom_poc;
1170*437bfbebSnyanmisaka         fs_top->layer_id = frame->layer_id;
1171*437bfbebSnyanmisaka         fs_btm->layer_id = frame->layer_id;
1172*437bfbebSnyanmisaka 
1173*437bfbebSnyanmisaka         fs_top->view_id = frame->view_id;
1174*437bfbebSnyanmisaka         fs_btm->view_id = frame->view_id;
1175*437bfbebSnyanmisaka         fs_top->frame_poc = frame->frame_poc;
1176*437bfbebSnyanmisaka 
1177*437bfbebSnyanmisaka         fs_top->bottom_poc = fs_btm->bottom_poc = frame->bottom_poc;
1178*437bfbebSnyanmisaka         fs_top->top_poc = fs_btm->top_poc = frame->top_poc;
1179*437bfbebSnyanmisaka         fs_btm->frame_poc = frame->frame_poc;
1180*437bfbebSnyanmisaka 
1181*437bfbebSnyanmisaka         fs_top->used_for_reference = fs_btm->used_for_reference = frame->used_for_reference;
1182*437bfbebSnyanmisaka         fs_top->is_long_term = fs_btm->is_long_term = frame->is_long_term;
1183*437bfbebSnyanmisaka         fs->long_term_frame_idx = fs_top->long_term_frame_idx = fs_btm->long_term_frame_idx = frame->long_term_frame_idx;
1184*437bfbebSnyanmisaka         fs_top->mb_aff_frame_flag = fs_btm->mb_aff_frame_flag = frame->mb_aff_frame_flag;
1185*437bfbebSnyanmisaka 
1186*437bfbebSnyanmisaka         frame->top_field = fs_top;
1187*437bfbebSnyanmisaka         frame->bottom_field = fs_btm;
1188*437bfbebSnyanmisaka         frame->frame = frame;
1189*437bfbebSnyanmisaka         fs_top->bottom_field = fs_btm;
1190*437bfbebSnyanmisaka         fs_top->frame = frame;
1191*437bfbebSnyanmisaka         fs_top->top_field = fs_top;
1192*437bfbebSnyanmisaka         fs_btm->top_field = fs_top;
1193*437bfbebSnyanmisaka         fs_btm->frame = frame;
1194*437bfbebSnyanmisaka         fs_btm->bottom_field = fs_btm;
1195*437bfbebSnyanmisaka 
1196*437bfbebSnyanmisaka         fs_top->is_mmco_5 = frame->is_mmco_5;
1197*437bfbebSnyanmisaka         fs_btm->is_mmco_5 = frame->is_mmco_5;
1198*437bfbebSnyanmisaka         fs_top->poc_mmco5 = frame->poc_mmco5;
1199*437bfbebSnyanmisaka         fs_btm->poc_mmco5 = frame->poc_mmco5;
1200*437bfbebSnyanmisaka         fs_top->top_poc_mmco5 = frame->top_poc_mmco5;
1201*437bfbebSnyanmisaka         fs_btm->bot_poc_mmco5 = frame->bot_poc_mmco5;
1202*437bfbebSnyanmisaka 
1203*437bfbebSnyanmisaka         fs_top->view_id = fs_btm->view_id = fs->view_id;
1204*437bfbebSnyanmisaka         fs_top->inter_view_flag = fs->inter_view_flag[0];
1205*437bfbebSnyanmisaka         fs_btm->inter_view_flag = fs->inter_view_flag[1];
1206*437bfbebSnyanmisaka 
1207*437bfbebSnyanmisaka         fs_top->chroma_format_idc = fs_btm->chroma_format_idc = frame->chroma_format_idc;
1208*437bfbebSnyanmisaka         fs_top->iCodingType = fs_btm->iCodingType = frame->iCodingType;
1209*437bfbebSnyanmisaka         fs_top->slice_type = fs_btm->slice_type = frame->slice_type;
1210*437bfbebSnyanmisaka     } else {
1211*437bfbebSnyanmisaka         fs->top_field = NULL;
1212*437bfbebSnyanmisaka         fs->bottom_field = NULL;
1213*437bfbebSnyanmisaka         frame->top_field = NULL;
1214*437bfbebSnyanmisaka         frame->bottom_field = NULL;
1215*437bfbebSnyanmisaka         frame->frame = frame;
1216*437bfbebSnyanmisaka     }
1217*437bfbebSnyanmisaka     return ret = MPP_OK;
1218*437bfbebSnyanmisaka __FAILED:
1219*437bfbebSnyanmisaka     mpp_mem_pool_put_f(p_Vid->pic_st, fs->top_field);
1220*437bfbebSnyanmisaka     mpp_mem_pool_put_f(p_Vid->pic_st, fs->bottom_field);
1221*437bfbebSnyanmisaka     fs->top_field = NULL;
1222*437bfbebSnyanmisaka     fs->bottom_field = NULL;
1223*437bfbebSnyanmisaka     return ret;
1224*437bfbebSnyanmisaka }
1225*437bfbebSnyanmisaka 
dpb_combine_field(H264dVideoCtx_t * p_Vid,H264_FrameStore_t * fs,RK_U8 combine_flag)1226*437bfbebSnyanmisaka static MPP_RET dpb_combine_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, RK_U8 combine_flag)
1227*437bfbebSnyanmisaka {
1228*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1229*437bfbebSnyanmisaka 
1230*437bfbebSnyanmisaka     FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, combine_flag));
1231*437bfbebSnyanmisaka     fs->frame->layer_id = fs->layer_id;
1232*437bfbebSnyanmisaka     fs->frame->view_id = fs->view_id;
1233*437bfbebSnyanmisaka     fs->frame->iCodingType = fs->top_field->iCodingType; //FIELD_CODING;
1234*437bfbebSnyanmisaka     fs->frame->frame_num = fs->top_field->frame_num;
1235*437bfbebSnyanmisaka     fs->frame->is_output = fs->is_output;
1236*437bfbebSnyanmisaka     fs->frame->slice_type = fs->slice_type;
1237*437bfbebSnyanmisaka 
1238*437bfbebSnyanmisaka     return ret = MPP_OK;
1239*437bfbebSnyanmisaka __FAILED:
1240*437bfbebSnyanmisaka     return ret;
1241*437bfbebSnyanmisaka }
1242*437bfbebSnyanmisaka 
direct_output(H264dVideoCtx_t * p_Vid,H264_DpbBuf_t * p_Dpb,H264_StorePic_t * p)1243*437bfbebSnyanmisaka static MPP_RET direct_output(H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p)
1244*437bfbebSnyanmisaka {
1245*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1246*437bfbebSnyanmisaka 
1247*437bfbebSnyanmisaka     memcpy(&p_Vid->old_pic, p, sizeof(H264_StorePic_t));
1248*437bfbebSnyanmisaka     p_Vid->last_pic = &p_Vid->old_pic;
1249*437bfbebSnyanmisaka     if (p->structure == FRAME) {
1250*437bfbebSnyanmisaka         //!< we have a frame (or complementary field pair), so output it directly
1251*437bfbebSnyanmisaka         FUN_CHECK(ret = flush_direct_output(p_Vid));
1252*437bfbebSnyanmisaka         H264D_WARNNING("write frame, line %d", __LINE__);
1253*437bfbebSnyanmisaka         write_picture(p, p_Vid);
1254*437bfbebSnyanmisaka         p_Dpb->last_output_poc = p->poc;
1255*437bfbebSnyanmisaka         free_storable_picture(p_Vid->p_Dec, p);
1256*437bfbebSnyanmisaka         p_Dpb->last_picture = NULL;
1257*437bfbebSnyanmisaka         p_Vid->out_buffer.is_used = 0;
1258*437bfbebSnyanmisaka         p_Vid->out_buffer.is_directout = 0;
1259*437bfbebSnyanmisaka         goto __RETURN;
1260*437bfbebSnyanmisaka     }
1261*437bfbebSnyanmisaka 
1262*437bfbebSnyanmisaka     if (p->structure == TOP_FIELD) {
1263*437bfbebSnyanmisaka         if (p_Vid->out_buffer.is_used & 1) {
1264*437bfbebSnyanmisaka             FUN_CHECK(ret = flush_direct_output(p_Vid));
1265*437bfbebSnyanmisaka         }
1266*437bfbebSnyanmisaka         p_Vid->out_buffer.top_field = p;
1267*437bfbebSnyanmisaka         p_Vid->out_buffer.is_used |= 1;
1268*437bfbebSnyanmisaka         p_Vid->out_buffer.frame_num = p->pic_num;
1269*437bfbebSnyanmisaka         p_Vid->out_buffer.is_directout = 1;
1270*437bfbebSnyanmisaka         p_Dpb->last_picture = &p_Vid->out_buffer;
1271*437bfbebSnyanmisaka     }
1272*437bfbebSnyanmisaka 
1273*437bfbebSnyanmisaka     if (p->structure == BOTTOM_FIELD) {
1274*437bfbebSnyanmisaka         if (p_Vid->out_buffer.is_used & 2) {
1275*437bfbebSnyanmisaka             FUN_CHECK(ret = flush_direct_output(p_Vid));
1276*437bfbebSnyanmisaka         }
1277*437bfbebSnyanmisaka         p_Vid->out_buffer.bottom_field = p;
1278*437bfbebSnyanmisaka         p_Vid->out_buffer.is_used |= 2;
1279*437bfbebSnyanmisaka         p_Vid->out_buffer.frame_num = p->pic_num;
1280*437bfbebSnyanmisaka         p_Vid->out_buffer.is_directout = 1;
1281*437bfbebSnyanmisaka         p_Dpb->last_picture = &p_Vid->out_buffer;
1282*437bfbebSnyanmisaka     }
1283*437bfbebSnyanmisaka 
1284*437bfbebSnyanmisaka     if (p_Vid->out_buffer.is_used == 3) {
1285*437bfbebSnyanmisaka         //!< we have both fields, so output them
1286*437bfbebSnyanmisaka         FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, &p_Vid->out_buffer, 0));
1287*437bfbebSnyanmisaka         p_Vid->out_buffer.frame->view_id = p_Vid->out_buffer.view_id;
1288*437bfbebSnyanmisaka         H264D_WARNNING("write frame, line %d", __LINE__);
1289*437bfbebSnyanmisaka         write_picture(p_Vid->out_buffer.frame, p_Vid);
1290*437bfbebSnyanmisaka         free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.frame);
1291*437bfbebSnyanmisaka         p_Vid->out_buffer.frame = NULL;
1292*437bfbebSnyanmisaka         free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.top_field);
1293*437bfbebSnyanmisaka         p_Vid->out_buffer.top_field = NULL;
1294*437bfbebSnyanmisaka         free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.bottom_field);
1295*437bfbebSnyanmisaka         p_Vid->out_buffer.bottom_field = NULL;
1296*437bfbebSnyanmisaka         p_Vid->out_buffer.is_used = 0;
1297*437bfbebSnyanmisaka         p_Vid->out_buffer.is_directout = 0;
1298*437bfbebSnyanmisaka         p_Dpb->last_output_poc = p->poc;
1299*437bfbebSnyanmisaka         p_Dpb->last_picture = NULL;
1300*437bfbebSnyanmisaka     }
1301*437bfbebSnyanmisaka 
1302*437bfbebSnyanmisaka __RETURN:
1303*437bfbebSnyanmisaka     return ret = MPP_OK;
1304*437bfbebSnyanmisaka __FAILED:
1305*437bfbebSnyanmisaka     return ret;
1306*437bfbebSnyanmisaka }
1307*437bfbebSnyanmisaka 
output_dpb_normal(H264_DpbBuf_t * p_Dpb)1308*437bfbebSnyanmisaka static MPP_RET output_dpb_normal(H264_DpbBuf_t *p_Dpb)
1309*437bfbebSnyanmisaka {
1310*437bfbebSnyanmisaka     MPP_RET ret = MPP_NOK;
1311*437bfbebSnyanmisaka     RK_S32 min_poc = 0;
1312*437bfbebSnyanmisaka     RK_S32 min_pos = 0;
1313*437bfbebSnyanmisaka     RK_S32 poc_inc = 0;
1314*437bfbebSnyanmisaka 
1315*437bfbebSnyanmisaka     while ((p_Dpb->last_output_poc > INT_MIN)
1316*437bfbebSnyanmisaka            && (get_smallest_poc(p_Dpb, &min_poc, &min_pos))) {
1317*437bfbebSnyanmisaka         poc_inc = min_poc - p_Dpb->last_output_poc;
1318*437bfbebSnyanmisaka         if ((p_Dpb->last_output_poc > INT_MIN) && (abs(poc_inc) & 0x1))
1319*437bfbebSnyanmisaka             p_Dpb->poc_interval = 1;
1320*437bfbebSnyanmisaka         if ((min_poc - p_Dpb->last_output_poc) <= p_Dpb->poc_interval) {
1321*437bfbebSnyanmisaka             FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, p_Dpb->fs[min_pos]));
1322*437bfbebSnyanmisaka         } else {
1323*437bfbebSnyanmisaka             break;
1324*437bfbebSnyanmisaka         }
1325*437bfbebSnyanmisaka     }
1326*437bfbebSnyanmisaka     while (!remove_unused_frame_from_dpb(p_Dpb));
1327*437bfbebSnyanmisaka 
1328*437bfbebSnyanmisaka     return MPP_OK;
1329*437bfbebSnyanmisaka __FAILED:
1330*437bfbebSnyanmisaka     return ret;
1331*437bfbebSnyanmisaka }
output_dpb_fastplay(H264_DpbBuf_t * p_Dpb,H264_FrameStore_t * fs,RK_U32 is_i_frm)1332*437bfbebSnyanmisaka static MPP_RET output_dpb_fastplay(H264_DpbBuf_t *p_Dpb, H264_FrameStore_t *fs, RK_U32 is_i_frm)
1333*437bfbebSnyanmisaka {
1334*437bfbebSnyanmisaka     MPP_RET ret = MPP_NOK;
1335*437bfbebSnyanmisaka 
1336*437bfbebSnyanmisaka     if ((p_Dpb->p_Vid->dpb_fast_out && is_i_frm)) {
1337*437bfbebSnyanmisaka         FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, fs));
1338*437bfbebSnyanmisaka     } else
1339*437bfbebSnyanmisaka         output_dpb_normal(p_Dpb);
1340*437bfbebSnyanmisaka 
1341*437bfbebSnyanmisaka     return MPP_OK;
1342*437bfbebSnyanmisaka __FAILED:
1343*437bfbebSnyanmisaka     return ret;
1344*437bfbebSnyanmisaka }
output_dpb_fastplay_once(H264_DpbBuf_t * p_Dpb,H264_FrameStore_t * fs,RK_U32 is_i_frm)1345*437bfbebSnyanmisaka static MPP_RET output_dpb_fastplay_once(H264_DpbBuf_t *p_Dpb, H264_FrameStore_t *fs, RK_U32 is_i_frm)
1346*437bfbebSnyanmisaka {
1347*437bfbebSnyanmisaka     MPP_RET ret = MPP_NOK;
1348*437bfbebSnyanmisaka 
1349*437bfbebSnyanmisaka     if (p_Dpb->p_Vid->dpb_fast_out && is_i_frm && !p_Dpb->p_Vid->dpb_first_fast_played) {
1350*437bfbebSnyanmisaka         FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, fs));
1351*437bfbebSnyanmisaka         p_Dpb->p_Vid->dpb_first_fast_played = 1;
1352*437bfbebSnyanmisaka     } else {
1353*437bfbebSnyanmisaka         // disable fast play once in the second gop
1354*437bfbebSnyanmisaka         if (p_Dpb->p_Vid->dpb_fast_out && is_i_frm && p_Dpb->p_Vid->dpb_first_fast_played) {
1355*437bfbebSnyanmisaka             p_Dpb->p_Vid->dpb_fast_out = MPP_DISABLE_FAST_PLAY;
1356*437bfbebSnyanmisaka         }
1357*437bfbebSnyanmisaka         output_dpb_normal(p_Dpb);
1358*437bfbebSnyanmisaka     }
1359*437bfbebSnyanmisaka 
1360*437bfbebSnyanmisaka     return MPP_OK;
1361*437bfbebSnyanmisaka __FAILED:
1362*437bfbebSnyanmisaka     return ret;
1363*437bfbebSnyanmisaka }
1364*437bfbebSnyanmisaka 
scan_dpb_output(H264_DpbBuf_t * p_Dpb,H264_StorePic_t * p)1365*437bfbebSnyanmisaka static MPP_RET scan_dpb_output(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p)
1366*437bfbebSnyanmisaka {
1367*437bfbebSnyanmisaka     MPP_RET ret = MPP_NOK;
1368*437bfbebSnyanmisaka     H264_FrameStore_t *fs = p_Dpb->fs[p_Dpb->used_size - 1];
1369*437bfbebSnyanmisaka 
1370*437bfbebSnyanmisaka     if (fs->is_used == 3) {
1371*437bfbebSnyanmisaka         H264dErrCtx_t *p_err = &p_Dpb->p_Vid->p_Dec->errctx;
1372*437bfbebSnyanmisaka         RK_U32 is_i_frm = p_err->i_slice_no < 2 && p_Dpb->last_output_poc == INT_MIN;
1373*437bfbebSnyanmisaka 
1374*437bfbebSnyanmisaka         if (p_Dpb->p_Vid->p_Dec->cfg->base.fast_out)
1375*437bfbebSnyanmisaka             FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, fs));
1376*437bfbebSnyanmisaka         else {
1377*437bfbebSnyanmisaka             switch (p_Dpb->p_Vid->p_Dec->cfg->base.enable_fast_play) {
1378*437bfbebSnyanmisaka             case MPP_DISABLE_FAST_PLAY:
1379*437bfbebSnyanmisaka                 FUN_CHECK(ret = output_dpb_normal(p_Dpb));
1380*437bfbebSnyanmisaka                 break;
1381*437bfbebSnyanmisaka             case MPP_ENABLE_FAST_PLAY:
1382*437bfbebSnyanmisaka                 FUN_CHECK(ret = output_dpb_fastplay(p_Dpb, fs, is_i_frm));
1383*437bfbebSnyanmisaka                 break;
1384*437bfbebSnyanmisaka             case MPP_ENABLE_FAST_PLAY_ONCE:
1385*437bfbebSnyanmisaka                 FUN_CHECK(ret = output_dpb_fastplay_once(p_Dpb, fs, is_i_frm));
1386*437bfbebSnyanmisaka                 break;
1387*437bfbebSnyanmisaka             default:
1388*437bfbebSnyanmisaka                 H264D_ERR("unsupport output mode");
1389*437bfbebSnyanmisaka             }
1390*437bfbebSnyanmisaka         }
1391*437bfbebSnyanmisaka 
1392*437bfbebSnyanmisaka         if (is_i_frm)
1393*437bfbebSnyanmisaka             p_err->first_iframe_is_output = fs->is_output;
1394*437bfbebSnyanmisaka     }
1395*437bfbebSnyanmisaka     (void )p;
1396*437bfbebSnyanmisaka     return MPP_OK;
1397*437bfbebSnyanmisaka __FAILED:
1398*437bfbebSnyanmisaka     return ret;
1399*437bfbebSnyanmisaka }
1400*437bfbebSnyanmisaka 
flush_one_dpb_mark(H264_DecCtx_t * p_Dec,H264_DpbMark_t * p_mark)1401*437bfbebSnyanmisaka static void flush_one_dpb_mark(H264_DecCtx_t *p_Dec, H264_DpbMark_t *p_mark)
1402*437bfbebSnyanmisaka {
1403*437bfbebSnyanmisaka     if (NULL == p_mark)
1404*437bfbebSnyanmisaka         return;
1405*437bfbebSnyanmisaka     if (p_mark->out_flag && (p_mark->slot_idx >= 0)) {
1406*437bfbebSnyanmisaka         MppFrame mframe = NULL;
1407*437bfbebSnyanmisaka 
1408*437bfbebSnyanmisaka         mpp_buf_slot_get_prop(p_Dec->frame_slots, p_mark->slot_idx, SLOT_FRAME_PTR, &mframe);
1409*437bfbebSnyanmisaka         if (mframe) {
1410*437bfbebSnyanmisaka             H264D_DBG(H264D_DBG_SLOT_FLUSH, "[DPB_BUF_FLUSH] slot_idx=%d, top_used=%d, bot_used=%d",
1411*437bfbebSnyanmisaka                       p_mark->slot_idx, p_mark->top_used, p_mark->bot_used);
1412*437bfbebSnyanmisaka             mpp_frame_set_discard(mframe, 1);
1413*437bfbebSnyanmisaka             mpp_buf_slot_set_flag(p_Dec->frame_slots, p_mark->slot_idx, SLOT_QUEUE_USE);
1414*437bfbebSnyanmisaka             mpp_buf_slot_enqueue(p_Dec->frame_slots, p_mark->slot_idx, QUEUE_DISPLAY);
1415*437bfbebSnyanmisaka             mpp_buf_slot_clr_flag(p_Dec->frame_slots, p_mark->slot_idx, SLOT_CODEC_USE);
1416*437bfbebSnyanmisaka             p_Dec->last_frame_slot_idx = p_mark->slot_idx;
1417*437bfbebSnyanmisaka         }
1418*437bfbebSnyanmisaka         reset_dpb_mark(p_mark);
1419*437bfbebSnyanmisaka         return;
1420*437bfbebSnyanmisaka     }
1421*437bfbebSnyanmisaka     H264D_DBG(H264D_DBG_WARNNING, "out_flag %d slot_idx %d\n", p_mark->out_flag, p_mark->slot_idx);
1422*437bfbebSnyanmisaka }
1423*437bfbebSnyanmisaka 
1424*437bfbebSnyanmisaka /*!
1425*437bfbebSnyanmisaka ***********************************************************************
1426*437bfbebSnyanmisaka * \brief
1427*437bfbebSnyanmisaka *    store picture to dpb
1428*437bfbebSnyanmisaka ***********************************************************************
1429*437bfbebSnyanmisaka */
1430*437bfbebSnyanmisaka //extern "C"
store_picture_in_dpb(H264_DpbBuf_t * p_Dpb,H264_StorePic_t * p)1431*437bfbebSnyanmisaka MPP_RET store_picture_in_dpb(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p)
1432*437bfbebSnyanmisaka {
1433*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1434*437bfbebSnyanmisaka     H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid;
1435*437bfbebSnyanmisaka     RK_U32 max_buf_size = 0;
1436*437bfbebSnyanmisaka 
1437*437bfbebSnyanmisaka     VAL_CHECK(ret, NULL != p);  //!< if frame, check for new store
1438*437bfbebSnyanmisaka     //!< set use flag
1439*437bfbebSnyanmisaka     if (p->mem_mark && (p->mem_mark->slot_idx >= 0)) {
1440*437bfbebSnyanmisaka         mpp_buf_slot_set_flag(p_Vid->p_Dec->frame_slots, p->mem_mark->slot_idx, SLOT_CODEC_USE);
1441*437bfbebSnyanmisaka     } else {
1442*437bfbebSnyanmisaka         H264D_ERR("error, p->mem_mark == NULL");
1443*437bfbebSnyanmisaka     }
1444*437bfbebSnyanmisaka     //!< deal with all frames in dpb
1445*437bfbebSnyanmisaka     p_Vid->last_has_mmco_5 = 0;
1446*437bfbebSnyanmisaka     p_Vid->last_pic_bottom_field = p->structure == BOTTOM_FIELD;
1447*437bfbebSnyanmisaka     if (p->idr_flag) {
1448*437bfbebSnyanmisaka         FUN_CHECK(ret = idr_memory_management(p_Dpb, p));
1449*437bfbebSnyanmisaka     } else {    //!< adaptive memory management
1450*437bfbebSnyanmisaka         if (p->used_for_reference && p->adaptive_ref_pic_buffering_flag) {
1451*437bfbebSnyanmisaka             FUN_CHECK(ret = adaptive_memory_management(p_Dpb, p));
1452*437bfbebSnyanmisaka         }
1453*437bfbebSnyanmisaka     }
1454*437bfbebSnyanmisaka     //!< if necessary, combine top and botteom to frame
1455*437bfbebSnyanmisaka     if (get_field_dpb_combine_flag(p_Dpb->last_picture, p)) {
1456*437bfbebSnyanmisaka         if (p_Dpb->last_picture->is_directout) {
1457*437bfbebSnyanmisaka             FUN_CHECK(ret = direct_output(p_Vid, p_Dpb, p));  //!< output frame
1458*437bfbebSnyanmisaka         } else {
1459*437bfbebSnyanmisaka             FUN_CHECK(ret = insert_picture_in_dpb(p_Vid, p_Dpb->last_picture, p, 1));  //!< field_dpb_combine
1460*437bfbebSnyanmisaka             scan_dpb_output(p_Dpb, p);
1461*437bfbebSnyanmisaka         }
1462*437bfbebSnyanmisaka         memcpy(&p_Vid->old_pic, p, sizeof(H264_StorePic_t));
1463*437bfbebSnyanmisaka         p_Vid->last_pic = &p_Vid->old_pic;
1464*437bfbebSnyanmisaka         p_Dpb->last_picture = NULL;
1465*437bfbebSnyanmisaka         goto __RETURN;
1466*437bfbebSnyanmisaka     }
1467*437bfbebSnyanmisaka     //!< sliding window
1468*437bfbebSnyanmisaka     if (!p->idr_flag && p->used_for_reference && !p->adaptive_ref_pic_buffering_flag) {
1469*437bfbebSnyanmisaka         ASSERT(!p->idr_flag);
1470*437bfbebSnyanmisaka         sliding_window_memory_management(p_Dpb);
1471*437bfbebSnyanmisaka         p->is_long_term = 0;
1472*437bfbebSnyanmisaka     }
1473*437bfbebSnyanmisaka     while (!remove_unused_frame_from_dpb(p_Dpb));
1474*437bfbebSnyanmisaka     H264D_DBG(H264D_DBG_DPB_INFO, "before out, dpb[%d] used_size %d, size %d",
1475*437bfbebSnyanmisaka               p_Dpb->layer_id, p_Dpb->used_size, p_Dpb->size);
1476*437bfbebSnyanmisaka     //!< when full output one frame or more then setting max_buf_size
1477*437bfbebSnyanmisaka     max_buf_size = p_Vid->p_Inp->max_buf_size;
1478*437bfbebSnyanmisaka     if (max_buf_size)
1479*437bfbebSnyanmisaka         H264D_DBG(H264D_DBG_DPB_INFO, "max_buf_size=%d\n", max_buf_size);
1480*437bfbebSnyanmisaka     while (p_Dpb->used_size >= p_Dpb->size ||
1481*437bfbebSnyanmisaka            (max_buf_size && p_Dpb->used_size >= max_buf_size)) {
1482*437bfbebSnyanmisaka         RK_S32 min_poc = 0, min_pos = 0;
1483*437bfbebSnyanmisaka         RK_S32 find_flag = 0;
1484*437bfbebSnyanmisaka 
1485*437bfbebSnyanmisaka         remove_unused_frame_from_dpb(p_Dpb);
1486*437bfbebSnyanmisaka         find_flag = get_smallest_poc(p_Dpb, &min_poc, &min_pos);
1487*437bfbebSnyanmisaka         if (!p->used_for_reference) {
1488*437bfbebSnyanmisaka             if ((!find_flag) || (p->poc < min_poc)) {
1489*437bfbebSnyanmisaka                 FUN_CHECK(ret = direct_output(p_Vid, p_Dpb, p));  //!< output frame
1490*437bfbebSnyanmisaka                 goto __RETURN;
1491*437bfbebSnyanmisaka             }
1492*437bfbebSnyanmisaka         }
1493*437bfbebSnyanmisaka         //!< used for reference, but not find, then flush a frame in the first
1494*437bfbebSnyanmisaka         if ((!find_flag) || (p->poc < min_poc)) {
1495*437bfbebSnyanmisaka             min_pos = 0;
1496*437bfbebSnyanmisaka             unmark_for_reference(p_Vid->p_Dec, p_Dpb->fs[min_pos]);
1497*437bfbebSnyanmisaka             if (!p_Dpb->fs[min_pos]->is_output) {
1498*437bfbebSnyanmisaka                 H264D_WARNNING("write_stored_frame, line %d", __LINE__);
1499*437bfbebSnyanmisaka                 FUN_CHECK(ret = write_stored_frame(p_Vid, p_Dpb, p_Dpb->fs[min_pos]));
1500*437bfbebSnyanmisaka             }
1501*437bfbebSnyanmisaka             FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, min_pos));
1502*437bfbebSnyanmisaka             p->is_long_term = 0;
1503*437bfbebSnyanmisaka         } else {
1504*437bfbebSnyanmisaka             FUN_CHECK(ret = output_one_frame_from_dpb(p_Dpb));
1505*437bfbebSnyanmisaka         }
1506*437bfbebSnyanmisaka     }
1507*437bfbebSnyanmisaka     H264D_DBG(H264D_DBG_DPB_INFO, "after out, dpb[%d] used_size %d, size %d",
1508*437bfbebSnyanmisaka               p_Dpb->layer_id, p_Dpb->used_size, p_Dpb->size);
1509*437bfbebSnyanmisaka     //!< store current decoder picture at end of dpb
1510*437bfbebSnyanmisaka     FUN_CHECK(ret = insert_picture_in_dpb(p_Vid, p_Dpb->fs[p_Dpb->used_size], p, 0));
1511*437bfbebSnyanmisaka     if (p->structure != FRAME) {
1512*437bfbebSnyanmisaka         p_Dpb->last_picture = p_Dpb->fs[p_Dpb->used_size];
1513*437bfbebSnyanmisaka     } else {
1514*437bfbebSnyanmisaka         p_Dpb->last_picture = NULL;
1515*437bfbebSnyanmisaka     }
1516*437bfbebSnyanmisaka     memcpy(&p_Vid->old_pic, p, sizeof(H264_StorePic_t));
1517*437bfbebSnyanmisaka     p_Vid->last_pic = &p_Vid->old_pic;
1518*437bfbebSnyanmisaka 
1519*437bfbebSnyanmisaka     p_Dpb->used_size++;
1520*437bfbebSnyanmisaka     H264D_DBG(H264D_DBG_DPB_INFO, "[DPB_size] p_Dpb->used_size=%d", p_Dpb->used_size);
1521*437bfbebSnyanmisaka     if (!p_Vid->p_Dec->mvc_valid)
1522*437bfbebSnyanmisaka         scan_dpb_output(p_Dpb, p);
1523*437bfbebSnyanmisaka     update_ref_list(p_Dpb);
1524*437bfbebSnyanmisaka     update_ltref_list(p_Dpb);
1525*437bfbebSnyanmisaka 
1526*437bfbebSnyanmisaka __RETURN:
1527*437bfbebSnyanmisaka     return ret = MPP_OK;
1528*437bfbebSnyanmisaka __FAILED:
1529*437bfbebSnyanmisaka     flush_one_dpb_mark(p_Vid->p_Dec, p->mem_mark);
1530*437bfbebSnyanmisaka     return ret;
1531*437bfbebSnyanmisaka }
1532*437bfbebSnyanmisaka 
1533*437bfbebSnyanmisaka /*!
1534*437bfbebSnyanmisaka ***********************************************************************
1535*437bfbebSnyanmisaka * \brief
1536*437bfbebSnyanmisaka *    free frame store picture
1537*437bfbebSnyanmisaka ***********************************************************************
1538*437bfbebSnyanmisaka */
1539*437bfbebSnyanmisaka //extern "C"
free_frame_store(H264_DecCtx_t * p_Dec,H264_FrameStore_t * f)1540*437bfbebSnyanmisaka void free_frame_store(H264_DecCtx_t *p_Dec, H264_FrameStore_t* f)
1541*437bfbebSnyanmisaka {
1542*437bfbebSnyanmisaka     if (f) {
1543*437bfbebSnyanmisaka         if (f->frame) {
1544*437bfbebSnyanmisaka             free_storable_picture(p_Dec, f->frame);
1545*437bfbebSnyanmisaka             f->frame = NULL;
1546*437bfbebSnyanmisaka         }
1547*437bfbebSnyanmisaka         if (f->top_field) {
1548*437bfbebSnyanmisaka             free_storable_picture(p_Dec, f->top_field);
1549*437bfbebSnyanmisaka             f->top_field = NULL;
1550*437bfbebSnyanmisaka         }
1551*437bfbebSnyanmisaka         if (f->bottom_field) {
1552*437bfbebSnyanmisaka             free_storable_picture(p_Dec, f->bottom_field);
1553*437bfbebSnyanmisaka             f->bottom_field = NULL;
1554*437bfbebSnyanmisaka         }
1555*437bfbebSnyanmisaka         MPP_FREE(f);
1556*437bfbebSnyanmisaka     }
1557*437bfbebSnyanmisaka }
1558*437bfbebSnyanmisaka 
1559*437bfbebSnyanmisaka /*!
1560*437bfbebSnyanmisaka ***********************************************************************
1561*437bfbebSnyanmisaka * \brief
1562*437bfbebSnyanmisaka *    free dpb
1563*437bfbebSnyanmisaka ***********************************************************************
1564*437bfbebSnyanmisaka */
1565*437bfbebSnyanmisaka //extern "C"
free_dpb(H264_DpbBuf_t * p_Dpb)1566*437bfbebSnyanmisaka void free_dpb(H264_DpbBuf_t *p_Dpb)
1567*437bfbebSnyanmisaka {
1568*437bfbebSnyanmisaka     RK_U32 i = 0;
1569*437bfbebSnyanmisaka     H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid;
1570*437bfbebSnyanmisaka 
1571*437bfbebSnyanmisaka     if (p_Dpb->fs) {
1572*437bfbebSnyanmisaka         for (i = 0; i < p_Dpb->allocated_size; i++) {
1573*437bfbebSnyanmisaka             free_frame_store(p_Vid->p_Dec, p_Dpb->fs[i]);
1574*437bfbebSnyanmisaka             p_Dpb->fs[i] = NULL;
1575*437bfbebSnyanmisaka         }
1576*437bfbebSnyanmisaka         MPP_FREE(p_Dpb->fs);
1577*437bfbebSnyanmisaka     }
1578*437bfbebSnyanmisaka     MPP_FREE(p_Dpb->fs_ref);
1579*437bfbebSnyanmisaka     MPP_FREE(p_Dpb->fs_ltref);
1580*437bfbebSnyanmisaka     if (p_Dpb->fs_ilref) {
1581*437bfbebSnyanmisaka         for (i = 0; i < 1; i++) {
1582*437bfbebSnyanmisaka             free_frame_store(p_Vid->p_Dec, p_Dpb->fs_ilref[i]);
1583*437bfbebSnyanmisaka             p_Dpb->fs_ilref[i] = NULL;
1584*437bfbebSnyanmisaka         }
1585*437bfbebSnyanmisaka         MPP_FREE(p_Dpb->fs_ilref);
1586*437bfbebSnyanmisaka     }
1587*437bfbebSnyanmisaka     p_Dpb->last_output_view_id = -1;
1588*437bfbebSnyanmisaka     p_Dpb->last_output_poc = INT_MIN;
1589*437bfbebSnyanmisaka     p_Dpb->init_done = 0;
1590*437bfbebSnyanmisaka     if (p_Vid->no_ref_pic) {
1591*437bfbebSnyanmisaka         free_storable_picture(p_Vid->p_Dec, p_Vid->no_ref_pic);
1592*437bfbebSnyanmisaka         p_Vid->no_ref_pic = NULL;
1593*437bfbebSnyanmisaka     }
1594*437bfbebSnyanmisaka }
1595*437bfbebSnyanmisaka 
1596*437bfbebSnyanmisaka /*!
1597*437bfbebSnyanmisaka ***********************************************************************
1598*437bfbebSnyanmisaka * \brief
1599*437bfbebSnyanmisaka *    alloc one picture
1600*437bfbebSnyanmisaka ***********************************************************************
1601*437bfbebSnyanmisaka */
1602*437bfbebSnyanmisaka //extern "C"
update_ref_list(H264_DpbBuf_t * p_Dpb)1603*437bfbebSnyanmisaka void update_ref_list(H264_DpbBuf_t *p_Dpb)
1604*437bfbebSnyanmisaka {
1605*437bfbebSnyanmisaka     RK_U8 i = 0, j = 0;
1606*437bfbebSnyanmisaka     for (i = 0, j = 0; i < p_Dpb->used_size; i++) {
1607*437bfbebSnyanmisaka         if (is_short_term_reference(p_Dpb->fs[i])) {
1608*437bfbebSnyanmisaka             p_Dpb->fs_ref[j++] = p_Dpb->fs[i];
1609*437bfbebSnyanmisaka         }
1610*437bfbebSnyanmisaka     }
1611*437bfbebSnyanmisaka 
1612*437bfbebSnyanmisaka     p_Dpb->ref_frames_in_buffer = j;
1613*437bfbebSnyanmisaka 
1614*437bfbebSnyanmisaka     while (j < p_Dpb->size) {
1615*437bfbebSnyanmisaka         p_Dpb->fs_ref[j++] = NULL;
1616*437bfbebSnyanmisaka     }
1617*437bfbebSnyanmisaka }
1618*437bfbebSnyanmisaka /*!
1619*437bfbebSnyanmisaka ***********************************************************************
1620*437bfbebSnyanmisaka * \brief
1621*437bfbebSnyanmisaka *    alloc one picture
1622*437bfbebSnyanmisaka ***********************************************************************
1623*437bfbebSnyanmisaka */
1624*437bfbebSnyanmisaka //extern "C"
update_ltref_list(H264_DpbBuf_t * p_Dpb)1625*437bfbebSnyanmisaka void update_ltref_list(H264_DpbBuf_t *p_Dpb)
1626*437bfbebSnyanmisaka {
1627*437bfbebSnyanmisaka     RK_U8 i = 0, j = 0;
1628*437bfbebSnyanmisaka     for (i = 0, j = 0; i < p_Dpb->used_size; i++) {
1629*437bfbebSnyanmisaka         if (is_long_term_reference(p_Dpb->fs[i])) {
1630*437bfbebSnyanmisaka             p_Dpb->fs_ltref[j++] = p_Dpb->fs[i];
1631*437bfbebSnyanmisaka         }
1632*437bfbebSnyanmisaka     }
1633*437bfbebSnyanmisaka 
1634*437bfbebSnyanmisaka     p_Dpb->ltref_frames_in_buffer = j;
1635*437bfbebSnyanmisaka 
1636*437bfbebSnyanmisaka     while (j < p_Dpb->size) {
1637*437bfbebSnyanmisaka         p_Dpb->fs_ltref[j++] = NULL;
1638*437bfbebSnyanmisaka     }
1639*437bfbebSnyanmisaka }
1640*437bfbebSnyanmisaka 
1641*437bfbebSnyanmisaka /*!
1642*437bfbebSnyanmisaka ***********************************************************************
1643*437bfbebSnyanmisaka * \brief
1644*437bfbebSnyanmisaka *    alloc one picture
1645*437bfbebSnyanmisaka ***********************************************************************
1646*437bfbebSnyanmisaka */
1647*437bfbebSnyanmisaka //extern "C"
idr_memory_management(H264_DpbBuf_t * p_Dpb,H264_StorePic_t * p)1648*437bfbebSnyanmisaka MPP_RET idr_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p)
1649*437bfbebSnyanmisaka {
1650*437bfbebSnyanmisaka     RK_U32 i = 0;
1651*437bfbebSnyanmisaka     RK_S32 type = -1;
1652*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1653*437bfbebSnyanmisaka     H264dErrCtx_t *p_err = &p_Dpb->p_Vid->p_Dec->errctx;
1654*437bfbebSnyanmisaka 
1655*437bfbebSnyanmisaka     if (p->no_output_of_prior_pics_flag) {
1656*437bfbebSnyanmisaka         //!< free all stored pictures
1657*437bfbebSnyanmisaka         for (i = 0; i < p_Dpb->used_size; i++) {
1658*437bfbebSnyanmisaka             //!< reset all reference settings
1659*437bfbebSnyanmisaka             //Set is_output flag to true to avoid real output this frame to
1660*437bfbebSnyanmisaka             //display queue. These frames will be mark as unused and remove from
1661*437bfbebSnyanmisaka             //dpb at flush_dpb
1662*437bfbebSnyanmisaka             p_Dpb->fs[i]->is_output = 1;
1663*437bfbebSnyanmisaka         }
1664*437bfbebSnyanmisaka     }
1665*437bfbebSnyanmisaka 
1666*437bfbebSnyanmisaka     type = (p->layer_id == 0) ? 1 : 2;
1667*437bfbebSnyanmisaka     FUN_CHECK(ret = flush_dpb(p_Dpb, type));
1668*437bfbebSnyanmisaka 
1669*437bfbebSnyanmisaka     p_Dpb->last_picture = NULL;
1670*437bfbebSnyanmisaka 
1671*437bfbebSnyanmisaka     update_ref_list(p_Dpb);
1672*437bfbebSnyanmisaka     update_ltref_list(p_Dpb);
1673*437bfbebSnyanmisaka     p_Dpb->last_output_poc = INT_MIN;
1674*437bfbebSnyanmisaka     p_err->i_slice_no = 1;
1675*437bfbebSnyanmisaka 
1676*437bfbebSnyanmisaka     if (p->long_term_reference_flag) {
1677*437bfbebSnyanmisaka         p_Dpb->max_long_term_pic_idx = 0;
1678*437bfbebSnyanmisaka         p->is_long_term = 1;
1679*437bfbebSnyanmisaka         p->long_term_frame_idx = 0;
1680*437bfbebSnyanmisaka     } else {
1681*437bfbebSnyanmisaka         p_Dpb->max_long_term_pic_idx = -1;
1682*437bfbebSnyanmisaka         p->is_long_term = 0;
1683*437bfbebSnyanmisaka     }
1684*437bfbebSnyanmisaka     p_Dpb->last_output_view_id = -1;
1685*437bfbebSnyanmisaka 
1686*437bfbebSnyanmisaka     return ret = MPP_OK;
1687*437bfbebSnyanmisaka 
1688*437bfbebSnyanmisaka __FAILED:
1689*437bfbebSnyanmisaka     for (i = 0; i < p_Dpb->used_size; i++) { // when error and free malloc buf
1690*437bfbebSnyanmisaka         free_frame_store(p_Dpb->p_Vid->p_Dec, p_Dpb->fs[i]);
1691*437bfbebSnyanmisaka     }
1692*437bfbebSnyanmisaka     return ret;
1693*437bfbebSnyanmisaka }
1694*437bfbebSnyanmisaka 
1695*437bfbebSnyanmisaka 
1696*437bfbebSnyanmisaka /*!
1697*437bfbebSnyanmisaka ***********************************************************************
1698*437bfbebSnyanmisaka * \brief
1699*437bfbebSnyanmisaka *    alloc one picture
1700*437bfbebSnyanmisaka ***********************************************************************
1701*437bfbebSnyanmisaka */
1702*437bfbebSnyanmisaka //extern "C"
insert_picture_in_dpb(H264dVideoCtx_t * p_Vid,H264_FrameStore_t * fs,H264_StorePic_t * p,RK_U8 combine_flag)1703*437bfbebSnyanmisaka MPP_RET insert_picture_in_dpb(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, H264_StorePic_t *p, RK_U8 combine_flag)
1704*437bfbebSnyanmisaka {
1705*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1706*437bfbebSnyanmisaka 
1707*437bfbebSnyanmisaka     ASSERT(p  != NULL);
1708*437bfbebSnyanmisaka     ASSERT(fs != NULL);
1709*437bfbebSnyanmisaka 
1710*437bfbebSnyanmisaka     switch (p->structure) {
1711*437bfbebSnyanmisaka     case FRAME:
1712*437bfbebSnyanmisaka         fs->frame = p;
1713*437bfbebSnyanmisaka         fs->is_used = 3;
1714*437bfbebSnyanmisaka         if (p->used_for_reference) {
1715*437bfbebSnyanmisaka             fs->is_reference = 3;
1716*437bfbebSnyanmisaka             fs->is_orig_reference = 3;
1717*437bfbebSnyanmisaka             if (p->is_long_term) {
1718*437bfbebSnyanmisaka                 fs->is_long_term = 3;
1719*437bfbebSnyanmisaka                 fs->long_term_frame_idx = p->long_term_frame_idx;
1720*437bfbebSnyanmisaka             }
1721*437bfbebSnyanmisaka         }
1722*437bfbebSnyanmisaka         fs->inter_view_flag[0] = fs->inter_view_flag[1] = p->inter_view_flag;
1723*437bfbebSnyanmisaka         fs->anchor_pic_flag[0] = fs->anchor_pic_flag[1] = p->anchor_pic_flag;
1724*437bfbebSnyanmisaka         FUN_CHECK(ret = dpb_split_field(p_Vid, fs));
1725*437bfbebSnyanmisaka         fs->poc = p->poc;
1726*437bfbebSnyanmisaka         break;
1727*437bfbebSnyanmisaka     case TOP_FIELD:
1728*437bfbebSnyanmisaka         fs->top_field = p;
1729*437bfbebSnyanmisaka         fs->is_used |= 1;
1730*437bfbebSnyanmisaka         fs->inter_view_flag[0] = p->inter_view_flag;
1731*437bfbebSnyanmisaka         fs->anchor_pic_flag[0] = p->anchor_pic_flag;
1732*437bfbebSnyanmisaka         if (p->used_for_reference) {
1733*437bfbebSnyanmisaka             fs->is_reference |= 1;
1734*437bfbebSnyanmisaka             fs->is_orig_reference |= 1;
1735*437bfbebSnyanmisaka             if (p->is_long_term) {
1736*437bfbebSnyanmisaka                 fs->is_long_term |= 1;
1737*437bfbebSnyanmisaka                 fs->long_term_frame_idx = p->long_term_frame_idx;
1738*437bfbebSnyanmisaka             }
1739*437bfbebSnyanmisaka         }
1740*437bfbebSnyanmisaka         if (fs->is_used == 3) {
1741*437bfbebSnyanmisaka             FUN_CHECK(ret = dpb_combine_field(p_Vid, fs, combine_flag));
1742*437bfbebSnyanmisaka         } else {
1743*437bfbebSnyanmisaka             fs->poc = p->poc;
1744*437bfbebSnyanmisaka         }
1745*437bfbebSnyanmisaka         break;
1746*437bfbebSnyanmisaka     case BOTTOM_FIELD:
1747*437bfbebSnyanmisaka         fs->bottom_field = p;
1748*437bfbebSnyanmisaka         fs->is_used |= 2;
1749*437bfbebSnyanmisaka         fs->inter_view_flag[1] = p->inter_view_flag;
1750*437bfbebSnyanmisaka         fs->anchor_pic_flag[1] = p->anchor_pic_flag;
1751*437bfbebSnyanmisaka         if (p->used_for_reference) {
1752*437bfbebSnyanmisaka             fs->is_reference |= 2;
1753*437bfbebSnyanmisaka             fs->is_orig_reference |= 2;
1754*437bfbebSnyanmisaka             if (p->is_long_term) {
1755*437bfbebSnyanmisaka                 fs->is_long_term |= 2;
1756*437bfbebSnyanmisaka                 fs->long_term_frame_idx = p->long_term_frame_idx;
1757*437bfbebSnyanmisaka             }
1758*437bfbebSnyanmisaka         }
1759*437bfbebSnyanmisaka         if (fs->is_used == 3) {
1760*437bfbebSnyanmisaka             FUN_CHECK(ret = dpb_combine_field(p_Vid, fs, combine_flag));
1761*437bfbebSnyanmisaka         } else {
1762*437bfbebSnyanmisaka             fs->poc = p->poc;
1763*437bfbebSnyanmisaka         }
1764*437bfbebSnyanmisaka         break;
1765*437bfbebSnyanmisaka     }
1766*437bfbebSnyanmisaka     fs->layer_id = p->layer_id;
1767*437bfbebSnyanmisaka     fs->view_id = p->view_id;
1768*437bfbebSnyanmisaka     fs->frame_num = p->pic_num;
1769*437bfbebSnyanmisaka     fs->is_output = p->is_output;
1770*437bfbebSnyanmisaka     fs->slice_type = p->slice_type;
1771*437bfbebSnyanmisaka     fs->structure = p->structure;
1772*437bfbebSnyanmisaka 
1773*437bfbebSnyanmisaka     return ret = MPP_OK;
1774*437bfbebSnyanmisaka __FAILED:
1775*437bfbebSnyanmisaka     return ret;
1776*437bfbebSnyanmisaka }
1777*437bfbebSnyanmisaka 
1778*437bfbebSnyanmisaka 
1779*437bfbebSnyanmisaka /*!
1780*437bfbebSnyanmisaka ***********************************************************************
1781*437bfbebSnyanmisaka * \brief
1782*437bfbebSnyanmisaka *    alloc one picture
1783*437bfbebSnyanmisaka ***********************************************************************
1784*437bfbebSnyanmisaka */
1785*437bfbebSnyanmisaka //extern "C"
free_storable_picture(H264_DecCtx_t * p_Dec,H264_StorePic_t * p)1786*437bfbebSnyanmisaka void free_storable_picture(H264_DecCtx_t *p_Dec, H264_StorePic_t *p)
1787*437bfbebSnyanmisaka {
1788*437bfbebSnyanmisaka     if (p) {
1789*437bfbebSnyanmisaka         if (p->mem_malloc_type == Mem_Malloc
1790*437bfbebSnyanmisaka             || p->mem_malloc_type == Mem_Clone) {
1791*437bfbebSnyanmisaka             free_dpb_mark(p_Dec, p->mem_mark, p->structure);
1792*437bfbebSnyanmisaka         }
1793*437bfbebSnyanmisaka         if (p->mem_malloc_type == Mem_TopOnly) {
1794*437bfbebSnyanmisaka             free_dpb_mark(p_Dec, p->mem_mark, TOP_FIELD);
1795*437bfbebSnyanmisaka         }
1796*437bfbebSnyanmisaka         if (p->mem_malloc_type == Mem_BotOnly) {
1797*437bfbebSnyanmisaka             free_dpb_mark(p_Dec, p->mem_mark, BOTTOM_FIELD);
1798*437bfbebSnyanmisaka         }
1799*437bfbebSnyanmisaka         mpp_mem_pool_put_f(p_Dec->p_Vid->pic_st, p);
1800*437bfbebSnyanmisaka     }
1801*437bfbebSnyanmisaka }
1802*437bfbebSnyanmisaka 
1803*437bfbebSnyanmisaka /*!
1804*437bfbebSnyanmisaka ***********************************************************************
1805*437bfbebSnyanmisaka * \brief
1806*437bfbebSnyanmisaka *    alloc one picture
1807*437bfbebSnyanmisaka ***********************************************************************
1808*437bfbebSnyanmisaka */
1809*437bfbebSnyanmisaka //extern "C"
alloc_storable_picture(H264dVideoCtx_t * p_Vid,RK_S32 structure)1810*437bfbebSnyanmisaka H264_StorePic_t *alloc_storable_picture(H264dVideoCtx_t *p_Vid, RK_S32 structure)
1811*437bfbebSnyanmisaka {
1812*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1813*437bfbebSnyanmisaka     H264_StorePic_t *s = mpp_mem_pool_get_f(p_Vid->pic_st);
1814*437bfbebSnyanmisaka 
1815*437bfbebSnyanmisaka     MEM_CHECK(ret, s);
1816*437bfbebSnyanmisaka     s->view_id = -1;
1817*437bfbebSnyanmisaka     s->structure = structure;
1818*437bfbebSnyanmisaka     (void)p_Vid;
1819*437bfbebSnyanmisaka 
1820*437bfbebSnyanmisaka     return s;
1821*437bfbebSnyanmisaka __FAILED:
1822*437bfbebSnyanmisaka     (void)ret;
1823*437bfbebSnyanmisaka     return NULL;
1824*437bfbebSnyanmisaka }
1825*437bfbebSnyanmisaka 
1826*437bfbebSnyanmisaka /*!
1827*437bfbebSnyanmisaka ***********************************************************************
1828*437bfbebSnyanmisaka * \brief
1829*437bfbebSnyanmisaka *    alloc one picture
1830*437bfbebSnyanmisaka ***********************************************************************
1831*437bfbebSnyanmisaka */
1832*437bfbebSnyanmisaka //extern "C"
get_field_dpb_combine_flag(H264_FrameStore_t * p_last,H264_StorePic_t * p)1833*437bfbebSnyanmisaka RK_U32 get_field_dpb_combine_flag(H264_FrameStore_t *p_last, H264_StorePic_t *p)
1834*437bfbebSnyanmisaka {
1835*437bfbebSnyanmisaka     RK_U32 combine_flag = 0;
1836*437bfbebSnyanmisaka 
1837*437bfbebSnyanmisaka     if ((p->structure == TOP_FIELD) || (p->structure == BOTTOM_FIELD)) {
1838*437bfbebSnyanmisaka         // check for frame store with same pic_number
1839*437bfbebSnyanmisaka         if (p_last) {
1840*437bfbebSnyanmisaka             if ((RK_S32)p_last->frame_num == p->pic_num) {
1841*437bfbebSnyanmisaka                 if (((p->structure == TOP_FIELD) && (p_last->is_used == 2))
1842*437bfbebSnyanmisaka                     || ((p->structure == BOTTOM_FIELD) && (p_last->is_used == 1))) {
1843*437bfbebSnyanmisaka #if 1
1844*437bfbebSnyanmisaka                     if ((p->used_for_reference && p_last->is_orig_reference) ||
1845*437bfbebSnyanmisaka                         (!p->used_for_reference && !p_last->is_orig_reference)) {
1846*437bfbebSnyanmisaka                         combine_flag = 1;
1847*437bfbebSnyanmisaka                     }
1848*437bfbebSnyanmisaka #else
1849*437bfbebSnyanmisaka                     combine_flag = 1;
1850*437bfbebSnyanmisaka #endif
1851*437bfbebSnyanmisaka                 }
1852*437bfbebSnyanmisaka             }
1853*437bfbebSnyanmisaka             /* set err to unpaired filed */
1854*437bfbebSnyanmisaka             if (!combine_flag) {
1855*437bfbebSnyanmisaka                 struct h264_store_pic_t *pic = NULL;
1856*437bfbebSnyanmisaka 
1857*437bfbebSnyanmisaka                 pic = p_last->structure == TOP_FIELD ? p_last->top_field : p_last->bottom_field;
1858*437bfbebSnyanmisaka                 if (pic && pic->mem_mark->mframe && !pic->combine_flag)
1859*437bfbebSnyanmisaka                     mpp_frame_set_errinfo(pic->mem_mark->mframe, 1);
1860*437bfbebSnyanmisaka             }
1861*437bfbebSnyanmisaka         }
1862*437bfbebSnyanmisaka     }
1863*437bfbebSnyanmisaka     return combine_flag;
1864*437bfbebSnyanmisaka }
1865*437bfbebSnyanmisaka 
enlarge_dpb(H264_DpbBuf_t * p_Dpb,RK_U32 size)1866*437bfbebSnyanmisaka static MPP_RET enlarge_dpb(H264_DpbBuf_t *p_Dpb, RK_U32 size)
1867*437bfbebSnyanmisaka {
1868*437bfbebSnyanmisaka     RK_U32 i = 0;
1869*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1870*437bfbebSnyanmisaka     void *tmp;
1871*437bfbebSnyanmisaka 
1872*437bfbebSnyanmisaka     if (!p_Dpb || !size || !p_Dpb->init_done)
1873*437bfbebSnyanmisaka         return MPP_ERR_VALUE;
1874*437bfbebSnyanmisaka 
1875*437bfbebSnyanmisaka     if (p_Dpb->size >= size) {
1876*437bfbebSnyanmisaka         H264D_WARNNING("DPB could not be shrinked!\n");
1877*437bfbebSnyanmisaka         return MPP_ERR_VALUE;
1878*437bfbebSnyanmisaka     }
1879*437bfbebSnyanmisaka 
1880*437bfbebSnyanmisaka     tmp = mpp_calloc(H264_FrameStore_t*, size);
1881*437bfbebSnyanmisaka     memcpy(tmp, p_Dpb->fs, sizeof(H264_FrameStore_t*) * p_Dpb->size);
1882*437bfbebSnyanmisaka     mpp_free(p_Dpb->fs);
1883*437bfbebSnyanmisaka     p_Dpb->fs = tmp;
1884*437bfbebSnyanmisaka 
1885*437bfbebSnyanmisaka     tmp = mpp_calloc(H264_FrameStore_t*, size);
1886*437bfbebSnyanmisaka     memcpy(tmp, p_Dpb->fs_ref, sizeof(H264_FrameStore_t*) * p_Dpb->size);
1887*437bfbebSnyanmisaka     mpp_free(p_Dpb->fs_ref);
1888*437bfbebSnyanmisaka     p_Dpb->fs_ref = tmp;
1889*437bfbebSnyanmisaka 
1890*437bfbebSnyanmisaka     tmp = mpp_calloc(H264_FrameStore_t*, size);
1891*437bfbebSnyanmisaka     memcpy(tmp, p_Dpb->fs_ltref, sizeof(H264_FrameStore_t*) * p_Dpb->size);
1892*437bfbebSnyanmisaka     mpp_free(p_Dpb->fs_ltref);
1893*437bfbebSnyanmisaka     p_Dpb->fs_ltref = tmp;
1894*437bfbebSnyanmisaka 
1895*437bfbebSnyanmisaka     tmp = mpp_calloc(H264_FrameStore_t*, size);
1896*437bfbebSnyanmisaka     memcpy(tmp, p_Dpb->fs_ilref, sizeof(H264_FrameStore_t*) * p_Dpb->size);
1897*437bfbebSnyanmisaka     mpp_free(p_Dpb->fs_ilref);
1898*437bfbebSnyanmisaka     p_Dpb->fs_ilref = tmp;
1899*437bfbebSnyanmisaka 
1900*437bfbebSnyanmisaka     for (i = p_Dpb->size; i < size; i++) {
1901*437bfbebSnyanmisaka         p_Dpb->fs[i] = alloc_frame_store();
1902*437bfbebSnyanmisaka         MEM_CHECK(ret, p_Dpb->fs[i]);
1903*437bfbebSnyanmisaka         p_Dpb->fs_ref[i] = NULL;
1904*437bfbebSnyanmisaka         p_Dpb->fs_ltref[i] = NULL;
1905*437bfbebSnyanmisaka         p_Dpb->fs[i]->layer_id = -1;
1906*437bfbebSnyanmisaka         p_Dpb->fs[i]->view_id = -1;
1907*437bfbebSnyanmisaka         p_Dpb->fs[i]->inter_view_flag[0] = p_Dpb->fs[i]->inter_view_flag[1] = 0;
1908*437bfbebSnyanmisaka         p_Dpb->fs[i]->anchor_pic_flag[0] = p_Dpb->fs[i]->anchor_pic_flag[1] = 0;
1909*437bfbebSnyanmisaka     }
1910*437bfbebSnyanmisaka 
1911*437bfbebSnyanmisaka     p_Dpb->size = size;
1912*437bfbebSnyanmisaka     p_Dpb->allocated_size = size;
1913*437bfbebSnyanmisaka     return ret = MPP_OK;
1914*437bfbebSnyanmisaka 
1915*437bfbebSnyanmisaka __FAILED:
1916*437bfbebSnyanmisaka     return ret;
1917*437bfbebSnyanmisaka }
1918*437bfbebSnyanmisaka 
check_mvc_dpb(H264dVideoCtx_t * p_Vid,H264_DpbBuf_t * p_Dpb_layer_0,H264_DpbBuf_t * p_Dpb_layer_1)1919*437bfbebSnyanmisaka MPP_RET check_mvc_dpb(H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb_layer_0,  H264_DpbBuf_t* p_Dpb_layer_1)
1920*437bfbebSnyanmisaka {
1921*437bfbebSnyanmisaka     MPP_RET ret = MPP_OK;
1922*437bfbebSnyanmisaka 
1923*437bfbebSnyanmisaka     if (!p_Vid || !p_Dpb_layer_0 || !p_Dpb_layer_1 || !p_Dpb_layer_0->init_done) {
1924*437bfbebSnyanmisaka         return ret = MPP_ERR_VALUE;
1925*437bfbebSnyanmisaka     }
1926*437bfbebSnyanmisaka 
1927*437bfbebSnyanmisaka     H264D_DBG(H264D_DBG_DPB_INFO, "p_Dpb[0].size %d vs p_Dpb[1].size %d\n",
1928*437bfbebSnyanmisaka               p_Dpb_layer_0->size, p_Dpb_layer_1->size);
1929*437bfbebSnyanmisaka 
1930*437bfbebSnyanmisaka     p_Dpb_layer_0->size = MPP_MIN(p_Dpb_layer_0->size, MAX_DPB_SIZE / 2);
1931*437bfbebSnyanmisaka     p_Dpb_layer_1->size = MPP_MIN(p_Dpb_layer_1->size, MAX_DPB_SIZE / 2);
1932*437bfbebSnyanmisaka 
1933*437bfbebSnyanmisaka     if (p_Dpb_layer_0->size == p_Dpb_layer_1->size) {
1934*437bfbebSnyanmisaka         ret = MPP_OK;
1935*437bfbebSnyanmisaka     } else if (p_Dpb_layer_0->size > p_Dpb_layer_1->size) {
1936*437bfbebSnyanmisaka         ret = enlarge_dpb(p_Dpb_layer_1, p_Dpb_layer_0->size);
1937*437bfbebSnyanmisaka         H264D_DBG(H264D_DBG_DPB_INFO, "Enlarge DPB[1] to %d", p_Dpb_layer_0->size);
1938*437bfbebSnyanmisaka     } else {
1939*437bfbebSnyanmisaka         ret = enlarge_dpb(p_Dpb_layer_0, p_Dpb_layer_1->size);
1940*437bfbebSnyanmisaka         H264D_DBG(H264D_DBG_DPB_INFO, "Enlarge DPB[0] to %d", p_Dpb_layer_1->size);
1941*437bfbebSnyanmisaka     }
1942*437bfbebSnyanmisaka 
1943*437bfbebSnyanmisaka     p_Vid->dpb_size[0] = p_Dpb_layer_0->size;
1944*437bfbebSnyanmisaka     p_Vid->dpb_size[1] = p_Dpb_layer_1->size;
1945*437bfbebSnyanmisaka 
1946*437bfbebSnyanmisaka     return ret;
1947*437bfbebSnyanmisaka }
1948*437bfbebSnyanmisaka 
1949*437bfbebSnyanmisaka /*!
1950*437bfbebSnyanmisaka ***********************************************************************
1951*437bfbebSnyanmisaka * \brief
1952*437bfbebSnyanmisaka *    init dpb
1953*437bfbebSnyanmisaka ***********************************************************************
1954*437bfbebSnyanmisaka */
1955*437bfbebSnyanmisaka //extern "C"
init_dpb(H264dVideoCtx_t * p_Vid,H264_DpbBuf_t * p_Dpb,RK_S32 type)1956*437bfbebSnyanmisaka MPP_RET init_dpb(H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb, RK_S32 type)  // type=1 AVC type=2 MVC
1957*437bfbebSnyanmisaka {
1958*437bfbebSnyanmisaka     RK_U32 i = 0;
1959*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
1960*437bfbebSnyanmisaka     H264_SPS_t *active_sps = p_Vid->active_sps;
1961*437bfbebSnyanmisaka     RK_U32 dpb_size;
1962*437bfbebSnyanmisaka 
1963*437bfbebSnyanmisaka     if (!active_sps) {
1964*437bfbebSnyanmisaka         ret = MPP_NOK;
1965*437bfbebSnyanmisaka         goto __FAILED;
1966*437bfbebSnyanmisaka     }
1967*437bfbebSnyanmisaka     p_Dpb->p_Vid = p_Vid;
1968*437bfbebSnyanmisaka     if (p_Dpb->init_done) {
1969*437bfbebSnyanmisaka         free_dpb(p_Dpb);
1970*437bfbebSnyanmisaka     }
1971*437bfbebSnyanmisaka     dpb_size = getDpbSize(p_Vid, active_sps);
1972*437bfbebSnyanmisaka     p_Dpb->size = MPP_MAX(1, dpb_size);
1973*437bfbebSnyanmisaka     p_Dpb->allocated_size = p_Dpb->size;
1974*437bfbebSnyanmisaka     p_Dpb->num_ref_frames = active_sps->max_num_ref_frames;
1975*437bfbebSnyanmisaka     if (active_sps->max_dec_frame_buffering < active_sps->max_num_ref_frames) {
1976*437bfbebSnyanmisaka         H264D_WARNNING("DPB size at specified level is smaller than reference frames");
1977*437bfbebSnyanmisaka     }
1978*437bfbebSnyanmisaka     p_Dpb->used_size = 0;
1979*437bfbebSnyanmisaka     p_Dpb->last_picture = NULL;
1980*437bfbebSnyanmisaka     p_Dpb->ref_frames_in_buffer = 0;
1981*437bfbebSnyanmisaka     p_Dpb->ltref_frames_in_buffer = 0;
1982*437bfbebSnyanmisaka     //--------
1983*437bfbebSnyanmisaka     p_Dpb->fs       = mpp_calloc(H264_FrameStore_t*, p_Dpb->size);
1984*437bfbebSnyanmisaka     p_Dpb->fs_ref   = mpp_calloc(H264_FrameStore_t*, p_Dpb->size);
1985*437bfbebSnyanmisaka     p_Dpb->fs_ltref = mpp_calloc(H264_FrameStore_t*, p_Dpb->size);
1986*437bfbebSnyanmisaka     p_Dpb->fs_ilref = mpp_calloc(H264_FrameStore_t*, 1);  //!< inter-layer reference (for multi-layered codecs)
1987*437bfbebSnyanmisaka     MEM_CHECK(ret, p_Dpb->fs && p_Dpb->fs_ref && p_Dpb->fs_ltref && p_Dpb->fs_ilref);
1988*437bfbebSnyanmisaka     for (i = 0; i < p_Dpb->size; i++) {
1989*437bfbebSnyanmisaka         p_Dpb->fs[i] = alloc_frame_store();
1990*437bfbebSnyanmisaka         MEM_CHECK(ret, p_Dpb->fs[i]);
1991*437bfbebSnyanmisaka         p_Dpb->fs_ref[i] = NULL;
1992*437bfbebSnyanmisaka         p_Dpb->fs_ltref[i] = NULL;
1993*437bfbebSnyanmisaka         p_Dpb->fs[i]->layer_id = -1;
1994*437bfbebSnyanmisaka         p_Dpb->fs[i]->view_id = -1;
1995*437bfbebSnyanmisaka         p_Dpb->fs[i]->inter_view_flag[0] = p_Dpb->fs[i]->inter_view_flag[1] = 0;
1996*437bfbebSnyanmisaka         p_Dpb->fs[i]->anchor_pic_flag[0] = p_Dpb->fs[i]->anchor_pic_flag[1] = 0;
1997*437bfbebSnyanmisaka     }
1998*437bfbebSnyanmisaka     if (type == 2) {
1999*437bfbebSnyanmisaka         p_Dpb->fs_ilref[0] = alloc_frame_store();
2000*437bfbebSnyanmisaka         MEM_CHECK(ret, p_Dpb->fs_ilref[0]);
2001*437bfbebSnyanmisaka         //!< These may need some cleanups
2002*437bfbebSnyanmisaka         p_Dpb->fs_ilref[0]->view_id = -1;
2003*437bfbebSnyanmisaka         p_Dpb->fs_ilref[0]->inter_view_flag[0] = p_Dpb->fs_ilref[0]->inter_view_flag[1] = 0;
2004*437bfbebSnyanmisaka         p_Dpb->fs_ilref[0]->anchor_pic_flag[0] = p_Dpb->fs_ilref[0]->anchor_pic_flag[1] = 0;
2005*437bfbebSnyanmisaka         //!< given that this is in a different buffer, do we even need proc_flag anymore?
2006*437bfbebSnyanmisaka     } else {
2007*437bfbebSnyanmisaka         p_Dpb->fs_ilref[0] = NULL;
2008*437bfbebSnyanmisaka     }
2009*437bfbebSnyanmisaka     //!< allocate a dummy storable picture
2010*437bfbebSnyanmisaka     if (!p_Vid->no_ref_pic) {
2011*437bfbebSnyanmisaka         p_Vid->no_ref_pic = alloc_storable_picture(p_Vid, FRAME);
2012*437bfbebSnyanmisaka         MEM_CHECK(ret, p_Vid->no_ref_pic);
2013*437bfbebSnyanmisaka         p_Vid->no_ref_pic->top_field = p_Vid->no_ref_pic;
2014*437bfbebSnyanmisaka         p_Vid->no_ref_pic->bottom_field = p_Vid->no_ref_pic;
2015*437bfbebSnyanmisaka         p_Vid->no_ref_pic->frame = p_Vid->no_ref_pic;
2016*437bfbebSnyanmisaka     }
2017*437bfbebSnyanmisaka     p_Dpb->last_output_poc = INT_MIN;
2018*437bfbebSnyanmisaka     p_Dpb->last_output_view_id = -1;
2019*437bfbebSnyanmisaka     p_Vid->last_has_mmco_5 = 0;
2020*437bfbebSnyanmisaka     p_Dpb->init_done = 1;
2021*437bfbebSnyanmisaka 
2022*437bfbebSnyanmisaka     return ret = MPP_OK;
2023*437bfbebSnyanmisaka __FAILED:
2024*437bfbebSnyanmisaka     return ret;
2025*437bfbebSnyanmisaka }
2026*437bfbebSnyanmisaka /*!
2027*437bfbebSnyanmisaka ***********************************************************************
2028*437bfbebSnyanmisaka * \brief
2029*437bfbebSnyanmisaka *    flush dpb
2030*437bfbebSnyanmisaka ***********************************************************************
2031*437bfbebSnyanmisaka */
2032*437bfbebSnyanmisaka //extern "C"
flush_dpb(H264_DpbBuf_t * p_Dpb,RK_S32 type)2033*437bfbebSnyanmisaka MPP_RET flush_dpb(H264_DpbBuf_t *p_Dpb, RK_S32 type)
2034*437bfbebSnyanmisaka {
2035*437bfbebSnyanmisaka     RK_U32 i = 0;
2036*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
2037*437bfbebSnyanmisaka 
2038*437bfbebSnyanmisaka     INP_CHECK(ret, !p_Dpb);
2039*437bfbebSnyanmisaka     //!< diagnostics
2040*437bfbebSnyanmisaka     if (!p_Dpb->init_done) {
2041*437bfbebSnyanmisaka         goto __RETURN;
2042*437bfbebSnyanmisaka     }
2043*437bfbebSnyanmisaka     H264D_DBG(H264D_DBG_DPB_INFO, "dpb layer %d, used_size %d",
2044*437bfbebSnyanmisaka               p_Dpb->layer_id, p_Dpb->used_size);
2045*437bfbebSnyanmisaka     //!< mark all frames unused
2046*437bfbebSnyanmisaka     for (i = 0; i < p_Dpb->used_size; i++) {
2047*437bfbebSnyanmisaka         if (p_Dpb->fs[i] && p_Dpb->p_Vid) {
2048*437bfbebSnyanmisaka             VAL_CHECK(ret, p_Dpb->fs[i]->layer_id == p_Dpb->layer_id);
2049*437bfbebSnyanmisaka             unmark_for_reference(p_Dpb->p_Vid->p_Dec, p_Dpb->fs[i]);
2050*437bfbebSnyanmisaka         }
2051*437bfbebSnyanmisaka     }
2052*437bfbebSnyanmisaka     while (!remove_unused_frame_from_dpb(p_Dpb));
2053*437bfbebSnyanmisaka     //!< output frames in POC order
2054*437bfbebSnyanmisaka     while (p_Dpb->used_size) {
2055*437bfbebSnyanmisaka         FUN_CHECK(ret = output_one_frame_from_dpb(p_Dpb));
2056*437bfbebSnyanmisaka     }
2057*437bfbebSnyanmisaka     p_Dpb->last_output_poc = INT_MIN;
2058*437bfbebSnyanmisaka     (void)type;
2059*437bfbebSnyanmisaka __RETURN:
2060*437bfbebSnyanmisaka     return ret = MPP_OK;
2061*437bfbebSnyanmisaka __FAILED:
2062*437bfbebSnyanmisaka     return ret;
2063*437bfbebSnyanmisaka }
2064*437bfbebSnyanmisaka /*!
2065*437bfbebSnyanmisaka ***********************************************************************
2066*437bfbebSnyanmisaka * \brief
2067*437bfbebSnyanmisaka *    write out all frames
2068*437bfbebSnyanmisaka ***********************************************************************
2069*437bfbebSnyanmisaka */
2070*437bfbebSnyanmisaka //extern "C"
output_dpb(H264_DecCtx_t * p_Dec,H264_DpbBuf_t * p_Dpb)2071*437bfbebSnyanmisaka MPP_RET output_dpb(H264_DecCtx_t *p_Dec, H264_DpbBuf_t *p_Dpb)
2072*437bfbebSnyanmisaka {
2073*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
2074*437bfbebSnyanmisaka 
2075*437bfbebSnyanmisaka     while (!remove_unused_frame_from_dpb(p_Dpb));
2076*437bfbebSnyanmisaka 
2077*437bfbebSnyanmisaka     (void)p_Dec;
2078*437bfbebSnyanmisaka     return ret = MPP_OK;
2079*437bfbebSnyanmisaka }
2080*437bfbebSnyanmisaka /*!
2081*437bfbebSnyanmisaka ***********************************************************************
2082*437bfbebSnyanmisaka * \brief
2083*437bfbebSnyanmisaka *    parse sps and process sps
2084*437bfbebSnyanmisaka ***********************************************************************
2085*437bfbebSnyanmisaka */
2086*437bfbebSnyanmisaka //extern "C"
exit_picture(H264dVideoCtx_t * p_Vid,H264_StorePic_t ** dec_pic)2087*437bfbebSnyanmisaka MPP_RET exit_picture(H264dVideoCtx_t *p_Vid, H264_StorePic_t **dec_pic)
2088*437bfbebSnyanmisaka {
2089*437bfbebSnyanmisaka     MPP_RET ret = MPP_ERR_UNKNOW;
2090*437bfbebSnyanmisaka 
2091*437bfbebSnyanmisaka     //!< return if the last picture has already been finished
2092*437bfbebSnyanmisaka     if (!(*dec_pic) || !p_Vid->exit_picture_flag
2093*437bfbebSnyanmisaka         || !p_Vid->have_outpicture_flag || !p_Vid->iNumOfSlicesDecoded) {
2094*437bfbebSnyanmisaka         goto __RETURN;
2095*437bfbebSnyanmisaka     }
2096*437bfbebSnyanmisaka     FUN_CHECK(ret = store_picture_in_dpb(p_Vid->p_Dpb_layer[(*dec_pic)->layer_id], *dec_pic));
2097*437bfbebSnyanmisaka     *dec_pic = NULL;
2098*437bfbebSnyanmisaka 
2099*437bfbebSnyanmisaka __RETURN:
2100*437bfbebSnyanmisaka     return ret = MPP_OK;
2101*437bfbebSnyanmisaka __FAILED:
2102*437bfbebSnyanmisaka     return ret;
2103*437bfbebSnyanmisaka }
2104