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