1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "mpi_enc_mt_test"
7
8 #include <string.h>
9 #include "rk_mpi.h"
10
11 #include "mpp_env.h"
12 #include "mpp_mem.h"
13 #include "mpp_time.h"
14 #include "mpp_list.h"
15 #include "mpp_lock.h"
16 #include "mpp_debug.h"
17 #include "mpp_common.h"
18
19 #include "utils.h"
20 #include "mpi_enc_utils.h"
21 #include "camera_source.h"
22 #include "mpp_enc_roi_utils.h"
23
24 #define BUF_COUNT 4
25
26 typedef struct {
27 // base flow context
28 MppCtx ctx;
29 MppApi *mpi;
30 RK_S32 chn;
31
32 // global flow control flag
33 RK_U32 frm_eos;
34 RK_U32 pkt_eos;
35 RK_U32 frm_pkt_cnt;
36 RK_S32 frame_num;
37 RK_S32 frm_cnt_in;
38 RK_S32 frm_cnt_out;
39 RK_S32 frm_step;
40 RK_U64 stream_size;
41 /* end of encoding flag when set quit the loop */
42 volatile RK_U32 loop_end;
43
44 // src and dst
45 FILE *fp_input;
46 FILE *fp_output;
47 FILE *fp_verify;
48
49 /* encoder config set */
50 MppEncCfg cfg;
51 MppEncPrepCfg prep_cfg;
52 MppEncRcCfg rc_cfg;
53 MppEncOSDPltCfg osd_plt_cfg;
54 MppEncOSDPlt osd_plt;
55 MppEncOSDData osd_data;
56 RoiRegionCfg roi_region;
57 MppEncROICfg roi_cfg;
58
59 // input / output
60 MppList *list_buf;
61 MppBufferGroup buf_grp;
62 MppBuffer frm_buf[BUF_COUNT];
63 MppBuffer pkt_buf[BUF_COUNT];
64 RK_S32 buf_idx;
65 MppEncSeiMode sei_mode;
66 MppEncHeaderMode header_mode;
67
68 // paramter for resource malloc
69 RK_U32 width;
70 RK_U32 height;
71 RK_U32 hor_stride;
72 RK_U32 ver_stride;
73 MppFrameFormat fmt;
74 MppCodingType type;
75 RK_S32 loop_times;
76 CamSource *cam_ctx;
77 MppEncRoiCtx roi_ctx;
78
79 // resources
80 size_t header_size;
81 size_t frame_size;
82 /* NOTE: packet buffer may overflow */
83 size_t packet_size;
84
85 RK_U32 osd_enable;
86 RK_U32 osd_mode;
87 RK_U32 split_mode;
88 RK_U32 split_arg;
89 RK_U32 split_out;
90
91 RK_U32 user_data_enable;
92 RK_U32 roi_enable;
93
94 // rate control runtime parameter
95 RK_S32 fps_in_flex;
96 RK_S32 fps_in_den;
97 RK_S32 fps_in_num;
98 RK_S32 fps_out_flex;
99 RK_S32 fps_out_den;
100 RK_S32 fps_out_num;
101 RK_S32 bps;
102 RK_S32 bps_max;
103 RK_S32 bps_min;
104 RK_S32 rc_mode;
105 RK_S32 gop_mode;
106 RK_S32 gop_len;
107 RK_S32 vi_len;
108
109 RK_S64 first_frm;
110 RK_S64 first_pkt;
111 RK_S64 last_pkt;
112 } MpiEncMtTestData;
113
114 /* For each instance thread return value */
115 typedef struct {
116 float frame_rate;
117 RK_U64 bit_rate;
118
119 RK_S64 time_start;
120 RK_S64 time_delay;
121 RK_S64 time_total;
122
123 RK_S64 elapsed_time;
124 RK_S32 frame_count;
125 RK_S64 stream_size;
126 RK_S64 delay;
127 } MpiEncMtCtxRet;
128
129 typedef struct {
130 MpiEncTestArgs *cmd; // pointer to global command line info
131 const char *name;
132 RK_S32 chn;
133
134 pthread_t thd_in; // thread for for frame input
135 pthread_t thd_out; // thread for for packet output
136
137 struct list_head frm_list;
138 spinlock_t frm_lock;
139
140 MpiEncMtTestData ctx; // context of encoder
141 MpiEncMtCtxRet ret; // return of encoder
142 } MpiEncMtCtxInfo;
143
mt_test_ctx_init(MpiEncMtCtxInfo * info)144 MPP_RET mt_test_ctx_init(MpiEncMtCtxInfo *info)
145 {
146 MpiEncTestArgs *cmd = info->cmd;
147 MpiEncMtTestData *p = &info->ctx;
148 MPP_RET ret = MPP_OK;
149
150 // get paramter from cmd
151 p->width = cmd->width;
152 p->height = cmd->height;
153 p->hor_stride = (cmd->hor_stride) ? (cmd->hor_stride) :
154 (MPP_ALIGN(cmd->width, 16));
155 p->ver_stride = (cmd->ver_stride) ? (cmd->ver_stride) :
156 (MPP_ALIGN(cmd->height, 16));
157 p->fmt = cmd->format;
158 p->type = cmd->type;
159 p->bps = cmd->bps_target;
160 p->bps_min = cmd->bps_min;
161 p->bps_max = cmd->bps_max;
162 p->rc_mode = cmd->rc_mode;
163 p->frame_num = cmd->frame_num;
164 if (cmd->type == MPP_VIDEO_CodingMJPEG && p->frame_num == 0) {
165 mpp_log("jpege default encode only one frame. Use -n [num] for rc case\n");
166 p->frame_num = 1;
167 }
168
169 p->frm_step = cmd->frm_step;
170 p->gop_mode = cmd->gop_mode;
171 p->gop_len = cmd->gop_len;
172 p->vi_len = cmd->vi_len;
173
174 p->fps_in_flex = cmd->fps_in_flex;
175 p->fps_in_den = cmd->fps_in_den;
176 p->fps_in_num = cmd->fps_in_num;
177 p->fps_out_flex = cmd->fps_out_flex;
178 p->fps_out_den = cmd->fps_out_den;
179 p->fps_out_num = cmd->fps_out_num;
180
181 if (cmd->file_input) {
182 if (!strncmp(cmd->file_input, "/dev/video", 10)) {
183 mpp_log("open camera device");
184 p->cam_ctx = camera_source_init(cmd->file_input, 4, p->width, p->height, p->fmt);
185 mpp_log("new framecap ok");
186 if (p->cam_ctx == NULL)
187 mpp_err("open %s fail", cmd->file_input);
188 } else {
189 p->fp_input = fopen(cmd->file_input, "rb");
190 if (NULL == p->fp_input) {
191 mpp_err("failed to open input file %s\n", cmd->file_input);
192 mpp_err("create default yuv image for test\n");
193 }
194 }
195 }
196
197 if (cmd->file_output) {
198 p->fp_output = fopen(cmd->file_output, "w+b");
199 if (NULL == p->fp_output) {
200 mpp_err("failed to open output file %s\n", cmd->file_output);
201 ret = MPP_ERR_OPEN_FILE;
202 }
203 }
204
205 if (cmd->file_slt) {
206 p->fp_verify = fopen(cmd->file_slt, "wt");
207 if (!p->fp_verify)
208 mpp_err("failed to open verify file %s\n", cmd->file_slt);
209 }
210
211 // update resource parameter
212 switch (p->fmt & MPP_FRAME_FMT_MASK) {
213 case MPP_FMT_YUV420SP:
214 case MPP_FMT_YUV420P: {
215 p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 3 / 2;
216 } break;
217
218 case MPP_FMT_YUV422_YUYV :
219 case MPP_FMT_YUV422_YVYU :
220 case MPP_FMT_YUV422_UYVY :
221 case MPP_FMT_YUV422_VYUY :
222 case MPP_FMT_YUV422P :
223 case MPP_FMT_YUV422SP : {
224 p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 2;
225 } break;
226 case MPP_FMT_YUV400 :
227 case MPP_FMT_RGB444 :
228 case MPP_FMT_BGR444 :
229 case MPP_FMT_RGB555 :
230 case MPP_FMT_BGR555 :
231 case MPP_FMT_RGB565 :
232 case MPP_FMT_BGR565 :
233 case MPP_FMT_RGB888 :
234 case MPP_FMT_BGR888 :
235 case MPP_FMT_RGB101010 :
236 case MPP_FMT_BGR101010 :
237 case MPP_FMT_ARGB8888 :
238 case MPP_FMT_ABGR8888 :
239 case MPP_FMT_BGRA8888 :
240 case MPP_FMT_RGBA8888 : {
241 p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64);
242 } break;
243
244 default: {
245 p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 4;
246 } break;
247 }
248
249 if (MPP_FRAME_FMT_IS_FBC(p->fmt))
250 p->header_size = MPP_ALIGN(MPP_ALIGN(p->width, 16) * MPP_ALIGN(p->height, 16) / 16, SZ_4K);
251 else
252 p->header_size = 0;
253
254 return ret;
255 }
256
mt_test_ctx_deinit(MpiEncMtCtxInfo * info)257 MPP_RET mt_test_ctx_deinit(MpiEncMtCtxInfo *info)
258 {
259 MpiEncMtTestData *p = NULL;
260
261 if (NULL == info)
262 return MPP_OK;
263
264 p = &info->ctx;
265
266 if (p->cam_ctx) {
267 camera_source_deinit(p->cam_ctx);
268 p->cam_ctx = NULL;
269 }
270 if (p->fp_input) {
271 fclose(p->fp_input);
272 p->fp_input = NULL;
273 }
274 if (p->fp_output) {
275 fclose(p->fp_output);
276 p->fp_output = NULL;
277 }
278 if (p->fp_verify) {
279 fclose(p->fp_verify);
280 p->fp_verify = NULL;
281 }
282
283 return MPP_OK;
284 }
285
test_mt_cfg_setup(MpiEncMtCtxInfo * info)286 MPP_RET test_mt_cfg_setup(MpiEncMtCtxInfo *info)
287 {
288 MpiEncTestArgs *cmd = info->cmd;
289 MpiEncMtTestData *p = &info->ctx;
290 MppApi *mpi = p->mpi;
291 MppCtx ctx = p->ctx;
292 MppEncCfg cfg = p->cfg;
293 RK_U32 gop_mode = p->gop_mode;
294 RK_U32 quiet = cmd->quiet;
295 MPP_RET ret;
296 MppEncRefCfg ref = NULL;
297
298 /* setup default parameter */
299 if (p->fps_in_den == 0)
300 p->fps_in_den = 1;
301 if (p->fps_in_num == 0)
302 p->fps_in_num = 30;
303 if (p->fps_out_den == 0)
304 p->fps_out_den = 1;
305 if (p->fps_out_num == 0)
306 p->fps_out_num = 30;
307
308 if (!p->bps)
309 p->bps = p->width * p->height / 8 * (p->fps_out_num / p->fps_out_den);
310
311 mpp_enc_cfg_set_s32(cfg, "codec:type", p->type);
312
313 mpp_enc_cfg_set_s32(cfg, "prep:width", p->width);
314 mpp_enc_cfg_set_s32(cfg, "prep:height", p->height);
315 mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", p->hor_stride);
316 mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", p->ver_stride);
317 mpp_enc_cfg_set_s32(cfg, "prep:format", p->fmt);
318
319 mpp_enc_cfg_set_s32(cfg, "rc:mode", p->rc_mode);
320
321 /* fix input / output frame rate */
322 mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", p->fps_in_flex);
323 mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", p->fps_in_num);
324 mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denom", p->fps_in_den);
325 mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", p->fps_out_flex);
326 mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", p->fps_out_num);
327 mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denom", p->fps_out_den);
328
329 /* drop frame or not when bitrate overflow */
330 mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED);
331 mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 20); /* 20% of max bps */
332 mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 1); /* Do not continuous drop frame */
333
334 /* setup bitrate for different rc_mode */
335 mpp_enc_cfg_set_s32(cfg, "rc:bps_target", p->bps);
336 switch (p->rc_mode) {
337 case MPP_ENC_RC_MODE_FIXQP : {
338 /* do not setup bitrate on FIXQP mode */
339 } break;
340 case MPP_ENC_RC_MODE_CBR : {
341 /* CBR mode has narrow bound */
342 mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
343 mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16);
344 } break;
345 case MPP_ENC_RC_MODE_VBR :
346 case MPP_ENC_RC_MODE_AVBR : {
347 /* VBR mode has wide bound */
348 mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
349 mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 1 / 16);
350 } break;
351 default : {
352 /* default use CBR mode */
353 mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16);
354 mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16);
355 } break;
356 }
357
358 /* setup qp for different codec and rc_mode */
359 switch (p->type) {
360 case MPP_VIDEO_CodingAVC :
361 case MPP_VIDEO_CodingHEVC : {
362 switch (p->rc_mode) {
363 case MPP_ENC_RC_MODE_FIXQP : {
364 RK_S32 fix_qp = cmd->qp_init;
365
366 mpp_enc_cfg_set_s32(cfg, "rc:qp_init", fix_qp);
367 mpp_enc_cfg_set_s32(cfg, "rc:qp_max", fix_qp);
368 mpp_enc_cfg_set_s32(cfg, "rc:qp_min", fix_qp);
369 mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", fix_qp);
370 mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", fix_qp);
371 mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 0);
372 } break;
373 case MPP_ENC_RC_MODE_CBR :
374 case MPP_ENC_RC_MODE_VBR :
375 case MPP_ENC_RC_MODE_AVBR : {
376 mpp_enc_cfg_set_s32(cfg, "rc:qp_init", cmd->qp_init ? cmd->qp_init : -1);
377 mpp_enc_cfg_set_s32(cfg, "rc:qp_max", cmd->qp_max ? cmd->qp_max : 51);
378 mpp_enc_cfg_set_s32(cfg, "rc:qp_min", cmd->qp_min ? cmd->qp_min : 10);
379 mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", cmd->qp_max_i ? cmd->qp_max_i : 51);
380 mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", cmd->qp_min_i ? cmd->qp_min_i : 10);
381 mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2);
382 } break;
383 default : {
384 mpp_err_f("unsupport encoder rc mode %d\n", p->rc_mode);
385 } break;
386 }
387 } break;
388 case MPP_VIDEO_CodingVP8 : {
389 /* vp8 only setup base qp range */
390 mpp_enc_cfg_set_s32(cfg, "rc:qp_init", cmd->qp_init ? cmd->qp_init : 40);
391 mpp_enc_cfg_set_s32(cfg, "rc:qp_max", cmd->qp_max ? cmd->qp_max : 127);
392 mpp_enc_cfg_set_s32(cfg, "rc:qp_min", cmd->qp_min ? cmd->qp_min : 0);
393 mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", cmd->qp_max_i ? cmd->qp_max_i : 127);
394 mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", cmd->qp_min_i ? cmd->qp_min_i : 0);
395 mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 6);
396 } break;
397 case MPP_VIDEO_CodingMJPEG : {
398 /* jpeg use special codec config to control qtable */
399 mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", cmd->qp_init ? cmd->qp_init : 80);
400 mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", cmd->qp_max ? cmd->qp_max : 99);
401 mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", cmd->qp_min ? cmd->qp_min : 1);
402 } break;
403 default : {
404 } break;
405 }
406
407 /* setup codec */
408 mpp_enc_cfg_set_s32(cfg, "codec:type", p->type);
409 switch (p->type) {
410 case MPP_VIDEO_CodingAVC : {
411 /*
412 * H.264 profile_idc parameter
413 * 66 - Baseline profile
414 * 77 - Main profile
415 * 100 - High profile
416 */
417 mpp_enc_cfg_set_s32(cfg, "h264:profile", 100);
418 /*
419 * H.264 level_idc parameter
420 * 10 / 11 / 12 / 13 - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps
421 * 20 / 21 / 22 - cif@30fps / half-D1@@25fps / D1@12.5fps
422 * 30 / 31 / 32 - D1@25fps / 720p@30fps / 720p@60fps
423 * 40 / 41 / 42 - 1080p@30fps / 1080p@30fps / 1080p@60fps
424 * 50 / 51 / 52 - 4K@30fps
425 */
426 mpp_enc_cfg_set_s32(cfg, "h264:level", 40);
427 mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1);
428 mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0);
429 mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1);
430 } break;
431 case MPP_VIDEO_CodingHEVC :
432 case MPP_VIDEO_CodingMJPEG :
433 case MPP_VIDEO_CodingVP8 : {
434 } break;
435 default : {
436 mpp_err_f("unsupport encoder coding type %d\n", p->type);
437 } break;
438 }
439
440 p->split_mode = 0;
441 p->split_arg = 0;
442 p->split_out = 0;
443
444 mpp_env_get_u32("split_mode", &p->split_mode, MPP_ENC_SPLIT_NONE);
445 mpp_env_get_u32("split_arg", &p->split_arg, 0);
446 mpp_env_get_u32("split_out", &p->split_out, 0);
447
448 if (p->split_mode) {
449 mpp_log_q(quiet, "%p split mode %d arg %d out %d\n", ctx,
450 p->split_mode, p->split_arg, p->split_out);
451 mpp_enc_cfg_set_s32(cfg, "split:mode", p->split_mode);
452 mpp_enc_cfg_set_s32(cfg, "split:arg", p->split_arg);
453 mpp_enc_cfg_set_s32(cfg, "split:out", p->split_out);
454 }
455
456 // config gop_len and ref cfg
457 mpp_enc_cfg_set_s32(cfg, "rc:gop", p->gop_len ? p->gop_len : p->fps_out_num * 2);
458
459 mpp_env_get_u32("gop_mode", &gop_mode, gop_mode);
460
461 if (gop_mode) {
462 mpp_enc_ref_cfg_init(&ref);
463
464 if (p->gop_mode < 4)
465 mpi_enc_gen_ref_cfg(ref, gop_mode);
466 else
467 mpi_enc_gen_smart_gop_ref_cfg(ref, p->gop_len, p->vi_len);
468
469 mpp_enc_cfg_set_ptr(cfg, "rc:ref_cfg", ref);
470 }
471
472 ret = mpi->control(ctx, MPP_ENC_SET_CFG, cfg);
473 if (ret) {
474 mpp_err("mpi control enc set cfg failed ret %d\n", ret);
475 goto RET;
476 }
477
478 if (ref)
479 mpp_enc_ref_cfg_deinit(&ref);
480
481 /* optional */
482 p->sei_mode = MPP_ENC_SEI_MODE_ONE_FRAME;
483 ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode);
484 if (ret) {
485 mpp_err("mpi control enc set sei cfg failed ret %d\n", ret);
486 goto RET;
487 }
488
489 if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) {
490 p->header_mode = MPP_ENC_HEADER_MODE_EACH_IDR;
491 ret = mpi->control(ctx, MPP_ENC_SET_HEADER_MODE, &p->header_mode);
492 if (ret) {
493 mpp_err("mpi control enc set header mode failed ret %d\n", ret);
494 goto RET;
495 }
496 }
497
498 /* setup test mode by env */
499 mpp_env_get_u32("osd_enable", &p->osd_enable, 0);
500 mpp_env_get_u32("osd_mode", &p->osd_mode, MPP_ENC_OSD_PLT_TYPE_DEFAULT);
501 mpp_env_get_u32("roi_enable", &p->roi_enable, 0);
502 mpp_env_get_u32("user_data_enable", &p->user_data_enable, 0);
503
504 if (p->roi_enable) {
505 mpp_enc_roi_init(&p->roi_ctx, p->width, p->height, p->type, 4);
506 mpp_assert(p->roi_ctx);
507 }
508
509 RET:
510 return ret;
511 }
512
mt_test_res_init(MpiEncMtCtxInfo * info)513 MPP_RET mt_test_res_init(MpiEncMtCtxInfo *info)
514 {
515 MpiEncTestArgs *cmd = info->cmd;
516 MpiEncMtTestData *p = &info->ctx;
517 MppPollType timeout = MPP_POLL_NON_BLOCK;
518 RK_U32 quiet = cmd->quiet;
519 MPP_RET ret = MPP_OK;
520 RK_S32 i;
521
522 mpp_log_q(quiet, "%s start\n", info->name);
523
524 p->list_buf = mpp_list_create(NULL);
525 if (NULL == p->list_buf) {
526 mpp_err_f("failed to get mpp buffer list\n");
527 return MPP_ERR_MALLOC;
528 }
529
530 ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM);
531 if (ret) {
532 mpp_err_f("failed to get mpp buffer group ret %d\n", ret);
533 return ret;
534 }
535
536 for (i = 0; i < BUF_COUNT; i++) {
537 ret = mpp_buffer_get(p->buf_grp, &p->frm_buf[i], p->frame_size + p->header_size);
538 if (ret) {
539 mpp_err_f("failed to get buffer for input frame ret %d\n", ret);
540 return ret;
541 }
542
543 ret = mpp_buffer_get(p->buf_grp, &p->pkt_buf[i], p->frame_size);
544 if (ret) {
545 mpp_err_f("failed to get buffer for output packet ret %d\n", ret);
546 return ret;
547 }
548
549 mpp_list_add_at_tail(p->list_buf, &p->frm_buf[i], sizeof(p->frm_buf[i]));
550 }
551
552 // encoder demo
553 ret = mpp_create(&p->ctx, &p->mpi);
554 if (ret) {
555 mpp_err("mpp_create failed ret %d\n", ret);
556 return ret;
557 }
558
559 mpp_log_q(quiet, "%p encoder test start w %d h %d type %d\n",
560 p->ctx, p->width, p->height, p->type);
561
562 ret = p->mpi->control(p->ctx, MPP_SET_INPUT_TIMEOUT, &timeout);
563 if (ret) {
564 mpp_err("mpi control set input timeout %d ret %d\n", timeout, ret);
565 return ret;
566 }
567
568 timeout = MPP_POLL_BLOCK;
569
570 ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout);
571 if (ret) {
572 mpp_err("mpi control set output timeout %d ret %d\n", timeout, ret);
573 return ret;
574 }
575
576 ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type);
577 if (ret) {
578 mpp_err("mpp_init failed ret %d\n", ret);
579 return ret;
580 }
581
582 ret = mpp_enc_cfg_init(&p->cfg);
583 if (ret) {
584 mpp_err_f("mpp_enc_cfg_init failed ret %d\n", ret);
585 return ret;
586 }
587
588 ret = p->mpi->control(p->ctx, MPP_ENC_GET_CFG, p->cfg);
589 if (ret) {
590 mpp_err_f("get enc cfg failed ret %d\n", ret);
591 return ret;
592 }
593
594 ret = test_mt_cfg_setup(info);
595 if (ret) {
596 mpp_err_f("test mpp setup failed ret %d\n", ret);
597 }
598
599 return ret;
600 }
601
mt_test_res_deinit(MpiEncMtCtxInfo * info)602 MPP_RET mt_test_res_deinit(MpiEncMtCtxInfo *info)
603 {
604 MpiEncMtTestData *p = &info->ctx;
605 MPP_RET ret = MPP_OK;
606 RK_S32 i;
607
608 p->mpi->reset(p->ctx);
609 if (ret) {
610 mpp_err("mpi->reset failed\n");
611 return ret;
612 }
613
614 if (p->ctx) {
615 mpp_destroy(p->ctx);
616 p->ctx = NULL;
617 }
618
619 if (p->cfg) {
620 mpp_enc_cfg_deinit(p->cfg);
621 p->cfg = NULL;
622 }
623
624 for (i = 0; i < BUF_COUNT; i++) {
625 if (p->frm_buf[i]) {
626 mpp_buffer_put(p->frm_buf[i]);
627 p->frm_buf[i] = NULL;
628 }
629
630 if (p->pkt_buf[i]) {
631 mpp_buffer_put(p->pkt_buf[i]);
632 p->pkt_buf[i] = NULL;
633 }
634 }
635
636 if (p->osd_data.buf) {
637 mpp_buffer_put(p->osd_data.buf);
638 p->osd_data.buf = NULL;
639 }
640
641 if (p->buf_grp) {
642 mpp_buffer_group_put(p->buf_grp);
643 p->buf_grp = NULL;
644 }
645
646 if (p->list_buf) {
647 mpp_list_destroy(p->list_buf);
648 p->list_buf = NULL;
649 }
650
651 if (p->roi_ctx) {
652 mpp_enc_roi_deinit(p->roi_ctx);
653 p->roi_ctx = NULL;
654 }
655
656 return MPP_OK;
657 }
658
enc_test_input(void * arg)659 void *enc_test_input(void *arg)
660 {
661 MpiEncMtCtxInfo *info = (MpiEncMtCtxInfo *)arg;
662 MpiEncTestArgs *cmd = info->cmd;
663 MpiEncMtTestData *p = &info->ctx;
664 RK_S32 chn = info->chn;
665 MppApi *mpi = p->mpi;
666 MppCtx ctx = p->ctx;
667 MppList *list_buf = p->list_buf;
668 RK_U32 cap_num = 0;
669 RK_U32 quiet = cmd->quiet;
670 MPP_RET ret = MPP_OK;
671
672 mpp_log_q(quiet, "%s start\n", info->name);
673
674 while (1) {
675 MppMeta meta = NULL;
676 MppFrame frame = NULL;
677 MppBuffer buffer = NULL;
678 void *buf = NULL;
679 RK_S32 cam_frm_idx = -1;
680 MppBuffer cam_buf = NULL;
681
682 mpp_mutex_cond_lock(&list_buf->cond_lock);
683 if (!mpp_list_size(list_buf))
684 mpp_list_wait(list_buf);
685
686 buffer = NULL;
687 mpp_list_del_at_head(list_buf, &buffer, sizeof(buffer));
688 if (NULL == buffer) {
689 mpp_mutex_cond_unlock(&list_buf->cond_lock);
690 continue;
691 }
692
693 buf = mpp_buffer_get_ptr(buffer);
694 mpp_mutex_cond_unlock(&list_buf->cond_lock);
695
696 if (p->fp_input) {
697 ret = read_image((RK_U8 *)buf, p->fp_input, p->width, p->height,
698 p->hor_stride, p->ver_stride, p->fmt);
699 if (ret == MPP_NOK || feof(p->fp_input)) {
700 p->frm_eos = 1;
701
702 if (p->frame_num < 0 || p->frm_cnt_in < p->frame_num) {
703 clearerr(p->fp_input);
704 rewind(p->fp_input);
705 p->frm_eos = 0;
706 mpp_log_q(quiet, "chn %d loop times %d\n", chn, ++p->loop_times);
707 if (buffer) {
708 mpp_mutex_cond_lock(&list_buf->cond_lock);
709 mpp_list_add_at_tail(list_buf, &buffer, sizeof(buffer));
710 mpp_mutex_cond_unlock(&list_buf->cond_lock);
711 }
712 continue;
713 }
714 mpp_log_q(quiet, "chn %d found last frame. feof %d\n", chn, feof(p->fp_input));
715 } else if (ret == MPP_ERR_VALUE)
716 break;
717 } else {
718 if (p->cam_ctx == NULL) {
719 ret = fill_image((RK_U8 *)buf, p->width, p->height, p->hor_stride,
720 p->ver_stride, p->fmt, p->frm_cnt_in * p->frm_step);
721 if (ret)
722 break;
723 } else {
724 cam_frm_idx = camera_source_get_frame(p->cam_ctx);
725 mpp_assert(cam_frm_idx >= 0);
726
727 /* skip unstable frames */
728 if (cap_num++ < 50) {
729 camera_source_put_frame(p->cam_ctx, cam_frm_idx);
730 continue;
731 }
732
733 cam_buf = camera_frame_to_buf(p->cam_ctx, cam_frm_idx);
734 mpp_assert(cam_buf);
735 }
736 }
737
738 ret = mpp_frame_init(&frame);
739 if (ret) {
740 mpp_err_f("mpp_frame_init failed\n");
741 break;
742 }
743
744 mpp_frame_set_width(frame, p->width);
745 mpp_frame_set_height(frame, p->height);
746 mpp_frame_set_hor_stride(frame, p->hor_stride);
747 mpp_frame_set_ver_stride(frame, p->ver_stride);
748 mpp_frame_set_fmt(frame, p->fmt);
749 mpp_frame_set_eos(frame, p->frm_eos);
750
751 if (p->fp_input && feof(p->fp_input))
752 mpp_frame_set_buffer(frame, NULL);
753 else if (cam_buf)
754 mpp_frame_set_buffer(frame, cam_buf);
755 else
756 mpp_frame_set_buffer(frame, buffer);
757
758 meta = mpp_frame_get_meta(frame);
759
760 if (p->osd_enable || p->user_data_enable || p->roi_enable) {
761 if (p->user_data_enable) {
762 MppEncUserData user_data;
763 const char *str = "this is user data\n";
764
765 if ((p->frm_cnt_in & 10) == 0) {
766 user_data.pdata = (void *)str;
767 user_data.len = strlen(str) + 1;
768 mpp_meta_set_ptr(meta, KEY_USER_DATA, &user_data);
769 }
770 static RK_U8 uuid_debug_info[16] = {
771 0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65,
772 0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a
773 };
774
775 MppEncUserDataSet data_group;
776 MppEncUserDataFull datas[2];
777 const char *str1 = "this is user data 1\n";
778 const char *str2 = "this is user data 2\n";
779 data_group.count = 2;
780 datas[0].len = strlen(str1) + 1;
781 datas[0].pdata = (void *)str1;
782 datas[0].uuid = uuid_debug_info;
783
784 datas[1].len = strlen(str2) + 1;
785 datas[1].pdata = (void *)str2;
786 datas[1].uuid = uuid_debug_info;
787
788 data_group.datas = datas;
789
790 mpp_meta_set_ptr(meta, KEY_USER_DATAS, &data_group);
791 }
792
793 if (p->osd_enable) {
794 /* gen and cfg osd plt */
795 mpi_enc_gen_osd_plt(&p->osd_plt, p->frm_cnt_in);
796
797 p->osd_plt_cfg.change = MPP_ENC_OSD_PLT_CFG_CHANGE_ALL;
798 p->osd_plt_cfg.type = MPP_ENC_OSD_PLT_TYPE_USERDEF;
799 p->osd_plt_cfg.plt = &p->osd_plt;
800
801 ret = mpi->control(ctx, MPP_ENC_SET_OSD_PLT_CFG, &p->osd_plt_cfg);
802 if (ret) {
803 mpp_err("mpi control enc set osd plt failed ret %d\n", ret);
804 break;
805 }
806
807 /* gen and cfg osd plt */
808 mpi_enc_gen_osd_data(&p->osd_data, p->buf_grp, p->width,
809 p->height, p->frm_cnt_in);
810 mpp_meta_set_ptr(meta, KEY_OSD_DATA, (void*)&p->osd_data);
811 }
812
813 if (p->roi_enable) {
814 RoiRegionCfg *region = &p->roi_region;
815
816 /* calculated in pixels */
817 region->x = MPP_ALIGN(p->width / 8, 16);
818 region->y = MPP_ALIGN(p->height / 8, 16);
819 region->w = 128;
820 region->h = 256;
821 region->force_intra = 0;
822 region->qp_mode = 1;
823 region->qp_val = 24;
824
825 mpp_enc_roi_add_region(p->roi_ctx, region);
826
827 region->x = MPP_ALIGN(p->width / 2, 16);
828 region->y = MPP_ALIGN(p->height / 4, 16);
829 region->w = 256;
830 region->h = 128;
831 region->force_intra = 1;
832 region->qp_mode = 1;
833 region->qp_val = 10;
834
835 mpp_enc_roi_add_region(p->roi_ctx, region);
836
837 /* send roi info by metadata */
838 mpp_enc_roi_setup_meta(p->roi_ctx, meta);
839 }
840 }
841
842 if (!p->first_frm)
843 p->first_frm = mpp_time();
844 /*
845 * NOTE: in non-block mode the frame can be resent.
846 * The default input timeout mode is block.
847 *
848 * User should release the input frame to meet the requirements of
849 * resource creator must be the resource destroyer.
850 */
851 p->frm_cnt_in++;
852 do {
853 ret = mpi->encode_put_frame(ctx, frame);
854 if (ret)
855 msleep(1);
856 } while (ret);
857
858 if (cam_frm_idx >= 0)
859 camera_source_put_frame(p->cam_ctx, cam_frm_idx);
860
861 if (p->frame_num > 0 && p->frm_cnt_in >= p->frame_num) {
862 p->frm_eos = 1;
863 break;
864 }
865
866 if (p->loop_end) {
867 p->frm_eos = 1;
868 break;
869 }
870
871 if (p->frm_eos)
872 break;
873 }
874
875 return NULL;
876 }
877
enc_test_output(void * arg)878 void *enc_test_output(void *arg)
879 {
880 MpiEncMtCtxInfo *info = (MpiEncMtCtxInfo *)arg;
881 MpiEncTestArgs *cmd = info->cmd;
882 MpiEncMtTestData *p = &info->ctx;
883 MpiEncMtCtxRet *enc_ret = &info->ret;
884 MppList *list_buf = p->list_buf;
885 RK_S32 chn = info->chn;
886 MppApi *mpi = p->mpi;
887 MppCtx ctx = p->ctx;
888 RK_U32 quiet = cmd->quiet;
889 MPP_RET ret = MPP_OK;
890 MppPacket packet = NULL;
891 RK_U32 eoi = 1;
892
893 void *ptr;
894 size_t len;
895 char log_buf[256];
896 RK_S32 log_size = sizeof(log_buf) - 1;
897 RK_S32 log_len = 0;
898
899 while (1) {
900 ret = mpi->encode_get_packet(ctx, &packet);
901 if (ret || NULL == packet) {
902 msleep(1);
903 continue;
904 }
905
906 p->last_pkt = mpp_time();
907
908 // write packet to file here
909 ptr = mpp_packet_get_pos(packet);
910 len = mpp_packet_get_length(packet);
911 log_size = sizeof(log_buf) - 1;
912 log_len = 0;
913
914 if (!p->first_pkt)
915 p->first_pkt = mpp_time();
916
917 p->pkt_eos = mpp_packet_get_eos(packet);
918
919 if (p->fp_output)
920 fwrite(ptr, 1, len, p->fp_output);
921
922 log_len += snprintf(log_buf + log_len, log_size - log_len,
923 "encoded frame %-4d", p->frm_cnt_out);
924
925 /* for low delay partition encoding */
926 if (mpp_packet_is_partition(packet)) {
927 eoi = mpp_packet_is_eoi(packet);
928
929 log_len += snprintf(log_buf + log_len, log_size - log_len,
930 " pkt %d", p->frm_pkt_cnt);
931 p->frm_pkt_cnt = (eoi) ? (0) : (p->frm_pkt_cnt + 1);
932 }
933
934 log_len += snprintf(log_buf + log_len, log_size - log_len,
935 " size %-7zu", len);
936
937 if (mpp_packet_has_meta(packet)) {
938 MppMeta meta = mpp_packet_get_meta(packet);
939 MppFrame frm = NULL;
940 RK_S32 temporal_id = 0;
941 RK_S32 lt_idx = -1;
942 RK_S32 avg_qp = -1;
943
944 if (MPP_OK == mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id))
945 log_len += snprintf(log_buf + log_len, log_size - log_len,
946 " tid %d", temporal_id);
947
948 if (MPP_OK == mpp_meta_get_s32(meta, KEY_LONG_REF_IDX, <_idx))
949 log_len += snprintf(log_buf + log_len, log_size - log_len,
950 " lt %d", lt_idx);
951
952 if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_AVERAGE_QP, &avg_qp))
953 log_len += snprintf(log_buf + log_len, log_size - log_len,
954 " qp %d", avg_qp);
955
956 if (MPP_OK == mpp_meta_get_frame(meta, KEY_INPUT_FRAME, &frm)) {
957 MppBuffer frm_buf = NULL;
958
959 mpp_assert(frm);
960 frm_buf = mpp_frame_get_buffer(frm);
961
962 if (frm_buf) {
963 mpp_mutex_cond_lock(&list_buf->cond_lock);
964 mpp_list_add_at_tail(list_buf, &frm_buf, sizeof(frm_buf));
965 mpp_list_signal(list_buf);
966 mpp_mutex_cond_unlock(&list_buf->cond_lock);
967 }
968
969 mpp_frame_deinit(&frm);
970 }
971 }
972
973 mpp_log_q(quiet, "chn %d %s\n", chn, log_buf);
974
975 mpp_packet_deinit(&packet);
976 fps_calc_inc(cmd->fps);
977
978 p->stream_size += len;
979 p->frm_cnt_out += eoi;
980
981 if (p->frm_cnt_out != p->frm_cnt_in)
982 continue;
983
984 if (p->frame_num > 0 && p->frm_cnt_out >= p->frame_num) {
985 p->pkt_eos = 1;
986 break;
987 }
988
989 if (p->frm_eos) {
990 p->pkt_eos = 1;
991 break;
992 }
993
994 if (p->pkt_eos) {
995 mpp_log_q(quiet, "chn %d found last packet\n", chn);
996 mpp_assert(p->frm_eos);
997 break;
998 }
999 } while (!eoi);
1000
1001 enc_ret->elapsed_time = p->last_pkt - p->first_frm;
1002 enc_ret->frame_count = p->frm_cnt_out;
1003 enc_ret->stream_size = p->stream_size;
1004 enc_ret->frame_rate = (float)p->frm_cnt_out * 1000000 / enc_ret->elapsed_time;
1005 enc_ret->bit_rate = (p->stream_size * 8 * (p->fps_out_num / p->fps_out_den)) / p->frm_cnt_out;
1006 enc_ret->delay = p->first_pkt - p->first_frm;
1007
1008 return NULL;
1009 }
1010
enc_test_mt(MpiEncTestArgs * cmd,const char * name)1011 int enc_test_mt(MpiEncTestArgs* cmd, const char *name)
1012 {
1013 MpiEncMtCtxInfo *ctxs = NULL;
1014 float total_rate = 0.0;
1015 RK_S32 ret = MPP_NOK;
1016 RK_S32 i = 0;
1017
1018 ctxs = mpp_calloc(MpiEncMtCtxInfo, cmd->nthreads);
1019 if (NULL == ctxs) {
1020 mpp_err("failed to alloc context for instances\n");
1021 return -1;
1022 }
1023
1024 for (i = 0; i < cmd->nthreads; i++) {
1025 ctxs[i].cmd = cmd;
1026 ctxs[i].name = name;
1027 ctxs[i].chn = i;
1028
1029 ret = mt_test_ctx_init(&ctxs[i]);
1030 if (ret) {
1031 mpp_err_f("test ctx init failed ret %d\n", ret);
1032 return ret;
1033 }
1034
1035 ret = mt_test_res_init(&ctxs[i]);
1036 if (ret) {
1037 mpp_err_f("test resource deinit failed ret %d\n", ret);
1038 return ret;
1039 }
1040
1041 ret = pthread_create(&ctxs[i].thd_out, NULL, enc_test_output, &ctxs[i]);
1042 if (ret) {
1043 mpp_err("failed to create thread %d\n", i);
1044 return ret;
1045 }
1046
1047 ret = pthread_create(&ctxs[i].thd_in, NULL, enc_test_input, &ctxs[i]);
1048 if (ret) {
1049 mpp_err("failed to create thread %d\n", i);
1050 return ret;
1051 }
1052 }
1053
1054
1055 if (cmd->frame_num < 0) {
1056 // wait for input then quit encoding
1057 mpp_log("*******************************************\n");
1058 mpp_log("**** Press Enter to stop loop encoding ****\n");
1059 mpp_log("*******************************************\n");
1060
1061 getc(stdin);
1062 mpp_log_f("loop_end start");
1063 for (i = 0; i < cmd->nthreads; i++)
1064 ctxs[i].ctx.loop_end = 1;
1065 }
1066
1067 for (i = 0; i < cmd->nthreads; i++) {
1068 pthread_join(ctxs[i].thd_in, NULL);
1069 pthread_join(ctxs[i].thd_out, NULL);
1070
1071 ret = mt_test_res_deinit(&ctxs[i]);
1072 if (ret) {
1073 mpp_err_f("test resource deinit failed ret %d\n", ret);
1074 return ret;
1075 }
1076
1077 ret = mt_test_ctx_deinit(&ctxs[i]);
1078 if (ret) {
1079 mpp_err_f("test ctx deinit failed ret %d\n", ret);
1080 return ret;
1081 }
1082 }
1083
1084 for (i = 0; i < cmd->nthreads; i++) {
1085 MpiEncMtCtxRet *enc_ret = &ctxs[i].ret;
1086
1087 mpp_log("chn %d encode %d frames time %lld ms delay %3d ms fps %3.2f bps %lld\n",
1088 i, enc_ret->frame_count, (RK_S64)(enc_ret->elapsed_time / 1000),
1089 (RK_S32)(enc_ret->delay / 1000), enc_ret->frame_rate, enc_ret->bit_rate);
1090
1091 total_rate += enc_ret->frame_rate;
1092 }
1093
1094 MPP_FREE(ctxs);
1095
1096 total_rate /= cmd->nthreads;
1097 mpp_log("%s average frame rate %.2f\n", name, total_rate);
1098
1099 return ret;
1100 }
1101
main(int argc,char ** argv)1102 int main(int argc, char **argv)
1103 {
1104 RK_S32 ret = MPP_NOK;
1105 MpiEncTestArgs* cmd = mpi_enc_test_cmd_get();
1106
1107 // parse the cmd option
1108 ret = mpi_enc_test_cmd_update_by_args(cmd, argc, argv);
1109 if (ret)
1110 goto DONE;
1111
1112 mpi_enc_test_cmd_show_opt(cmd);
1113
1114 ret = enc_test_mt(cmd, argv[0]);
1115
1116 DONE:
1117 mpi_enc_test_cmd_put(cmd);
1118
1119 return ret;
1120 }
1121