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