xref: /rockchip-linux_mpp/mpp/base/mpp_enc_ref.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3  * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4  */
5 
6 #define MODULE_TAG "mpp_enc_ref"
7 
8 #include <string.h>
9 
10 #include "mpp_env.h"
11 #include "mpp_log.h"
12 #include "mpp_mem.h"
13 #include "mpp_time.h"
14 
15 #include "mpp_rc_defs.h"
16 #include "mpp_enc_ref.h"
17 #include "mpp_enc_refs.h"
18 
19 #define setup_mpp_enc_ref_cfg(ref) \
20     ((MppEncRefCfgImpl*)ref)->name = MODULE_TAG;
21 
_check_is_mpp_enc_ref_cfg(const char * func,void * ref)22 MPP_RET _check_is_mpp_enc_ref_cfg(const char *func, void *ref)
23 {
24     if (NULL == ref) {
25         mpp_err("%s input ref check NULL failed\n", func);
26         return MPP_NOK;
27     }
28 
29     if (strcmp(((MppEncRefCfgImpl*)(ref))->name, MODULE_TAG) != 0) {
30         mpp_err("%s input ref check %p %p failed\n", func, ((MppEncRefCfgImpl*)(ref))->name);
31         return MPP_NOK;
32     }
33 
34     return MPP_OK;
35 }
36 
mpp_enc_ref_cfg_init(MppEncRefCfg * ref)37 MPP_RET mpp_enc_ref_cfg_init(MppEncRefCfg *ref)
38 {
39     if (NULL == ref) {
40         mpp_err_f("invalid NULL input ref_cfg\n");
41         return MPP_ERR_NULL_PTR;
42     }
43 
44     MppEncRefCfgImpl *p = mpp_calloc(MppEncRefCfgImpl, 1);
45     *ref = p;
46     if (NULL == p) {
47         mpp_err_f("malloc failed\n");
48         return MPP_ERR_NULL_PTR;
49     }
50 
51     mpp_env_get_u32("enc_ref_cfg_debug", &p->debug, 0);
52 
53     setup_mpp_enc_ref_cfg(p);
54 
55     return MPP_OK;
56 }
57 
mpp_enc_ref_cfg_deinit(MppEncRefCfg * ref)58 MPP_RET mpp_enc_ref_cfg_deinit(MppEncRefCfg *ref)
59 {
60     if (!ref || check_is_mpp_enc_ref_cfg(*ref)) {
61         mpp_err_f("input %p check failed\n", ref);
62         return MPP_ERR_VALUE;
63     }
64 
65     MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)(*ref);
66     MPP_FREE(p->lt_cfg);
67     MPP_FREE(p->st_cfg);
68     MPP_FREE(p);
69 
70     return MPP_OK;
71 }
72 
mpp_enc_ref_cfg_reset(MppEncRefCfg ref)73 MPP_RET mpp_enc_ref_cfg_reset(MppEncRefCfg ref)
74 {
75     if (check_is_mpp_enc_ref_cfg(ref))
76         return MPP_ERR_VALUE;
77 
78     MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref;
79     MPP_FREE(p->lt_cfg);
80     MPP_FREE(p->st_cfg);
81     memset(p, 0, sizeof(*p));
82     setup_mpp_enc_ref_cfg(p);
83 
84     return MPP_OK;
85 }
86 
mpp_enc_ref_cfg_set_cfg_cnt(MppEncRefCfg ref,RK_S32 lt_cnt,RK_S32 st_cnt)87 MPP_RET mpp_enc_ref_cfg_set_cfg_cnt(MppEncRefCfg ref, RK_S32 lt_cnt, RK_S32 st_cnt)
88 {
89     if (check_is_mpp_enc_ref_cfg(ref))
90         return MPP_ERR_NULL_PTR;
91 
92     MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref;
93     MppEncRefLtFrmCfg *lt_cfg = p->lt_cfg;
94     MppEncRefStFrmCfg *st_cfg = p->st_cfg;;
95 
96     if (lt_cfg || st_cfg) {
97         mpp_err_f("do call reset before setup new cnout\n");
98         MPP_FREE(lt_cfg);
99         MPP_FREE(st_cfg);
100     }
101 
102     if (lt_cnt) {
103         lt_cfg = mpp_calloc(MppEncRefLtFrmCfg, lt_cnt);
104         if (NULL == lt_cfg)
105             mpp_log_f("failed to create %d lt ref cfg\n", lt_cnt);
106     }
107 
108     if (st_cnt) {
109         st_cfg = mpp_calloc(MppEncRefStFrmCfg, st_cnt);
110         if (NULL == st_cfg)
111             mpp_log_f("failed to create %d st ref cfg\n", lt_cnt);
112     }
113 
114     p->max_lt_cfg = lt_cnt;
115     p->max_st_cfg = st_cnt;
116     p->lt_cfg_cnt = 0;
117     p->st_cfg_cnt = 0;
118     p->lt_cfg = lt_cfg;
119     p->st_cfg = st_cfg;
120 
121     return MPP_OK;
122 }
123 
mpp_enc_ref_cfg_add_lt_cfg(MppEncRefCfg ref,RK_S32 cnt,MppEncRefLtFrmCfg * frm)124 MPP_RET mpp_enc_ref_cfg_add_lt_cfg(MppEncRefCfg ref, RK_S32 cnt, MppEncRefLtFrmCfg *frm)
125 {
126     if (check_is_mpp_enc_ref_cfg(ref))
127         return MPP_ERR_VALUE;
128 
129     MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref;
130 
131     if (p->debug)
132         mpp_log("ref %p add lt %d cfg idx %d tid %d gap %d delay %d ref mode %x\n",
133                 ref, p->lt_cfg_cnt, frm->lt_idx, frm->temporal_id,
134                 frm->lt_gap, frm->lt_delay, frm->ref_mode);
135 
136     memcpy(&p->lt_cfg[p->lt_cfg_cnt], frm, sizeof(*frm) * cnt);
137     p->lt_cfg_cnt += cnt;
138 
139     return MPP_OK;
140 }
141 
mpp_enc_ref_cfg_add_st_cfg(MppEncRefCfg ref,RK_S32 cnt,MppEncRefStFrmCfg * frm)142 MPP_RET mpp_enc_ref_cfg_add_st_cfg(MppEncRefCfg ref, RK_S32 cnt, MppEncRefStFrmCfg *frm)
143 {
144     if (check_is_mpp_enc_ref_cfg(ref)) {
145         mpp_err_f("input %p check failed\n", ref);
146         return MPP_ERR_VALUE;
147     }
148 
149     MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref;
150 
151     if (p->debug)
152         mpp_log("ref %p add lt %d cfg non %d tid %d gap repeat %d ref mode %x arg %d\n",
153                 ref, p->st_cfg_cnt, frm->is_non_ref, frm->temporal_id,
154                 frm->repeat, frm->ref_mode, frm->ref_arg);
155 
156     memcpy(&p->st_cfg[p->st_cfg_cnt], frm, sizeof(*frm) * cnt);
157     p->st_cfg_cnt += cnt;
158 
159     return MPP_OK;
160 }
161 
mpp_enc_ref_cfg_check(MppEncRefCfg ref)162 MPP_RET mpp_enc_ref_cfg_check(MppEncRefCfg ref)
163 {
164     if (check_is_mpp_enc_ref_cfg(ref))
165         return MPP_ERR_VALUE;
166 
167     MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref;
168     RK_S32 lt_cfg_cnt = p->lt_cfg_cnt;
169     RK_S32 st_cfg_cnt = p->st_cfg_cnt;
170     RK_S32 max_lt_ref_cnt   = 0;
171     RK_S32 max_lt_ref_idx   = 0;
172     RK_S32 lt_idx_used_mask = 0;
173     RK_S32 lt_dryrun_length = 0;
174     RK_S32 max_st_ref_cnt   = 0;
175     RK_S32 max_st_tid       = 0;
176     RK_S32 st_tid_used_mask = 0;
177     RK_S32 st_dryrun_length = 0;
178     RK_S32 ready = 1;
179 
180     /* parse and check gop config for encoder */
181     if (lt_cfg_cnt) {
182         RK_S32 pos = 0;
183         MppEncRefLtFrmCfg *cfg = p->lt_cfg;
184 
185         for (pos = 0; pos < lt_cfg_cnt; pos++, cfg++) {
186             MppEncRefMode ref_mode = cfg->ref_mode;
187             RK_S32 temporal_id = cfg->temporal_id;
188             RK_S32 lt_idx = cfg->lt_idx;
189             RK_U32 lt_idx_mask = 1 << lt_idx;
190 
191             /* check lt idx */
192             if (lt_idx >= MPP_ENC_MAX_LT_REF_NUM) {
193                 mpp_err_f("ref cfg %p lt cfg %d with invalid lt_idx %d larger than MPP_ENC_MAX_LT_REF_NUM\n",
194                           ref, pos, lt_idx);
195                 ready = 0;
196             }
197 
198             if (lt_idx_used_mask & lt_idx_mask) {
199                 mpp_err_f("ref cfg %p lt cfg %d with redefined lt_idx %d config\n",
200                           ref, pos, lt_idx);
201                 ready = 0;
202             }
203 
204             if (!(lt_idx_used_mask & lt_idx_mask)) {
205                 lt_idx_used_mask |= lt_idx_mask;
206                 max_lt_ref_cnt++;
207             }
208 
209             if (lt_idx > max_lt_ref_idx)
210                 max_lt_ref_idx = lt_idx;
211 
212             /* check temporal id */
213             if (temporal_id != 0) {
214                 mpp_err_f("ref cfg %p lt cfg %d with invalid temporal_id %d is non-zero\n",
215                           ref, pos, temporal_id);
216                 ready = 0;
217             }
218 
219             /* check gop mode */
220             if (!REF_MODE_IS_GLOBAL(ref_mode) && !REF_MODE_IS_LT_MODE(ref_mode)) {
221                 mpp_err_f("ref cfg %p lt cfg %d with invalid ref mode %x\n",
222                           ref, pos, ref_mode);
223                 ready = 0;
224             }
225 
226             /* if check failed just quit */
227             if (!ready)
228                 break;
229 
230             if (cfg->lt_gap && (cfg->lt_gap + cfg->lt_delay > lt_dryrun_length))
231                 lt_dryrun_length = cfg->lt_gap + cfg->lt_delay;
232         }
233     }
234 
235     /* check st-ref config */
236     if (ready && st_cfg_cnt) {
237         RK_S32 pos = 0;
238         MppEncRefStFrmCfg *cfg = p->st_cfg;
239 
240         for (pos = 0; pos < st_cfg_cnt; pos++, cfg++) {
241             MppEncRefMode ref_mode = cfg->ref_mode;
242             RK_S32 temporal_id = cfg->temporal_id;
243             RK_U32 tid_mask = 1 << temporal_id;
244 
245             /* check temporal_id */
246             if (temporal_id > MPP_ENC_MAX_TEMPORAL_LAYER_NUM - 1) {
247                 mpp_err_f("ref cfg %p st cfg %d with invalid temporal_id %d larger than MPP_ENC_MAX_TEMPORAL_LAYER_NUM\n",
248                           ref, pos, temporal_id);
249                 ready = 0;
250             }
251 
252             /* check gop mode */
253             if (!REF_MODE_IS_GLOBAL(ref_mode) && !REF_MODE_IS_ST_MODE(ref_mode)) {
254                 mpp_err_f("ref cfg %p st cfg %d with invalid ref mode %x\n",
255                           ref, pos, ref_mode);
256                 ready = 0;
257             }
258 
259             if (cfg->repeat < 0) {
260                 mpp_err_f("ref cfg %p st cfg %d with negative repeat %d set to zero\n",
261                           ref, pos, cfg->repeat);
262                 cfg->repeat = 0;
263             }
264 
265             /* constrain on head and tail frame */
266             if (pos == 0 || (pos == st_cfg_cnt - 1)) {
267                 if (cfg->is_non_ref) {
268                     mpp_err_f("ref cfg %p st cfg %d with invalid non-ref frame on head/tail frame\n",
269                               ref, pos);
270                     ready = 0;
271                 }
272 
273                 if (temporal_id > 0) {
274                     mpp_err_f("ref cfg %p st cfg %d with invalid non-zero temporal id %d on head/tail frame\n",
275                               ref, pos, temporal_id);
276                     ready = 0;
277                 }
278             }
279 
280             if (!ready)
281                 break;
282 
283             if (!cfg->is_non_ref && !(st_tid_used_mask & tid_mask)) {
284                 max_st_ref_cnt++;
285                 st_tid_used_mask |= tid_mask;
286             }
287 
288             if (temporal_id > max_st_tid)
289                 max_st_tid = temporal_id;
290 
291             st_dryrun_length++;
292             st_dryrun_length += cfg->repeat;
293         }
294     }
295 
296     if (ready) {
297         MppEncCpbInfo *cpb_info = &p->cpb_info;
298         MppEncRefs refs = NULL;
299         MPP_RET ret = MPP_OK;
300 
301         cpb_info->dpb_size = 0;
302         cpb_info->max_lt_cnt = max_lt_ref_cnt;
303         cpb_info->max_st_cnt = max_st_ref_cnt;
304         cpb_info->max_lt_idx = max_lt_ref_idx;
305         cpb_info->max_st_tid = max_st_tid;
306         cpb_info->lt_gop     = lt_dryrun_length;
307         cpb_info->st_gop     = st_dryrun_length - 1;
308 
309         ret = mpp_enc_refs_init(&refs);
310         ready = (ret) ? 0 : (ready);
311         ret = mpp_enc_refs_set_cfg(refs, ref);
312         ready = (ret) ? 0 : (ready);
313         ret = mpp_enc_refs_dryrun(refs);
314         ready = (ret) ? 0 : (ready);
315 
316         /* update dpb size */
317         ret = mpp_enc_refs_get_cpb_info(refs, cpb_info);
318         ready = (ret) ? 0 : (ready);
319 
320         ret = mpp_enc_refs_deinit(&refs);
321         ready = (ret) ? 0 : (ready);
322     } else {
323         mpp_err_f("check ref cfg %p failed\n", ref);
324     }
325     p->ready = ready;
326 
327     return ready ? MPP_OK : MPP_NOK;
328 }
329 
mpp_enc_ref_cfg_set_keep_cpb(MppEncRefCfg ref,RK_S32 keep)330 MPP_RET mpp_enc_ref_cfg_set_keep_cpb(MppEncRefCfg ref, RK_S32 keep)
331 {
332     if (check_is_mpp_enc_ref_cfg(ref))
333         return MPP_ERR_VALUE;
334 
335     MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref;
336     p->keep_cpb = keep;
337 
338     return MPP_OK;
339 }
340 
mpp_enc_ref_cfg_show(MppEncRefCfg ref)341 MPP_RET mpp_enc_ref_cfg_show(MppEncRefCfg ref)
342 {
343     if (check_is_mpp_enc_ref_cfg(ref))
344         return MPP_ERR_VALUE;
345 
346     return MPP_OK;
347 }
348 
mpp_enc_ref_cfg_copy(MppEncRefCfg dst,MppEncRefCfg src)349 MPP_RET mpp_enc_ref_cfg_copy(MppEncRefCfg dst, MppEncRefCfg src)
350 {
351     if (check_is_mpp_enc_ref_cfg(dst) || check_is_mpp_enc_ref_cfg(src))
352         return MPP_ERR_VALUE;
353 
354     MPP_RET ret = MPP_OK;
355     MppEncRefCfgImpl *d = (MppEncRefCfgImpl *)dst;
356     MppEncRefCfgImpl *s = (MppEncRefCfgImpl *)src;
357     RK_S32 max_lt_cfg = s->max_lt_cfg;
358     RK_S32 max_st_cfg = s->max_st_cfg;
359 
360     /* step 1 - free cfg in dst */
361     MPP_FREE(d->lt_cfg);
362     MPP_FREE(d->st_cfg);
363 
364     /* step 2 - copy contex from src */
365     memcpy(d, s, sizeof(*d));
366 
367     /* step 3 - create new storage and copy lt/st cfg */
368     if (max_lt_cfg) {
369         MppEncRefLtFrmCfg *lt_cfg = mpp_calloc(MppEncRefLtFrmCfg, max_lt_cfg);
370 
371         if (NULL == lt_cfg) {
372             mpp_log_f("failed to create %d lt ref cfg\n", max_lt_cfg);
373             ret = MPP_NOK;
374         } else
375             memcpy(lt_cfg, s->lt_cfg, sizeof(lt_cfg[0]) * s->max_lt_cfg);
376 
377         d->lt_cfg = lt_cfg;
378     }
379 
380     if (max_st_cfg) {
381         MppEncRefStFrmCfg *st_cfg = mpp_calloc(MppEncRefStFrmCfg, max_st_cfg);
382 
383         if (NULL == st_cfg) {
384             mpp_log_f("failed to create %d st ref cfg\n", max_st_cfg);
385             ret = MPP_NOK;
386         } else
387             memcpy(st_cfg, s->st_cfg, sizeof(st_cfg[0]) * s->max_st_cfg);
388 
389         d->st_cfg = st_cfg;
390     }
391 
392     if (ret)
393         mpp_enc_ref_cfg_reset(dst);
394 
395     return ret;
396 }
397 
mpp_enc_ref_cfg_get_cpb_info(MppEncRefCfg ref)398 MppEncCpbInfo *mpp_enc_ref_cfg_get_cpb_info(MppEncRefCfg ref)
399 {
400     if (check_is_mpp_enc_ref_cfg(ref))
401         return NULL;
402 
403     MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref;
404     return &p->cpb_info;
405 }
406 
407 static MppEncRefStFrmCfg default_st_ref_cfg = {
408     .is_non_ref         = 0,
409     .temporal_id        = 0,
410     .ref_mode           = REF_TO_PREV_REF_FRM,
411     .ref_arg            = 0,
412     .repeat             = 0,
413 };
414 
415 static const MppEncRefCfgImpl default_ref_cfg = {
416     .name               = MODULE_TAG,
417     .ready              = 1,
418     .debug              = 0,
419     .keep_cpb           = 0,
420     .max_lt_cfg         = 0,
421     .max_st_cfg         = 1,
422     .lt_cfg_cnt         = 0,
423     .st_cfg_cnt         = 1,
424     .max_tlayers        = 1,
425     .lt_cfg             = NULL,
426     .st_cfg             = &default_st_ref_cfg,
427     .cpb_info           = { 1, 0, 1, 0, 0, 0, 0 },
428 };
429 
mpp_enc_ref_default(void)430 MppEncRefCfg mpp_enc_ref_default(void)
431 {
432     return (MppEncRefCfg)&default_ref_cfg;
433 }
434