1 /*
2  * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #define MODULE_TAG "mpi_enc_utils"
17 
18 #include <string.h>
19 #include "securec.h"
20 #include "mpp_mem.h"
21 #include "mpp_env.h"
22 #include "mpp_log.h"
23 #include "mpp_buffer.h"
24 #include "rk_mpi.h"
25 #include "mpp_common.h"
26 #include "mpp_packet.h"
27 #include "mpi_enc_utils.h"
28 
29 #define GOP_MODE_TSVC4 3
30 #define GOP_MODE_TSVC3 2
31 #define GOP_MODE_TSVC2 1
32 
33 #define TEMPORAL_ID_0 0
34 #define TEMPORAL_ID_1 1
35 #define TEMPORAL_ID_2 2
36 #define TEMPORAL_ID_3 3
37 
38 #define REF_NUM_0  0
39 #define REF_NUM_1  1
40 #define REF_NUM_2  2
41 #define REF_NUM_3  3
42 #define REF_NUM_4  4
43 #define REF_NUM_5  5
44 #define REF_NUM_6  6
45 #define REF_NUM_7  7
46 #define REF_NUM_8  8
47 
48 #define ST_COUNT_3 3
49 #define ST_COUNT_5 5
50 
mpi_enc_gen_ref_cfg(MppEncRefCfg ref, RK_S32 gop_mode)51 static MPP_RET mpi_enc_gen_ref_cfg(MppEncRefCfg ref, RK_S32 gop_mode)
52 {
53     MppEncRefLtFrmCfg lt_ref[4];
54     MppEncRefStFrmCfg st_ref[16];
55     RK_S32 lt_cnt = 0;
56     RK_S32 st_cnt = 0;
57     MPP_RET ret = 0;
58 
59     errno_t eok = memset_s(&lt_ref, sizeof(lt_ref), 0, sizeof(lt_ref));
60     if (eok != EOK) {
61         mpp_err("memset_s failed\n");
62         return MPP_NOK;
63     }
64     eok = memset_s(&st_ref, sizeof(st_ref), 0, sizeof(st_ref));
65     if (eok != EOK) {
66         mpp_err("memset_s failed\n");
67         return MPP_NOK;
68     }
69 
70     switch (gop_mode) {
71         case GOP_MODE_TSVC4 : {
72             // tsvc4
73             //      /-> P1      /-> P3        /-> P5      /-> P7
74             //     /           /             /           /
75             //    //--------> P2            //--------> P6
76             //   //                        //
77             //  ///---------------------> P4
78             // ///
79             // P0 ------------------------------------------------> P8
80             lt_cnt = 1;
81 
82             /* set 8 frame lt-ref gap */
83             lt_ref[REF_NUM_0].lt_idx        = 0;
84             lt_ref[REF_NUM_0].temporal_id   = TEMPORAL_ID_0;
85             lt_ref[REF_NUM_0].ref_mode      = REF_TO_PREV_LT_REF;
86             lt_ref[REF_NUM_0].lt_gap        = 8; // 8:set 8 frame
87             lt_ref[REF_NUM_0].lt_delay      = 0;
88 
89             st_cnt = 9;
90             /* set tsvc4 st-ref struct */
91             /* st 0 layer 0 - ref */
92             st_ref[REF_NUM_0].is_non_ref    = 0;
93             st_ref[REF_NUM_0].temporal_id   = TEMPORAL_ID_0;
94             st_ref[REF_NUM_0].ref_mode      = REF_TO_TEMPORAL_LAYER;
95             st_ref[REF_NUM_0].ref_arg       = 0;
96             st_ref[REF_NUM_0].repeat        = 0;
97             /* st 1 layer 3 - non-ref */
98             st_ref[REF_NUM_1].is_non_ref    = 1;
99             st_ref[REF_NUM_1].temporal_id   = TEMPORAL_ID_3;
100             st_ref[REF_NUM_1].ref_mode      = REF_TO_PREV_REF_FRM;
101             st_ref[REF_NUM_1].ref_arg       = 0;
102             st_ref[REF_NUM_1].repeat        = 0;
103             /* st 2 layer 2 - ref */
104             st_ref[REF_NUM_2].is_non_ref    = 0;
105             st_ref[REF_NUM_2].temporal_id   = TEMPORAL_ID_2;
106             st_ref[REF_NUM_2].ref_mode      = REF_TO_PREV_REF_FRM;
107             st_ref[REF_NUM_2].ref_arg       = 0;
108             st_ref[REF_NUM_2].repeat        = 0;
109             /* st 3 layer 3 - non-ref */
110             st_ref[REF_NUM_3].is_non_ref    = 1;
111             st_ref[REF_NUM_3].temporal_id   = TEMPORAL_ID_3;
112             st_ref[REF_NUM_3].ref_mode      = REF_TO_PREV_REF_FRM;
113             st_ref[REF_NUM_3].ref_arg       = 0;
114             st_ref[REF_NUM_3].repeat        = 0;
115             /* st 4 layer 1 - ref */
116             st_ref[REF_NUM_4].is_non_ref    = 0;
117             st_ref[REF_NUM_4].temporal_id   = TEMPORAL_ID_1;
118             st_ref[REF_NUM_4].ref_mode      = REF_TO_PREV_LT_REF;
119             st_ref[REF_NUM_4].ref_arg       = 0;
120             st_ref[REF_NUM_4].repeat        = 0;
121             /* st 5 layer 3 - non-ref */
122             st_ref[REF_NUM_5].is_non_ref    = 1;
123             st_ref[REF_NUM_5].temporal_id   = TEMPORAL_ID_3;
124             st_ref[REF_NUM_5].ref_mode      = REF_TO_PREV_REF_FRM;
125             st_ref[REF_NUM_5].ref_arg       = 0;
126             st_ref[REF_NUM_5].repeat        = 0;
127             /* st 6 layer 2 - ref */
128             st_ref[REF_NUM_6].is_non_ref    = 0;
129             st_ref[REF_NUM_6].temporal_id   = TEMPORAL_ID_2;
130             st_ref[REF_NUM_6].ref_mode      = REF_TO_PREV_REF_FRM;
131             st_ref[REF_NUM_6].ref_arg       = 0;
132             st_ref[REF_NUM_6].repeat        = 0;
133             /* st 7 layer 3 - non-ref */
134             st_ref[REF_NUM_7].is_non_ref    = 1;
135             st_ref[REF_NUM_7].temporal_id   = TEMPORAL_ID_3;
136             st_ref[REF_NUM_7].ref_mode      = REF_TO_PREV_REF_FRM;
137             st_ref[REF_NUM_7].ref_arg       = 0;
138             st_ref[REF_NUM_7].repeat        = 0;
139             /* st 8 layer 0 - ref */
140             st_ref[REF_NUM_8].is_non_ref    = 0;
141             st_ref[REF_NUM_8].temporal_id   = TEMPORAL_ID_0;
142             st_ref[REF_NUM_8].ref_mode      = REF_TO_TEMPORAL_LAYER;
143             st_ref[REF_NUM_8].ref_arg       = 0;
144             st_ref[REF_NUM_8].repeat        = 0;
145         }
146             break;
147         case GOP_MODE_TSVC3 : {
148             // tsvc3
149             //     /-> P1      /-> P3
150             //    /           /
151             //   //--------> P2
152             //  //
153             // P0/---------------------> P4
154             lt_cnt = 0;
155 
156             st_cnt = ST_COUNT_5;
157             /* set tsvc4 st-ref struct */
158             /* st 0 layer 0 - ref */
159             st_ref[REF_NUM_0].is_non_ref    = 0;
160             st_ref[REF_NUM_0].temporal_id   = TEMPORAL_ID_0;
161             st_ref[REF_NUM_0].ref_mode      = REF_TO_TEMPORAL_LAYER;
162             st_ref[REF_NUM_0].ref_arg       = 0;
163             st_ref[REF_NUM_0].repeat        = 0;
164             /* st 1 layer 2 - non-ref */
165             st_ref[REF_NUM_1].is_non_ref    = 1;
166             st_ref[REF_NUM_1].temporal_id   = TEMPORAL_ID_2;
167             st_ref[REF_NUM_1].ref_mode      = REF_TO_PREV_REF_FRM;
168             st_ref[REF_NUM_1].ref_arg       = 0;
169             st_ref[REF_NUM_1].repeat        = 0;
170             /* st 2 layer 1 - ref */
171             st_ref[REF_NUM_2].is_non_ref    = 0;
172             st_ref[REF_NUM_2].temporal_id   = TEMPORAL_ID_1;
173             st_ref[REF_NUM_2].ref_mode      = REF_TO_PREV_REF_FRM;
174             st_ref[REF_NUM_2].ref_arg       = 0;
175             st_ref[REF_NUM_2].repeat        = 0;
176             /* st 3 layer 2 - non-ref */
177             st_ref[REF_NUM_3].is_non_ref    = 1;
178             st_ref[REF_NUM_3].temporal_id   = TEMPORAL_ID_2;
179             st_ref[REF_NUM_3].ref_mode      = REF_TO_PREV_REF_FRM;
180             st_ref[REF_NUM_3].ref_arg       = 0;
181             st_ref[REF_NUM_3].repeat        = 0;
182             /* st 4 layer 0 - ref */
183             st_ref[REF_NUM_4].is_non_ref    = 0;
184             st_ref[REF_NUM_4].temporal_id   = TEMPORAL_ID_0;
185             st_ref[REF_NUM_4].ref_mode      = REF_TO_TEMPORAL_LAYER;
186             st_ref[REF_NUM_4].ref_arg       = 0;
187             st_ref[REF_NUM_4].repeat        = 0;
188         }
189             break;
190         case GOP_MODE_TSVC2 : {
191             // tsvc2
192             //   /-> P1
193             //  /
194             // P0--------> P2
195             lt_cnt = 0;
196 
197             st_cnt = ST_COUNT_3;
198             /* set tsvc4 st-ref struct */
199             /* st 0 layer 0 - ref */
200             st_ref[REF_NUM_0].is_non_ref    = 0;
201             st_ref[REF_NUM_0].temporal_id   = TEMPORAL_ID_0;
202             st_ref[REF_NUM_0].ref_mode      = REF_TO_TEMPORAL_LAYER;
203             st_ref[REF_NUM_0].ref_arg       = 0;
204             st_ref[REF_NUM_0].repeat        = 0;
205             /* st 1 layer 2 - non-ref */
206             st_ref[REF_NUM_1].is_non_ref    = 1;
207             st_ref[REF_NUM_1].temporal_id   = TEMPORAL_ID_1;
208             st_ref[REF_NUM_1].ref_mode      = REF_TO_PREV_REF_FRM;
209             st_ref[REF_NUM_1].ref_arg       = 0;
210             st_ref[REF_NUM_1].repeat        = 0;
211             /* st 2 layer 1 - ref */
212             st_ref[REF_NUM_2].is_non_ref    = 0;
213             st_ref[REF_NUM_2].temporal_id   = TEMPORAL_ID_0;
214             st_ref[REF_NUM_2].ref_mode      = REF_TO_PREV_REF_FRM;
215             st_ref[REF_NUM_2].ref_arg       = 0;
216             st_ref[REF_NUM_2].repeat        = 0;
217         }
218             break;
219         default : {
220             mpp_err_f("unsupport gop mode %d\n", gop_mode);
221         }
222             break;
223     }
224 
225     if (lt_cnt || st_cnt) {
226         ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cnt, st_cnt);
227 
228         if (lt_cnt)
229             ret = mpp_enc_ref_cfg_add_lt_cfg(ref, lt_cnt, lt_ref);
230 
231         if (st_cnt)
232             ret = mpp_enc_ref_cfg_add_st_cfg(ref, st_cnt, st_ref);
233 
234         /* check and get dpb size */
235         ret = mpp_enc_ref_cfg_check(ref);
236     }
237 
238     return ret;
239 }
240 
mpi_enc_gen_smart_gop_ref_cfg(MppEncRefCfg ref, RK_S32 gop_len, RK_S32 vi_len)241 static MPP_RET mpi_enc_gen_smart_gop_ref_cfg(MppEncRefCfg ref, RK_S32 gop_len, RK_S32 vi_len)
242 {
243     MppEncRefLtFrmCfg lt_ref[4];
244     MppEncRefStFrmCfg st_ref[16];
245     RK_S32 lt_cnt = 1;
246     RK_S32 st_cnt = 8;
247     RK_S32 pos = 0;
248     MPP_RET ret = 0;
249 
250     errno_t eok = memset_s(&lt_ref, sizeof(lt_ref), 0, sizeof(lt_ref));
251     if (eok != EOK) {
252         mpp_err("memset_s failed\n");
253         return MPP_NOK;
254     }
255     eok = memset_s(&st_ref, sizeof(st_ref), 0, sizeof(st_ref));
256     if (eok != EOK) {
257         mpp_err("memset_s failed\n");
258         return MPP_NOK;
259     }
260 
261     ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cnt, st_cnt);
262 
263     /* set 8 frame lt-ref gap */
264     lt_ref[0].lt_idx        = 0;
265     lt_ref[0].temporal_id   = 0;
266     lt_ref[0].ref_mode      = REF_TO_PREV_LT_REF;
267     lt_ref[0].lt_gap        = gop_len;
268     lt_ref[0].lt_delay      = 0;
269 
270     mpp_enc_ref_cfg_add_lt_cfg(ref, 1, lt_ref);
271 
272     /* st 0 layer 0 - ref */
273     st_ref[pos].is_non_ref  = 0;
274     st_ref[pos].temporal_id = 0;
275     st_ref[pos].ref_mode    = REF_TO_PREV_INTRA;
276     st_ref[pos].ref_arg     = 0;
277     st_ref[pos].repeat      = 0;
278     pos++;
279 
280     /* st 1 layer 1 - non-ref */
281     if (vi_len > 1) {
282         st_ref[pos].is_non_ref  = 0;
283         st_ref[pos].temporal_id = 1;
284         st_ref[pos].ref_mode    = REF_TO_PREV_REF_FRM;
285         st_ref[pos].ref_arg     = 0;
286         st_ref[pos].repeat      = vi_len - 2;
287         pos++;
288     }
289 
290     st_ref[pos].is_non_ref  = 0;
291     st_ref[pos].temporal_id = 0;
292     st_ref[pos].ref_mode    = REF_TO_PREV_INTRA;
293     st_ref[pos].ref_arg     = 0;
294     st_ref[pos].repeat      = 0;
295     pos++;
296 
297     mpp_enc_ref_cfg_add_st_cfg(ref, pos, st_ref);
298 
299     /* check and get dpb size */
300     ret = mpp_enc_ref_cfg_check(ref);
301 
302     return ret;
303 }
304 
305 /* ���˱������õ�һЩ����������ߣ�����ͼ���ʽ����������ʽ�ȣ�����������֪��ֱ����0
306  * test_mpp_enc_cfg_setup�������Զ�����Ĭ�ϵIJ�����bps�� gop�Ȳ���
307  */
test_ctx_init(MpiEncTestData **data, MpiEncTestArgs *cmd)308 static MPP_RET test_ctx_init(MpiEncTestData **data, MpiEncTestArgs *cmd)
309 {
310     MpiEncTestData *p = NULL;
311     MPP_RET ret = 0;
312 
313     if (!data || !cmd) {
314         mpp_err_f("invalid input data %p cmd %p\n", data, cmd);
315         return MPP_ERR_NULL_PTR;
316     }
317 
318     p = mpp_calloc(MpiEncTestData, 1);
319     if (!p) {
320         mpp_err_f("create MpiEncTestData failed\n");
321         ret = MPP_ERR_MALLOC;
322         *data = p;
323         return ret;
324     }
325 
326     // get paramter from cmd
327     p->width        = cmd->width;
328     p->height       = cmd->height;
329     p->hor_stride   = MPP_ALIGN(cmd->width, 16); // 16:hor_stride
330     p->ver_stride   = MPP_ALIGN(cmd->height, 16); // 16:ver_stride
331     p->fmt          = cmd->format;
332     p->type         = cmd->type;
333 
334     // update resource parameter
335     switch (p->fmt & MPP_FRAME_FMT_MASK) {
336         case MPP_FMT_YUV420SP:
337         case MPP_FMT_YUV420P: {
338             p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 3 / 2;
339         }
340             break;
341 
342         case MPP_FMT_YUV422_YUYV :
343         case MPP_FMT_YUV422_YVYU :
344         case MPP_FMT_YUV422_UYVY :
345         case MPP_FMT_YUV422_VYUY :
346         case MPP_FMT_YUV422P :
347         case MPP_FMT_YUV422SP :
348         case MPP_FMT_RGB444 :
349         case MPP_FMT_BGR444 :
350         case MPP_FMT_RGB555 :
351         case MPP_FMT_BGR555 :
352         case MPP_FMT_RGB565 :
353         case MPP_FMT_BGR565 : {
354             p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 2;
355         }
356             break;
357         default: {
358             p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 4;
359         }
360             break;
361     }
362     *data = p;
363     return ret;
364 }
365 
test_ctx_deinit(MpiEncTestData **data)366 static MPP_RET test_ctx_deinit(MpiEncTestData **data)
367 {
368     MpiEncTestData *p = NULL;
369 
370     if (!data) {
371         mpp_err_f("invalid input data %p\n", data);
372         return MPP_ERR_NULL_PTR;
373     }
374     p = *data;
375     if (p) {
376         MPP_FREE(p);
377         *data = NULL;
378     }
379     return MPP_OK;
380 }
381 
test_mpp_enc_cfg_setup(MpiEncTestData *p)382 static MPP_RET test_mpp_enc_cfg_setup(MpiEncTestData *p)
383 {
384     MPP_RET ret;
385     MppApi *mpi;
386     MppCtx ctx;
387     MppEncCfg cfg;
388 
389     if (p == NULL)
390         return MPP_ERR_NULL_PTR;
391 
392     mpi = p->mpi;
393     ctx = p->ctx;
394     cfg = p->cfg;
395 
396     /* setup default parameter */
397     if (p->fps_in_den == 0)
398         p->fps_in_den = 1;
399     if (p->fps_in_num == 0)
400         p->fps_in_num = 30;
401     if (p->fps_out_den == 0)
402         p->fps_out_den = 1;
403     if (p->fps_out_num == 0)
404         p->fps_out_num = 30;
405 
406     /* ����Ĭ��bps */
407     if (!p->bps)
408         p->bps = p->width * p->height / 8 * (p->fps_out_num / p->fps_out_den);
409 
410     mpp_enc_cfg_set_s32(cfg, "prep:width", p->width);
411     mpp_enc_cfg_set_s32(cfg, "prep:height", p->height);
412     mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", p->hor_stride);
413     mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", p->ver_stride);
414     mpp_enc_cfg_set_s32(cfg, "prep:format", p->fmt);
415 
416     mpp_enc_cfg_set_s32(cfg, "rc:mode", p->rc_mode);
417 
418     /* fix input / output frame rate */
419     mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", p->fps_in_flex);
420     mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", p->fps_in_num);
421     mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denorm", p->fps_in_den);
422     mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", p->fps_out_flex);
423     mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", p->fps_out_num);
424     mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denorm", p->fps_out_den);
425     mpp_enc_cfg_set_s32(cfg, "rc:gop", p->gop_len ? p->gop_len : p->fps_out_num * 2);
426 
427     /* drop frame or not when bitrate overflow */
428     mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED);
429     mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 20);        /* 20% of max bps */
430     mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 1);         /* Do not continuous drop frame */
431 
432     /* setup bitrate for different rc_mode */
433     mpp_enc_cfg_set_s32(cfg, "rc:bps_target", p->bps);
434     switch (p->rc_mode) {
435         case MPP_ENC_RC_MODE_FIXQP : {
436             /* do not setup bitrate on FIXQP mode */
437         }
438             break;
439         case MPP_ENC_RC_MODE_CBR : {
440             /* CBR mode has narrow bound */
441             mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
442             mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16);
443         }
444             break;
445         case MPP_ENC_RC_MODE_VBR :
446         case MPP_ENC_RC_MODE_AVBR : {
447             /* VBR mode has wide bound */
448             mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
449             mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 1 / 16);
450         }
451             break;
452         default : {
453             /* default use CBR mode */
454             mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
455             mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16);
456         }
457             break;
458     }
459 
460     /* setup qp for different codec and rc_mode */
461     switch (p->type) {
462         case MPP_VIDEO_CodingAVC :
463         case MPP_VIDEO_CodingHEVC : {
464             switch (p->rc_mode) {
465                 case MPP_ENC_RC_MODE_FIXQP : {
466                     mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 20); // 20:mpp cfg value
467                     mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 20); // 20:mpp cfg value
468                     mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 20); // 20:mpp cfg value
469                     mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 20); // 20:mpp cfg value
470                     mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 20); // 20:mpp cfg value
471                     mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2);
472                 }
473                     break;
474                 case MPP_ENC_RC_MODE_CBR :
475                 case MPP_ENC_RC_MODE_VBR :
476                 case MPP_ENC_RC_MODE_AVBR : {
477                     mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 26); // 26:mpp cfg value
478                     mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 51); // 51:mpp cfg value
479                     mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 10); // 10:mpp cfg value
480                     mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 51); // 51:mpp cfg value
481                     mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 10); // 10:mpp cfg value
482                     mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2);
483                 }
484                     break;
485                 default : {
486                     mpp_err_f("unsupport encoder rc mode %d\n", p->rc_mode);
487                 }
488                     break;
489             }
490         }
491             break;
492         case MPP_VIDEO_CodingVP8 : {
493             /* vp8 only setup base qp range */
494             mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 40); // 40:mpp cfg value
495             mpp_enc_cfg_set_s32(cfg, "rc:qp_max",  127); // 127:mpp cfg value
496             mpp_enc_cfg_set_s32(cfg, "rc:qp_min",  0);
497             mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 127); // 127:mpp cfg value
498             mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 0);
499             mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 6); // 6:mpp cfg value
500         }
501             break;
502         case MPP_VIDEO_CodingMJPEG : {
503             /* jpeg use special codec config to control qtable */
504             mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", 80); // 80:mpp cfg value
505             mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", 99); // 99:mpp cfg value
506             mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", 1);
507         }
508             break;
509         default : {
510         }
511             break;
512     }
513 
514     /* setup codec  */
515     mpp_enc_cfg_set_s32(cfg, "codec:type", p->type);
516     switch (p->type) {
517         case MPP_VIDEO_CodingAVC : {
518             /*
519             * H.264 profile_idc parameter
520             * 66  - Baseline profile
521             * 77  - Main profile
522             * 100 - High profile
523             */
524             mpp_enc_cfg_set_s32(cfg, "h264:profile", 100);
525             /*
526             * H.264 level_idc parameter
527             * 10 / 11 / 12 / 13    - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps
528             * 20 / 21 / 22         - cif@30fps / half-D1@@25fps / D1@12.5fps
529             * 30 / 31 / 32         - D1@25fps / 720p@30fps / 720p@60fps
530             * 40 / 41 / 42         - 1080p@30fps / 1080p@30fps / 1080p@60fps
531             * 50 / 51 / 52         - 4K@30fps
532             */
533             mpp_enc_cfg_set_s32(cfg, "h264:level", 40);
534             mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1);
535             mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0);
536             mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1);
537         }
538             break;
539         case MPP_VIDEO_CodingHEVC :
540         case MPP_VIDEO_CodingMJPEG :
541         case MPP_VIDEO_CodingVP8 : {
542         }
543             break;
544         default : {
545             mpp_err_f("unsupport encoder coding type %d\n", p->type);
546         }
547             break;
548     }
549 
550     p->split_mode = 0;
551     p->split_arg = 0;
552 
553     mpp_env_get_u32("split_mode", &p->split_mode, MPP_ENC_SPLIT_NONE);
554     mpp_env_get_u32("split_arg", &p->split_arg, 0);
555 
556     if (p->split_mode) {
557         mpp_log("%p split_mode %d split_arg %d\n", ctx, p->split_mode, p->split_arg);
558         mpp_enc_cfg_set_s32(cfg, "split:mode", p->split_mode);
559         mpp_enc_cfg_set_s32(cfg, "split:arg", p->split_arg);
560     }
561 
562     ret = mpi->control(ctx, MPP_ENC_SET_CFG, cfg);
563     if (ret) {
564         mpp_err("mpi control enc set cfg failed ret %d\n", ret);
565         return ret;
566     }
567 
568     /* optional */
569     p->sei_mode = MPP_ENC_SEI_MODE_ONE_FRAME;
570     ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode);
571     if (ret) {
572         mpp_err("mpi control enc set sei cfg failed ret %d\n", ret);
573         return ret;
574     }
575 
576     if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) {
577         p->header_mode = MPP_ENC_HEADER_MODE_EACH_IDR;
578         ret = mpi->control(ctx, MPP_ENC_SET_HEADER_MODE, &p->header_mode);
579         if (ret) {
580             mpp_err("mpi control enc set header mode failed ret %d\n", ret);
581             return ret;
582         }
583     }
584 
585     RK_U32 gop_mode = p->gop_mode;
586 
587     mpp_env_get_u32("gop_mode", &gop_mode, gop_mode);
588     if (gop_mode) {
589         MppEncRefCfg ref;
590 
591         mpp_enc_ref_cfg_init(&ref);
592 
593         if (p->gop_mode < 4) {
594             mpi_enc_gen_ref_cfg(ref, gop_mode);
595         } else {
596             mpi_enc_gen_smart_gop_ref_cfg(ref, p->gop_len, p->vi_len);
597         }
598         ret = mpi->control(ctx, MPP_ENC_SET_REF_CFG, ref);
599         if (ret) {
600             mpp_err("mpi control enc set ref cfg failed ret %d\n", ret);
601             return ret;
602         }
603         mpp_enc_ref_cfg_deinit(&ref);
604     }
605     return ret;
606 }
607 
test_mpp_frame_set_param(MppFrame frame, MpiEncTestData *p)608 static void test_mpp_frame_set_param(MppFrame frame, MpiEncTestData *p)
609 {
610     mpp_frame_set_width(frame, p->width);
611     mpp_frame_set_height(frame, p->height);
612     mpp_frame_set_hor_stride(frame, p->hor_stride);
613     mpp_frame_set_ver_stride(frame, p->ver_stride);
614     mpp_frame_set_fmt(frame, p->fmt);
615     mpp_frame_set_eos(frame, p->frm_eos);
616 }
617 
test_mpp_ctx_cleanup(MpiEncTestData *p)618 static void test_mpp_ctx_cleanup(MpiEncTestData *p)
619 {
620     if (!p) {
621         mpp_err("test_mpp_ctx_cleanup p == NULL\n");
622         return;
623     }
624 
625     if (p->mpi->reset) {
626         p->mpi->reset(p->ctx);
627     }
628 
629     if (p->ctx) {
630         mpp_destroy(p->ctx);
631         p->ctx = NULL;
632     }
633 
634     if (p->cfg) {
635         mpp_enc_cfg_deinit(p->cfg);
636         p->cfg = NULL;
637     }
638 
639     if (p->pkt_buf) {
640         mpp_buffer_put(p->pkt_buf);
641         p->pkt_buf = NULL;
642     }
643 
644     if (p->buf_grp) {
645         mpp_buffer_group_put(p->buf_grp);
646         p->buf_grp = NULL;
647     }
648 
649     test_ctx_deinit(&p);
650 }
651 
hal_mpp_get_sps(void *ctx, unsigned char *buf, size_t *buf_size)652 int hal_mpp_get_sps(void *ctx, unsigned char *buf, size_t *buf_size)
653 {
654     int ret;
655     MppApi *mpi;
656     MppCtx mpp_ctx;
657     MppPacket packet = NULL;
658     MpiEncTestData *p = (MpiEncTestData *)ctx;
659     errno_t eok;
660 
661     if (!p) {
662         mpp_err("mpi control enc get extra info failed\n");
663         return MPP_NOK;
664     }
665     mpi = p->mpi;
666     mpp_ctx = p->ctx;
667 
668     /*
669      * Can use packet with normal malloc buffer as input not pkt_buf.
670      * Please refer to vpu_api_legacy.cpp for normal buffer case.
671      * Using pkt_buf buffer here is just for simplifing demo.
672      */
673 
674     mpp_packet_init_with_buffer(&packet, p->pkt_buf);
675     /* NOTE: It is important to clear output packet length!! */
676     mpp_packet_set_length(packet, 0);
677 
678     // ����һ��H264��H265ר�õ�һЩ����
679     if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) {
680         ret = mpi->control(mpp_ctx, MPP_ENC_GET_HDR_SYNC, packet);
681         if (ret) {
682             mpp_err("mpi control enc get extra info failed\n");
683             ret = MPP_NOK;
684             mpp_packet_deinit(&packet);
685             return ret;
686         }
687     }
688 
689     void *ptr = mpp_packet_get_pos(packet);
690     size_t len = mpp_packet_get_length(packet);
691     if (*buf_size < len) {
692         mpp_err("mpi buffer size too small\n");
693         ret = MPP_NOK;
694         mpp_packet_deinit(&packet);
695         return ret;
696     }
697 
698     eok = memcpy_s(buf, len, ptr, len);
699     if (eok != EOK) {
700         mpp_err("memcpy_s failed\n");
701         return MPP_NOK;
702     }
703 
704     *buf_size = len;
705 
706     ret = MPP_OK;
707     mpp_packet_deinit(&packet);
708     return ret;
709 }
710 
hal_mpp_encode(void *ctx, int dma_fd, unsigned char *buf, size_t *buf_size)711 int hal_mpp_encode(void *ctx, int dma_fd, unsigned char *buf, size_t *buf_size)
712 {
713     if (!ctx) {
714         mpp_err("memset_s failed\n");
715         return MPP_NOK;
716     }
717 
718     MPP_RET ret = 0;
719     MppFrame frame = NULL;
720     MppMeta meta = NULL;
721     MppPacket packet = NULL;
722     MpiEncTestData *p = (MpiEncTestData *)ctx;
723     MppApi *mpi = p->mpi;
724     RK_U32 eoi = 1;
725     RK_U32 packet_num = 0;
726     MppBuffer cam_buf = NULL;
727     MppBufferInfo info;
728 
729     errno_t eok = memset_s(&info, sizeof(MppBufferInfo), 0, sizeof(MppBufferInfo));
730     if (eok != EOK) {
731         mpp_err("memset_s failed\n");
732         return MPP_NOK;
733     }
734     info.type = MPP_BUFFER_TYPE_EXT_DMA;
735     info.fd = dma_fd;
736     info.size = p->frame_size & 0x07ffffff;
737     info.index = (p->frame_size & 0xf8000000) >> 27;
738 
739     ret = mpp_buffer_import(&cam_buf, &info);
740     if (ret != MPP_SUCCESS) {
741         mpp_err_f("mpp_buffer_import failed\n");
742         return MPP_NOK;
743     }
744 
745     ret = mpp_frame_init(&frame);
746     if (ret) {
747         mpp_err_f("mpp_frame_init failed\n");
748         return MPP_NOK;
749     }
750 
751     /* set frame size info */
752     test_mpp_frame_set_param(frame, p);
753 
754     /* set frame data include fd */
755     mpp_frame_set_buffer(frame, cam_buf);
756 
757     /* packet init */
758     mpp_packet_init_with_buffer(&packet, p->pkt_buf);
759     /* NOTE: It is important to clear output packet length!! */
760     mpp_packet_set_length(packet, 0);
761 
762     meta = mpp_frame_get_meta(frame);
763     mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet);
764 
765     /*
766      * NOTE: in non-block mode the frame can be resent.
767      * The default input timeout mode is block.
768      *
769      * User should release the input frame to meet the requirements of
770      * resource creator must be the resource destroyer.
771      */
772     ret = mpi->encode_put_frame(p->ctx, frame);
773     if (ret) {
774         mpp_err("mpp encode put frame failed\n");
775         mpp_frame_deinit(&frame);
776         if (cam_buf) {
777             mpp_buffer_put(cam_buf);
778         }
779         mpp_packet_deinit(&packet);
780         return ret;
781     }
782 
783     mpp_frame_deinit(&frame);
784 
785     packet_num = 0;
786 
787     do {
788         ret = mpi->encode_get_packet(p->ctx, &packet);
789         if (ret) {
790             mpp_err("mpp encode get packet failed\n");
791             if (cam_buf) {
792                 mpp_buffer_put(cam_buf);
793             }
794             mpp_packet_deinit(&packet);
795             return ret;
796         }
797 
798         mpp_assert(packet);
799 
800         if (packet) {
801             /* for low delay partition encoding */
802             if (mpp_packet_is_partition(packet)) {
803                 eoi = mpp_packet_is_eoi(packet);
804             }
805 
806             p->frame_count += eoi;
807             packet_num++;
808         }
809     } while (!eoi);
810 
811     void *ptr = mpp_packet_get_pos(packet);
812     size_t len = mpp_packet_get_length(packet);
813 
814     if (packet_num != 1) {
815         mpp_err("packet_num %u != 1\n");
816         ret = MPP_NOK;
817         if (cam_buf) {
818             mpp_buffer_put(cam_buf);
819         }
820         mpp_packet_deinit(&packet);
821         return ret;
822     }
823 
824     if (*buf_size < len) {
825         mpp_err("mpi buffer size too small\n");
826         ret = MPP_NOK;
827         if (cam_buf) {
828             mpp_buffer_put(cam_buf);
829         }
830         mpp_packet_deinit(&packet);
831         return ret;
832     }
833 
834     eok = memcpy_s(buf, len, ptr, len);
835     if (eok != EOK) {
836         mpp_err("memcpy_s failed\n");
837         return MPP_NOK;
838     }
839 
840     *buf_size = len;
841 
842     ret = MPP_OK;
843     if (cam_buf)
844         mpp_buffer_put(cam_buf);
845 
846     mpp_packet_deinit(&packet);
847     return ret;
848 }
849 
hal_mpp_ctx_create(MpiEncTestArgs *args)850 void *hal_mpp_ctx_create(MpiEncTestArgs *args)
851 {
852     MPP_RET ret = 0;
853     MpiEncTestData *p = NULL;
854     MppPollType timeout = MPP_POLL_BLOCK;
855 
856     /* ��ʼ��һ�³��õIJ������ã�cmd�����ñȽ϶� */
857     ret = test_ctx_init(&p, args);
858     if (ret) {
859         mpp_err_f("test data init failed ret %d\n", ret);
860         mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
861         return NULL;
862     }
863 
864     ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM);
865     if (ret) {
866         mpp_err_f("failed to get mpp buffer group ret %d\n", ret);
867         mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
868         return NULL;
869     }
870 
871     /* pkt_buf�����Ա���?���Ǹ�packetʹ�õ�buffer */
872     ret = mpp_buffer_get(p->buf_grp, &p->pkt_buf, p->frame_size);
873     if (ret) {
874         mpp_err_f("failed to get buffer for output packet ret %d\n", ret);
875         mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
876         return NULL;
877     }
878 
879     // encoder demo
880     ret = mpp_create(&p->ctx, &p->mpi);
881     if (ret) {
882         mpp_err("mpp_create failed ret %d\n", ret);
883         mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
884         return NULL;
885     }
886 
887     mpp_log("%p mpi_enc_test encoder test start w %d h %d type %d\n",
888             p->ctx, p->width, p->height, p->type);
889 
890     ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout);
891     if (MPP_OK != ret) {
892         mpp_err("mpi control set output timeout %d ret %d\n", timeout, ret);
893         mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
894         return NULL;
895     }
896 
897     ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type);
898     if (ret) {
899         mpp_err("mpp_init failed ret %d\n", ret);
900         mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
901         return NULL;
902     }
903 
904     ret = mpp_enc_cfg_init(&p->cfg);
905     if (ret) {
906         mpp_err_f("mpp_enc_cfg_init failed ret %d\n", ret);
907         mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
908         return NULL;
909     }
910 
911     ret = test_mpp_enc_cfg_setup(p);
912     if (ret) {
913         mpp_err_f("test mpp setup failed ret %d\n", ret);
914         mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
915         return NULL;
916     }
917 
918     return p;
919 }
920 
hal_mpp_ctx_delete(void *ctx)921 void hal_mpp_ctx_delete(void *ctx)
922 {
923     test_mpp_ctx_cleanup(ctx);
924 }
925