xref: /OK3568_Linux_fs/external/mpp/mpp/codec/rc/rc.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2016 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 "rc"
18 
19 #include <math.h>
20 #include <memory.h>
21 
22 #include "mpp_env.h"
23 #include "mpp_mem.h"
24 #include "mpp_list.h"
25 #include "mpp_common.h"
26 
27 #include "rc_debug.h"
28 #include "rc.h"
29 #include "rc_impl.h"
30 #include "rc_base.h"
31 
32 typedef struct MppRcImpl_t {
33     void            *ctx;
34     const RcImplApi *api;
35     RcCfg           cfg;
36 
37     RcFpsCfg        fps;
38     RK_S32          frm_cnt;
39 
40     RK_U32          frm_send;
41     RK_U32          frm_done;
42 } MppRcImpl;
43 
44 RK_U32 rc_debug = 0;
45 
46 const static char default_rc_api[] = "default";
47 
rc_init(RcCtx * ctx,MppCodingType type,const char ** request_name)48 MPP_RET rc_init(RcCtx *ctx, MppCodingType type, const char **request_name)
49 {
50     MPP_RET ret = MPP_NOK;
51     MppRcImpl *p = NULL;
52     const char *name = NULL;
53 
54     mpp_env_get_u32("rc_debug", &rc_debug, 0);
55 
56     if (NULL == request_name || NULL == *request_name)
57         name = default_rc_api;
58     else
59         name = *request_name;
60 
61     rc_dbg_func("enter type %x name %s\n", type, name);
62 
63     RcImplApi *api = RcImplApiService::get_instance()->api_get(type, name);
64 
65     mpp_assert(api);
66 
67     if (api) {
68         void *rc_ctx = mpp_calloc_size(void, api->ctx_size);
69         p = mpp_calloc(MppRcImpl, 1);
70 
71         if (NULL == p || NULL == rc_ctx) {
72             mpp_err_f("failed to create context size %d\n", api->ctx_size);
73             MPP_FREE(p);
74             MPP_FREE(rc_ctx);
75             ret = MPP_ERR_MALLOC;
76         } else {
77             p->ctx = rc_ctx;
78             p->api = api;
79             p->frm_cnt = -1;
80             if (request_name && *request_name)
81                 mpp_log("using rc impl %s\n", api->name);
82             ret = MPP_OK;
83         }
84     }
85 
86     *ctx = p;
87     if (request_name)
88         *request_name = name;
89 
90     rc_dbg_func("leave %p\n", p);
91 
92     return ret;
93 }
94 
rc_deinit(RcCtx ctx)95 MPP_RET rc_deinit(RcCtx ctx)
96 {
97     MppRcImpl *p = (MppRcImpl *)ctx;
98     const RcImplApi *api = p->api;
99     MPP_RET ret = MPP_OK;
100 
101     rc_dbg_func("enter %p\n", ctx);
102 
103     if (api && api->deinit && p->ctx) {
104         ret = api->deinit(p->ctx);
105         MPP_FREE(p->ctx);
106     }
107 
108     MPP_FREE(p);
109 
110     rc_dbg_func("leave %p\n", ctx);
111 
112     return ret;
113 }
114 
rc_update_usr_cfg(RcCtx ctx,RcCfg * cfg)115 MPP_RET rc_update_usr_cfg(RcCtx ctx, RcCfg *cfg)
116 {
117     MppRcImpl *p = (MppRcImpl *)ctx;
118     const RcImplApi *api = p->api;
119     MPP_RET ret = MPP_OK;
120 
121     rc_dbg_func("enter %p\n", ctx);
122 
123     p->cfg = *cfg;
124     p->fps = cfg->fps;
125 
126     if (api && api->init && p->ctx)
127         api->init(p->ctx, &p->cfg);
128 
129     rc_dbg_func("leave %p\n", ctx);
130 
131     return ret;
132 }
133 
rc_frm_check_drop(RcCtx ctx,EncRcTask * task)134 MPP_RET rc_frm_check_drop(RcCtx ctx, EncRcTask *task)
135 {
136     MppRcImpl *p = (MppRcImpl *)ctx;
137     const RcImplApi *api = p->api;
138     MPP_RET ret = MPP_OK;
139 
140     rc_dbg_func("enter %p\n", ctx);
141 
142     if (api && api->check_drop && p->ctx && task) {
143         ret = api->check_drop(p->ctx, task);
144         return ret;
145     } else {
146         RcFpsCfg *cfg = &p->fps;
147         RK_S32 frm_cnt  = p->frm_cnt;
148         RK_S32 rate_in  = cfg->fps_in_num * cfg->fps_out_denorm;
149         RK_S32 rate_out = cfg->fps_out_num * cfg->fps_in_denorm;
150         RK_S32 drop = 0;
151 
152         mpp_assert(cfg->fps_in_denorm >= 1);
153         mpp_assert(cfg->fps_out_denorm >= 1);
154         mpp_assert(rate_in >= rate_out);
155 
156         // frame counter is inited to (rate_in - rate_out)  to encode first frame
157         if (frm_cnt < 0)
158             frm_cnt = rate_in - rate_out;
159 
160         frm_cnt += rate_out;
161 
162         if (frm_cnt < rate_in)
163             drop = 1;
164         else
165             frm_cnt -= rate_in;
166 
167         p->frm_cnt = frm_cnt;
168         task->frm.drop = drop;
169     }
170 
171     rc_dbg_func("leave %p drop %d\n", ctx, task->frm.drop);
172 
173     return ret;
174 }
175 
rc_frm_check_reenc(RcCtx ctx,EncRcTask * task)176 MPP_RET rc_frm_check_reenc(RcCtx ctx, EncRcTask *task)
177 {
178     MppRcImpl *p = (MppRcImpl *)ctx;
179     const RcImplApi *api = p->api;
180 
181     if (!api || !api->check_reenc || !p->ctx || !task)
182         return MPP_OK;
183 
184     return api->check_reenc(p->ctx, task);
185 }
186 
rc_frm_start(RcCtx ctx,EncRcTask * task)187 MPP_RET rc_frm_start(RcCtx ctx, EncRcTask *task)
188 {
189     MppRcImpl *p = (MppRcImpl *)ctx;
190     const RcImplApi *api = p->api;
191 
192     if (!api || !api->frm_start || !p->ctx || !task)
193         return MPP_OK;
194 
195     return api->frm_start(p->ctx, task);
196 }
197 
rc_frm_end(RcCtx ctx,EncRcTask * task)198 MPP_RET rc_frm_end(RcCtx ctx, EncRcTask *task)
199 {
200     MppRcImpl *p = (MppRcImpl *)ctx;
201     const RcImplApi *api = p->api;
202 
203     if (!api || !api->frm_end || !p->ctx || !task)
204         return MPP_OK;
205 
206     return api->frm_end(p->ctx, task);
207 }
208 
rc_hal_start(RcCtx ctx,EncRcTask * task)209 MPP_RET rc_hal_start(RcCtx ctx, EncRcTask *task)
210 {
211     MppRcImpl *p = (MppRcImpl *)ctx;
212     const RcImplApi *api = p->api;
213 
214     if (!api || !api->hal_start || !p->ctx || !task)
215         return MPP_OK;
216 
217     return api->hal_start(p->ctx, task);
218 }
219 
rc_hal_end(RcCtx ctx,EncRcTask * task)220 MPP_RET rc_hal_end(RcCtx ctx, EncRcTask *task)
221 {
222     MppRcImpl *p = (MppRcImpl *)ctx;
223     const RcImplApi *api = p->api;
224 
225     if (!api || !api->hal_end || !p->ctx || !task)
226         return MPP_OK;
227 
228     return api->hal_end(p->ctx, task);
229 }
230