1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2018 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "iep_test"
7
8 #include <string.h>
9
10 #include "mpp_mem.h"
11 #include "mpp_time.h"
12 #include "mpp_debug.h"
13 #include "mpp_common.h"
14 #include "mpp_thread.h"
15 #include "mpp_buffer.h"
16
17 #include "iep_api.h"
18 #include "utils.h"
19 #include "iniparser.h"
20
21 #define MAX_URL_LEN (100)
22 #define ADD_OFFSET(base, offset) ((RK_U32)base + ((RK_U32)(offset) << 10))
23
24 typedef enum {
25 TEST_CASE_NONE,
26 TEST_CASE_DEINTERLACE,
27 TEST_CASE_YUVENHANCE,
28 TEST_CASE_RGBENHANCE,
29 } TEST_CASE;
30
31 typedef struct IepTestCfg_t {
32 RK_S32 src_w;
33 RK_S32 src_h;
34 RK_S32 src_fmt;
35
36 RK_S32 dst_w;
37 RK_S32 dst_h;
38 RK_S32 dst_fmt;
39
40 char src_url[MAX_URL_LEN];
41 char dst_url[MAX_URL_LEN];
42 char cfg_url[MAX_URL_LEN];
43
44 FILE *fp_src;
45 FILE *fp_dst;
46
47 TEST_CASE mode;
48
49 dictionary *ini;
50 IepCmdParamDeiCfg *dei_cfg;
51 IepCmdParamYuvEnhance *yuv_enh;
52 IepCmdParamRgbEnhance *rgb_enh;
53 IepCmdParamColorConvert *colorcvt;
54 } IepTestCfg;
55
56 typedef struct IepTestInfo_t {
57 IepTestCfg *cfg;
58
59 size_t src_size;
60 size_t dst_size;
61
62 RK_U32 phy_src0;
63 RK_U32 phy_src1;
64 RK_U32 phy_dst0;
65 RK_U32 phy_dst1;
66
67 RK_U8 *vir_src0;
68 RK_U8 *vir_src1;
69 RK_U8 *vir_dst0;
70 RK_U8 *vir_dst1;
71
72 IepImg src;
73 IepImg dst;
74
75 IepCtx ctx;
76 } IepTestInfo;
77
parse_cfg(IepTestCfg * cfg)78 static void parse_cfg(IepTestCfg *cfg)
79 {
80 dictionary *ini = cfg->ini;
81
82 cfg->dei_cfg = mpp_calloc(IepCmdParamDeiCfg, 1);
83 if (iniparser_find_entry(ini, "deinterlace")) {
84 mpp_assert(cfg->dei_cfg);
85 cfg->dei_cfg->dei_high_freq_en =
86 iniparser_getint(ini, "deinterlace:high_freq_en", 0);
87 cfg->dei_cfg->dei_mode =
88 (IepDeiMode)iniparser_getint(ini, "deinterlace:dei_mode", 0);
89 cfg->dei_cfg->dei_high_freq_fct =
90 iniparser_getint(ini, "deinterlace:dei_high_freq_fct", 0);
91 cfg->dei_cfg->dei_ei_mode =
92 iniparser_getint(ini, "deinterlace:dei_ei_mode", 0);
93 cfg->dei_cfg->dei_ei_smooth =
94 iniparser_getint(ini, "deinterlace:dei_ei_smooth", 0);
95 cfg->dei_cfg->dei_ei_sel =
96 iniparser_getint(ini, "deinterlace:dei_ei_sel", 0);
97 cfg->dei_cfg->dei_ei_radius =
98 iniparser_getint(ini, "deinterlace:dei_ei_radius", 0);
99 } else {
100 cfg->dei_cfg->dei_high_freq_en = 1;
101 cfg->dei_cfg->dei_mode = IEP_DEI_MODE_I4O1;
102 cfg->dei_cfg->dei_field_order = IEP_DEI_FLD_ORDER_BOT_FIRST;
103 cfg->dei_cfg->dei_ei_mode = 0;
104 cfg->dei_cfg->dei_ei_smooth = 0;
105 cfg->dei_cfg->dei_ei_sel = 0;
106 cfg->dei_cfg->dei_ei_radius = 0;
107 }
108
109 if (iniparser_find_entry(ini, "yuv enhance")) {
110 cfg->yuv_enh = mpp_calloc(IepCmdParamYuvEnhance, 1);
111 cfg->yuv_enh->saturation =
112 iniparser_getint(ini, "yuv enhance:saturation", 0);
113 cfg->yuv_enh->contrast =
114 iniparser_getint(ini, "yuv enhance:contrast", 0);
115 cfg->yuv_enh->brightness =
116 iniparser_getint(ini, "yuv enhance:brightness", 0);
117 cfg->yuv_enh->hue_angle =
118 iniparser_getint(ini, "yuv enhance:hue_angle", 0);
119 cfg->yuv_enh->video_mode =
120 (IepVideoMode)
121 iniparser_getint(ini, "yuv enhance:video_mode", 0);
122 cfg->yuv_enh->color_bar_y =
123 iniparser_getint(ini, "yuv enhance:color_bar_y", 0);
124 cfg->yuv_enh->color_bar_u =
125 iniparser_getint(ini, "yuv enhance:color_bar_u", 0);
126 cfg->yuv_enh->color_bar_v =
127 iniparser_getint(ini, "yuv enhance:color_bar_v", 0);
128 }
129
130 if (iniparser_find_entry(ini, "rgb enhance")) {
131 cfg->rgb_enh = mpp_calloc(IepCmdParamRgbEnhance, 1);
132 cfg->rgb_enh->coe =
133 iniparser_getint(ini, "rgb enhance:coe", 0);
134 cfg->rgb_enh->mode =
135 (IepRgbEnhanceMode)
136 iniparser_getint(ini, "rgb enhance:mode", 0);
137 cfg->rgb_enh->cg_en =
138 iniparser_getint(ini, "rgb enhance:cg_en", 0);
139 cfg->rgb_enh->cg_rr =
140 iniparser_getint(ini, "rgb enhance:cg_rr", 0);
141 cfg->rgb_enh->cg_rg =
142 iniparser_getint(ini, "rgb enhance:cg_rg", 0);
143 cfg->rgb_enh->cg_rb =
144 iniparser_getint(ini, "rgb enhance:cg_rb", 0);
145 cfg->rgb_enh->order =
146 (IepRgbEnhanceOrder)
147 iniparser_getint(ini, "rgb enhance:order", 0);
148 cfg->rgb_enh->threshold =
149 iniparser_getint(ini, "rgb enhance:threshold", 0);
150 cfg->rgb_enh->alpha_num =
151 iniparser_getint(ini, "rgb enhance:alpha_num", 0);
152 cfg->rgb_enh->alpha_base =
153 iniparser_getint(ini, "rgb enhance:alpha_base", 0);
154 cfg->rgb_enh->radius =
155 iniparser_getint(ini, "rgb enhance:radius", 0);
156 }
157
158 if (iniparser_find_entry(ini, "colorcvt")) {
159 cfg->colorcvt = mpp_calloc(IepCmdParamColorConvert, 1);
160 cfg->colorcvt->rgb2yuv_mode =
161 (IepColorConvertMode)
162 iniparser_getint(ini, "colorcvt:rgb2yuv_mode", 0);
163 cfg->colorcvt->yuv2rgb_mode =
164 (IepColorConvertMode)
165 iniparser_getint(ini, "colorcvt:yuv2rgb_mode", 0);
166 cfg->colorcvt->rgb2yuv_input_clip =
167 iniparser_getint(ini, "colorcvt:rgb2yuv_input_clip", 0);
168 cfg->colorcvt->yuv2rgb_input_clip =
169 iniparser_getint(ini, "colorcvt:yuv2rgb_input_clip", 0);
170 cfg->colorcvt->global_alpha_value =
171 iniparser_getint(ini, "colorcvt:global_alpha_value", 0);
172 cfg->colorcvt->dither_up_en =
173 iniparser_getint(ini, "colorcvt:dither_up_en", 0);
174 cfg->colorcvt->dither_down_en =
175 iniparser_getint(ini, "colorcvt:dither_down_en", 0);
176 }
177 }
178
get_image_size(RK_S32 w,RK_S32 h,RK_S32 fmt)179 static RK_S32 get_image_size(RK_S32 w, RK_S32 h, RK_S32 fmt)
180 {
181 RK_S32 img_size = 0;
182
183 switch (fmt) {
184 case IEP_FORMAT_ABGR_8888:
185 case IEP_FORMAT_ARGB_8888:
186 case IEP_FORMAT_BGRA_8888:
187 case IEP_FORMAT_RGBA_8888:
188 img_size = w * h * 4;
189 break;
190 case IEP_FORMAT_BGR_565:
191 case IEP_FORMAT_RGB_565:
192 case IEP_FORMAT_YCbCr_422_P:
193 case IEP_FORMAT_YCbCr_422_SP:
194 case IEP_FORMAT_YCrCb_422_P:
195 case IEP_FORMAT_YCrCb_422_SP:
196 img_size = w * h * 2;
197 break;
198 case IEP_FORMAT_YCbCr_420_P:
199 case IEP_FORMAT_YCbCr_420_SP:
200 case IEP_FORMAT_YCrCb_420_P:
201 case IEP_FORMAT_YCrCb_420_SP:
202 img_size = w * h * 3 / 2;
203 break;
204 default : {
205 } break;
206 }
207 return img_size;
208 }
209
config_iep_img(IepImg * img,RK_S32 w,RK_S32 h,RK_S32 fmt,RK_U32 base)210 static void config_iep_img(IepImg *img, RK_S32 w, RK_S32 h, RK_S32 fmt, RK_U32 base)
211 {
212 switch (fmt) {
213 case IEP_FORMAT_ABGR_8888:
214 case IEP_FORMAT_ARGB_8888:
215 case IEP_FORMAT_BGRA_8888:
216 case IEP_FORMAT_RGBA_8888:
217 img->v_addr = 0;
218 break;
219 case IEP_FORMAT_BGR_565:
220 case IEP_FORMAT_RGB_565:
221 case IEP_FORMAT_YCbCr_422_P:
222 case IEP_FORMAT_YCbCr_422_SP:
223 case IEP_FORMAT_YCrCb_422_P:
224 case IEP_FORMAT_YCrCb_422_SP:
225 img->v_addr = ADD_OFFSET(base, w * h + w * h / 2);
226 break;
227 case IEP_FORMAT_YCbCr_420_P:
228 case IEP_FORMAT_YCbCr_420_SP:
229 case IEP_FORMAT_YCrCb_420_P:
230 case IEP_FORMAT_YCrCb_420_SP:
231 img->v_addr = ADD_OFFSET(base, w * h + w * h / 4);
232 break;
233 default : {
234 } break;
235 }
236
237 img->act_w = w;
238 img->act_h = h;
239 img->x_off = 0;
240 img->y_off = 0;
241 img->vir_w = w;
242 img->vir_h = h;
243 img->format = fmt;
244 img->mem_addr = base;
245 img->uv_addr = ADD_OFFSET(base, w * h);
246 }
247
iep_process_thread(void * param)248 void* iep_process_thread(void *param)
249 {
250 IepTestInfo *info = (IepTestInfo*)param;
251 IepTestCfg *cfg = info->cfg;
252
253 config_iep_img(&info->src, cfg->src_w, cfg->src_h, cfg->src_fmt, info->phy_src0);
254 config_iep_img(&info->dst, cfg->dst_w, cfg->dst_h, cfg->dst_fmt, info->phy_dst0);
255
256 if (info->src_size > fread(info->vir_src0, 1, info->src_size, cfg->fp_src)) {
257 mpp_err("read file failed\n");
258 return NULL;
259 }
260
261 iep_control(info->ctx, IEP_CMD_INIT, NULL);
262 iep_control(info->ctx, IEP_CMD_SET_SRC, &info->src);
263 iep_control(info->ctx, IEP_CMD_SET_DST, &info->dst);
264
265 switch (cfg->mode) {
266 case TEST_CASE_YUVENHANCE: {
267 iep_control(info->ctx, IEP_CMD_SET_YUV_ENHANCE, cfg->yuv_enh);
268 } break;
269 case TEST_CASE_RGBENHANCE: {
270 iep_control(info->ctx, IEP_CMD_SET_RGB_ENHANCE, cfg->rgb_enh);
271 } break;
272 case TEST_CASE_DEINTERLACE: {
273 IepImg src1;
274 IepImg dst1;
275
276 if (info->src_size != fread(info->vir_src1, 1, info->src_size, cfg->fp_src))
277 mpp_err("failed to read %d from input\n", info->src_size);
278
279 config_iep_img(&src1, cfg->src_w, cfg->src_h, cfg->src_fmt, info->phy_src1);
280 config_iep_img(&dst1, cfg->src_w, cfg->src_h, cfg->src_fmt, info->phy_dst1);
281
282 iep_control(info->ctx, IEP_CMD_SET_DEI_SRC1, &src1);
283 iep_control(info->ctx, IEP_CMD_SET_DEI_DST1, &dst1);
284 iep_control(info->ctx, IEP_CMD_SET_DEI_CFG, cfg->dei_cfg);
285 } break;
286 default: {
287 } break;
288 }
289
290 RK_S64 intime = mpp_time();
291 if (0 == iep_control(info->ctx, IEP_CMD_RUN_SYNC, NULL))
292 mpp_log("%d success\n", getpid());
293 else
294 mpp_log("%d failure\n", getpid());
295
296 mpp_log("%s consume %lld ms\n", __func__, (mpp_time() - intime) / 1000);
297
298 if (cfg->fp_dst)
299 fwrite(info->vir_dst0, 1, info->dst_size, cfg->fp_dst);
300
301 return NULL;
302 }
303
str_to_iep_fmt(const char * str)304 static RK_S32 str_to_iep_fmt(const char *str)
305 {
306 RK_S32 fmt = -1;
307
308 if (!strcmp(str, "argb8888"))
309 fmt = IEP_FORMAT_ARGB_8888;
310 else if (!strcmp(str, "abgr8888"))
311 fmt = IEP_FORMAT_ABGR_8888;
312 else if (!strcmp(str, "rgba8888"))
313 fmt = IEP_FORMAT_BGRA_8888;
314 else if (!strcmp(str, "bgra8888"))
315 fmt = IEP_FORMAT_BGRA_8888;
316 else if (!strcmp(str, "rgb565"))
317 fmt = IEP_FORMAT_RGB_565;
318 else if (!strcmp(str, "bgr565"))
319 fmt = IEP_FORMAT_BGR_565;
320 else if (!strcmp(str, "yuv422sp"))
321 fmt = IEP_FORMAT_YCbCr_422_SP;
322 else if (!strcmp(str, "yuv422p"))
323 fmt = IEP_FORMAT_YCbCr_422_P;
324 else if (!strcmp(str, "yuv420sp"))
325 fmt = IEP_FORMAT_YCbCr_420_SP;
326 else if (!strcmp(str, "yuv420p"))
327 fmt = IEP_FORMAT_YCbCr_420_P;
328 else if (!strcmp(str, "yvu422sp"))
329 fmt = IEP_FORMAT_YCrCb_422_SP;
330 else if (!strcmp(str, "yvu422p"))
331 fmt = IEP_FORMAT_YCrCb_422_P;
332 else if (!strcmp(str, "yvu420sp"))
333 fmt = IEP_FORMAT_YCrCb_420_SP;
334 else if (!strcmp(str, "yvu420p"))
335 fmt = IEP_FORMAT_YCrCb_420_P;
336 else
337 mpp_err("invalid format %s\n", str);
338
339 return fmt;
340 }
341
check_input_cmd(IepTestCfg * cfg)342 static MPP_RET check_input_cmd(IepTestCfg *cfg)
343 {
344 MPP_RET ret = MPP_OK;
345
346 if (cfg->src_w <= 0) {
347 mpp_err("non-positive input width %d\n", cfg->src_w);
348 ret = MPP_NOK;
349 }
350 if (cfg->src_h <= 0) {
351 mpp_err("non-positive input height %d\n", cfg->src_h);
352 ret = MPP_NOK;
353 }
354 if (cfg->src_fmt < IEP_FORMAT_ARGB_8888 ||
355 cfg->src_fmt > IEP_FORMAT_YCrCb_420_P) {
356 mpp_err("invalid input format\n");
357 ret = MPP_NOK;
358 }
359 if (cfg->fp_src == NULL) {
360 mpp_err("failed to open input file %s\n", cfg->src_url);
361 ret = MPP_NOK;
362 }
363 if (cfg->dst_w <= 0) {
364 mpp_err("non-positive input width %d\n", cfg->dst_w);
365 ret = MPP_NOK;
366 }
367 if (cfg->dst_h <= 0) {
368 mpp_err("non-positive input height %d\n", cfg->dst_h);
369 ret = MPP_NOK;
370 }
371 if (cfg->dst_fmt < IEP_FORMAT_ARGB_8888 ||
372 cfg->dst_fmt > IEP_FORMAT_YCrCb_420_P) {
373 mpp_err("invalid input format\n");
374 ret = MPP_NOK;
375 }
376 if (cfg->mode == TEST_CASE_NONE) {
377 mpp_err("invalid work mode\n");
378 ret = MPP_NOK;
379 }
380
381 return ret;
382 }
383
384 static OptionInfo iep_test_cmd[] = {
385 {"w", "src_width", "input image width"},
386 {"h", "src_height", "input image height"},
387 {"c", "src_format", "input image format in ASCII string"},
388 {"f", "src_file", "input image file name"},
389 {"W", "dst_width", "output image width"},
390 {"H", "dst_height", "output image height"},
391 {"C", "dst_format", "output image format in ASCII string"},
392 {"F", "dst_file", "output image file name"},
393 {"m", "work_mode", "working mode of iep in ASCII string"},
394 {"x", "configure", "configure file of working mode"},
395 };
396
iep_test_help()397 static void iep_test_help()
398 {
399 mpp_log("usage: iep_test [options]\n");
400 mpp_log("*******************************\n");
401 show_options(iep_test_cmd);
402 mpp_log("*******************************\n");
403 mpp_log("supported ASCII format strings:\n");
404 mpp_log(" 0 - argb8888\n");
405 mpp_log(" 1 - abgr8888\n");
406 mpp_log(" 2 - rgba8888\n");
407 mpp_log(" 3 - bgra8888\n");
408 mpp_log(" 4 - rgb565\n");
409 mpp_log(" 5 - bgr565\n");
410 mpp_log(" 6 - yuv422sp\n");
411 mpp_log(" 7 - yuv422p\n");
412 mpp_log(" 8 - yuv420sp\n");
413 mpp_log(" 9 - yuv420p\n");
414 mpp_log("10 - yvu422sp\n");
415 mpp_log("11 - yvu422p\n");
416 mpp_log("12 - yvu420sp\n");
417 mpp_log("13 - yvu420p\n");
418 mpp_log("*******************************\n");
419 mpp_log("supported work mode strings:\n");
420 mpp_log(" 1 - deinterlace\n");
421 mpp_log(" 2 - yuvenhance\n");
422 mpp_log(" 3 - rgbenhance\n");
423 mpp_log("************ sample ***********\n");
424 mpp_log("iep_test -w 720 -h 480 -c yuv420p -f input.yuv -W 720 -H 480 -C yuv420p -F output.yuv -m deinterlace -x dil.cfg\n");
425 }
426
main(int argc,char ** argv)427 int main(int argc, char **argv)
428 {
429 IepTestCfg cfg;
430 IepTestInfo info;
431 int ch;
432
433 if (argc < 2) {
434 iep_test_help();
435 return 0;
436 }
437
438 memset(&cfg, 0, sizeof(cfg));
439 memset(&info, 0, sizeof(info));
440 cfg.src_fmt = IEP_FORMAT_YCbCr_420_SP;
441 cfg.dst_fmt = IEP_FORMAT_YCbCr_420_SP;
442
443 /// get options
444 opterr = 0;
445 while ((ch = getopt(argc, argv, "f:w:h:c:F:W:H:C:m:x:")) != -1) {
446 switch (ch) {
447 case 'w': {
448 cfg.src_w = atoi(optarg);
449 } break;
450 case 'h': {
451 cfg.src_h = atoi(optarg);
452 } break;
453 case 'c': {
454 cfg.src_fmt = str_to_iep_fmt(optarg);
455 } break;
456 case 'W': {
457 cfg.dst_w = atoi(optarg);
458 } break;
459 case 'H': {
460 cfg.dst_h = atoi(optarg);
461 } break;
462 case 'C': {
463 cfg.dst_fmt = str_to_iep_fmt(optarg);
464 } break;
465 case 'f': {
466 mpp_log("input filename: %s\n", optarg);
467 strncpy(cfg.src_url, optarg, sizeof(cfg.src_url) - 1);
468 cfg.fp_src = fopen(cfg.src_url, "rb");
469 } break;
470 case 'F': {
471 mpp_log("output filename: %s\n", optarg);
472 strncpy(cfg.dst_url, optarg, sizeof(cfg.dst_url) - 1);
473 cfg.fp_dst = fopen(cfg.dst_url, "w+b");
474 } break;
475 case 'm': {
476 if (!strcmp(optarg, "deinterlace")) {
477 cfg.mode = TEST_CASE_DEINTERLACE;
478 } else if (!strcmp(optarg, "yuvenhance")) {
479 cfg.mode = TEST_CASE_YUVENHANCE;
480 } else if (!strcmp(optarg, "rgbenhance")) {
481 cfg.mode = TEST_CASE_RGBENHANCE;
482 } else {
483 mpp_err("invalid work mode %s\n", optarg);
484 cfg.mode = TEST_CASE_NONE;
485 }
486 } break;
487 case 'x': {
488 mpp_log("configure filename: %s\n", optarg);
489 strncpy(cfg.cfg_url, optarg, sizeof(cfg.cfg_url) - 1);
490 cfg.ini = iniparser_load(cfg.cfg_url);
491 if (cfg.ini)
492 parse_cfg(&cfg);
493 else
494 mpp_err("invalid configure file %s\n", optarg);
495 } break;
496 default: {
497 } break;
498 }
499 }
500
501 if (check_input_cmd(&cfg)) {
502 mpp_err("failed to pass cmd line check\n");
503 iep_test_help();
504 return -1;
505 }
506
507 info.cfg = &cfg;
508 info.src_size = get_image_size(cfg.src_w, cfg.src_h, cfg.src_fmt);
509 info.dst_size = get_image_size(cfg.dst_w, cfg.dst_h, cfg.dst_fmt);
510
511 // allocate 12M in/out memory and initialize memory address
512 MppBuffer buffer = NULL;
513 size_t src_size = MPP_ALIGN(info.src_size, SZ_4K);
514 size_t dst_size = MPP_ALIGN(info.dst_size, SZ_4K);
515 // NOTE: deinterlace need 4 fields (2 frames) as input and output 2 frames
516 size_t total_size = src_size * 2 + dst_size * 2;
517
518 mpp_buffer_get(NULL, &buffer, total_size);
519 mpp_assert(buffer);
520
521 int buf_fd = mpp_buffer_get_fd(buffer);
522 RK_U8 *buf_ptr = (RK_U8 *)mpp_buffer_get_ptr(buffer);
523
524 memset(buf_ptr, 0xff, total_size);
525
526 info.phy_src0 = ADD_OFFSET(buf_fd, 0);
527 info.phy_src1 = ADD_OFFSET(buf_fd, src_size);
528 info.phy_dst0 = ADD_OFFSET(buf_fd, src_size * 2);
529 info.phy_dst1 = ADD_OFFSET(buf_fd, src_size * 2 + dst_size);
530
531 info.vir_src0 = buf_ptr;
532 info.vir_src1 = buf_ptr + src_size;
533 info.vir_dst0 = buf_ptr + src_size * 2;
534 info.vir_dst1 = buf_ptr + src_size * 2 + dst_size;
535
536 iep_init(&info.ctx);
537
538 pthread_t td;
539 pthread_create(&td, NULL, iep_process_thread, &info);
540 pthread_join(td, NULL);
541
542 if (info.ctx) {
543 iep_deinit(info.ctx);
544 info.ctx = NULL;
545 }
546
547 if (cfg.fp_src) {
548 fclose(cfg.fp_src);
549 cfg.fp_src = NULL;
550 }
551
552 if (cfg.fp_dst) {
553 fclose(cfg.fp_dst);
554 cfg.fp_dst = NULL;
555 }
556
557 if (cfg.ini) {
558 iniparser_freedict(cfg.ini);
559 cfg.ini = NULL;
560 if (cfg.yuv_enh)
561 mpp_free(cfg.yuv_enh);
562 if (cfg.rgb_enh)
563 mpp_free(cfg.rgb_enh);
564 if (cfg.dei_cfg)
565 mpp_free(cfg.dei_cfg);
566 if (cfg.colorcvt)
567 mpp_free(cfg.colorcvt);
568 }
569
570 mpp_buffer_put(buffer);
571
572 return 0;
573 }
574