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