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_utils"
18
19 #include <string.h>
20
21 #include "mpp_mem.h"
22 #include "mpp_debug.h"
23 #include "mpp_buffer.h"
24
25 #include "rk_mpi.h"
26 #include "utils.h"
27 #include "mpp_common.h"
28
29 #include "mpp_opt.h"
30 #include "mpi_enc_utils.h"
31
32 #define MAX_FILE_NAME_LENGTH 256
33
mpi_enc_width_default_stride(RK_S32 width,MppFrameFormat fmt)34 RK_S32 mpi_enc_width_default_stride(RK_S32 width, MppFrameFormat fmt)
35 {
36 RK_S32 stride = 0;
37
38 switch (fmt & MPP_FRAME_FMT_MASK) {
39 case MPP_FMT_YUV420SP :
40 case MPP_FMT_YUV420SP_VU : {
41 stride = MPP_ALIGN(width, 8);
42 } break;
43 case MPP_FMT_YUV420P : {
44 /* NOTE: 420P need to align to 16 so chroma can align to 8 */
45 stride = MPP_ALIGN(width, 16);
46 } break;
47 case MPP_FMT_YUV422P:
48 case MPP_FMT_YUV422SP:
49 case MPP_FMT_YUV422SP_VU: {
50 /* NOTE: 422 need to align to 8 so chroma can align to 16 */
51 stride = MPP_ALIGN(width, 8);
52 } break;
53 case MPP_FMT_YUV444SP :
54 case MPP_FMT_YUV444P : {
55 stride = MPP_ALIGN(width, 8);
56 } break;
57 case MPP_FMT_RGB565:
58 case MPP_FMT_BGR565:
59 case MPP_FMT_RGB555:
60 case MPP_FMT_BGR555:
61 case MPP_FMT_RGB444:
62 case MPP_FMT_BGR444:
63 case MPP_FMT_YUV422_YUYV :
64 case MPP_FMT_YUV422_YVYU :
65 case MPP_FMT_YUV422_UYVY :
66 case MPP_FMT_YUV422_VYUY : {
67 /* NOTE: for vepu limitation */
68 stride = MPP_ALIGN(width, 8) * 2;
69 } break;
70 case MPP_FMT_RGB888 :
71 case MPP_FMT_BGR888 : {
72 /* NOTE: for vepu limitation */
73 stride = MPP_ALIGN(width, 8) * 3;
74 } break;
75 case MPP_FMT_RGB101010 :
76 case MPP_FMT_BGR101010 :
77 case MPP_FMT_ARGB8888 :
78 case MPP_FMT_ABGR8888 :
79 case MPP_FMT_BGRA8888 :
80 case MPP_FMT_RGBA8888 : {
81 /* NOTE: for vepu limitation */
82 stride = MPP_ALIGN(width, 8) * 4;
83 } break;
84 default : {
85 mpp_err_f("do not support type %d\n", fmt);
86 } break;
87 }
88
89 return stride;
90 }
91
mpi_enc_test_cmd_get(void)92 MpiEncTestArgs *mpi_enc_test_cmd_get(void)
93 {
94 MpiEncTestArgs *args = mpp_calloc(MpiEncTestArgs, 1);
95
96 if (args)
97 args->nthreads = 1;
98
99 return args;
100 }
101
mpi_enc_opt_i(void * ctx,const char * next)102 RK_S32 mpi_enc_opt_i(void *ctx, const char *next)
103 {
104 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
105
106 if (next) {
107 size_t len = strnlen(next, MAX_FILE_NAME_LENGTH);
108 if (len) {
109 cmd->file_input = mpp_calloc(char, len + 1);
110 strcpy(cmd->file_input, next);
111 name_to_frame_format(cmd->file_input, &cmd->format);
112
113 if (cmd->type_src == MPP_VIDEO_CodingUnused)
114 name_to_coding_type(cmd->file_input, &cmd->type_src);
115 }
116
117 return 1;
118 }
119
120 mpp_err("input file is invalid\n");
121 return 0;
122 }
123
mpi_enc_opt_o(void * ctx,const char * next)124 RK_S32 mpi_enc_opt_o(void *ctx, const char *next)
125 {
126 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
127
128 if (next) {
129 size_t len = strnlen(next, MAX_FILE_NAME_LENGTH);
130 if (len) {
131 cmd->file_output = mpp_calloc(char, len + 1);
132 strcpy(cmd->file_output, next);
133 name_to_coding_type(cmd->file_output, &cmd->type);
134 }
135
136 return 1;
137 }
138
139 mpp_log("output file is invalid\n");
140 return 0;
141 }
142
mpi_enc_opt_w(void * ctx,const char * next)143 RK_S32 mpi_enc_opt_w(void *ctx, const char *next)
144 {
145 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
146
147 if (next) {
148 cmd->width = atoi(next);
149 return 1;
150 }
151
152 mpp_err("invalid input width\n");
153 return 0;
154 }
155
mpi_enc_opt_h(void * ctx,const char * next)156 RK_S32 mpi_enc_opt_h(void *ctx, const char *next)
157 {
158 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
159
160 if (next) {
161 cmd->height = atoi(next);
162 return 1;
163 }
164
165 mpp_err("invalid input height\n");
166 return 0;
167 }
168
mpi_enc_opt_hstride(void * ctx,const char * next)169 RK_S32 mpi_enc_opt_hstride(void *ctx, const char *next)
170 {
171 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
172
173 if (next) {
174 cmd->hor_stride = atoi(next);
175 return 1;
176 }
177
178 mpp_err("invalid input horizontal stride\n");
179 return 0;
180 }
181
mpi_enc_opt_vstride(void * ctx,const char * next)182 RK_S32 mpi_enc_opt_vstride(void *ctx, const char *next)
183 {
184 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
185
186 if (next) {
187 cmd->ver_stride = atoi(next);
188 return 1;
189 }
190
191 mpp_err("invalid input vertical stride\n");
192 return 0;
193 }
194
mpi_enc_opt_f(void * ctx,const char * next)195 RK_S32 mpi_enc_opt_f(void *ctx, const char *next)
196 {
197 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
198 MppFrameFormat format = MPP_FMT_BUTT;
199
200 if (next) {
201 if (strstr(next, "x") || strstr(next, "X")) {
202 /* hex value with 0x prefix, use sscanf */
203 sscanf(next, "0x%x", &format);
204 } else if (strstr(next, "a") || strstr(next, "A") ||
205 strstr(next, "b") || strstr(next, "B") ||
206 strstr(next, "c") || strstr(next, "C") ||
207 strstr(next, "d") || strstr(next, "D") ||
208 strstr(next, "e") || strstr(next, "E") ||
209 strstr(next, "f") || strstr(next, "F")) {
210 /* hex value without 0x prefix, use sscanf */
211 sscanf(next, "%x", &format);
212 } else {
213 /* decimal value, use atoi */
214 format = (MppFrameFormat)atoi(next);
215 }
216 if (MPP_FRAME_FMT_IS_BE(format) &&
217 (MPP_FRAME_FMT_IS_YUV(format) || MPP_FRAME_FMT_IS_RGB(format))) {
218 cmd->format = format;
219 return 1;
220 }
221 }
222
223 mpp_err("invalid input format %x\n", format);
224 cmd->format = MPP_FMT_YUV420SP;
225 return 0;
226 }
227
mpi_enc_opt_t(void * ctx,const char * next)228 RK_S32 mpi_enc_opt_t(void *ctx, const char *next)
229 {
230 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
231 MppCodingType type = MPP_VIDEO_CodingUnused;
232
233 if (next) {
234 type = (MppCodingType)atoi(next);
235 if (!mpp_check_support_format(MPP_CTX_ENC, type))
236 cmd->type = type;
237 return 1;
238 }
239
240 mpp_err("invalid input coding type %d\n", type);
241 return 0;
242 }
243
mpi_enc_opt_tsrc(void * ctx,const char * next)244 RK_S32 mpi_enc_opt_tsrc(void *ctx, const char *next)
245 {
246 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
247 MppCodingType type = MPP_VIDEO_CodingUnused;
248
249 if (next) {
250 type = (MppCodingType)atoi(next);
251 if (!mpp_check_support_format(MPP_CTX_DEC, type))
252 cmd->type_src = type;
253 return 1;
254 }
255
256 mpp_err("invalid input coding type %d\n", type);
257 return 0;
258 }
259
260
mpi_enc_opt_n(void * ctx,const char * next)261 RK_S32 mpi_enc_opt_n(void *ctx, const char *next)
262 {
263 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
264
265 if (next) {
266 cmd->frame_num = atoi(next);
267 return 1;
268 }
269
270 mpp_err("invalid input max number of frames\n");
271 return 0;
272 }
273
mpi_enc_opt_g(void * ctx,const char * next)274 RK_S32 mpi_enc_opt_g(void *ctx, const char *next)
275 {
276 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
277 RK_S32 cnt = 0;
278
279 if (next) {
280 cnt = sscanf(next, "%d:%d:%d",
281 &cmd->gop_mode, &cmd->gop_len, &cmd->vi_len);
282 if (cnt)
283 return 1;
284 }
285
286 mpp_err("invalid gop mode use -g gop_mode:gop_len:vi_len\n");
287 return 0;
288 }
289
mpi_enc_opt_rc(void * ctx,const char * next)290 RK_S32 mpi_enc_opt_rc(void *ctx, const char *next)
291 {
292 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
293 RK_S32 cnt = 0;
294
295 if (next) {
296 cnt = sscanf(next, "%d", &cmd->rc_mode);
297 if (cnt)
298 return 1;
299 }
300
301 mpp_err("invalid rate control usage -rc rc_mode\n");
302 mpp_err("rc_mode 0:vbr 1:cbr 2:avbr 3:cvbr 4:fixqp\n");
303 return 0;
304 }
305
mpi_enc_opt_bps(void * ctx,const char * next)306 RK_S32 mpi_enc_opt_bps(void *ctx, const char *next)
307 {
308 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
309 RK_S32 cnt = 0;
310
311 if (next) {
312 cnt = sscanf(next, "%d:%d:%d",
313 &cmd->bps_target, &cmd->bps_min, &cmd->bps_max);
314 if (cnt)
315 return 1;
316 }
317
318 mpp_err("invalid bit rate usage -bps bps_target:bps_min:bps_max\n");
319 return 0;
320 }
321
mpi_enc_opt_fps(void * ctx,const char * next)322 RK_S32 mpi_enc_opt_fps(void *ctx, const char *next)
323 {
324 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
325
326 if (next) {
327 RK_U32 num = sscanf(next, "%d:%d:%d/%d:%d:%d",
328 &cmd->fps_in_num, &cmd->fps_in_den, &cmd->fps_in_flex,
329 &cmd->fps_out_num, &cmd->fps_out_den, &cmd->fps_out_flex);
330 switch (num) {
331 case 1 : {
332 cmd->fps_out_num = cmd->fps_in_num;
333 cmd->fps_out_den = cmd->fps_in_den = 1;
334 cmd->fps_out_flex = cmd->fps_in_flex = 0;
335 } break;
336 case 2 : {
337 cmd->fps_out_num = cmd->fps_in_num;
338 cmd->fps_out_den = cmd->fps_in_den;
339 cmd->fps_out_flex = cmd->fps_in_flex = 0;
340 } break;
341 case 3 : {
342 cmd->fps_out_num = cmd->fps_in_num;
343 cmd->fps_out_den = cmd->fps_in_den;
344 cmd->fps_out_flex = cmd->fps_in_flex;
345 } break;
346 case 4 : {
347 cmd->fps_out_den = 1;
348 cmd->fps_out_flex = 0;
349 } break;
350 case 5 : {
351 cmd->fps_out_flex = 0;
352 } break;
353 case 6 : {
354 } break;
355 default : {
356 mpp_err("invalid in/out frame rate,"
357 " use \"-fps numerator:denominator:flex\""
358 " for set the input to the same fps as the output, such as 50:1:1\n"
359 " or \"-fps numerator:denominator:flex/numerator:denominator:flex\""
360 " for set input and output separately, such as 40:1:1/30:1:0\n");
361 } break;
362 }
363
364 return (num && num <= 6);
365 }
366
367 mpp_err("invalid output frame rate\n");
368 return 0;
369 }
370
mpi_enc_opt_qc(void * ctx,const char * next)371 RK_S32 mpi_enc_opt_qc(void *ctx, const char *next)
372 {
373 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
374 RK_S32 cnt = 0;
375
376 if (next) {
377 cnt = sscanf(next, "%d:%d:%d:%d:%d", &cmd->qp_init,
378 &cmd->qp_min, &cmd->qp_max, &cmd->qp_min_i, &cmd->qp_max_i);
379 if (cnt)
380 return 1;
381 }
382
383 mpp_err("invalid quality control usage -qc qp_init:min:max:min_i:max_i\n");
384 return 0;
385 }
386
mpi_enc_opt_s(void * ctx,const char * next)387 RK_S32 mpi_enc_opt_s(void *ctx, const char *next)
388 {
389 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
390
391 cmd->nthreads = -1;
392 if (next) {
393 cmd->nthreads = atoi(next);
394 if (cmd->nthreads >= 1)
395 return 1;
396 }
397
398 mpp_err("invalid nthreads %d\n", cmd->nthreads);
399 cmd->nthreads = 1;
400 return 0;
401 }
402
mpi_enc_opt_l(void * ctx,const char * next)403 RK_S32 mpi_enc_opt_l(void *ctx, const char *next)
404 {
405 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
406
407 if (next) {
408 cmd->loop_cnt = atoi(next);
409 return 1;
410 }
411
412 mpp_err("invalid loop count\n");
413 return 0;
414 }
415
mpi_enc_opt_v(void * ctx,const char * next)416 RK_S32 mpi_enc_opt_v(void *ctx, const char *next)
417 {
418 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
419
420 if (next) {
421 if (strstr(next, "q"))
422 cmd->quiet = 1;
423 if (strstr(next, "f"))
424 cmd->trace_fps = 1;
425
426 return 1;
427 }
428
429 return 0;
430 }
431
mpi_enc_opt_ini(void * ctx,const char * next)432 RK_S32 mpi_enc_opt_ini(void *ctx, const char *next)
433 {
434 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
435
436 if (next) {
437 size_t len = strnlen(next, MAX_FILE_NAME_LENGTH);
438 if (len) {
439 cmd->file_cfg = mpp_calloc(char, len + 1);
440 strncpy(cmd->file_cfg, next, len);
441 cmd->cfg_ini = iniparser_load(cmd->file_cfg);
442
443 return 1;
444 }
445 }
446
447 mpp_err("input ini file is invalid\n");
448 return 0;
449 }
450
mpi_enc_opt_slt(void * ctx,const char * next)451 RK_S32 mpi_enc_opt_slt(void *ctx, const char *next)
452 {
453 MpiEncTestArgs *cmd = (MpiEncTestArgs *)ctx;
454
455 if (next) {
456 size_t len = strnlen(next, MAX_FILE_NAME_LENGTH);
457 if (len) {
458 cmd->file_slt = mpp_calloc(char, len + 1);
459 strncpy(cmd->file_slt, next, len);
460
461 return 1;
462 }
463 }
464
465 mpp_err("input slt verify file is invalid\n");
466 return 0;
467 }
468
mpi_enc_opt_help(void * ctx,const char * next)469 RK_S32 mpi_enc_opt_help(void *ctx, const char *next)
470 {
471 (void)ctx;
472 (void)next;
473 return -1;
474 }
475
476 static MppOptInfo enc_opts[] = {
477 {"i", "input_file", "input frame file", mpi_enc_opt_i},
478 {"o", "output_file", "output encoded bitstream file", mpi_enc_opt_o},
479 {"w", "width", "the width of input picture", mpi_enc_opt_w},
480 {"h", "height", "the height of input picture", mpi_enc_opt_h},
481 {"hstride", "hor_stride", "the horizontal stride of input picture", mpi_enc_opt_hstride},
482 {"vstride", "ver_stride", "the vertical stride of input picture", mpi_enc_opt_vstride},
483 {"f", "format", "the format of input picture", mpi_enc_opt_f},
484 {"t", "type", "output stream coding type", mpi_enc_opt_t},
485 {"tsrc", "source type", "input file source coding type", mpi_enc_opt_tsrc},
486 {"n", "max frame number", "max encoding frame number", mpi_enc_opt_n},
487 {"g", "gop reference mode", "gop_mode:gop_len:vi_len", mpi_enc_opt_g},
488 {"rc", "rate control mode", "set rc_mode, 0:vbr 1:cbr 2:fixqp 3:avbr", mpi_enc_opt_rc},
489 {"bps", "bps target:min:max", "set tareget:min:max bps", mpi_enc_opt_bps},
490 {"fps", "in/output fps", "set input and output frame rate", mpi_enc_opt_fps},
491 {"qc", "quality control", "set qp_init:min:max:min_i:max_i", mpi_enc_opt_qc},
492 {"s", "instance_nb", "number of instances", mpi_enc_opt_s},
493 {"v", "trace option", "q - quiet f - show fps", mpi_enc_opt_v},
494 {"l", "loop count", "loop encoding times for each frame", mpi_enc_opt_l},
495 {"ini", "ini file", "encoder extra ini config file", mpi_enc_opt_ini},
496 {"slt", "slt file", "slt verify data file", mpi_enc_opt_slt},
497 };
498
499 static RK_U32 enc_opt_cnt = MPP_ARRAY_ELEMS(enc_opts);
500
mpi_enc_show_help(const char * name)501 RK_S32 mpi_enc_show_help(const char *name)
502 {
503 RK_U32 max_name = 1;
504 RK_U32 max_full_name = 1;
505 RK_U32 max_help = 1;
506 char logs[256];
507 RK_U32 len;
508 RK_U32 i;
509
510 mpp_log("usage: %s [options]\n", name);
511
512 for (i = 0; i < enc_opt_cnt; i++) {
513 MppOptInfo *opt = &enc_opts[i];
514
515 if (opt->name) {
516 len = strlen(opt->name);
517 if (len > max_name)
518 max_name = len;
519 }
520
521 if (opt->full_name) {
522 len = strlen(opt->full_name);
523 if (len > max_full_name)
524 max_full_name = len;
525 }
526
527 if (opt->help) {
528 len = strlen(opt->help);
529 if (len > max_help)
530 max_help = len;
531 }
532 }
533
534 snprintf(logs, sizeof(logs) - 1, "-%%-%ds %%-%ds %%-%ds\n", max_name, max_full_name, max_help);
535
536 for (i = 0; i < enc_opt_cnt; i++) {
537 MppOptInfo *opt = &enc_opts[i];
538
539 mpp_log(logs, opt->name, opt->full_name, opt->help);
540 }
541 mpp_show_support_format();
542 mpp_show_color_format();
543
544 return -1;
545 }
546
show_enc_fps(RK_S64 total_time,RK_S64 total_count,RK_S64 last_time,RK_S64 last_count)547 void show_enc_fps(RK_S64 total_time, RK_S64 total_count, RK_S64 last_time, RK_S64 last_count)
548 {
549 float avg_fps = (float)total_count * 1000000 / total_time;
550 float ins_fps = (float)last_count * 1000000 / last_time;
551
552 mpp_log("encoded %10lld frame fps avg %7.2f ins %7.2f\n",
553 total_count, avg_fps, ins_fps);
554 }
555
mpi_enc_test_cmd_update_by_args(MpiEncTestArgs * cmd,int argc,char ** argv)556 MPP_RET mpi_enc_test_cmd_update_by_args(MpiEncTestArgs* cmd, int argc, char **argv)
557 {
558 MppOpt opts = NULL;
559 RK_S32 ret = -1;
560 RK_U32 i;
561
562 if ((argc < 2) || NULL == cmd || NULL == argv)
563 goto done;
564
565 cmd->rc_mode = MPP_ENC_RC_MODE_BUTT;
566
567 mpp_opt_init(&opts);
568 /* should change node count when option increases */
569 mpp_opt_setup(opts, cmd, 67, enc_opt_cnt);
570
571 for (i = 0; i < enc_opt_cnt; i++)
572 mpp_opt_add(opts, &enc_opts[i]);
573
574 /* mark option end */
575 mpp_opt_add(opts, NULL);
576
577 ret = mpp_opt_parse(opts, argc, argv);
578
579 /* check essential parameter */
580 if (cmd->type <= MPP_VIDEO_CodingAutoDetect) {
581 mpp_err("invalid type %d\n", cmd->type);
582 ret = MPP_NOK;
583 }
584
585 if (cmd->rc_mode == MPP_ENC_RC_MODE_BUTT)
586 cmd->rc_mode = (cmd->type == MPP_VIDEO_CodingMJPEG) ?
587 MPP_ENC_RC_MODE_FIXQP : MPP_ENC_RC_MODE_VBR;
588
589 if (!cmd->hor_stride)
590 cmd->hor_stride = mpi_enc_width_default_stride(cmd->width, cmd->format);
591 if (!cmd->ver_stride)
592 cmd->ver_stride = cmd->height;
593
594 if (cmd->type_src == MPP_VIDEO_CodingUnused) {
595 if (cmd->width <= 0 || cmd->height <= 0 ||
596 cmd->hor_stride <= 0 || cmd->ver_stride <= 0) {
597 mpp_err("invalid w:h [%d:%d] stride [%d:%d]\n",
598 cmd->width, cmd->height, cmd->hor_stride, cmd->ver_stride);
599 ret = MPP_NOK;
600 }
601 }
602
603 if (cmd->rc_mode == MPP_ENC_RC_MODE_FIXQP) {
604 if (!cmd->qp_init) {
605 if (cmd->type == MPP_VIDEO_CodingAVC ||
606 cmd->type == MPP_VIDEO_CodingHEVC)
607 cmd->qp_init = 26;
608 }
609 }
610
611 if (cmd->trace_fps) {
612 fps_calc_init(&cmd->fps);
613 mpp_assert(cmd->fps);
614 fps_calc_set_cb(cmd->fps, show_enc_fps);
615 }
616
617 done:
618 if (opts) {
619 mpp_opt_deinit(opts);
620 opts = NULL;
621 }
622 if (ret)
623 mpi_enc_show_help(argv[0]);
624
625 return ret;
626 }
627
mpi_enc_test_cmd_put(MpiEncTestArgs * cmd)628 MPP_RET mpi_enc_test_cmd_put(MpiEncTestArgs* cmd)
629 {
630 if (NULL == cmd)
631 return MPP_OK;
632
633 if (cmd->cfg_ini) {
634 iniparser_freedict(cmd->cfg_ini);
635 cmd->cfg_ini = NULL;
636 }
637
638 if (cmd->fps) {
639 fps_calc_deinit(cmd->fps);
640 cmd->fps = NULL;
641 }
642
643 MPP_FREE(cmd->file_input);
644 MPP_FREE(cmd->file_output);
645 MPP_FREE(cmd->file_cfg);
646 MPP_FREE(cmd->file_slt);
647 MPP_FREE(cmd);
648
649 return MPP_OK;
650 }
651
mpi_enc_gen_ref_cfg(MppEncRefCfg ref,RK_S32 gop_mode)652 MPP_RET mpi_enc_gen_ref_cfg(MppEncRefCfg ref, RK_S32 gop_mode)
653 {
654 MppEncRefLtFrmCfg lt_ref[4];
655 MppEncRefStFrmCfg st_ref[16];
656 RK_S32 lt_cnt = 0;
657 RK_S32 st_cnt = 0;
658 MPP_RET ret = MPP_OK;
659
660 memset(<_ref, 0, sizeof(lt_ref));
661 memset(&st_ref, 0, sizeof(st_ref));
662
663 switch (gop_mode) {
664 case 3 : {
665 // tsvc4
666 // /-> P1 /-> P3 /-> P5 /-> P7
667 // / / / /
668 // //--------> P2 //--------> P6
669 // // //
670 // ///---------------------> P4
671 // ///
672 // P0 ------------------------------------------------> P8
673 lt_cnt = 1;
674
675 /* set 8 frame lt-ref gap */
676 lt_ref[0].lt_idx = 0;
677 lt_ref[0].temporal_id = 0;
678 lt_ref[0].ref_mode = REF_TO_PREV_LT_REF;
679 lt_ref[0].lt_gap = 8;
680 lt_ref[0].lt_delay = 0;
681
682 st_cnt = 9;
683 /* set tsvc4 st-ref struct */
684 /* st 0 layer 0 - ref */
685 st_ref[0].is_non_ref = 0;
686 st_ref[0].temporal_id = 0;
687 st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER;
688 st_ref[0].ref_arg = 0;
689 st_ref[0].repeat = 0;
690 /* st 1 layer 3 - non-ref */
691 st_ref[1].is_non_ref = 1;
692 st_ref[1].temporal_id = 3;
693 st_ref[1].ref_mode = REF_TO_PREV_REF_FRM;
694 st_ref[1].ref_arg = 0;
695 st_ref[1].repeat = 0;
696 /* st 2 layer 2 - ref */
697 st_ref[2].is_non_ref = 0;
698 st_ref[2].temporal_id = 2;
699 st_ref[2].ref_mode = REF_TO_PREV_REF_FRM;
700 st_ref[2].ref_arg = 0;
701 st_ref[2].repeat = 0;
702 /* st 3 layer 3 - non-ref */
703 st_ref[3].is_non_ref = 1;
704 st_ref[3].temporal_id = 3;
705 st_ref[3].ref_mode = REF_TO_PREV_REF_FRM;
706 st_ref[3].ref_arg = 0;
707 st_ref[3].repeat = 0;
708 /* st 4 layer 1 - ref */
709 st_ref[4].is_non_ref = 0;
710 st_ref[4].temporal_id = 1;
711 st_ref[4].ref_mode = REF_TO_PREV_LT_REF;
712 st_ref[4].ref_arg = 0;
713 st_ref[4].repeat = 0;
714 /* st 5 layer 3 - non-ref */
715 st_ref[5].is_non_ref = 1;
716 st_ref[5].temporal_id = 3;
717 st_ref[5].ref_mode = REF_TO_PREV_REF_FRM;
718 st_ref[5].ref_arg = 0;
719 st_ref[5].repeat = 0;
720 /* st 6 layer 2 - ref */
721 st_ref[6].is_non_ref = 0;
722 st_ref[6].temporal_id = 2;
723 st_ref[6].ref_mode = REF_TO_PREV_REF_FRM;
724 st_ref[6].ref_arg = 0;
725 st_ref[6].repeat = 0;
726 /* st 7 layer 3 - non-ref */
727 st_ref[7].is_non_ref = 1;
728 st_ref[7].temporal_id = 3;
729 st_ref[7].ref_mode = REF_TO_PREV_REF_FRM;
730 st_ref[7].ref_arg = 0;
731 st_ref[7].repeat = 0;
732 /* st 8 layer 0 - ref */
733 st_ref[8].is_non_ref = 0;
734 st_ref[8].temporal_id = 0;
735 st_ref[8].ref_mode = REF_TO_TEMPORAL_LAYER;
736 st_ref[8].ref_arg = 0;
737 st_ref[8].repeat = 0;
738 } break;
739 case 2 : {
740 // tsvc3
741 // /-> P1 /-> P3
742 // / /
743 // //--------> P2
744 // //
745 // P0/---------------------> P4
746 lt_cnt = 0;
747
748 st_cnt = 5;
749 /* set tsvc4 st-ref struct */
750 /* st 0 layer 0 - ref */
751 st_ref[0].is_non_ref = 0;
752 st_ref[0].temporal_id = 0;
753 st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER;
754 st_ref[0].ref_arg = 0;
755 st_ref[0].repeat = 0;
756 /* st 1 layer 2 - non-ref */
757 st_ref[1].is_non_ref = 1;
758 st_ref[1].temporal_id = 2;
759 st_ref[1].ref_mode = REF_TO_PREV_REF_FRM;
760 st_ref[1].ref_arg = 0;
761 st_ref[1].repeat = 0;
762 /* st 2 layer 1 - ref */
763 st_ref[2].is_non_ref = 0;
764 st_ref[2].temporal_id = 1;
765 st_ref[2].ref_mode = REF_TO_PREV_REF_FRM;
766 st_ref[2].ref_arg = 0;
767 st_ref[2].repeat = 0;
768 /* st 3 layer 2 - non-ref */
769 st_ref[3].is_non_ref = 1;
770 st_ref[3].temporal_id = 2;
771 st_ref[3].ref_mode = REF_TO_PREV_REF_FRM;
772 st_ref[3].ref_arg = 0;
773 st_ref[3].repeat = 0;
774 /* st 4 layer 0 - ref */
775 st_ref[4].is_non_ref = 0;
776 st_ref[4].temporal_id = 0;
777 st_ref[4].ref_mode = REF_TO_TEMPORAL_LAYER;
778 st_ref[4].ref_arg = 0;
779 st_ref[4].repeat = 0;
780 } break;
781 case 1 : {
782 // tsvc2
783 // /-> P1
784 // /
785 // P0--------> P2
786 lt_cnt = 0;
787
788 st_cnt = 3;
789 /* set tsvc4 st-ref struct */
790 /* st 0 layer 0 - ref */
791 st_ref[0].is_non_ref = 0;
792 st_ref[0].temporal_id = 0;
793 st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER;
794 st_ref[0].ref_arg = 0;
795 st_ref[0].repeat = 0;
796 /* st 1 layer 2 - non-ref */
797 st_ref[1].is_non_ref = 1;
798 st_ref[1].temporal_id = 1;
799 st_ref[1].ref_mode = REF_TO_PREV_REF_FRM;
800 st_ref[1].ref_arg = 0;
801 st_ref[1].repeat = 0;
802 /* st 2 layer 1 - ref */
803 st_ref[2].is_non_ref = 0;
804 st_ref[2].temporal_id = 0;
805 st_ref[2].ref_mode = REF_TO_PREV_REF_FRM;
806 st_ref[2].ref_arg = 0;
807 st_ref[2].repeat = 0;
808 } break;
809 default : {
810 mpp_err_f("unsupport gop mode %d\n", gop_mode);
811 } break;
812 }
813
814 if (lt_cnt || st_cnt) {
815 ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cnt, st_cnt);
816
817 if (lt_cnt)
818 ret = mpp_enc_ref_cfg_add_lt_cfg(ref, lt_cnt, lt_ref);
819
820 if (st_cnt)
821 ret = mpp_enc_ref_cfg_add_st_cfg(ref, st_cnt, st_ref);
822
823 /* check and get dpb size */
824 ret = mpp_enc_ref_cfg_check(ref);
825 }
826
827 return ret;
828 }
829
mpi_enc_gen_smart_gop_ref_cfg(MppEncRefCfg ref,RK_S32 gop_len,RK_S32 vi_len)830 MPP_RET mpi_enc_gen_smart_gop_ref_cfg(MppEncRefCfg ref, RK_S32 gop_len, RK_S32 vi_len)
831 {
832 MppEncRefLtFrmCfg lt_ref[4];
833 MppEncRefStFrmCfg st_ref[16];
834 RK_S32 lt_cnt = 1;
835 RK_S32 st_cnt = 8;
836 RK_S32 pos = 0;
837 MPP_RET ret = MPP_OK;
838
839 memset(<_ref, 0, sizeof(lt_ref));
840 memset(&st_ref, 0, sizeof(st_ref));
841
842 ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cnt, st_cnt);
843
844 /* set 8 frame lt-ref gap */
845 lt_ref[0].lt_idx = 0;
846 lt_ref[0].temporal_id = 0;
847 lt_ref[0].ref_mode = REF_TO_PREV_LT_REF;
848 lt_ref[0].lt_gap = gop_len;
849 lt_ref[0].lt_delay = 0;
850
851 ret = mpp_enc_ref_cfg_add_lt_cfg(ref, 1, lt_ref);
852
853 /* st 0 layer 0 - ref */
854 st_ref[pos].is_non_ref = 0;
855 st_ref[pos].temporal_id = 0;
856 st_ref[pos].ref_mode = REF_TO_PREV_INTRA;
857 st_ref[pos].ref_arg = 0;
858 st_ref[pos].repeat = 0;
859 pos++;
860
861 /* st 1 layer 1 - non-ref */
862 if (vi_len > 1) {
863 st_ref[pos].is_non_ref = 0;
864 st_ref[pos].temporal_id = 1;
865 st_ref[pos].ref_mode = REF_TO_PREV_REF_FRM;
866 st_ref[pos].ref_arg = 0;
867 st_ref[pos].repeat = vi_len - 2;
868 pos++;
869 }
870
871 st_ref[pos].is_non_ref = 0;
872 st_ref[pos].temporal_id = 0;
873 st_ref[pos].ref_mode = REF_TO_PREV_INTRA;
874 st_ref[pos].ref_arg = 0;
875 st_ref[pos].repeat = 0;
876 pos++;
877
878 ret = mpp_enc_ref_cfg_add_st_cfg(ref, pos, st_ref);
879
880 /* check and get dpb size */
881 ret = mpp_enc_ref_cfg_check(ref);
882
883 return ret;
884 }
885
mpi_enc_gen_osd_plt(MppEncOSDPlt * osd_plt,RK_U32 frame_cnt)886 MPP_RET mpi_enc_gen_osd_plt(MppEncOSDPlt *osd_plt, RK_U32 frame_cnt)
887 {
888 /*
889 * osd idx size range from 16x16 bytes(pixels) to hor_stride*ver_stride(bytes).
890 * for general use, 1/8 Y buffer is enough.
891 */
892 static RK_U32 plt_table[8] = {
893 MPP_ENC_OSD_PLT_RED,
894 MPP_ENC_OSD_PLT_YELLOW,
895 MPP_ENC_OSD_PLT_BLUE,
896 MPP_ENC_OSD_PLT_GREEN,
897 MPP_ENC_OSD_PLT_CYAN,
898 MPP_ENC_OSD_PLT_TRANS,
899 MPP_ENC_OSD_PLT_BLACK,
900 MPP_ENC_OSD_PLT_WHITE,
901 };
902
903 if (osd_plt) {
904 RK_U32 k = 0;
905 RK_U32 base = frame_cnt & 7;
906
907 for (k = 0; k < 256; k++)
908 osd_plt->data[k].val = plt_table[(base + k) % 8];
909 }
910 return MPP_OK;
911 }
912
mpi_enc_gen_osd_data(MppEncOSDData * osd_data,MppBufferGroup group,RK_U32 width,RK_U32 height,RK_U32 frame_cnt)913 MPP_RET mpi_enc_gen_osd_data(MppEncOSDData *osd_data, MppBufferGroup group,
914 RK_U32 width, RK_U32 height, RK_U32 frame_cnt)
915 {
916 MppEncOSDRegion *region = NULL;
917 RK_U32 k = 0;
918 RK_U32 num_region = 8;
919 RK_U32 buf_offset = 0;
920 RK_U32 buf_size = 0;
921 RK_U32 mb_w_max = MPP_ALIGN(width, 16) / 16;
922 RK_U32 mb_h_max = MPP_ALIGN(height, 16) / 16;
923 RK_U32 step_x = MPP_ALIGN(mb_w_max, 8) / 8;
924 RK_U32 step_y = MPP_ALIGN(mb_h_max, 16) / 16;
925 RK_U32 mb_x = (frame_cnt * step_x) % mb_w_max;
926 RK_U32 mb_y = (frame_cnt * step_y) % mb_h_max;
927 RK_U32 mb_w = step_x;
928 RK_U32 mb_h = step_y;
929 MppBuffer buf = osd_data->buf;
930
931 if (buf)
932 buf_size = mpp_buffer_get_size(buf);
933
934 /* generate osd region info */
935 osd_data->num_region = num_region;
936
937 region = osd_data->region;
938
939 for (k = 0; k < num_region; k++, region++) {
940 // NOTE: offset must be 16 byte aligned
941 RK_U32 region_size = MPP_ALIGN(mb_w * mb_h * 256, 16);
942
943 region->inverse = 1;
944 region->start_mb_x = mb_x;
945 region->start_mb_y = mb_y;
946 region->num_mb_x = mb_w;
947 region->num_mb_y = mb_h;
948 region->buf_offset = buf_offset;
949 region->enable = (mb_w && mb_h);
950
951 buf_offset += region_size;
952
953 mb_x += step_x;
954 mb_y += step_y;
955 if (mb_x >= mb_w_max)
956 mb_x -= mb_w_max;
957 if (mb_y >= mb_h_max)
958 mb_y -= mb_h_max;
959 }
960
961 /* create buffer and write osd index data */
962 if (buf_size < buf_offset) {
963 if (buf)
964 mpp_buffer_put(buf);
965
966 mpp_buffer_get(group, &buf, buf_offset);
967 if (NULL == buf)
968 mpp_err_f("failed to create osd buffer size %d\n", buf_offset);
969 }
970
971 if (buf) {
972 void *ptr = mpp_buffer_get_ptr(buf);
973 region = osd_data->region;
974
975 for (k = 0; k < num_region; k++, region++) {
976 mb_w = region->num_mb_x;
977 mb_h = region->num_mb_y;
978 buf_offset = region->buf_offset;
979
980 memset(ptr + buf_offset, k, mb_w * mb_h * 256);
981 }
982 }
983
984 osd_data->buf = buf;
985
986 return MPP_OK;
987 }
988
mpi_enc_test_cmd_show_opt(MpiEncTestArgs * cmd)989 MPP_RET mpi_enc_test_cmd_show_opt(MpiEncTestArgs* cmd)
990 {
991 mpp_log("cmd parse result:\n");
992 mpp_log("input file name: %s\n", cmd->file_input);
993 mpp_log("output file name: %s\n", cmd->file_output);
994 mpp_log("width : %d\n", cmd->width);
995 mpp_log("height : %d\n", cmd->height);
996 mpp_log("format : %d\n", cmd->format);
997 mpp_log("type : %d\n", cmd->type);
998 if (cmd->file_slt)
999 mpp_log("verify : %s\n", cmd->file_slt);
1000
1001 return MPP_OK;
1002 }
1003