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