xref: /rockchip-linux_mpp/mpp/vproc/iep2/test/iep2_test.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /*
2  * Copyright 2020 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 "iep2_test"
18 
19 #include <string.h>
20 
21 #include "mpp_mem.h"
22 #include "mpp_time.h"
23 #include "mpp_debug.h"
24 #include "mpp_common.h"
25 #include "mpp_thread.h"
26 #include "mpp_buffer.h"
27 
28 #include "iep2_api.h"
29 #include "utils.h"
30 //#include "iniparser.h"
31 
32 #define MAX_URL_LEN                 (100)
33 
34 typedef struct iep2_test_cfg_t {
35     RK_S32      w;
36     RK_S32      h;
37     RK_S32      src_fmt;
38     RK_S32      src_swa;
39 
40     RK_S32      dst_fmt;
41     RK_S32      dst_swa;
42 
43     char        src_url[MAX_URL_LEN];
44     char        dst_url[MAX_URL_LEN];
45     char        slt_url[MAX_URL_LEN];
46 
47     FILE        *fp_src;
48     FILE        *fp_dst;
49     FILE        *fp_slt;
50     RK_U32      field_order;
51 } iep2_test_cfg;
52 
53 static OptionInfo iep2_test_cmd[] = {
54     {"w",   "width",            "input image width"},
55     {"h",   "height",           "input image height"},
56     {"c",   "format",           "input image format in ASCII string"},
57     {"i",   "src_file",         "input  image file name"},
58     {"C",   "dst_format",       "output image format in ASCII string"},
59     {"o",   "dst_file",         "output image file name"},
60     {"v",   "slt_file",         "slt verify data file"}
61 };
62 
iep2_test_help()63 static void iep2_test_help()
64 {
65     mpp_log("usage: iep2_test [options]\n");
66     mpp_log("*******************************\n");
67     show_options(iep2_test_cmd);
68     mpp_log("*******************************\n");
69     mpp_log("supported ASCII format strings:\n");
70     mpp_log("1 - yuv422sp\n");
71     mpp_log("2 - yuv422p [just for source format]\n");
72     mpp_log("3 - yuv420sp\n");
73     mpp_log("4 - yuv420p [just for source format]\n");
74     mpp_log("5 - yvu422sp\n");
75     mpp_log("6 - yvu420sp\n");
76     mpp_log("************ sample ***********\n");
77     mpp_log("iep2_test -w 720 -h 480 -c yuv420p -i input.yuv -C yuv420p -o output.yuv\n");
78 }
79 
str_to_iep2_fmt(const char * str)80 static RK_S32 str_to_iep2_fmt(const char *str)
81 {
82     RK_S32 fmt = -1;
83 
84     mpp_log("format %s\n", str);
85 
86     if (!strcmp(str, "yuv422sp") ||
87         !strcmp(str, "yuv422p") ||
88         !strcmp(str, "yvu422sp"))
89         fmt = IEP2_FMT_YUV422;
90     else if (!strcmp(str, "yuv420p") ||
91              !strcmp(str, "yuv420sp") ||
92              !strcmp(str, "yvu420sp"))
93         fmt = IEP2_FMT_YUV420;
94     else
95         mpp_err("invalid format %s\n", str);
96 
97     return fmt;
98 }
99 
str_to_iep2_swa(const char * str)100 static RK_S32 str_to_iep2_swa(const char *str)
101 {
102     RK_S32 swa = -1;
103 
104     if (!strcmp(str, "yuv422p") ||
105         !strcmp(str, "yuv420p"))
106         swa = IEP2_YUV_SWAP_P;
107     else if (!strcmp(str, "yvu422sp") ||
108              !strcmp(str, "yvu420sp"))
109         swa = IEP2_YUV_SWAP_SP_VU;
110     else if (!strcmp(str, "yuv422sp") ||
111              !strcmp(str, "yuv420sp"))
112         swa = IEP2_YUV_SWAP_SP_UV;
113     else
114         mpp_err("invalid format %s\n", str);
115 
116     return swa;
117 }
118 
check_input_cmd(iep2_test_cfg * cfg)119 static MPP_RET check_input_cmd(iep2_test_cfg *cfg)
120 {
121     MPP_RET ret = MPP_OK;
122 
123     if (cfg->w < 16 || cfg->w > 1920) {
124         mpp_err("invalid width %d\n", cfg->w);
125         ret = MPP_NOK;
126     }
127 
128     if (cfg->h < 4 || cfg->h > 1088) {
129         mpp_err("invalid height %d\n", cfg->h);
130         ret = MPP_NOK;
131     }
132 
133     mpp_log("src fmt %d, %d dst fmt %d, %d\n",
134             cfg->src_fmt, cfg->src_swa,
135             cfg->dst_fmt, cfg->dst_swa);
136 
137     if (cfg->src_fmt < IEP2_FMT_YUV422 ||
138         cfg->src_fmt > IEP2_FMT_YUV420 ||
139         cfg->src_swa < IEP2_YUV_SWAP_SP_UV ||
140         cfg->src_swa > IEP2_YUV_SWAP_P) {
141         mpp_err("invalid input format\n");
142         ret = MPP_NOK;
143     }
144 
145     if (cfg->fp_src == NULL) {
146         mpp_err("failed to open input file %s\n", cfg->src_url);
147         ret = MPP_NOK;
148     }
149 
150     if (cfg->dst_fmt < IEP2_FMT_YUV422 ||
151         cfg->dst_fmt > IEP2_FMT_YUV420 ||
152         cfg->dst_swa < IEP2_YUV_SWAP_SP_UV ||
153         cfg->dst_swa > IEP2_YUV_SWAP_SP_VU) {
154         mpp_err("invalid output format\n");
155         ret = MPP_NOK;
156     }
157 
158     return ret;
159 }
160 
get_frm_size(RK_S32 fmt,int w,int h)161 static inline size_t get_frm_size(RK_S32 fmt, int w, int h)
162 {
163     switch (fmt) {
164     case IEP2_FMT_YUV422:
165         return w * h * 2;
166     case IEP2_FMT_YUV420:
167         return w * h * 3 / 2;
168     default:
169         abort();
170         return 0;
171     }
172 }
173 
iep2_test_set_img(iep_com_ctx * ctx,int w,int h,IepImg * img,RK_S32 fd,IepCmd cmd)174 static void iep2_test_set_img(iep_com_ctx *ctx, int w, int h,
175                               IepImg *img, RK_S32 fd, IepCmd cmd)
176 {
177     RK_S32 y_size = w * h;
178     img->mem_addr = fd;
179     img->uv_addr = fd + (y_size << 10);
180     switch (img->format) {
181     case IEP2_FMT_YUV422:
182         img->v_addr = fd + ((y_size + y_size / 2) << 10);
183         break;
184     case IEP2_FMT_YUV420:
185         img->v_addr = fd + ((y_size + y_size / 4) << 10);
186         break;
187     default:
188         break;
189     }
190 
191     MPP_RET ret = ctx->ops->control(ctx->priv, cmd, img);
192     if (ret)
193         mpp_log_f("control %08x failed %d\n", cmd, ret);
194 }
195 
iep2_test(iep2_test_cfg * cfg)196 void iep2_test(iep2_test_cfg *cfg)
197 {
198     iep_com_ctx* iep2 = rockchip_iep2_api_alloc_ctx();
199     size_t srcfrmsize = get_frm_size(cfg->src_fmt, cfg->w, cfg->h);
200     size_t dstfrmsize = get_frm_size(cfg->dst_fmt, cfg->w, cfg->h);
201     MppBuffer srcbuf[3];
202     MppBuffer dstbuf[2];
203     RK_U8 *psrc[3];
204     RK_U8 *pdst[2];
205     RK_S32 fdsrc[3];
206     RK_S32 fddst[2];
207     int prev, curr, next;
208     struct iep2_api_params params;
209     RK_U32 i;
210     RK_S32 field_order = IEP2_FIELD_ORDER_TFF;
211     RK_S32 out_order = field_order == IEP2_FIELD_ORDER_TFF ? 0 : 1;
212     DataCrc checkcrc;
213     struct iep2_api_info dei_info;
214 
215     // NOTISE, used IepImg structure for version compatibility consideration,
216     // only addresses in this structure are useful in iep2
217     IepImg imgsrc[3];
218     IepImg imgdst[2];
219 
220     mpp_assert(iep2);
221     MppBufferGroup memGroup;
222     MPP_RET ret = mpp_buffer_group_get_internal(&memGroup, MPP_BUFFER_TYPE_DRM);
223     if (MPP_OK != ret) {
224         mpp_err("memGroup mpp_buffer_group_get failed\n");
225         mpp_assert(0);
226     }
227 
228     memset(&checkcrc, 0, sizeof(checkcrc));
229     checkcrc.sum = mpp_malloc(RK_ULONG, 512);
230 
231     mpp_buffer_get(memGroup, &srcbuf[0], srcfrmsize);
232     mpp_buffer_get(memGroup, &srcbuf[1], srcfrmsize);
233     mpp_buffer_get(memGroup, &srcbuf[2], srcfrmsize);
234     mpp_buffer_get(memGroup, &dstbuf[0], dstfrmsize);
235     mpp_buffer_get(memGroup, &dstbuf[1], dstfrmsize);
236     mpp_assert(srcbuf[0] && srcbuf[1] && srcbuf[2] && dstbuf[0] && dstbuf[1]);
237 
238     psrc[0] = mpp_buffer_get_ptr(srcbuf[0]);
239     psrc[1] = mpp_buffer_get_ptr(srcbuf[1]);
240     psrc[2] = mpp_buffer_get_ptr(srcbuf[2]);
241 
242     pdst[0] = mpp_buffer_get_ptr(dstbuf[0]);
243     pdst[1] = mpp_buffer_get_ptr(dstbuf[1]);
244 
245     fdsrc[0] = mpp_buffer_get_fd(srcbuf[0]);
246     fdsrc[1] = mpp_buffer_get_fd(srcbuf[1]);
247     fdsrc[2] = mpp_buffer_get_fd(srcbuf[2]);
248 
249     fddst[0] = mpp_buffer_get_fd(dstbuf[0]);
250     fddst[1] = mpp_buffer_get_fd(dstbuf[1]);
251 
252     iep2->ops->init(&iep2->priv);
253 
254     if (srcfrmsize > fread(psrc[0], 1, srcfrmsize, cfg->fp_src)) {
255         mpp_log("source exhaused\n");
256         goto ret;
257     }
258 
259     if (srcfrmsize > fread(psrc[1], 1, srcfrmsize, cfg->fp_src)) {
260         mpp_log("source exhaused\n");
261         goto ret;
262     }
263 
264     curr = 1;
265 
266     // set running mode.
267     /* if deinterlacing mode is one in the following list:
268         IEP2_DIL_MODE_I5O2,
269         IEP2_DIL_MODE_I5O1T,
270         IEP2_DIL_MODE_I5O1B,
271         IEP2_DIL_MODE_DECT
272        field order will auto detect by iep2 library.
273        so don't try to set field order during the playback.
274     */
275     params.ptype = IEP2_PARAM_TYPE_MODE;
276     params.param.mode.dil_mode = IEP2_DIL_MODE_I5O2;
277     params.param.mode.out_mode = IEP2_OUT_MODE_LINE;
278     params.param.mode.dil_order = cfg->field_order;
279 
280     iep2->ops->control(iep2->priv, IEP_CMD_SET_DEI_CFG, &params);
281 
282     // set the image format.
283     params.ptype = IEP2_PARAM_TYPE_COM;
284     params.param.com.sfmt = cfg->src_fmt;
285     params.param.com.dfmt = cfg->dst_fmt;
286     params.param.com.sswap = cfg->src_swa;
287     params.param.com.dswap = cfg->dst_swa;
288     params.param.com.width = cfg->w;
289     params.param.com.height = cfg->h;
290     params.param.com.hor_stride = cfg->w;
291     iep2->ops->control(iep2->priv, IEP_CMD_SET_DEI_CFG, &params);
292 
293     for (i = 0; i < MPP_ARRAY_ELEMS(imgsrc); i++)
294         imgsrc[i].format = cfg->src_fmt;
295 
296     for (i = 0; i < MPP_ARRAY_ELEMS(imgdst); i++)
297         imgdst[i].format = cfg->dst_fmt;
298 
299     while (1) {
300         prev = (curr - 1) % 3;
301         curr = curr % 3;
302         next = (curr + 1) % 3;
303 
304         if (srcfrmsize > fread(psrc[next], 1, srcfrmsize, cfg->fp_src)) {
305             mpp_log("source exhaused\n");
306             break;
307         }
308 
309         // notice the order of the input frames.
310         iep2_test_set_img(iep2, cfg->w, cfg->h,
311                           &imgsrc[curr], fdsrc[curr], IEP_CMD_SET_SRC);
312         iep2_test_set_img(iep2, cfg->w, cfg->h,
313                           &imgsrc[next], fdsrc[next], IEP_CMD_SET_DEI_SRC1);
314         iep2_test_set_img(iep2, cfg->w, cfg->h,
315                           &imgsrc[prev], fdsrc[prev], IEP_CMD_SET_DEI_SRC2);
316         iep2_test_set_img(iep2, cfg->w, cfg->h,
317                           &imgdst[0], fddst[0], IEP_CMD_SET_DST);
318         iep2_test_set_img(iep2, cfg->w, cfg->h,
319                           &imgdst[1], fddst[1], IEP_CMD_SET_DEI_DST1);
320 
321         memset(pdst[0], 0, dstfrmsize);
322         memset(pdst[1], 0, dstfrmsize);
323         iep2->ops->control(iep2->priv, IEP_CMD_RUN_SYNC, &dei_info);
324 
325         if (cfg->fp_slt) {
326             calc_data_crc(pdst[out_order], dstfrmsize, &checkcrc);
327             write_data_crc(cfg->fp_slt, &checkcrc);
328             calc_data_crc(pdst[1 - out_order], dstfrmsize, &checkcrc);
329             write_data_crc(cfg->fp_slt, &checkcrc);
330         }
331 
332         out_order = dei_info.dil_order == IEP2_FIELD_ORDER_BFF ? 1 : 0;
333 
334         if (cfg->fp_dst) {
335             if (dstfrmsize > fwrite(pdst[out_order], 1, dstfrmsize, cfg->fp_dst)) {
336                 mpp_err("destination dump failed\n");
337                 break;
338             }
339 
340             if (dstfrmsize > fwrite(pdst[1 - out_order], 1, dstfrmsize, cfg->fp_dst)) {
341                 mpp_err("destination dump failed\n");
342                 break;
343             }
344         }
345 
346         curr++;
347     }
348 
349 ret:
350     mpp_buffer_put(srcbuf[0]);
351     mpp_buffer_put(srcbuf[1]);
352     mpp_buffer_put(srcbuf[2]);
353 
354     mpp_buffer_put(dstbuf[0]);
355     mpp_buffer_put(dstbuf[1]);
356 
357     MPP_FREE(checkcrc.sum);
358 
359     if (memGroup) {
360         mpp_buffer_group_put(memGroup);
361         memGroup = NULL;
362     }
363 
364     iep2->ops->deinit(iep2->priv);
365 
366     rockchip_iep2_api_release_ctx(iep2);
367 }
368 
main(int argc,char ** argv)369 int main(int argc, char **argv)
370 {
371     iep2_test_cfg cfg;
372     int ch;
373 
374     if (argc < 2) {
375         iep2_test_help();
376         return 0;
377     }
378 
379     memset(&cfg, 0, sizeof(cfg));
380     cfg.src_fmt = IEP2_FMT_YUV420;
381     cfg.src_swa = IEP2_YUV_SWAP_SP_UV;
382     cfg.dst_fmt = IEP2_FMT_YUV420;
383     cfg.dst_swa = IEP2_YUV_SWAP_SP_UV;
384 
385     /// get options
386     opterr = 0;
387     while ((ch = getopt(argc, argv, "i:w:h:c:o:C:v:f:")) != -1) {
388         switch (ch) {
389         case 'w': {
390             cfg.w = atoi(optarg);
391         } break;
392         case 'h': {
393             cfg.h = atoi(optarg);
394         } break;
395         case 'c': {
396             cfg.src_fmt = str_to_iep2_fmt(optarg);
397             cfg.src_swa = str_to_iep2_swa(optarg);
398         } break;
399         case 'C': {
400             cfg.dst_fmt = str_to_iep2_fmt(optarg);
401             cfg.dst_swa = str_to_iep2_swa(optarg);
402         } break;
403         case 'i': {
404             mpp_log("input filename: %s\n", optarg);
405             strncpy(cfg.src_url, optarg, sizeof(cfg.src_url) - 1);
406             cfg.fp_src = fopen(cfg.src_url, "rb");
407         } break;
408         case 'o': {
409             mpp_log("output filename: %s\n", optarg);
410             strncpy(cfg.dst_url, optarg, sizeof(cfg.dst_url) - 1);
411             cfg.fp_dst = fopen(cfg.dst_url, "w+b");
412         } break;
413         case 'v': {
414             mpp_log("verify file: %s\n", optarg);
415             strncpy(cfg.slt_url, optarg, sizeof(cfg.slt_url) - 1);
416             cfg.fp_slt = fopen(cfg.slt_url, "w+b");
417         } break;
418         case 'f': {
419             if (!strcmp(optarg, "TFF"))
420                 cfg.field_order = IEP2_FIELD_ORDER_TFF;
421             else
422                 cfg.field_order = IEP2_FIELD_ORDER_BFF;
423         } break;
424         default: {
425         } break;
426         }
427     }
428 
429     if (check_input_cmd(&cfg)) {
430         mpp_err("failed to pass cmd line check\n");
431         iep2_test_help();
432         return -1;
433     }
434 
435     iep2_test(&cfg);
436 
437     if (cfg.fp_src) {
438         fclose(cfg.fp_src);
439         cfg.fp_src = NULL;
440     }
441 
442     if (cfg.fp_dst) {
443         fclose(cfg.fp_dst);
444         cfg.fp_dst = NULL;
445     }
446 
447     if (cfg.fp_slt) {
448         fclose(cfg.fp_slt);
449         cfg.fp_slt = NULL;
450     }
451 
452     return 0;
453 }
454