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