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