xref: /OK3568_Linux_fs/external/mpp/utils/mpi_enc_utils.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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(&lt_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(&lt_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