xref: /rockchip-linux_mpp/mpp/codec/enc/h264/h264e_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  "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