xref: /OK3568_Linux_fs/external/mpp/mpp/codec/enc/h265/h265e_dpb.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2015 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define MODULE_TAG  "h265e_dpb"
18 
19 #include <string.h>
20 
21 #include "mpp_mem.h"
22 #include "mpp_debug.h"
23 #include "mpp_common.h"
24 
25 #include "h265e_codec.h"
26 #include "h265e_dpb.h"
27 
h265e_dpb_set_ref_list(H265eRpsList * RpsList,H265eReferencePictureSet * m_pRps,RK_S32 delta_poc)28 void h265e_dpb_set_ref_list(H265eRpsList *RpsList, H265eReferencePictureSet *m_pRps, RK_S32 delta_poc)
29 {
30     RK_S32 i;
31     RK_S32 ref_idx = -1;
32     H265eRefPicListModification* refPicListModification = RpsList->m_RefPicListModification;
33 
34     h265e_dbg_func("enter\n");
35     refPicListModification->m_refPicListModificationFlagL0 = 0;
36     refPicListModification->m_refPicListModificationFlagL1 = 0;
37 
38     for (i = 0; i < REF_PIC_LIST_NUM_IDX; i ++) {
39         refPicListModification->m_RefPicSetIdxL0[i] = 0;
40         refPicListModification->m_RefPicSetIdxL0[i] = 0;
41     }
42 
43     refPicListModification->m_refPicListModificationFlagL0 = 0;
44 
45     if (m_pRps->m_numberOfPictures > 1) {
46         for (i = 0; i < m_pRps->m_numberOfPictures; i++) {
47             h265e_dbg_dpb("m_pRps->delta_poc[%d] = %d", i, m_pRps->delta_poc[i]);
48             if (m_pRps->delta_poc[i] == delta_poc) {
49                 ref_idx = i;
50                 h265e_dbg_dpb("get ref ref_idx %d", ref_idx);
51                 break;
52             }
53         }
54         if (-1 == ref_idx) {
55             mpp_err("Did not find the right reference picture");
56             return;
57         } else if (ref_idx != 0) {
58             refPicListModification->m_refPicListModificationFlagL0 = 1;
59             refPicListModification->m_RefPicSetIdxL0[0] = ref_idx;
60             for ( i = 1; i < m_pRps->m_numberOfPictures - 1; i++) {
61                 if (i != ref_idx)
62                     refPicListModification->m_RefPicSetIdxL0[i] = i;
63             }
64             refPicListModification->m_RefPicSetIdxL0[ref_idx] = 0;
65         }
66     }
67     refPicListModification->m_refPicListModificationFlagL1 = 0;
68     h265e_dbg_func("leave\n");
69 }
70 
71 /* get buffer at init */
h265e_dpb_init_curr(H265eDpb * dpb,H265eDpbFrm * frm)72 MPP_RET h265e_dpb_init_curr(H265eDpb *dpb, H265eDpbFrm *frm)
73 {
74     h265e_dbg_func("enter\n");
75     mpp_assert(!frm->on_used);
76 
77     frm->dpb = dpb;
78 
79     if (!frm->slice) {
80         frm->slice = mpp_calloc(H265eSlice, 1);
81     }
82 
83     frm->inited = 1;
84     frm->on_used = 1;
85     frm->seq_idx = dpb->seq_idx;
86     dpb->seq_idx++;
87 
88     h265e_dbg_func("leave\n");
89     return MPP_OK;
90 }
91 
h265e_dpb_get_curr(H265eDpb * dpb)92 MPP_RET h265e_dpb_get_curr(H265eDpb *dpb)
93 {
94     RK_U32 i;
95 
96     h265e_dbg_func("enter\n");
97     for (i = 0; i < MPP_ARRAY_ELEMS(dpb->frame_list); i++) {
98         if (!dpb->frame_list[i].on_used) {
99             dpb->curr = &dpb->frame_list[i];
100             h265e_dbg_dpb("get free dpb slot_index %d", dpb->curr->slot_idx);
101             break;
102         }
103     }
104     h265e_dpb_init_curr(dpb, dpb->curr);
105     h265e_dbg_func("leave\n");
106     return MPP_OK;
107 }
108 
109 /* put buffer at deinit */
h265e_dpb_frm_deinit(H265eDpbFrm * frm)110 MPP_RET h265e_dpb_frm_deinit(H265eDpbFrm *frm)
111 {
112 
113     MPP_FREE(frm->slice);
114     frm->inited = 0;
115     h265e_dbg_func("leave\n");
116     return MPP_OK;
117 }
118 
h265e_dpb_init(H265eDpb ** dpb)119 MPP_RET h265e_dpb_init(H265eDpb **dpb)
120 {
121     MPP_RET ret = MPP_OK;
122     H265eDpb *p = NULL;
123     RK_U32 i;
124 
125     h265e_dbg_func("enter\n");
126     if (NULL == dpb) {
127         mpp_err_f("invalid parameter %p \n", dpb);
128         return MPP_ERR_VALUE;
129     }
130 
131     p = mpp_calloc_size(H265eDpb, sizeof(H265eDpb));
132 
133     if (NULL == p)
134         return MPP_ERR_MALLOC;
135 
136     p->last_idr = 0;
137     p->poc_cra = 0;
138     p->max_ref_l0 = 1;
139     p->max_ref_l1 = 0;
140 
141     H265eRpsList *rps_list = &p->RpsList;
142 
143     rps_list->lt_num = 0;
144     rps_list->st_num = 0;
145 
146     memset(rps_list->poc, 0, sizeof(rps_list->poc));
147 
148     rps_list->m_RefPicListModification = mpp_calloc(H265eRefPicListModification, 1);
149 
150 
151     for (i = 0; i < MPP_ARRAY_ELEMS(p->frame_list); i++)
152         p->frame_list[i].slot_idx = i;
153 
154     mpp_assert(dpb);
155     *dpb = p;
156     h265e_dbg_func("leave\n");
157     return ret;
158 }
159 
h265e_dpb_deinit(H265eDpb * dpb)160 MPP_RET h265e_dpb_deinit(H265eDpb *dpb)
161 {
162     RK_U32 i;
163 
164     if (NULL == dpb)
165         return MPP_OK;
166 
167     h265e_dbg_func("enter\n");
168     for (i = 0; i < MPP_ARRAY_ELEMS(dpb->frame_list); i++) {
169         if (dpb->frame_list[i].inited)
170             h265e_dpb_frm_deinit(&dpb->frame_list[i]);
171     }
172 
173     MPP_FREE(dpb->RpsList.m_RefPicListModification);
174 
175     MPP_FREE(dpb);
176 
177     h265e_dbg_func("leave\n");
178     return MPP_OK;
179 }
180 
get_nal_unit_type(H265eDpb * dpb,int curPOC)181 enum NALUnitType get_nal_unit_type(H265eDpb *dpb, int curPOC)
182 {
183     h265e_dbg_func("enter\n");
184     if (curPOC == 0) {
185         return NAL_IDR_W_RADL;
186     }
187     if (dpb->curr->is_key_frame) {
188         return NAL_IDR_W_RADL;
189     }
190     if (dpb->poc_cra > 0) {
191         if (curPOC < dpb->poc_cra) {
192             // All leading pictures are being marked as TFD pictures here since current encoder uses all
193             // reference pictures while encoding leading pictures. An encoder can ensure that a leading
194             // picture can be still decodable when random accessing to a CRA/CRANT/BLA/BLANT picture by
195             // controlling the reference pictures used for encoding that leading picture. Such a leading
196             // picture need not be marked as a TFD picture.
197             return NAL_RASL_R;
198         }
199     }
200     if (dpb->last_idr > 0) {
201         if (curPOC < dpb->last_idr) {
202             return NAL_RADL_R;
203         }
204     }
205 
206     h265e_dbg_func("leave\n");
207     return NAL_TRAIL_R;
208 }
209 
getLSB(int poc,int maxLSB)210 static inline int getLSB(int poc, int maxLSB)
211 {
212     if (poc >= 0) {
213         return poc % maxLSB;
214     } else {
215         return (maxLSB - ((-poc) % maxLSB)) % maxLSB;
216     }
217 }
218 
sort_delta_poc(H265eReferencePictureSet * rps)219 void sort_delta_poc(H265eReferencePictureSet *rps)
220 {
221     // sort in increasing order (smallest first)
222     RK_S32 j, k;
223     for (j = 1; j < rps->m_numberOfPictures; j++) {
224         RK_S32 deltaPOC = rps->delta_poc[j];
225         RK_U32 used = rps->m_used[j];
226         RK_U32 refed = rps->m_ref[j];
227         for (k = j - 1; k >= 0; k--) {
228             int temp = rps->delta_poc[k];
229             if (deltaPOC < temp) {
230                 rps->delta_poc[k + 1] = temp;
231                 rps->m_used[k + 1] =  rps->m_used[k];
232                 rps->m_ref[k + 1] = rps->m_ref[k];
233                 rps->delta_poc[k] = deltaPOC;
234                 rps->m_used[k] = used;
235                 rps->m_ref[k] = refed;
236             }
237         }
238     }
239 
240     // flip the negative values to largest first
241     RK_S32 numNegPics =  rps->num_negative_pic;
242     for (j = 0, k = numNegPics - 1; j < numNegPics >> 1; j++, k--) {
243         RK_S32 deltaPOC = rps->delta_poc[j];
244         RK_U32 used = rps->m_used[j];
245         RK_U32 refed = rps->m_ref[j];
246         rps->delta_poc[j] = rps->delta_poc[k];
247         rps->m_used[j] = rps->m_used[k];
248         rps->m_ref[j] = rps->m_ref[k];
249         rps->delta_poc[k] =  deltaPOC;
250         rps->m_used[k] = used;
251         rps->m_ref[k] = refed;
252     }
253 }
254 
255 
h265e_dpb_apply_rps(H265eDpb * dpb,H265eReferencePictureSet * rps,int curPoc)256 void h265e_dpb_apply_rps(H265eDpb *dpb, H265eReferencePictureSet *rps, int curPoc)
257 {
258     H265eDpbFrm *outPic = NULL;
259     RK_S32 i, isReference;
260     // loop through all pictures in the reference picture buffer
261     RK_U32 index = 0;
262     H265eDpbFrm *frame_list = &dpb->frame_list[0];
263     h265e_dbg_func("enter\n");
264     for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) {
265         outPic = &frame_list[index];
266         if (!outPic->inited || !outPic->slice->is_referenced) {
267             continue;
268         }
269 
270         isReference = 0;
271         // loop through all pictures in the Reference Picture Set
272         // to see if the picture should be kept as reference picture
273         for (i = 0; i < rps->num_positive_pic + rps->num_negative_pic; i++) {
274             h265e_dbg_dpb("outPic->slice->poc %d,curPoc %d dealt %d", outPic->slice->poc, curPoc, rps->delta_poc[i]);
275             if (!outPic->is_long_term && outPic->slice->poc == curPoc + rps->delta_poc[i]) {
276                 isReference = 1;
277                 outPic->used_by_cur = (rps->m_used[i] == 1);
278                 outPic->is_long_term = 0;
279             }
280         }
281 
282         for (; i < rps->m_numberOfPictures; i++) {
283             if (rps->check_lt_msb[i] == 0) {
284                 if (outPic->is_long_term && (outPic->slice->poc == rps->m_RealPoc[i])) {
285                     isReference = 1;
286                     outPic->used_by_cur = (rps->m_used[i] == 1);
287                 }
288             } else {
289                 if (outPic->is_long_term && (outPic->slice->poc == rps->m_RealPoc[i])) {
290                     isReference = 1;
291                     outPic->used_by_cur = (rps->m_used[i] == 1);
292                 }
293             }
294         }
295 
296         // mark the picture as "unused for reference" if it is not in
297         // the Reference Picture Set
298         if (outPic->slice->poc != curPoc && isReference == 0) {
299             h265e_dbg_dpb("free unreference buf poc %d", outPic->slice->poc);
300             outPic->slice->is_referenced = 0;
301             outPic->used_by_cur = 0;
302             outPic->on_used = 0;
303             outPic->is_long_term = 0;
304         }
305     }
306     h265e_dbg_func("leave\n");
307 }
308 
h265e_dpb_dec_refresh_marking(H265eDpb * dpb,RK_S32 poc_cur,enum NALUnitType nalUnitType)309 void h265e_dpb_dec_refresh_marking(H265eDpb *dpb, RK_S32 poc_cur, enum NALUnitType nalUnitType)
310 {
311     RK_U32 index = 0;
312 
313     h265e_dbg_func("enter\n");
314 
315     if (nalUnitType == NAL_BLA_W_LP
316         || nalUnitType == NAL_BLA_W_RADL
317         || nalUnitType == NAL_BLA_N_LP
318         || nalUnitType == NAL_IDR_W_RADL
319         || nalUnitType == NAL_IDR_N_LP) { // IDR or BLA picture
320         // mark all pictures as not used for reference
321         H265eDpbFrm *frame_List = &dpb->frame_list[0];
322         for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) {
323             H265eDpbFrm *frame = &frame_List[index];
324             if (frame->inited && (frame->poc != poc_cur)) {
325                 frame->slice->is_referenced = 0;
326                 frame->is_long_term = 0;
327                 if (frame->poc < poc_cur) {
328                     frame->used_by_cur = 0;
329                     frame->on_used = 0;
330                     frame->status.val = 0;
331                 }
332             }
333         }
334 
335         if (nalUnitType == NAL_BLA_W_LP
336             || nalUnitType == NAL_BLA_W_RADL
337             || nalUnitType == NAL_BLA_N_LP) {
338             dpb->poc_cra = poc_cur;
339         }
340     } else { // CRA or No DR
341         if (dpb->refresh_pending == 1 && poc_cur > dpb->poc_cra) { // CRA reference marking pending
342             H265eDpbFrm *frame_list = &dpb->frame_list[0];
343             for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) {
344 
345                 H265eDpbFrm *frame = &frame_list[index];
346                 if (frame->inited && frame->poc != poc_cur && frame->poc != dpb->poc_cra) {
347                     frame->slice->is_referenced = 0;
348                     frame->on_used = 0;
349                 }
350             }
351 
352             dpb->refresh_pending = 0;
353         }
354         if (nalUnitType == NAL_CRA_NUT) { // CRA picture found
355             dpb->refresh_pending = 1;
356             dpb->poc_cra = poc_cur;
357         }
358     }
359     h265e_dbg_func("leave\n");
360 }
361 
362 // Function will arrange the long-term pictures in the decreasing order of poc_lsb_lt,
363 // and among the pictures with the same lsb, it arranges them in increasing delta_poc_msb_cycle_lt value
h265e_dpb_arrange_lt_rps(H265eDpb * dpb,H265eSlice * slice)364 void h265e_dpb_arrange_lt_rps(H265eDpb *dpb, H265eSlice *slice)
365 {
366     H265eReferencePictureSet *rps = slice->m_rps;
367     RK_U32 tempArray[MAX_REFS];
368     RK_S32 offset = rps->num_negative_pic + rps->num_positive_pic;
369     RK_S32 i, j, ctr = 0;
370     RK_S32 maxPicOrderCntLSB = 1 << slice->m_sps->m_bitsForPOC;
371     RK_S32 numLongPics;
372     RK_S32 currMSB = 0, currLSB = 0;
373     (void)dpb;
374 
375     // Arrange long-term reference pictures in the correct order of LSB and MSB,
376     // and assign values for pocLSBLT and MSB present flag
377     RK_S32 longtermPicsPoc[MAX_REFS], longtermPicsLSB[MAX_REFS], indices[MAX_REFS];
378     RK_S32 longtermPicsRealPoc[MAX_REFS];
379     RK_S32 longtermPicsMSB[MAX_REFS];
380     RK_U32 mSBPresentFlag[MAX_REFS];
381 
382     h265e_dbg_func("enter\n");
383     if (!rps->num_long_term_pic) {
384         return;
385     }
386     memset(longtermPicsPoc, 0, sizeof(longtermPicsPoc));  // Store POC values of LTRP
387     memset(longtermPicsLSB, 0, sizeof(longtermPicsLSB));  // Store POC LSB values of LTRP
388     memset(longtermPicsMSB, 0, sizeof(longtermPicsMSB));  // Store POC LSB values of LTRP
389     memset(longtermPicsRealPoc, 0, sizeof(longtermPicsRealPoc));
390     memset(indices, 0, sizeof(indices));                  // Indices to aid in tracking sorted LTRPs
391     memset(mSBPresentFlag, 0, sizeof(mSBPresentFlag));    // Indicate if MSB needs to be present
392 
393     // Get the long-term reference pictures
394 
395     for (i = rps->m_numberOfPictures - 1; i >= offset; i--, ctr++) {
396         longtermPicsPoc[ctr] = rps->poc[i];                                  // LTRP POC
397         longtermPicsRealPoc[ctr] = rps->m_RealPoc[i];
398         longtermPicsLSB[ctr] = getLSB(longtermPicsPoc[ctr], maxPicOrderCntLSB); // LTRP POC LSB
399         indices[ctr] = i;
400         longtermPicsMSB[ctr] = longtermPicsPoc[ctr] - longtermPicsLSB[ctr];
401     }
402 
403     numLongPics = rps->num_long_term_pic;
404     mpp_assert(ctr == numLongPics);
405 
406     // Arrange pictures in decreasing order of MSB;
407     for (i = 0; i < numLongPics; i++) {
408         for (j = 0; j < numLongPics - 1; j++) {
409             if (longtermPicsMSB[j] < longtermPicsMSB[j + 1]) {
410                 MPP_SWAP(RK_S32, longtermPicsPoc[j], longtermPicsPoc[j + 1]);
411                 MPP_SWAP(RK_S32, longtermPicsRealPoc[j], longtermPicsRealPoc[j + 1]);
412                 MPP_SWAP(RK_S32, longtermPicsLSB[j], longtermPicsLSB[j + 1]);
413                 MPP_SWAP(RK_S32, longtermPicsMSB[j], longtermPicsMSB[j + 1]);
414                 MPP_SWAP(RK_S32, indices[j], indices[j + 1]);
415             }
416         }
417     }
418 
419     for (i = 0; i < numLongPics; i++) {
420         if (slice->gop_idx / maxPicOrderCntLSB > 0) {
421             mSBPresentFlag[i] = 1;
422         }
423     }
424 
425     // tempArray for usedByCurr flag
426     memset(tempArray, 0, sizeof(tempArray));
427     for (i = 0; i < numLongPics; i++) {
428         tempArray[i] = rps->m_used[indices[i]] ? 1 : 0;
429     }
430 
431     // Now write the final values;
432     ctr = 0;
433     // currPicPoc = currMSB + currLSB
434     currLSB = getLSB(slice->gop_idx, maxPicOrderCntLSB);
435     currMSB = slice->gop_idx - currLSB;
436 
437     for (i = rps->m_numberOfPictures - 1; i >= offset; i--, ctr++) {
438         rps->poc[i] = longtermPicsPoc[ctr];
439         rps->delta_poc[i] = -slice->poc + longtermPicsRealPoc[ctr];
440 
441         rps->m_used[i] = tempArray[ctr];
442         rps->m_pocLSBLT[i] = longtermPicsLSB[ctr];
443         rps->m_deltaPOCMSBCycleLT[i] = (currMSB - (longtermPicsPoc[ctr] - longtermPicsLSB[ctr])) / maxPicOrderCntLSB;
444         rps->m_deltaPocMSBPresentFlag[i] = mSBPresentFlag[ctr];
445 
446         mpp_assert(rps->m_deltaPOCMSBCycleLT[i] >= 0); // Non-negative value
447     }
448 
449     for (i = rps->m_numberOfPictures - 1, ctr = 1; i >= offset; i--, ctr++) {
450         for (j = rps->m_numberOfPictures - 1 - ctr; j >= offset; j--) {
451             // Here at the encoder we know that we have set the full POC value for the LTRPs, hence we
452             // don't have to check the MSB present flag values for this constraint.
453             mpp_assert(rps->m_RealPoc[i] != rps->m_RealPoc[j]); // If assert fails, LTRP entry repeated in RPS!!!
454         }
455     }
456 
457     h265e_dbg_func("leave\n");
458 }
459 
h265e_find_cpb_in_dpb(H265eDpbFrm * frms,RK_S32 cnt,EncFrmStatus * frm)460 static H265eDpbFrm *h265e_find_cpb_in_dpb(H265eDpbFrm *frms, RK_S32 cnt, EncFrmStatus *frm)
461 {
462     RK_S32 seq_idx = frm->seq_idx;
463     RK_S32 i;
464 
465     if (!frm->valid)
466         return NULL;
467 
468     h265e_dbg_dpb("frm %d start finding slot \n", frm->seq_idx);
469     for (i = 0; i < cnt; i++) {
470         if (!frms[i].inited) {
471             continue;
472         }
473         EncFrmStatus *p = &frms[i].status;
474 
475         if (p->valid && p->seq_idx == seq_idx) {
476             h265e_dbg_dpb("frm %d match slot %d valid %d\n",
477                           p->seq_idx, i, p->valid);
478             return &frms[i];
479         }
480     }
481     mpp_err_f("can not find match frm %d\n", seq_idx);
482     return NULL;
483 }
484 
h265e_find_cpb_frame(H265eDpbFrm * frms,RK_S32 cnt,EncFrmStatus * frm)485 static H265eDpbFrm *h265e_find_cpb_frame(H265eDpbFrm *frms, RK_S32 cnt, EncFrmStatus *frm)
486 {
487     RK_S32 seq_idx = frm->seq_idx;
488     RK_S32 i;
489 
490     if (!frm->valid)
491         return NULL;
492 
493     h265e_dbg_dpb("frm %d start finding slot \n", frm->seq_idx);
494     for (i = 0; i < cnt; i++) {
495         if (!frms[i].on_used) {
496             continue;
497         }
498 
499         EncFrmStatus *p = &frms[i].status;
500 
501         if (p->valid && p->seq_idx == seq_idx) {
502             h265e_dbg_dpb("frm %d match slot %d valid %d\n",
503                           p->seq_idx, i, p->valid);
504             mpp_assert(p->is_non_ref == frm->is_non_ref);
505             mpp_assert(p->is_lt_ref == frm->is_lt_ref);
506             mpp_assert(p->lt_idx == frm->lt_idx);
507             mpp_assert(p->temporal_id == frm->temporal_id);
508             return &frms[i];
509         }
510     }
511 
512     mpp_err_f("can not find match frm %d\n", seq_idx);
513 
514     return NULL;
515 }
516 
h265e_check_frame_cpb(H265eDpbFrm * frm,RK_S32 cnt,EncFrmStatus * frms)517 static MPP_RET h265e_check_frame_cpb(H265eDpbFrm *frm, RK_S32 cnt, EncFrmStatus *frms)
518 {
519     EncFrmStatus *p = &frm->status;
520     RK_S32 seq_idx, i;
521     MPP_RET ret = MPP_NOK;
522     h265e_dbg_func("enter\n");
523 
524     seq_idx = p->seq_idx;
525     for (i = 0; i < cnt; i++) {
526 
527         if (!frms[i].valid) {
528             continue;
529         }
530 
531         if (frms[i].seq_idx == seq_idx) {
532             ret =  MPP_OK;
533         }
534     }
535 
536     h265e_dbg_func("leave\n");
537     return ret;
538 }
539 
540 
h265e_dpb_cpb2rps(H265eDpb * dpb,RK_S32 curPoc,H265eSlice * slice,EncCpbStatus * cpb)541 void h265e_dpb_cpb2rps(H265eDpb *dpb, RK_S32 curPoc, H265eSlice *slice, EncCpbStatus *cpb)
542 {
543     h265e_dbg_func("enter\n");
544     RK_S32 i;
545     RK_S32 st_size = 0;
546     RK_S32 lt_size = 0;
547     RK_S32 nLongTermRefPicPoc[MAX_NUM_LONG_TERM_REF_PIC_POC];
548     RK_S32 nLongTermRefPicRealPoc[MAX_NUM_LONG_TERM_REF_PIC_POC];
549     RK_S32 nLongTermDealtPoc[MAX_NUM_LONG_TERM_REF_PIC_POC];
550     RK_U32 isMsbValid[MAX_NUM_LONG_TERM_REF_PIC_POC];
551     RK_U32 isShortTermValid[MAX_REFS];
552     H265eRpsList *RpsList = &dpb->RpsList;
553     H265eReferencePictureSet * rps = (H265eReferencePictureSet*)&slice->m_localRPS;
554     RK_S32 idx_rps;
555     H265eDpbFrm *p = NULL;
556     RK_S32 ref_dealt_poc = 0;
557     slice->m_bdIdx = -1;
558 
559     memset(isShortTermValid, 1, sizeof(RK_U32)*MAX_REFS);
560     memset(rps, 0, sizeof(H265eReferencePictureSet));
561     for (idx_rps = 0; idx_rps < 16; idx_rps++) {
562         rps->delta_poc[idx_rps] = 0;
563         rps->m_used[idx_rps] = 0;
564         rps->m_ref[idx_rps] = 0;
565     }
566 
567     memset(rps->delta_poc, 0, MAX_REFS * sizeof(int));
568 
569     if (cpb->curr.is_lt_ref)
570         mpp_assert(slice->m_sps->m_bLongTermRefsPresent);
571 
572     idx_rps = 0;
573     for (i = 0; i < MAX_CPB_REFS; i++) {
574         EncFrmStatus *frm = &cpb->init[i];
575 
576         if (!frm->valid)
577             continue;
578 
579         mpp_assert(!frm->is_non_ref);
580 
581         h265e_dbg_dpb("idx %d frm %d valid %d is_non_ref %d lt_ref %d\n",
582                       i, frm->seq_idx, frm->valid, frm->is_non_ref, frm->is_lt_ref);
583 
584         p = h265e_find_cpb_frame(dpb->frame_list, MAX_REFS, frm);
585         if (p) {
586             if (!frm->is_lt_ref) {
587                 p->status.val = frm->val;
588                 rps->delta_poc[idx_rps] = p->poc - curPoc;
589                 rps->m_used[idx_rps] = 1;
590                 idx_rps++;
591                 st_size++;
592                 h265e_dbg_dpb("found st %d st_size %d %p deat_poc %d\n", i, st_size,
593                               frm,  rps->delta_poc[idx_rps - 1]);
594             } else {
595                 nLongTermRefPicPoc[lt_size] = p->gop_idx;
596                 nLongTermRefPicRealPoc[lt_size] = p->poc;
597                 nLongTermDealtPoc[lt_size] = p->poc - curPoc;
598                 isMsbValid[lt_size] = p->gop_idx >= (RK_S32)(1 << p->slice->m_sps->m_bitsForPOC);
599                 p->status.val = frm->val;
600                 h265e_dbg_dpb("found lt %d lt_size %d %p dealt poc %d\n", i, lt_size,
601                               frm, nLongTermDealtPoc[lt_size]);
602                 lt_size++;
603             }
604         }
605     }
606     sort_delta_poc(rps);
607 
608     if (slice->m_sliceType == I_SLICE) {
609         rps->m_interRPSPrediction = 0;
610         rps->num_long_term_pic = 0;
611         rps->num_negative_pic = 0;
612         rps->num_positive_pic = 0;
613         rps->m_numberOfPictures = 0;
614 
615     } else {
616         p = h265e_find_cpb_frame(dpb->frame_list, MAX_REFS, &cpb->refr);
617         if (p == NULL) {
618             mpp_err("ref frame no found in refer index %d", cpb->refr.seq_idx);
619         } else {
620             ref_dealt_poc = p->poc - curPoc;
621         }
622 
623         for (i = 0; i < st_size; i++) {
624             rps->m_ref[i] = (rps->delta_poc[i] == ref_dealt_poc);
625         }
626     }
627 
628     if (lt_size > 0) {
629         for ( i = 0; i < lt_size; i++) {
630             h265e_dbg_dpb("numLongTermRefPic %d nShortTerm %d", lt_size, st_size);
631             rps->poc[i + st_size] = nLongTermRefPicPoc[i];
632             rps->m_RealPoc[i + st_size] = nLongTermRefPicRealPoc[i];
633             rps->m_used[i + st_size] = 1;
634             rps->m_ref[i + st_size] = p->is_long_term;
635             rps->delta_poc[i + st_size] = nLongTermDealtPoc[i];
636             rps->check_lt_msb[i + st_size] = isMsbValid[i];
637         }
638     }
639 
640     rps->num_negative_pic = st_size;
641     rps->num_positive_pic = 0;
642     rps->num_long_term_pic = lt_size;
643     rps->m_numberOfPictures = st_size + lt_size;
644     slice->m_rps = rps;
645     h265e_dpb_apply_rps(dpb, slice->m_rps, curPoc);
646     h265e_dpb_arrange_lt_rps(dpb, slice);
647     h265e_dpb_set_ref_list(RpsList, rps, ref_dealt_poc);
648     memcpy(&slice->m_RefPicListModification, RpsList->m_RefPicListModification,
649            sizeof(H265eRefPicListModification));
650     h265e_dbg_func("leave\n");
651 }
652 
h265e_dpb_free_unsed(H265eDpb * dpb,EncCpbStatus * cpb)653 void h265e_dpb_free_unsed(H265eDpb *dpb, EncCpbStatus *cpb)
654 {
655     RK_S32 i = 0;
656 
657     h265e_dbg_func("enter\n");
658 
659     if (cpb->curr.is_non_ref) {
660         H265eDpbFrm *frm = h265e_find_cpb_frame(dpb->frame_list, MAX_REFS, &cpb->curr);
661         if (frm) {
662             h265e_dbg_dpb("free curr unreference buf poc %d", frm->slice->poc);
663             frm->is_long_term = 0;
664             frm->used_by_cur = 0;
665             frm->on_used = 0;
666             frm->slice->is_referenced = 0;
667         }
668     }
669 
670     for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dpb->frame_list); i++) {
671         H265eDpbFrm *frm = &dpb->frame_list[i];
672         if (!frm->on_used)
673             continue;
674         if (h265e_check_frame_cpb(frm, MAX_REFS, &cpb->final[0])) {
675             h265e_dbg_dpb("cpb final unreference buf poc %d", frm->slice->poc);
676             frm->is_long_term = 0;
677             frm->used_by_cur = 0;
678             frm->on_used = 0;
679             frm->slice->is_referenced = 0;
680         }
681     }
682 
683     h265e_dbg_func("leave\n");
684 }
685 
h265e_dpb_proc_cpb(H265eDpb * dpb,EncCpbStatus * cpb)686 void h265e_dpb_proc_cpb(H265eDpb *dpb, EncCpbStatus *cpb)
687 {
688     EncFrmStatus *curr = &cpb->curr;
689     RK_U32 index = 0, i = 0;
690     H265eDpbFrm *p = NULL;
691     RK_U32 need_rebuild = 0;
692     RK_S32 max_gop_id = 0, max_poc = 0;
693 
694     if (!dpb || !cpb)
695         return;
696 
697     if (curr->is_idr) {
698         for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) {
699             H265eDpbFrm *frame = &dpb->frame_list[index];
700             if (frame->inited) {
701                 frame->slice->is_referenced = 0;
702                 frame->is_long_term = 0;
703                 frame->used_by_cur = 0;
704                 frame->on_used = 0;
705                 frame->status.val = 0;
706             }
707         }
708         return;
709     }
710 
711     for (i = 0; i < MAX_CPB_REFS; i++) {
712         EncFrmStatus *frm = &cpb->init[i];
713 
714         if (!frm->valid)
715             continue;
716 
717         mpp_assert(!frm->is_non_ref);
718 
719         h265e_dbg_dpb("idx %d frm %d valid %d is_non_ref %d lt_ref %d\n",
720                       i, frm->seq_idx, frm->valid, frm->is_non_ref, frm->is_lt_ref);
721 
722         p = h265e_find_cpb_in_dpb(dpb->frame_list, MAX_REFS, frm);
723         if (!p->on_used) {
724             p->on_used = 1;
725             p->status.val = frm->val;
726             p->slice->is_referenced = 1;
727             need_rebuild = 1;
728         }
729     }
730 
731     if (need_rebuild) {
732         h265e_dbg_dpb("cpb roll back found");
733         for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) {
734             H265eDpbFrm *frame = &dpb->frame_list[index];
735             if (frame->on_used) {
736                 if (max_poc < frame->slice->poc) {
737                     max_poc = frame->slice->poc;
738                 }
739                 if (max_gop_id < frame->slice->gop_idx) {
740                     max_gop_id = frame->slice->gop_idx;
741                 }
742             }
743         }
744         H265eDpbFrm *frame = dpb->curr;
745         if (frame->inited) {
746             frame->slice->is_referenced = 0;
747             frame->is_long_term = 0;
748             frame->used_by_cur = 0;
749             frame->on_used = 0;
750             frame->status.val = 0;
751         }
752         dpb->seq_idx = max_poc;
753         dpb->gop_idx = max_gop_id;
754     }
755 
756     for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) {
757         H265eDpbFrm *frame = &dpb->frame_list[index];
758         if (frame->inited && !frame->on_used) {
759             h265e_dbg_dpb("reset index %d frame->inited %d rame->on_used %d",
760                           index, frame->inited, frame->on_used);
761             frame->status.val = 0;
762         }
763     }
764 }
765 
h265e_dpb_build_list(H265eDpb * dpb,EncCpbStatus * cpb)766 void h265e_dpb_build_list(H265eDpb *dpb, EncCpbStatus *cpb)
767 {
768     RK_S32 poc_cur = dpb->curr->slice->poc;
769     H265eSlice* slice = dpb->curr->slice;
770     RK_U32 bGPBcheck = 0;
771     RK_S32 i;
772 
773     h265e_dbg_func("enter\n");
774     if (get_nal_unit_type(dpb, poc_cur) == NAL_IDR_W_RADL ||
775         get_nal_unit_type(dpb, poc_cur) == NAL_IDR_N_LP) {
776         dpb->last_idr = poc_cur;
777     }
778 
779     slice->last_idr = dpb->last_idr;
780     slice->m_temporalLayerNonReferenceFlag = !slice->is_referenced;
781     // Set the nal unit type
782     slice->m_nalUnitType = get_nal_unit_type(dpb, poc_cur);
783 
784     // If the slice is un-referenced, change from _R "referenced" to _N "non-referenced" NAL unit type
785     if (slice->m_temporalLayerNonReferenceFlag) {
786         switch (slice->m_nalUnitType) {
787         case NAL_TRAIL_R:
788             slice->m_nalUnitType = NAL_TRAIL_N;
789             break;
790         case NAL_RADL_R:
791             slice->m_nalUnitType = NAL_RADL_N;
792             break;
793         case NAL_RASL_R:
794             slice->m_nalUnitType  = NAL_RASL_N;
795             break;
796         default:
797             break;
798         }
799     }
800 
801     // Do decoding refresh marking if any
802     h265e_dpb_dec_refresh_marking(dpb, poc_cur, slice->m_nalUnitType);
803     h265e_dpb_cpb2rps(dpb, poc_cur, slice, cpb);
804 
805     slice->m_numRefIdx[L0] =  MPP_MIN(dpb->max_ref_l0, slice->m_rps->m_numberOfPictures); // Ensuring L0 contains just the -ve POC
806     slice->m_numRefIdx[L1] =  MPP_MIN(dpb->max_ref_l1, slice->m_rps->m_numberOfPictures);
807 
808     h265e_slice_set_ref_list(dpb->frame_list, slice);
809 
810     // Slice type refinement
811     if ((slice->m_sliceType == B_SLICE) && (slice->m_numRefIdx[L1] == 0)) {
812         slice->m_sliceType = P_SLICE;
813     }
814 
815     if (slice->m_sliceType == B_SLICE) {
816         // TODO: Can we estimate this from lookahead?
817         slice->m_colFromL0Flag = 0;
818 
819         RK_U32 bLowDelay = 1;
820         RK_S32 curPOC = slice->poc;
821         RK_S32 refIdx = 0;
822 
823         for (refIdx = 0; refIdx < slice->m_numRefIdx[L0] && bLowDelay; refIdx++) {
824             if (slice->m_refPicList[L0][refIdx]->poc > curPOC) {
825                 bLowDelay = 0;
826             }
827         }
828 
829         for (refIdx = 0; refIdx < slice->m_numRefIdx[L1] && bLowDelay; refIdx++) {
830             if (slice->m_refPicList[L1][refIdx]->poc > curPOC) {
831                 bLowDelay = 0;
832             }
833         }
834 
835         slice->m_bCheckLDC = bLowDelay;
836     } else {
837         slice->m_bCheckLDC = 1;
838     }
839 
840     h265e_slice_set_ref_poc_list(slice);
841     if (slice->m_sliceType == B_SLICE) {
842         if (slice->m_numRefIdx[L0] == slice->m_numRefIdx[L1]) {
843             bGPBcheck = 0;
844             for (i = 0; i < slice->m_numRefIdx[L1]; i++) {
845                 if (slice->m_refPOCList[L1][i] != slice->m_refPOCList[L0][i]) {
846                     bGPBcheck = 0;
847                     break;
848                 }
849             }
850         }
851     }
852 
853     slice->m_bLMvdL1Zero = bGPBcheck;
854     slice->m_nextSlice = 0;
855     if (slice->m_sliceType == I_SLICE) {
856         slice->tot_poc_num = 0;
857     } else {
858         slice->tot_poc_num = slice->m_localRPS.m_numberOfPictures;
859     }
860     h265e_dpb_free_unsed(dpb, cpb);
861     h265e_dbg_func("leave\n");
862 }
863