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