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 "h264e_dpb"
18
19 #include <string.h>
20
21 #include "mpp_mem.h"
22 #include "mpp_common.h"
23
24 #include "h264e_debug.h"
25 #include "h264e_dpb.h"
26 #include "h264e_slice.h"
27
h264e_dpb_dump_usage(H264eDpb * dpb,const char * fmt)28 void h264e_dpb_dump_usage(H264eDpb *dpb, const char *fmt)
29 {
30 RK_S32 i = 0;
31 char buf[256];
32 RK_S32 pos = 0;
33
34 pos += snprintf(buf, sizeof(buf) - 1, "total %2d ", dpb->total_cnt);
35
36 for (i = 0; i < dpb->total_cnt; i++) {
37 H264eDpbFrm *frm = &dpb->frames[i];
38
39 pos += snprintf(buf + pos, sizeof(buf) - 1 - pos, "%04x ", frm->on_used);
40 }
41 mpp_log("%s %s", fmt, buf);
42 }
43
h264e_dpb_dump_frm(H264eDpb * dpb,const char * caller,RK_S32 line)44 void h264e_dpb_dump_frm(H264eDpb *dpb, const char *caller, RK_S32 line)
45 {
46 RK_S32 i = 0;
47
48 mpp_log_f("dump dpb frame info in %s line %d\n", caller, line);
49
50 mpp_log_f("dpb %p total count %d size %d\n", dpb, dpb->total_cnt, dpb->dpb_size);
51 mpp_log_f("dpb %5s %5s %5s %5s %5s %5s %5s %5s %5s\n",
52 "slot", "use", "seq", "type", "tid", "ref", "idx", "mode", "arg");
53
54 for (i = 0; i < dpb->total_cnt; i++) {
55 H264eDpbFrm *frm = &dpb->frames[i];
56 EncFrmStatus *status = &frm->status;
57
58 mpp_log_f("frm %5d %5d %5d %5s %5d %5s %5d %5x %5d\n",
59 i, frm->on_used, status->seq_idx,
60 (status->is_intra) ? (status->is_idr ? "I" : "i" ) :
61 status->is_non_ref ? "p" : "P",
62 status->temporal_id,
63 status->is_non_ref ? "non" : status->is_lt_ref ? "lt" : "st",
64 status->lt_idx,
65 status->ref_mode,
66 status->ref_arg);
67 }
68 }
69
h264e_dpb_dump_listX(H264eDpbFrm ** list,RK_S32 count)70 void h264e_dpb_dump_listX(H264eDpbFrm **list, RK_S32 count)
71 {
72 RK_S32 i;
73
74 for (i = 0; i < count; i++) {
75 H264eDpbFrm *frm = list[i];
76 EncFrmStatus *status = &frm->status;
77
78 mpp_log_f("frm %2d %d %-3d %s %-3d %-3s %-3d %-4x %-3d\n",
79 i, frm->on_used, status->seq_idx,
80 (status->is_intra) ? (status->is_idr ? "I" : "i" ) :
81 status->is_non_ref ? "p" : "P",
82 status->temporal_id,
83 status->is_non_ref ? "non" : status->is_lt_ref ? "lt" : "st",
84 status->lt_idx,
85 status->ref_mode,
86 status->ref_arg);
87 }
88 }
89
h264e_dpb_dump_list(H264eDpb * dpb)90 void h264e_dpb_dump_list(H264eDpb *dpb)
91 {
92 mpp_log_f("dump dpb list info\n");
93
94 mpp_log_f("dpb size %d used %d st %d lt %d\n",
95 dpb->dpb_size, dpb->used_size, dpb->st_size, dpb->lt_size);
96
97 if (dpb->st_size + dpb->lt_size) {
98 mpp_log_f("list slot use seq type tid ref idx mode arg\n", dpb, dpb->total_cnt);
99
100 h264e_dpb_dump_listX(dpb->list, dpb->st_size + dpb->lt_size);
101 }
102 }
103
h264e_dpb_init(H264eDpb * dpb,H264eReorderInfo * reorder,H264eMarkingInfo * marking)104 MPP_RET h264e_dpb_init(H264eDpb *dpb, H264eReorderInfo *reorder, H264eMarkingInfo *marking)
105 {
106 RK_S32 i;
107
108 h264e_dbg_dpb("enter %p\n", dpb);
109
110 memset(dpb, 0, sizeof(*dpb));
111
112 dpb->reorder = reorder;
113 dpb->marking = marking;
114 for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dpb->frames); i++)
115 dpb->frames[i].slot_idx = i;
116
117 h264e_dbg_dpb("leave %p\n", dpb);
118
119 return MPP_OK;
120 }
121
h264e_dpb_setup(H264eDpb * dpb,MppEncCfgSet * cfg,H264eSps * sps)122 MPP_RET h264e_dpb_setup(H264eDpb *dpb, MppEncCfgSet* cfg, H264eSps *sps)
123 {
124 MPP_RET ret = MPP_OK;
125 MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(cfg->ref_cfg);
126
127 h264e_dbg_dpb("enter %p\n", dpb);
128
129 RK_S32 ref_frm_num = sps->num_ref_frames;
130 RK_S32 log2_max_frm_num = sps->log2_max_frame_num_minus4 + 4;
131 RK_S32 log2_max_poc_lsb = sps->log2_max_poc_lsb_minus4 + 4;
132
133 /* NOTE: new configure needs to clear dpb first */
134 h264e_dpb_init(dpb, dpb->reorder, dpb->marking);
135
136 memcpy(&dpb->info, info, sizeof(dpb->info));
137 dpb->dpb_size = info->dpb_size;
138 dpb->total_cnt = info->dpb_size + 1;
139 dpb->max_frm_num = 1 << log2_max_frm_num;
140 dpb->max_poc_lsb = (1 << log2_max_poc_lsb);
141 dpb->poc_type = sps->pic_order_cnt_type;
142
143 if (cfg->hw.extra_buf)
144 dpb->total_cnt++;
145
146 h264e_dbg_dpb("max ref frm num %d total slot %d\n",
147 ref_frm_num, dpb->total_cnt);
148 h264e_dbg_dpb("log2 max frm num %d -> %d\n",
149 log2_max_frm_num, dpb->max_frm_num);
150 h264e_dbg_dpb("log2 max poc lsb %d -> %d\n",
151 log2_max_poc_lsb, dpb->max_poc_lsb);
152
153 h264e_dbg_dpb("leave %p\n", dpb);
154
155 return ret;
156 }
157
find_cpb_frame(H264eDpb * dpb,EncFrmStatus * frm)158 H264eDpbFrm *find_cpb_frame(H264eDpb *dpb, EncFrmStatus *frm)
159 {
160 H264eDpbFrm *frms = dpb->frames;
161 RK_S32 seq_idx = frm->seq_idx;
162 RK_S32 cnt = dpb->total_cnt;
163 RK_S32 i;
164
165 if (!frm->valid)
166 return NULL;
167
168 h264e_dbg_dpb("frm %d start finding slot\n", frm->seq_idx);
169
170 for (i = 0; i < cnt; i++) {
171 EncFrmStatus *p = &frms[i].status;
172
173 if (p->valid && p->seq_idx == seq_idx) {
174 h264e_dbg_dpb("frm %d match slot %d valid %d\n",
175 p->seq_idx, i, p->valid);
176
177 mpp_assert(p->is_non_ref == frm->is_non_ref);
178 mpp_assert(p->is_lt_ref == frm->is_lt_ref);
179 mpp_assert(p->lt_idx == frm->lt_idx);
180 mpp_assert(p->temporal_id == frm->temporal_id);
181 return &frms[i];
182 }
183 }
184
185 mpp_err_f("can not find match frm %d\n", seq_idx);
186 h264e_dpb_dump_frms(dpb);
187 abort();
188
189 return NULL;
190 }
191
192
cmp_st_list(const void * p0,const void * p1)193 static int cmp_st_list(const void *p0, const void *p1)
194 {
195 H264eDpbFrm *frm0 = *(H264eDpbFrm **)p0;
196 H264eDpbFrm *frm1 = *(H264eDpbFrm **)p1;
197
198 if (frm0->frame_num == frm1->frame_num)
199 return 0;
200 if (frm0->frame_num < frm1->frame_num)
201 return 1;
202 else
203 return -1;
204 }
205
cmp_lt_list(const void * p0,const void * p1)206 static int cmp_lt_list(const void *p0, const void *p1)
207 {
208 H264eDpbFrm *frm0 = *(H264eDpbFrm **)p0;
209 H264eDpbFrm *frm1 = *(H264eDpbFrm **)p1;
210
211 if (frm0->lt_idx == frm1->lt_idx)
212 return 0;
213 if (frm0->lt_idx > frm1->lt_idx)
214 return 1;
215 else
216 return -1;
217 }
218
219 /*
220 * Build list function
221 *
222 * This function should build the default list for current frame.
223 * Then check the reference frame is the default one or not.
224 * Reorder command is need if the reference frame is not match.
225 */
h264e_dpb_build_list(H264eDpb * dpb,EncCpbStatus * cpb)226 void h264e_dpb_build_list(H264eDpb *dpb, EncCpbStatus *cpb)
227 {
228 RK_S32 i, j;
229 RK_S32 st_size = 0;
230 RK_S32 lt_size = 0;
231
232 h264e_dbg_dpb("enter %p\n", dpb);
233
234 /* clear list */
235 memset(dpb->list, 0, sizeof(dpb->list));
236
237 if (cpb->curr.is_intra) {
238 h264e_dbg_dpb("leave %p\n", dpb);
239 return ;
240 }
241
242 // 2.1 init list
243 // 2.1.1 found all short term and long term ref
244 h264e_dbg_list("cpb init scaning start\n");
245
246 for (i = 0; i < MAX_CPB_REFS; i++) {
247 EncFrmStatus *frm = &cpb->init[i];
248
249 if (!frm->valid)
250 continue;
251
252 mpp_assert(!frm->is_non_ref);
253
254 h264e_dbg_list("idx %d frm %d valid %d is_non_ref %d lt_ref %d\n",
255 i, frm->seq_idx, frm->valid, frm->is_non_ref, frm->is_lt_ref);
256
257 H264eDpbFrm *p = find_cpb_frame(dpb, frm);
258 if (!frm->is_lt_ref) {
259 dpb->stref[st_size++] = p;
260 p->status.val = frm->val;
261 h264e_dbg_list("found st %d st_size %d %p\n", i, st_size, frm);
262 } else {
263 dpb->ltref[lt_size++] = p;
264 p->status.val = frm->val;
265 h264e_dbg_list("found lt %d lt_size %d %p\n", i, lt_size, frm);
266 }
267 }
268
269 h264e_dbg_list("cpb init scaning done\n");
270 h264e_dbg_dpb("dpb_size %d st_size %d lt_size %d\n", dpb->dpb_size, st_size, lt_size);
271
272 // sort st list
273 if (st_size > 1) {
274 if (h264e_debug & H264E_DBG_LIST) {
275 mpp_log_f("dpb st list before sort\n");
276 h264e_dpb_dump_listX(dpb->stref, st_size);
277 }
278
279 qsort(dpb->stref, st_size, sizeof(dpb->stref[0]), cmp_st_list);
280
281 if (h264e_debug & H264E_DBG_LIST) {
282 mpp_log_f("dpb st list after sort\n");
283 h264e_dpb_dump_listX(dpb->stref, st_size);
284 }
285 }
286
287 if (lt_size > 1) {
288 if (h264e_debug & H264E_DBG_LIST) {
289 mpp_log_f("dpb lt list before sort\n");
290 h264e_dpb_dump_listX(dpb->ltref, lt_size);
291 }
292
293 qsort(dpb->ltref, lt_size, sizeof(dpb->ltref[0]), cmp_lt_list);
294
295 if (h264e_debug & H264E_DBG_LIST) {
296 mpp_log_f("dpb lt list after sort\n");
297 h264e_dpb_dump_listX(dpb->ltref, lt_size);
298 }
299 }
300
301 // generate list before reorder
302 memset(dpb->list, 0, sizeof(dpb->list));
303 j = 0;
304 for (i = 0; i < st_size; i++)
305 dpb->list[j++] = dpb->stref[i];
306
307 for (i = 0; i < lt_size; i++)
308 dpb->list[j++] = dpb->ltref[i];
309
310 dpb->st_size = st_size;
311 dpb->lt_size = lt_size;
312
313 mpp_assert(dpb->dpb_size >= st_size + lt_size);
314
315 if (h264e_debug & H264E_DBG_LIST)
316 h264e_dpb_dump_list(dpb);
317
318 /* generate syntax */
319 h264e_reorder_wr_rewind(dpb->reorder);
320
321 if (dpb->st_size + dpb->lt_size) {
322 H264eDpbFrm *curr = dpb->curr;
323 H264eDpbFrm *refr = dpb->refr;
324 H264eDpbFrm *def_ref = dpb->list[0];
325
326 RK_S32 curr_frm_cnt = curr->status.seq_idx;
327 RK_S32 set_ref_frm_cnt = refr->status.seq_idx;
328 RK_S32 def_ref_frm_cnt = def_ref->status.seq_idx;
329
330 h264e_dbg_list("refer curr %d def %d set %d reorder %d\n",
331 curr_frm_cnt, def_ref_frm_cnt, set_ref_frm_cnt,
332 (def_ref_frm_cnt != set_ref_frm_cnt));
333
334 if (def_ref_frm_cnt != set_ref_frm_cnt) {
335 H264eRplmo op;
336
337 h264e_dbg_list("reorder to frm %d\n", refr->status.seq_idx);
338
339 mpp_assert(!refr->status.is_non_ref);
340
341 op.modification_of_pic_nums_idc = (refr->status.is_lt_ref) ? (2) : (0);
342 if (refr->status.is_lt_ref) {
343 op.modification_of_pic_nums_idc = 2;
344 op.long_term_pic_idx = refr->status.lt_idx;
345
346 h264e_dbg_list("reorder lt idx %d \n", op.long_term_pic_idx);
347 } else {
348 op.modification_of_pic_nums_idc = curr->frame_num > refr->frame_num ? 0 : 1;
349 op.abs_diff_pic_num_minus1 = MPP_ABS(curr->frame_num - refr->frame_num) - 1;
350
351 h264e_dbg_list("reorder st cur %d refr %d diff - 1 %d\n",
352 curr->frame_num, refr->frame_num,
353 op.abs_diff_pic_num_minus1);
354 }
355
356 h264e_reorder_wr_op(dpb->reorder, &op);
357 }
358 } else {
359 h264e_dbg_list("refer NULL\n");
360 }
361
362 h264e_dbg_dpb("leave %p\n", dpb);
363 }
364
h264e_dpb_build_marking(H264eDpb * dpb)365 void h264e_dpb_build_marking(H264eDpb *dpb)
366 {
367 H264eDpbFrm *frm = dpb->curr;
368 H264eMarkingInfo *marking = dpb->marking;
369
370 h264e_dbg_dpb("enter %p\n", dpb);
371
372 h264e_marking_wr_rewind(marking);
373
374 // refernce frame can not mark itself as unreferenced.
375 if (frm->status.is_idr) {
376 marking->idr_flag = 1;
377 marking->no_output_of_prior_pics = 0;
378 marking->long_term_reference_flag = frm->status.is_lt_ref;
379 goto DONE;
380 }
381
382 marking->idr_flag = 0;
383 marking->long_term_reference_flag = 0;
384 marking->adaptive_ref_pic_buffering = 0;
385
386 h264e_dbg_dpb("frm %d ref %d lt %d T%d\n",
387 frm->status.seq_idx, !frm->status.is_non_ref,
388 frm->status.is_lt_ref, frm->status.temporal_id);
389
390 if (frm->status.is_non_ref)
391 goto DONE;
392
393 // When current frame is lt_ref update max_lt_idx
394 if (frm->status.is_lt_ref) {
395 H264eMmco op;
396
397 dpb->next_max_lt_idx = dpb->info.max_lt_idx;
398
399 if (dpb->next_max_lt_idx != dpb->curr_max_lt_idx) {
400 RK_S32 max_lt_idx_p1 = dpb->next_max_lt_idx + 1;
401
402 op.mmco = 4;
403 op.max_long_term_frame_idx_plus1 = max_lt_idx_p1;
404
405 h264e_marking_wr_op(marking, &op);
406 h264e_dbg_mmco("add mmco 4 %d\n", max_lt_idx_p1);
407
408 dpb->curr_max_lt_idx = dpb->next_max_lt_idx;
409 }
410
411 op.mmco = 6;
412 op.long_term_frame_idx = frm->lt_idx;
413
414 h264e_marking_wr_op(marking, &op);
415 h264e_dbg_mmco("add mmco 6 %d\n", frm->lt_idx);
416 }
417
418 // TODO: check and mark used frame
419 DONE:
420 h264e_dbg_dpb("dpb size %d used %d\n", dpb->dpb_size, dpb->used_size);
421 h264e_dbg_dpb("leave %p\n", dpb);
422 }
423
h264e_dpb_proc(H264eDpb * dpb,EncCpbStatus * cpb)424 MPP_RET h264e_dpb_proc(H264eDpb *dpb, EncCpbStatus *cpb)
425 {
426 EncFrmStatus *curr = &cpb->curr;
427 EncFrmStatus *refr = &cpb->refr;
428 EncFrmStatus *init = cpb->init;
429 H264eDpbFrm *frames = dpb->frames;
430 H264eDpbRt *rt = &dpb->rt;
431 RK_S32 used_size = 0;
432 RK_S32 seq_idx = curr->seq_idx;
433 RK_S32 i;
434
435 h264e_dbg_dpb("enter %p total %d\n", dpb, dpb->total_cnt);
436
437 if (curr->is_idr) {
438 for (i = 0; i < H264E_MAX_REFS_CNT + 1; i++) {
439 frames[i].dpb_used = 0;
440 frames[i].status.valid = 0;
441 }
442 dpb->used_size = 0;
443 dpb->curr_max_lt_idx = 0;
444 dpb->next_max_lt_idx = 0;
445 } else {
446 if (curr->seq_idx == rt->last_seq_idx) {
447 h264e_dbg_dpb("NOTE: reenc found at %d\n", curr->seq_idx);
448 memcpy(rt, &dpb->rt_bak, sizeof(*rt));
449 memcpy(frames, dpb->frm_bak, sizeof(dpb->frm_bak));
450 }
451 }
452
453 if (h264e_debug & H264E_DBG_DPB)
454 h264e_dpb_dump_frms(dpb);
455 /*
456 * 1. scan and map cpb to internal cpb h264edpb is bridge from
457 * user defined cpb to hal slot index
458 */
459 for (i = 0; i < MAX_CPB_REFS; i++) {
460 H264eDpbFrm *frm = find_cpb_frame(dpb, &init[i]);
461 dpb->map[i] = frm;
462 if (frm) {
463 if (!frm->on_used && !frm->status.force_pskip_is_ref)
464 mpp_err_f("warning frm %d is used by cpb but on not used status\n",
465 frm->seq_idx);
466 frm->dpb_used = 1;
467 used_size++;
468 }
469 }
470
471 mpp_assert(dpb->used_size == used_size);
472 h264e_dbg_dpb("frm %d init cpb used size %d vs %d\n", seq_idx,
473 used_size, dpb->used_size);
474
475 /* backup current runtime status */
476 memcpy(&dpb->rt_bak, rt, sizeof(dpb->rt_bak));
477 memcpy(dpb->frm_bak, frames, sizeof(dpb->frm_bak));
478
479 /* mark current cpb */
480 RK_S32 found_curr = 0;
481
482 /* 2. scan all slot for used map and find a slot for current */
483 dpb->curr = NULL;
484
485 h264e_dbg_dpb("frm %d start finding slot for storage\n", seq_idx);
486 for (i = 0; i < H264E_MAX_REFS_CNT + 1; i++) {
487 H264eDpbFrm *p = &frames[i];
488 RK_S32 curr_frm_num = rt->last_frm_num + rt->last_is_ref;
489 RK_S32 curr_poc_lsb = rt->last_poc_lsb;
490 RK_S32 curr_poc_msb = rt->last_poc_msb;
491 RK_S32 valid = 0;
492 RK_S32 j;
493
494 for (j = 0; j < MAX_CPB_REFS; j++) {
495 if (p == dpb->map[j] || p->as_pskip_ref) {
496 valid = 1;
497 break;
498 }
499 }
500
501 h264e_dbg_dpb("slot %2d check in cpb init valid %d used %04x\n",
502 i, valid, p->on_used);
503
504 if (valid) {
505 if ((!p->as_pskip_ref) &&
506 (!p->on_used || !p->status.valid)) {
507 mpp_assert(p->on_used);
508 mpp_assert(p->status.valid);
509 h264e_dpb_dump_frms(dpb);
510 }
511 continue;
512 }
513
514 h264e_dbg_dpb("slot %2d used %04x checking\n", i, p->on_used);
515
516 if (p->hal_used)
517 continue;
518
519 if (found_curr) {
520 p->dpb_used = 0;
521 p->status.valid = 0;
522 continue;
523 }
524
525 h264e_dbg_dpb("slot %2d used %04x mark as current\n", i, p->on_used);
526
527 dpb->curr = p;
528 p->status.val = curr->val;
529 p->seq_idx = curr->seq_idx;
530 if (curr->is_idr) {
531 p->frame_num = 0;
532 p->poc = 0;
533 curr_frm_num = 0;
534 curr_poc_lsb = 0;
535 curr_poc_msb = 0;
536 } else {
537 if (curr_frm_num >= dpb->max_frm_num)
538 curr_frm_num = 0;
539
540 p->frame_num = curr_frm_num;
541
542 if (dpb->poc_type == 0)
543 curr_poc_lsb += 2;
544 else if (dpb->poc_type == 2)
545 curr_poc_lsb += 1 + rt->last_is_ref;
546 else
547 mpp_err_f("do not support poc type 1\n");
548
549 if (curr_poc_lsb >= dpb->max_poc_lsb) {
550 curr_poc_lsb = 0;
551 curr_poc_msb++;
552 }
553
554 p->poc = curr_poc_lsb + curr_poc_msb * dpb->max_poc_lsb;
555
556 }
557 p->lt_idx = curr->lt_idx;
558 p->dpb_used = 1;
559
560 rt->last_seq_idx = curr->seq_idx;
561 rt->last_is_ref = !curr->is_non_ref;
562 rt->last_frm_num = curr_frm_num;
563 rt->last_poc_lsb = curr_poc_lsb;
564 rt->last_poc_msb = curr_poc_msb;
565
566 found_curr = 1;
567 h264e_dbg_dpb("frm %d update slot %d with frame_num %d poc %d\n",
568 seq_idx, i, p->frame_num, p->poc);
569 }
570
571 mpp_assert(dpb->curr);
572
573 if (NULL == dpb->curr)
574 mpp_err_f("frm %d failed to find a slot for curr %d\n", seq_idx);
575
576 h264e_dbg_dpb("frm %d start finding slot for refr %d\n", seq_idx, refr->seq_idx);
577 dpb->refr = find_cpb_frame(dpb, refr);
578 if (NULL == dpb->refr)
579 dpb->refr = dpb->curr;
580
581 h264e_dbg_dpb("frm %d curr %d refr %d start building list\n",
582 seq_idx, dpb->curr->slot_idx, dpb->refr->slot_idx);
583
584 h264e_dpb_build_list(dpb, cpb);
585
586 if (h264e_debug & H264E_DBG_DPB)
587 h264e_dpb_dump_frms(dpb);
588
589 h264e_dpb_build_marking(dpb);
590
591 if (h264e_debug & H264E_DBG_DPB)
592 h264e_dpb_dump_frms(dpb);
593
594 h264e_dbg_dpb("leave %p\n", dpb);
595
596 return MPP_OK;
597 }
598
h264e_dpb_check(H264eDpb * dpb,EncCpbStatus * cpb)599 void h264e_dpb_check(H264eDpb *dpb, EncCpbStatus *cpb)
600 {
601 H264eDpbFrm *curr = dpb->curr;
602 H264eDpbFrm *refr = dpb->refr;
603 RK_S32 i;
604
605 h264e_dbg_dpb("enter %p\n", dpb);
606
607 h264e_dbg_dpb("frm %d refr -> frm %d ready\n",
608 curr->seq_idx, refr->seq_idx);
609
610 if (curr->status.is_non_ref) {
611 curr->dpb_used = 0;
612 curr->status.valid = 0;
613 } else {
614 /* sliding window process */
615 RK_S32 used_size = dpb->used_size;
616 RK_S32 dpb_size = dpb->dpb_size;
617
618 h264e_dbg_dpb("frm %d %s insert dpb used %d max %d\n",
619 curr->seq_idx, curr->status.is_lt_ref ? "lt" : "st",
620 used_size, dpb_size);
621
622 used_size++;
623
624 /* replace lt ref with same lt_idx */
625 if (curr->status.is_lt_ref) {
626 RK_S32 lt_idx = curr->lt_idx;
627
628 dpb->lt_size++;
629
630 for (i = 0; i < dpb->total_cnt; i++) {
631 H264eDpbFrm *tmp = &dpb->frames[i];
632
633 if (tmp == curr)
634 continue;
635
636 if (!tmp->dpb_used)
637 continue;
638
639 if (!tmp->status.valid)
640 continue;
641
642 mpp_assert(!tmp->status.is_non_ref);
643
644 if (!tmp->status.is_lt_ref)
645 continue;
646
647 if (tmp->lt_idx == lt_idx) {
648 tmp->dpb_used = 0;
649 tmp->status.valid = 0;
650 h264e_dbg_dpb("frm %d lt_idx %d replace %d\n",
651 curr->seq_idx, curr->lt_idx, tmp->slot_idx);
652 dpb->lt_size--;
653 used_size--;
654 }
655 }
656 } else {
657 dpb->st_size++;
658 }
659
660 if (used_size > dpb_size) {
661 mpp_assert(dpb->lt_size <= dpb_size);
662
663 while (used_size > dpb_size) {
664 RK_S32 small_poc = 0x7fffffff;
665 H264eDpbFrm *unref = NULL;
666
667 h264e_dbg_dpb("sliding window cpb proc: st %d lt %d max %d\n",
668 dpb->st_size, dpb->lt_size, dpb_size);
669
670 for (i = 0; i < dpb->total_cnt; i++) {
671 H264eDpbFrm *tmp = &dpb->frames[i];
672
673 h264e_dbg_dpb("frm %d num %d poc %d\n",
674 tmp->seq_idx, tmp->frame_num, tmp->poc);
675
676 if (tmp->as_pskip_ref)
677 continue;
678
679 if (!tmp->on_used)
680 continue;
681
682 if (!tmp->status.valid)
683 continue;
684
685 mpp_assert(!tmp->status.is_non_ref);
686
687 if (tmp->status.is_lt_ref)
688 continue;
689
690 if (tmp->poc < small_poc) {
691 unref = tmp;
692 small_poc = tmp->poc;
693
694 h264e_dbg_dpb("frm %d update smallest poc to %d\n",
695 tmp->seq_idx, tmp->poc);
696 }
697 }
698
699 if (unref) {
700 h264e_dbg_dpb("removing frm %d poc %d\n",
701 unref->seq_idx, unref->poc);
702
703 unref->dpb_used = 0;
704 dpb->st_size--;
705 mpp_assert(dpb->st_size >= 0);
706 used_size--;
707 } else
708 break;
709 }
710 }
711
712 dpb->used_size = used_size;
713 if (used_size > dpb_size) {
714 mpp_err_f("error found used_size %d > dpb_size %d\n", used_size, dpb_size);
715 mpp_assert(used_size <= dpb_size);
716 }
717 }
718
719 h264e_dbg_dpb("curr %d done used_size %d\n", curr->seq_idx, dpb->used_size);
720
721 RK_S32 used_size = 0;
722 for (i = 0; i < MAX_CPB_REFS; i++) {
723 dpb->map[i] = find_cpb_frame(dpb, &cpb->final[i]);
724 if (dpb->map[i])
725 used_size++;
726 }
727
728 h264e_dbg_dpb("curr %d cpb final used_size %d vs %d\n",
729 curr->seq_idx, used_size, dpb->used_size);
730 mpp_assert(dpb->used_size == used_size);
731
732 h264e_dbg_dpb("leave %p\n", dpb);
733 }
734
h264e_dpb_hal_start(H264eDpb * dpb,RK_S32 slot_idx)735 MPP_RET h264e_dpb_hal_start(H264eDpb *dpb, RK_S32 slot_idx)
736 {
737 H264eDpbFrm *frm = &dpb->frames[slot_idx];
738
739 frm->hal_used++;
740 //h264e_dpb_dump_usage(dpb, __FUNCTION__);
741 return MPP_OK;
742 }
743
h264e_dpb_hal_end(H264eDpb * dpb,RK_S32 slot_idx)744 MPP_RET h264e_dpb_hal_end(H264eDpb *dpb, RK_S32 slot_idx)
745 {
746 H264eDpbFrm *frm = &dpb->frames[slot_idx];
747
748 frm->hal_used--;
749 //h264e_dpb_dump_usage(dpb, __FUNCTION__);
750 return MPP_OK;
751 }
752