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