xref: /OK3568_Linux_fs/external/mpp/mpp/codec/enc/vp8/vp8e_api_v2.c (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 #define MODULE_TAG  "vp8e_api_v2"
17 
18 #include <string.h>
19 #include <vp8e_syntax.h>
20 
21 #include "mpp_env.h"
22 #include "mpp_mem.h"
23 #include "mpp_debug.h"
24 #include "mpp_common.h"
25 #include "mpp_rc.h"
26 #include "mpp_enc_cfg_impl.h"
27 
28 #include "vp8e_api_v2.h"
29 #include "vp8e_rc.h"
30 #include "vp8e_syntax.h"
31 
32 #define VP8E_DBG_FUNCTION            (0x00000001)
33 #define VP8E_DBG_CFG                 (0x00000002)
34 
35 #define vp8e_dbg_cfg(fmt, ...)    _mpp_dbg_f(vp8e_debug, VP8E_DBG_CFG, fmt, ## __VA_ARGS__)
36 #define vp8e_dbg_fun(fmt, ...)    _mpp_dbg_f(vp8e_debug, VP8E_DBG_FUNCTION, fmt, ## __VA_ARGS__)
37 
38 RK_U32 vp8e_debug = 0;
39 #define VP8E_SYN_BUTT 2
40 
41 typedef struct {
42     /* config from mpp_enc */
43     MppEncCfgSet    *cfg;
44 
45     /* internal rate control config*/
46     Vp8eRc          *rc;
47 
48     Vp8eSyntax      vp8e_syntax[VP8E_SYN_BUTT];
49 } Vp8eCtx;
50 
vp8e_init(void * ctx,EncImplCfg * ctrl_cfg)51 static MPP_RET vp8e_init(void *ctx, EncImplCfg *ctrl_cfg)
52 {
53     MPP_RET ret = MPP_OK;
54     Vp8eCtx *p = (Vp8eCtx *)ctx;
55 
56     MppEncRcCfg *rc_cfg = &ctrl_cfg->cfg->rc;
57     MppEncPrepCfg *prep = &ctrl_cfg->cfg->prep;
58 
59     vp8e_dbg_fun("enter\n");
60     if (NULL == ctx || NULL == ctrl_cfg) {
61         mpp_err_f("Init failed, contex or controller cfg is null!\n");
62         ret = MPP_NOK;
63         goto __ERR_RET;
64     }
65 
66     p->cfg = ctrl_cfg->cfg;
67 
68     /*
69      * default prep:
70      * 720p
71      * YUV420SP
72      */
73     prep->change = 0;
74     prep->width = 1280;
75     prep->height = 720;
76     prep->hor_stride = 1280;
77     prep->ver_stride = 720;
78     prep->format = MPP_FMT_YUV420SP;
79     prep->rotation = MPP_ENC_ROT_0;
80     prep->rotation_ext = MPP_ENC_ROT_0;
81     prep->mirroring = 0;
82     prep->mirroring_ext = 0;
83     prep->denoise = 0;
84 
85     /*
86      * default rc_cfg:
87      * CBR
88      * 2Mbps +-25%
89      * 30fps
90      * gop 60
91      */
92     rc_cfg->change = 0;
93     rc_cfg->rc_mode = MPP_ENC_RC_MODE_CBR;
94     rc_cfg->quality = MPP_ENC_RC_QUALITY_MEDIUM;
95     rc_cfg->bps_target = 2000 * 1000;
96     rc_cfg->bps_max = rc_cfg->bps_target * 5 / 4;
97     rc_cfg->bps_min = rc_cfg->bps_target * 3 / 4;
98     rc_cfg->fps_in_flex = 0;
99     rc_cfg->fps_in_num = 30;
100     rc_cfg->fps_in_denorm = 1;
101     rc_cfg->fps_out_flex = 0;
102     rc_cfg->fps_out_num = 30;
103     rc_cfg->fps_out_denorm = 1;
104     rc_cfg->gop = 60;
105     rc_cfg->max_reenc_times = 1;
106 
107     p->rc = mpp_calloc(Vp8eRc, 1);
108     memset(p->rc, 0, sizeof(Vp8eRc));
109     p->rc->frame_coded = 1;
110     if (NULL == p->rc) {
111         mpp_err_f("failed to malloc vp8_rc\n");
112         ret = MPP_ERR_MALLOC;
113         goto __ERR_RET;
114     }
115 
116     mpp_env_get_u32("vp8e_debug", &vp8e_debug, 0);
117 
118     vp8e_dbg_fun("leave ret %d\n", ret);
119     return ret;
120 
121 __ERR_RET:
122     vp8e_dbg_fun("leave ret %d\n", ret);
123     return ret;
124 }
125 
vp8e_deinit(void * ctx)126 static MPP_RET vp8e_deinit(void *ctx)
127 {
128     Vp8eCtx *p = (Vp8eCtx *)ctx;
129 
130     vp8e_dbg_fun("enter\n");
131 
132     if (p->rc)
133         mpp_free(p->rc);
134 
135     vp8e_dbg_fun("leave\n");
136     return MPP_OK;
137 }
138 
vp8e_start(void * ctx,HalEncTask * task)139 static MPP_RET vp8e_start(void *ctx, HalEncTask *task)
140 {
141     (void)ctx;
142     (void)task;
143 
144     return MPP_OK;
145 }
146 
vp8e_proc_dpb(void * ctx,HalEncTask * task)147 static MPP_RET vp8e_proc_dpb(void *ctx, HalEncTask *task)
148 {
149     (void)ctx;
150     EncRcTask    *rc_task = task->rc_task;
151     EncCpbStatus *cpb = &task->rc_task->cpb;
152     rc_task->frm.val = cpb->curr.val;
153     return MPP_OK;
154 }
155 
vp8e_proc_prep_cfg(MppEncPrepCfg * dst,MppEncPrepCfg * src)156 static MPP_RET vp8e_proc_prep_cfg(MppEncPrepCfg *dst, MppEncPrepCfg *src)
157 {
158     MPP_RET ret = MPP_OK;
159     RK_U32 change = src->change;
160 
161     mpp_assert(change);
162     if (change) {
163         RK_S32 mirroring;
164         RK_S32 rotation;
165 
166         if (change & MPP_ENC_PREP_CFG_CHANGE_FORMAT) {
167             if ((src->format < MPP_FRAME_FMT_RGB &&
168                  src->format >= MPP_FMT_YUV_BUTT) ||
169                 src->format >= MPP_FMT_RGB_BUTT) {
170                 mpp_err("invalid format %d\n", src->format);
171                 ret = MPP_NOK;
172             }
173             dst->format = src->format;
174         }
175 
176         if (change & MPP_ENC_PREP_CFG_CHANGE_ROTATION)
177             dst->rotation_ext = src->rotation_ext;
178 
179         if (change & MPP_ENC_PREP_CFG_CHANGE_MIRRORING)
180             dst->mirroring_ext = src->mirroring_ext;
181 
182         if (change & MPP_ENC_PREP_CFG_CHANGE_FLIP)
183             dst->flip = src->flip;
184 
185         // parameter checking
186         if (dst->rotation_ext >= MPP_ENC_ROT_BUTT || dst->rotation_ext < 0 ||
187             dst->mirroring_ext < 0 || dst->flip < 0) {
188             mpp_err("invalid trans: rotation %d, mirroring %d\n", dst->rotation_ext, dst->mirroring_ext);
189             ret = MPP_ERR_VALUE;
190         }
191 
192         rotation = dst->rotation_ext;
193         mirroring = dst->mirroring_ext;
194 
195         if (dst->flip) {
196             mirroring = !mirroring;
197             rotation += MPP_ENC_ROT_180;
198             rotation &= MPP_ENC_ROT_270;
199         }
200 
201         dst->mirroring = mirroring;
202         dst->rotation = rotation;
203 
204         /* vp8 encoder do not have denoise/sharpen feature */
205 
206         if (change & MPP_ENC_PREP_CFG_CHANGE_INPUT ||
207             (change & MPP_ENC_PREP_CFG_CHANGE_ROTATION)) {
208             if ((src->width < 0 || src->width > 1920) ||
209                 (src->height < 0 || src->height > 3840) ||
210                 (src->hor_stride < 0 || src->hor_stride > 7680) ||
211                 (src->ver_stride < 0 || src->ver_stride > 3840)) {
212                 mpp_err("invalid input w:h [%d:%d] [%d:%d]\n",
213                         src->width, src->height,
214                         src->hor_stride, src->ver_stride);
215                 ret = MPP_NOK;
216             }
217 
218             if (dst->rotation == MPP_ENC_ROT_90 || dst->rotation == MPP_ENC_ROT_270) {
219                 dst->width = src->height;
220                 dst->height = src->width;
221             } else {
222                 dst->width = src->width;
223                 dst->height = src->height;
224             }
225             dst->ver_stride = src->ver_stride;
226             dst->hor_stride = src->hor_stride;
227         }
228 
229         dst->change |= src->change;
230 
231         if (dst->rotation == MPP_ENC_ROT_90 || dst->rotation == MPP_ENC_ROT_270) {
232             if (dst->height > dst->hor_stride || dst->width > dst->ver_stride) {
233                 mpp_err("invalid size w:h [%d:%d] stride [%d:%d]\n",
234                         dst->width, dst->height, dst->hor_stride, dst->ver_stride);
235                 ret = MPP_ERR_VALUE;
236             }
237         } else {
238             if (dst->width > dst->hor_stride || dst->height > dst->ver_stride) {
239                 mpp_err("invalid size w:h [%d:%d] stride [%d:%d]\n",
240                         dst->width, dst->height, dst->hor_stride, dst->ver_stride);
241                 ret = MPP_ERR_VALUE;
242             }
243         }
244 
245         vp8e_dbg_cfg("width %d height %d hor_stride %d ver_srtride %d format 0x%x\n",
246                      dst->width, dst->height, dst->hor_stride, dst->ver_stride, dst->format);
247     }
248     return ret;
249 }
250 
vp8e_proc_split_cfg(MppEncSliceSplit * dst,MppEncSliceSplit * src)251 static MPP_RET vp8e_proc_split_cfg(MppEncSliceSplit *dst, MppEncSliceSplit *src)
252 {
253     MPP_RET ret = MPP_OK;
254     RK_U32 change = src->change;
255 
256     if (change & MPP_ENC_SPLIT_CFG_CHANGE_MODE) {
257         dst->split_mode = src->split_mode;
258         dst->split_arg = src->split_arg;
259     }
260 
261     if (change & MPP_ENC_SPLIT_CFG_CHANGE_ARG)
262         dst->split_arg = src->split_arg;
263 
264     dst->change |= change;
265 
266     return ret;
267 }
268 
vp8e_proc_vp8_cfg(MppEncVp8Cfg * dst,MppEncVp8Cfg * src)269 static MPP_RET vp8e_proc_vp8_cfg(MppEncVp8Cfg *dst, MppEncVp8Cfg *src)
270 {
271     RK_U32 change = src->change;
272 
273     if (change & MPP_ENC_VP8_CFG_CHANGE_QP) {
274         dst->qp_init = src->qp_init;
275         dst->qp_max = src->qp_max;
276         dst->qp_min = src->qp_min;
277         dst->qp_max_i = src->qp_max_i;
278         dst->qp_min_i = src->qp_min_i;
279     }
280     if (change & MPP_ENC_VP8_CFG_CHANGE_DIS_IVF) {
281         dst->disable_ivf = src->disable_ivf;
282     }
283     vp8e_dbg_cfg("rc cfg qp_init %d qp_max %d qp_min %d qp_max_i %d qp_min_i %d, disable_ivf %d\n",
284                  dst->qp_init, dst->qp_max, dst->qp_min, dst->qp_max_i, dst->qp_min_i, dst->disable_ivf);
285     dst->change |= src->change;
286     return MPP_OK;
287 }
288 
vp8e_proc_cfg(void * ctx,MpiCmd cmd,void * param)289 static MPP_RET vp8e_proc_cfg(void *ctx, MpiCmd cmd, void *param)
290 {
291     MPP_RET ret = MPP_OK;
292     Vp8eCtx *p = (Vp8eCtx *)ctx;
293     MppEncCfgSet *cfg = p->cfg;
294     MppEncCfgImpl *impl = (MppEncCfgImpl *)param;
295     MppEncCfgSet *src = &impl->cfg;
296 
297     vp8e_dbg_fun("enter ctx %p cmd %x param %p\n", ctx, cmd, param);
298     switch (cmd) {
299     case MPP_ENC_SET_CFG : {
300         if (src->prep.change) {
301             ret |= vp8e_proc_prep_cfg(&cfg->prep, &src->prep);
302             src->prep.change = 0;
303         }
304         if (src->codec.vp8.change) {
305             ret |= vp8e_proc_vp8_cfg(&cfg->codec.vp8, &src->codec.vp8);
306             src->codec.vp8.change = 0;
307         }
308         if (src->split.change) {
309             ret |= vp8e_proc_split_cfg(&cfg->split, &src->split);
310             src->split.change = 0;
311         }
312     } break;
313     default: {
314         mpp_err("No correspond cmd found, and can not config!");
315         ret = MPP_NOK;
316     } break;
317     }
318 
319     vp8e_dbg_fun("leave ret %d\n", ret);
320     return ret;
321 }
322 
vp8e_proc_hal(void * ctx,HalEncTask * task)323 static MPP_RET vp8e_proc_hal(void *ctx, HalEncTask *task)
324 {
325     Vp8eCtx *p = (Vp8eCtx *)ctx;
326     Vp8eSyntax *syntax = &p->vp8e_syntax[0];
327     RK_U32 syn_num = 0;
328 
329     syntax[syn_num].type = VP8E_SYN_CFG;
330     syntax[syn_num].data = p->cfg;
331     syn_num++;
332     syntax[syn_num].type = VP8E_SYN_RC;
333     syntax[syn_num].data = p->rc;
334     syn_num++;
335     task->syntax.data = syntax;
336     task->syntax.number = syn_num;
337 
338     task->valid = 1;
339     return MPP_OK;
340 }
341 
342 const EncImplApi api_vp8e = {
343     .name       = "vp8_control",
344     .coding     = MPP_VIDEO_CodingVP8,
345     .ctx_size   = sizeof(Vp8eCtx),
346     .flag       = 0,
347     .init       = vp8e_init,
348     .deinit     = vp8e_deinit,
349     .proc_cfg   = vp8e_proc_cfg,
350     .gen_hdr    = NULL,
351     .start      = vp8e_start,
352     .proc_dpb   = vp8e_proc_dpb,
353     .proc_hal   = vp8e_proc_hal,
354     .add_prefix = NULL,
355     .sw_enc     = NULL,
356 };
357