Fixed Svace critical issues
[platform/core/api/mediavision.git] / test / testsuites / barcode / barcode_test_suite.c
1 /**
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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 #include <mv_barcode.h>
18
19 #include <image_helper.h>
20 #include <mv_private.h>
21
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #include <libswscale/swscale.h>
28 #include <libavcodec/avcodec.h>
29 #include <libavutil/pixfmt.h>
30
31 typedef struct {
32         mv_barcode_type_e type;
33         mv_barcode_qr_ecc_e ecc;
34         mv_barcode_qr_mode_e mode;
35         int version;
36         size_t width;
37         size_t height;
38         mv_barcode_image_format_e out_image_format;
39         mv_colorspace_e colorspace;
40         char *message;
41         char *file_name;
42         char *out_file_name;
43         unsigned char *out_buffer_ptr;
44 } barcode_model_s;
45
46 typedef enum {
47         MV_TS_GENERATE_TO_IMAGE_FCN,
48         MV_TS_GENERATE_TO_SOURCE_FCN
49 } generation_fcn_e;
50
51 int convert_rgb_to(unsigned char *src_buffer, unsigned char **dst_buffer,
52                 image_data_s image_data, mv_colorspace_e dst_colorspace,
53                 unsigned long *cvt_buffer_size)
54 {
55         enum PixelFormat pixel_format = PIX_FMT_NONE;
56
57         MEDIA_VISION_FUNCTION_ENTER();
58
59         switch (dst_colorspace) {
60         case MEDIA_VISION_COLORSPACE_Y800:
61                 pixel_format = PIX_FMT_GRAY8;
62                 break;
63         case MEDIA_VISION_COLORSPACE_I420:
64                 pixel_format = PIX_FMT_YUV420P;
65                 break;
66         case MEDIA_VISION_COLORSPACE_NV12:
67                 pixel_format = PIX_FMT_NV12;
68                 break;
69         case MEDIA_VISION_COLORSPACE_YV12:
70                 /* the same as I420 with inversed U and V */
71                 pixel_format = PIX_FMT_YUV420P;
72                 break;
73         case MEDIA_VISION_COLORSPACE_NV21:
74                 pixel_format = PIX_FMT_NV21;
75                 break;
76         case MEDIA_VISION_COLORSPACE_YUYV:
77                 pixel_format = PIX_FMT_YUYV422;
78                 break;
79         case MEDIA_VISION_COLORSPACE_UYVY:
80                 pixel_format = PIX_FMT_UYVY422;
81                 break;
82         case MEDIA_VISION_COLORSPACE_422P:
83                 pixel_format = PIX_FMT_YUV422P;
84                 break;
85         case MEDIA_VISION_COLORSPACE_RGB565:
86                 pixel_format = PIX_FMT_RGB565BE;
87                 break;
88         case MEDIA_VISION_COLORSPACE_RGBA:
89                 pixel_format = PIX_FMT_RGBA;
90                 break;
91         case MEDIA_VISION_COLORSPACE_RGB888:
92                 *cvt_buffer_size = image_data.image_width * image_data.image_height * 3;
93                 (*dst_buffer) = (unsigned char*)malloc(*cvt_buffer_size);
94                 memcpy(*dst_buffer, src_buffer, *cvt_buffer_size);
95
96                 MEDIA_VISION_FUNCTION_LEAVE();
97                 return MEDIA_VISION_ERROR_NONE;
98         default:
99                 MEDIA_VISION_FUNCTION_LEAVE();
100                 return MEDIA_VISION_ERROR_NOT_SUPPORTED;
101         }
102
103         AVPicture src_picture;
104         AVPicture dst_picture;
105
106         avpicture_fill(&src_picture, (uint8_t*)src_buffer, PIX_FMT_RGB24,
107                         image_data.image_width, image_data.image_height);
108
109         avpicture_alloc(&dst_picture, pixel_format,
110                         image_data.image_width, image_data.image_height);
111
112         struct SwsContext *context = sws_getContext(
113                         image_data.image_width, image_data.image_height, PIX_FMT_RGB24,
114                         image_data.image_width, image_data.image_height, pixel_format,
115                         SWS_FAST_BILINEAR, 0, 0, 0);
116
117         sws_scale(context, (const uint8_t * const *)src_picture.data,
118                         src_picture.linesize, 0, image_data.image_height,
119                         dst_picture.data, dst_picture.linesize);
120
121         *cvt_buffer_size = avpicture_get_size(pixel_format,
122                         image_data.image_width, image_data.image_height);
123         (*dst_buffer) = (unsigned char*)malloc(*cvt_buffer_size);
124         memcpy(*dst_buffer, dst_picture.data[0], *cvt_buffer_size);
125
126         avpicture_free(&dst_picture);
127
128         MEDIA_VISION_FUNCTION_LEAVE();
129
130         return MEDIA_VISION_ERROR_NONE;
131 }
132
133 int find_min_x(const mv_quadrangle_s *quadrangle, int *minX)
134 {
135         MEDIA_VISION_FUNCTION_ENTER();
136
137         if (NULL == quadrangle) {
138                 MEDIA_VISION_FUNCTION_LEAVE();
139                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
140         }
141
142         *minX = quadrangle->points[0].x;
143         *minX = quadrangle->points[1].x < *minX ? quadrangle->points[1].x : *minX;
144         *minX = quadrangle->points[2].x < *minX ? quadrangle->points[2].x : *minX;
145         *minX = quadrangle->points[3].x < *minX ? quadrangle->points[3].x : *minX;
146
147         MEDIA_VISION_FUNCTION_LEAVE();
148
149         return MEDIA_VISION_ERROR_NONE;
150 }
151
152 int find_min_y(const mv_quadrangle_s *quadrangle, int *minY)
153 {
154         MEDIA_VISION_FUNCTION_ENTER();
155
156         if (NULL == quadrangle) {
157                 MEDIA_VISION_FUNCTION_LEAVE();
158                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
159         }
160
161         *minY = quadrangle->points[0].y;
162         *minY = quadrangle->points[1].y < *minY ? quadrangle->points[1].y : *minY;
163         *minY = quadrangle->points[2].y < *minY ? quadrangle->points[2].y : *minY;
164         *minY = quadrangle->points[3].y < *minY ? quadrangle->points[3].y : *minY;
165
166         MEDIA_VISION_FUNCTION_LEAVE();
167
168         return MEDIA_VISION_ERROR_NONE;
169 }
170
171 int find_max_x(const mv_quadrangle_s *quadrangle, int *maxX)
172 {
173         MEDIA_VISION_FUNCTION_ENTER();
174
175         if (NULL == quadrangle) {
176                 MEDIA_VISION_FUNCTION_LEAVE();
177                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
178         }
179
180         *maxX = quadrangle->points[0].x;
181         *maxX = quadrangle->points[1].x > *maxX ? quadrangle->points[1].x : *maxX;
182         *maxX = quadrangle->points[2].x > *maxX ? quadrangle->points[2].x : *maxX;
183         *maxX = quadrangle->points[3].x > *maxX ? quadrangle->points[3].x : *maxX;
184
185         MEDIA_VISION_FUNCTION_LEAVE();
186
187         return MEDIA_VISION_ERROR_NONE;
188 }
189
190 int find_max_y(const mv_quadrangle_s *quadrangle, int *maxY)
191 {
192         MEDIA_VISION_FUNCTION_ENTER();
193
194         if (NULL == quadrangle) {
195                 MEDIA_VISION_FUNCTION_LEAVE();
196                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
197         }
198
199         *maxY = quadrangle->points[0].y;
200         *maxY = quadrangle->points[1].y > *maxY ? quadrangle->points[1].y : *maxY;
201         *maxY = quadrangle->points[2].y > *maxY ? quadrangle->points[2].y : *maxY;
202         *maxY = quadrangle->points[3].y > *maxY ? quadrangle->points[3].y : *maxY;
203
204         MEDIA_VISION_FUNCTION_LEAVE();
205
206         return MEDIA_VISION_ERROR_NONE;
207 }
208
209 bool _mv_engine_config_supported_attribute(mv_config_attribute_type_e attribute_type,
210                 const char *attribute_name, void *user_data)
211 {
212         printf("Callback call for engine configuration attribute\n");
213
214         if (user_data == NULL)
215                 return false;
216
217         mv_engine_config_h mv_engine_config = (mv_engine_config_h *)user_data;
218
219         int int_value = 0;
220         double double_value = 0.0;
221         bool bool_value = false;
222         char str_value[1024];
223         switch (attribute_type) {
224         case MV_ENGINE_CONFIG_ATTR_TYPE_DOUBLE:
225                 if (MEDIA_VISION_ERROR_KEY_NOT_AVAILABLE ==
226                         mv_engine_config_get_double_attribute(
227                                                 mv_engine_config, attribute_name, &double_value)) {
228                         printf("Default double attribute %s wasn't set in engine\n",
229                                         attribute_name);
230                         return false;
231                 }
232                 printf("Default double attribute %s was set to %f in engine\n",
233                                         attribute_name, double_value);
234                 break;
235         case MV_ENGINE_CONFIG_ATTR_TYPE_INTEGER:
236                 if (MEDIA_VISION_ERROR_KEY_NOT_AVAILABLE ==
237                         mv_engine_config_get_int_attribute(
238                                                 mv_engine_config, attribute_name, &int_value)) {
239                         printf("Default integer attribute %s wasn't set in engine\n",
240                                         attribute_name);
241                         return false;
242                 }
243                 printf("Default interget attribute %s was set to %d in engine\n",
244                                 attribute_name, int_value);
245                 break;
246         case MV_ENGINE_CONFIG_ATTR_TYPE_BOOLEAN:
247                 if (MEDIA_VISION_ERROR_KEY_NOT_AVAILABLE ==
248                         mv_engine_config_get_bool_attribute(
249                                                 mv_engine_config, attribute_name, &bool_value)) {
250                         printf("Default bool attribute %s wasn't set in engine\n",
251                                         attribute_name);
252                         return false;
253                 }
254                 printf("Default bool attribute %s was set to %s in engine\n",
255                                         attribute_name,  bool_value ? "TRUE" : "FALSE");
256                 break;
257         case MV_ENGINE_CONFIG_ATTR_TYPE_STRING:
258                 if (MEDIA_VISION_ERROR_KEY_NOT_AVAILABLE ==
259                         mv_engine_config_get_string_attribute(
260                                                 mv_engine_config, attribute_name, &str_value)) {
261                         printf("Default string ttribute %s wasn't set in engine\n",
262                                         attribute_name);
263                         return false;
264                 }
265                 printf("Default string attribute %s was set to %s in engine\n",
266                                 attribute_name, str_value);
267                 break;
268         default:
269                 printf("Not supported attribute type\n");
270                 return false;
271         }
272
273         return true;
274 }
275
276 void barcode_detected_cb(
277                 mv_source_h source,
278                 mv_engine_config_h engine_cfg,
279                 const mv_quadrangle_s *barcodes_locations,
280                 const char *messages[],
281                 const mv_barcode_type_e *types,
282                 int number_of_barcodes,
283                 void *user_data)
284 {
285         MEDIA_VISION_FUNCTION_ENTER();
286
287         printf("%i barcodes were detected on the image.\n", number_of_barcodes);
288         if (number_of_barcodes > 0) {
289                 int is_source_data_loaded = 0;
290
291                 char *file_name = NULL;
292                 unsigned char *out_buffer = NULL;
293                 unsigned char *draw_buffer = NULL;
294                 unsigned int buf_size = 0;
295                 image_data_s image_data = { 0, 0, MEDIA_VISION_COLORSPACE_INVALID };
296                 /* Check Media Vision source: */
297                 if (MEDIA_VISION_ERROR_NONE != mv_source_get_buffer(source, &out_buffer, &buf_size) ||
298                         MEDIA_VISION_ERROR_NONE != mv_source_get_width(source, &(image_data.image_width)) ||
299                         MEDIA_VISION_ERROR_NONE != mv_source_get_height(source, &(image_data.image_height)) ||
300                         MEDIA_VISION_ERROR_NONE != mv_source_get_colorspace(source, &(image_data.image_colorspace)) ||
301                         user_data == NULL) {
302                         printf("ERROR: Creating out image is impossible.\n");
303                 } else {
304                         file_name = ((barcode_model_s *)user_data)->out_file_name;
305                         draw_buffer = ((barcode_model_s *)user_data)->out_buffer_ptr;
306                         image_data.image_colorspace = MEDIA_VISION_COLORSPACE_RGB888;
307                         is_source_data_loaded = 1;
308                 }
309
310                 int i = 0;
311                 for (i = 0; i < number_of_barcodes; ++i) {
312                         const char *cur_message = messages[i];
313                         mv_barcode_type_e cur_type = types[i];
314                         const char *str_type = NULL;
315                         switch (cur_type) {
316                         case MV_BARCODE_QR:
317                                 str_type = "QR";
318                                 break;
319                         case MV_BARCODE_UPC_A:
320                                 str_type = "UPC-A";
321                                 break;
322                         case MV_BARCODE_UPC_E:
323                                 str_type = "UPC-E";
324                                 break;
325                         case MV_BARCODE_EAN_8:
326                         case MV_BARCODE_EAN_13:
327                                 str_type = "EAN-8/13";
328                                 break;
329                         case MV_BARCODE_CODE128:
330                                 str_type = "CODE128";
331                                 break;
332                         case MV_BARCODE_CODE39:
333                                 str_type = "CODE39";
334                                 break;
335                         case MV_BARCODE_I2_5:
336                                 str_type = "I25";
337                                 break;
338                         default:
339                                 str_type = "Undetected";
340                                 break;
341                         }
342                         printf("\tBarcode %i : type is %s\n", i, str_type);
343                         if (cur_message != NULL)
344                                 printf("\t            message is %s\n", cur_message);
345                         else
346                                 printf("\t            message wasn't detected\n");
347
348                         if (is_source_data_loaded == 1) {
349                                 int minX = 0;
350                                 int minY = 0;
351                                 int maxX = 0;
352                                 int maxY = 0;
353                                 if (MEDIA_VISION_ERROR_NONE != find_min_x(&barcodes_locations[i], &minX) ||
354                                         MEDIA_VISION_ERROR_NONE != find_min_y(&barcodes_locations[i], &minY) ||
355                                         MEDIA_VISION_ERROR_NONE != find_max_x(&barcodes_locations[i], &maxX) ||
356                                         MEDIA_VISION_ERROR_NONE != find_max_y(&barcodes_locations[i], &maxY)) {
357                                         continue;
358                                 }
359
360                                 const int rectangle_thickness = 6;
361                                 const int drawing_color[] = {255, 0, 0};
362                                 if (MEDIA_VISION_ERROR_NONE != draw_rectangle_on_buffer(
363                                         minX,
364                                         minY,
365                                         maxX,
366                                         maxY,
367                                         drawing_color,
368                                         rectangle_thickness,
369                                         &image_data,
370                                         draw_buffer)) {
371                                         continue;
372                                 }
373                         }
374                 }
375
376                 if (file_name != NULL &&
377                         MEDIA_VISION_ERROR_NONE == save_image_from_buffer(file_name, draw_buffer, &image_data, 100)) {
378                         printf("Image was generated as %s\n", file_name);
379                 } else {
380                         printf("ERROR: Failed to generate output file. Check file name and permissions. \n");
381                 }
382
383                 printf("\n");
384         }
385
386         MEDIA_VISION_FUNCTION_LEAVE();
387 }
388
389 int generate_barcode_to_image(barcode_model_s model)
390 {
391         MEDIA_VISION_FUNCTION_ENTER();
392
393         if (model.message   == NULL ||
394                 model.file_name == NULL) {
395                 MEDIA_VISION_FUNCTION_LEAVE();
396                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
397         }
398
399         LOGI("Call the mv_barcode_generate_image() function");
400
401         const int err = mv_barcode_generate_image(
402                                 NULL,
403                                 model.message,
404                                 model.width,
405                                 model.height,
406                                 model.type,
407                                 model.mode,
408                                 model.ecc,
409                                 model.version,
410                                 model.file_name,
411                                 model.out_image_format);
412
413         MEDIA_VISION_FUNCTION_LEAVE();
414
415         return err;
416 }
417
418 int generate_barcode_to_source(barcode_model_s model)
419 {
420         MEDIA_VISION_FUNCTION_ENTER();
421
422         if (model.message   == NULL ||
423                 model.file_name == NULL) {
424                 MEDIA_VISION_FUNCTION_LEAVE();
425
426                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
427         }
428
429         LOGI("mv_source_h creation started");
430
431         mv_source_h source = NULL;
432         int err = mv_create_source(&source);
433         if (MEDIA_VISION_ERROR_NONE != err) {
434                 printf("ERROR: Error occurred when trying to create Media Vision "
435                                 "source. Error code: %i\n", err);
436
437                         MEDIA_VISION_FUNCTION_LEAVE();
438
439                         return err;
440         }
441
442         LOGI("mv_source_h creation finished");
443
444         LOGI("Call the mv_barcode_generate_source() function");
445
446         err = mv_barcode_generate_source(
447                         NULL,
448                         model.message,
449                         model.type,
450                         model.mode,
451                         model.ecc,
452                         model.version,
453                         source);
454
455         if (MEDIA_VISION_ERROR_NONE != err) {
456                 printf("ERROR: Error occurred during generation barcode to the "
457                                 "Media Vision source. Error code: %i\n", err);
458
459                 const int err2 = mv_destroy_source(source);
460                 if (MEDIA_VISION_ERROR_NONE != err2) {
461                         printf("ERROR: Error occurred when try to destroy Media Vision source."
462                                         "Error code: %i\n", err2);
463                 }
464
465                 MEDIA_VISION_FUNCTION_LEAVE();
466
467                 return err;
468         }
469
470         unsigned char *data_buffer = NULL;
471         unsigned int buffer_size = 0;
472         unsigned int image_width = 0;
473         unsigned int image_height = 0;
474         mv_colorspace_e image_colorspace = MEDIA_VISION_COLORSPACE_INVALID;
475
476         bool is_source_corrupted = false;
477         err = mv_source_get_buffer(source, &data_buffer, &buffer_size);
478         if (MEDIA_VISION_ERROR_NONE != err) {
479                 printf("ERROR: Error occurred when trying to get buffer from "
480                                 "Media Vision source. Error code: %i\n", err);
481                 is_source_corrupted = true;
482         }
483
484         err = mv_source_get_width(source, &image_width);
485         if (MEDIA_VISION_ERROR_NONE != err) {
486                 printf("ERROR: Error occurred when trying to get width of "
487                                 "Media Vision source. Error code: %i\n", err);
488                 is_source_corrupted = true;
489         }
490
491         err = mv_source_get_height(source, &image_height);
492         if (MEDIA_VISION_ERROR_NONE != err) {
493                 printf("ERROR: Error occurred when trying to get height of "
494                                 "Media Vision source. Error code: %i\n", err);
495                 is_source_corrupted = true;
496         }
497
498         err = mv_source_get_colorspace(source, &image_colorspace);
499         if (MEDIA_VISION_ERROR_NONE != err) {
500                 printf("ERROR: Error occurred when trying to get colorspace of "
501                                 "Media Vision source. Error code: %i\n", err);
502                 is_source_corrupted = true;
503         }
504
505         if (is_source_corrupted) {
506                 err = mv_destroy_source(source);
507                 if (MEDIA_VISION_ERROR_NONE != err) {
508                         printf("ERROR: Error occurred when trying to destroy Media Vision "
509                                         "source. Error code: %i\n", err);
510                 }
511
512                 MEDIA_VISION_FUNCTION_LEAVE();
513
514                 return MEDIA_VISION_ERROR_INTERNAL;
515         }
516
517         const image_data_s image_data = { image_width, image_height, image_colorspace };
518
519         char *jpeg_file_name = "";
520         if (0 == strcmp(model.file_name + strlen(model.file_name) - 4, ".jpg") ||
521                 0 == strcmp(model.file_name + strlen(model.file_name) - 5, ".jpeg")) {
522                 jpeg_file_name = (char*)malloc(strlen(model.file_name) + 1);
523                 strcpy(jpeg_file_name, model.file_name);
524                 jpeg_file_name[strlen(model.file_name)] = '\0';
525         } else {
526                 jpeg_file_name = (char*)malloc(strlen(model.file_name) + 5);
527                 strcpy(jpeg_file_name, model.file_name);
528                 strcpy(jpeg_file_name + strlen(model.file_name), ".jpg");
529                 jpeg_file_name[strlen(model.file_name) + 4] = '\0';
530         }
531
532         save_image_from_buffer(jpeg_file_name, data_buffer, &image_data, 100);
533
534         free(jpeg_file_name);
535
536         const int err2 = mv_destroy_source(source);
537         if (MEDIA_VISION_ERROR_NONE != err2) {
538                 printf("ERROR: Error occurred when try to destroy Media Vision source."
539                         "Error code: %i\n", err2);
540         }
541
542         MEDIA_VISION_FUNCTION_LEAVE();
543
544         return err;
545 }
546
547 int detect_barcode(barcode_model_s model, mv_rectangle_s roi)
548 {
549         MEDIA_VISION_FUNCTION_ENTER();
550
551         unsigned char *data_buffer = NULL;
552         unsigned long buffer_size = 0;
553         image_data_s image_data;
554
555         int err = load_image_to_buffer(
556                         model.file_name, &data_buffer, &buffer_size, &image_data);
557         if (MEDIA_VISION_ERROR_NONE != err) {
558                 printf("ERROR: Errors were occurred during opening the file!!! code: %i\n", err);
559
560                 MEDIA_VISION_FUNCTION_LEAVE();
561
562                 return err;
563         }
564
565         unsigned char *converted_buffer = NULL;
566         unsigned long converted_buffer_size = 0;
567         err = convert_rgb_to(data_buffer, &converted_buffer, image_data, model.colorspace, &converted_buffer_size);
568         if (MEDIA_VISION_ERROR_NONE != err) {
569                 printf("ERROR: Can't convert to the selected colorspace!!! code: %i\n", err);
570
571                 MEDIA_VISION_FUNCTION_LEAVE();
572
573                 return err;
574         }
575
576         model.out_buffer_ptr = data_buffer;
577
578         mv_engine_config_h mv_engine_config;
579         err = mv_create_engine_config(&mv_engine_config);
580         if (MEDIA_VISION_ERROR_NONE != err)
581                 printf("ERROR: Errors were occurred during creating the media engine config: %i\n", err);
582
583         mv_engine_config_foreach_supported_attribute(_mv_engine_config_supported_attribute, mv_engine_config);
584
585         mv_engine_config_set_int_attribute(mv_engine_config, MV_BARCODE_DETECT_ATTR_TARGET, MV_BARCODE_DETECT_ATTR_TARGET_2D_BARCODE);
586
587         mv_source_h source;
588         err = mv_create_source(&source);
589         if (MEDIA_VISION_ERROR_NONE != err) {
590                 printf("ERROR: Errors were occurred during creating the source!!! code: %i\n", err);
591
592                 MEDIA_VISION_FUNCTION_LEAVE();
593
594                 return err;
595         }
596
597         err = mv_source_fill_by_buffer(source, converted_buffer, converted_buffer_size,
598                         image_data.image_width, image_data.image_height, model.colorspace);
599         if (MEDIA_VISION_ERROR_NONE != err) {
600                 printf("ERROR: Errors were occurred during filling the source!!! code: %i\n", err);
601
602                 MEDIA_VISION_FUNCTION_LEAVE();
603
604                 return err;
605         }
606
607         if (converted_buffer != NULL)
608                 free(converted_buffer);
609
610         err = mv_barcode_detect(source, mv_engine_config, roi, barcode_detected_cb, &model);
611
612         if (data_buffer != NULL)
613                 destroy_loaded_buffer(data_buffer);
614
615         if (MEDIA_VISION_ERROR_NONE != err) {
616                 printf("ERROR: Errors were occurred during barcode detection!!! code: %i\n", err);
617
618                 MEDIA_VISION_FUNCTION_LEAVE();
619
620                 return err;
621         }
622
623         err = mv_destroy_source(source);
624         if (MEDIA_VISION_ERROR_NONE != err)
625                 printf("ERROR: Errors were occurred during destroying the source!!! code: %i\n", err);
626
627         err = mv_destroy_engine_config(mv_engine_config);
628         if (MEDIA_VISION_ERROR_NONE != err)
629                 printf("ERROR: Error were occurred during destroying the source!!! code: %i\n", err);
630
631         MEDIA_VISION_FUNCTION_LEAVE();
632
633         return err;
634 }
635
636 int input_string(const char *prompt, size_t max_len, char **string)
637 {
638         MEDIA_VISION_FUNCTION_ENTER();
639
640         printf("\n");
641         printf("%s ", prompt);
642
643         if (scanf("\n") != 0) {
644                 MEDIA_VISION_FUNCTION_LEAVE();
645                 return -1;
646         }
647
648         char buffer[max_len];
649         int last_char = 0;
650         buffer[last_char] = '\0';
651         buffer[sizeof(buffer) - 1] = ~'\0';
652         if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
653                 MEDIA_VISION_FUNCTION_LEAVE();
654                 return -1;
655         }
656         size_t real_string_len = strlen(buffer);
657         buffer[real_string_len - 1] = '\0';
658         *string = (char*)malloc(real_string_len * sizeof(char));
659         strcpy(*string, buffer);
660
661         size_t str_len = strlen(*string);
662
663         MEDIA_VISION_FUNCTION_LEAVE();
664
665         return str_len;
666 }
667
668 int input_size(const char *prompt, size_t max_size, size_t *size)
669 {
670         MEDIA_VISION_FUNCTION_ENTER();
671
672         printf("\n");
673         printf("%s ", prompt);
674
675         if (scanf("%20zu", size) == 0) {
676                 if (scanf("%*[^\n]%*c") != 0) {
677                         printf("ERROR: Reading the input line error.\n");
678                         MEDIA_VISION_FUNCTION_LEAVE();
679                         return -1;
680                 }
681                 printf("ERROR: Incorrect input.\n");
682                 MEDIA_VISION_FUNCTION_LEAVE();
683                 return -1;
684         }
685
686         int ret = (*size > max_size ? -1 : 0);
687
688         MEDIA_VISION_FUNCTION_LEAVE();
689
690         return ret;
691 }
692
693 int input_int(const char *prompt, int min_value, int max_value, int *value)
694 {
695         MEDIA_VISION_FUNCTION_ENTER();
696
697         printf("\n");
698         printf("%s ", prompt);
699
700         if (scanf("%20i", value) == 0) {
701                 if (scanf("%*[^\n]%*c") != 0) {
702                         printf("ERROR: Reading the input line error.\n");
703                         MEDIA_VISION_FUNCTION_LEAVE();
704                         return -1;
705                 }
706                 printf("ERROR: Incorrect input.\n");
707                 MEDIA_VISION_FUNCTION_LEAVE();
708                 return -1;
709         }
710
711         int ret = (*value < min_value || *value > max_value ? -1 : 0);
712
713         MEDIA_VISION_FUNCTION_LEAVE();
714
715         return ret;
716 }
717
718 int show_menu(const char *title, const int *options, const char **names, int cnt)
719 {
720         MEDIA_VISION_FUNCTION_ENTER();
721
722         printf("***************************\n");
723         printf("* %23s *\n", title);
724         printf("*-------------------------*\n");
725         int i = 0;
726         for (i = 0; i < cnt; ++i)
727                 printf("* %2i. %19s *\n", options[i], names[i]);
728
729         printf("***************************\n\n");
730         int selection = 0;
731         printf("Your choise: ");
732         if (scanf("%20i", &selection) == 0) {
733                 if (scanf("%*[^\n]%*c") != 0) {
734                         printf("ERROR: Reading the input line error.\n");
735                         MEDIA_VISION_FUNCTION_LEAVE();
736                         return -1;
737                 }
738                 printf("ERROR: Incorrect input.\n");
739         }
740
741         MEDIA_VISION_FUNCTION_LEAVE();
742
743         return selection;
744 }
745
746 mv_barcode_type_e select_type(void)
747 {
748         mv_barcode_type_e selected_type = MV_BARCODE_UNDEFINED;
749         int sel_opt = 0;
750         const int options[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
751         const char *names[8] = { "qr", "upca", "upce", "ean8", "ean13", "code39", "code128", "interleave25" };
752
753         MEDIA_VISION_FUNCTION_ENTER();
754
755         while (sel_opt == 0) {
756                 sel_opt = show_menu("Select barcode type:", options, names, 8);
757
758                 switch (sel_opt) {
759                 case 1:
760                         selected_type = MV_BARCODE_QR;
761                         break;
762                 case 2:
763                         selected_type = MV_BARCODE_UPC_A;
764                         break;
765                 case 3:
766                         selected_type = MV_BARCODE_UPC_E;
767                         break;
768                 case 4:
769                         selected_type = MV_BARCODE_EAN_8;
770                         break;
771                 case 5:
772                         selected_type = MV_BARCODE_EAN_13;
773                         break;
774                 case 6:
775                         selected_type = MV_BARCODE_CODE39;
776                         break;
777                 case 7:
778                         selected_type = MV_BARCODE_CODE128;
779                         break;
780                 case 8:
781                         selected_type = MV_BARCODE_I2_5;
782                         break;
783                 default:
784                         sel_opt = 0;
785                         break;
786                 }
787         }
788
789         MEDIA_VISION_FUNCTION_LEAVE();
790
791         return selected_type;
792 }
793
794 mv_barcode_qr_mode_e select_mode(void)
795 {
796         mv_barcode_qr_mode_e selected_mode = MV_BARCODE_QR_MODE_UNAVAILABLE;
797         int sel_opt = 0;
798         const int options[4] = { 1, 2, 3, 4 };
799         const char *names[4] = { "numeric", "alphanumeric", "byte", "utf8" };
800
801         MEDIA_VISION_FUNCTION_ENTER();
802
803         while (sel_opt == 0) {
804                 sel_opt = show_menu("Select encoding mode:", options, names, 4);
805                 switch (sel_opt) {
806                 case 1:
807                         selected_mode = MV_BARCODE_QR_MODE_NUMERIC;
808                         break;
809                 case 2:
810                         selected_mode = MV_BARCODE_QR_MODE_ALPHANUMERIC;
811                         break;
812                 case 3:
813                         selected_mode = MV_BARCODE_QR_MODE_BYTE;
814                         break;
815                 case 4:
816                         selected_mode = MV_BARCODE_QR_MODE_UTF8;
817                         break;
818                 default:
819                         sel_opt = 0;
820                         break;
821                 }
822         }
823
824         MEDIA_VISION_FUNCTION_LEAVE();
825
826         return selected_mode;
827 }
828
829 mv_barcode_qr_ecc_e select_ecc(void)
830 {
831         mv_barcode_qr_ecc_e selected_ecc = MV_BARCODE_QR_ECC_UNAVAILABLE;
832         int sel_opt = 0;
833         const int options[4] = { 1, 2, 3, 4 };
834         const char *names[4] = { "low", "medium", "quartile", "high" };
835
836         MEDIA_VISION_FUNCTION_ENTER();
837
838         while (sel_opt == 0) {
839                 sel_opt = show_menu("Select ECC level:", options, names, 4);
840                 switch (sel_opt) {
841                 case 1:
842                         selected_ecc = MV_BARCODE_QR_ECC_LOW;
843                         break;
844                 case 2:
845                         selected_ecc = MV_BARCODE_QR_ECC_MEDIUM;
846                         break;
847                 case 3:
848                         selected_ecc = MV_BARCODE_QR_ECC_QUARTILE;
849                         break;
850                 case 4:
851                         selected_ecc = MV_BARCODE_QR_ECC_HIGH;
852                         break;
853                 default:
854                         sel_opt = 0;
855                         break;
856                 }
857         }
858
859         MEDIA_VISION_FUNCTION_LEAVE();
860
861         return selected_ecc;
862 }
863
864 int select_version(void)
865 {
866         MEDIA_VISION_FUNCTION_ENTER();
867
868         int sel_opt = 0;
869         while (sel_opt == 0) {
870                 const int options[2] = {1, 40};
871                 const char *names[2] = { "1..", "..40" };
872                 sel_opt = show_menu("Select QR version:", options, names, 2);
873                 if (sel_opt < 1 || sel_opt > 40)
874                         sel_opt = 0;
875         }
876
877         MEDIA_VISION_FUNCTION_LEAVE();
878
879         return sel_opt;
880 }
881
882 generation_fcn_e select_gen_function(void)
883 {
884         generation_fcn_e ret_fcn_type = MV_TS_GENERATE_TO_IMAGE_FCN;
885         int sel_opt = 0;
886         const int options[2] = { 1, 2 };
887         const char *names[2] = { "Generate to file", "Generate to source" };
888
889         MEDIA_VISION_FUNCTION_ENTER();
890
891         while (sel_opt == 0) {
892                 sel_opt = show_menu("Select API function:", options, names, 2);
893                 switch (sel_opt) {
894                 case 1:
895                         ret_fcn_type = MV_TS_GENERATE_TO_IMAGE_FCN;
896                         break;
897                 case 2:
898                         ret_fcn_type = MV_TS_GENERATE_TO_SOURCE_FCN;
899                         break;
900                 default:
901                         sel_opt = 0;
902                         break;
903                 }
904         }
905
906         MEDIA_VISION_FUNCTION_LEAVE();
907
908         return ret_fcn_type;
909 }
910
911 mv_barcode_image_format_e select_file_format(void)
912 {
913         mv_barcode_image_format_e image_format = MV_BARCODE_IMAGE_FORMAT_JPG;
914         int sel_opt = 0;
915         const int options[3] = { 1, 2, 3 };
916         const char *names[3] = { "BMP", "JPG", "PNG" };
917
918         MEDIA_VISION_FUNCTION_ENTER();
919
920         while (sel_opt == 0) {
921                 sel_opt = show_menu("Select file format:", options, names, 3);
922                 switch (sel_opt) {
923                 case 1:
924                         image_format = MV_BARCODE_IMAGE_FORMAT_BMP;
925                         break;
926                 case 2:
927                         image_format = MV_BARCODE_IMAGE_FORMAT_JPG;
928                         break;
929                 case 3:
930                         image_format = MV_BARCODE_IMAGE_FORMAT_PNG;
931                         break;
932                 default:
933                         sel_opt = 0;
934                         break;
935                 }
936         }
937
938         MEDIA_VISION_FUNCTION_LEAVE();
939
940         return image_format;
941 }
942
943 int perform_detect()
944 {
945         MEDIA_VISION_FUNCTION_ENTER();
946
947         barcode_model_s detect_model = {
948                 MV_BARCODE_UNDEFINED,
949                 MV_BARCODE_QR_ECC_UNAVAILABLE,
950                 MV_BARCODE_QR_MODE_UNAVAILABLE,
951                 0, 0, 0,
952                 MV_BARCODE_IMAGE_FORMAT_PNG,
953                 MEDIA_VISION_COLORSPACE_INVALID,
954                 NULL, NULL, NULL, NULL };
955
956         while (input_string("Input file name to be analyzed:", 1024, &(detect_model.file_name)) == -1)
957                 printf("Incorrect input! Try again.\n");
958
959         LOGI("Barcode input image has been specified");
960
961         mv_rectangle_s roi = { {0, 0}, 0, 0 };
962
963         while (input_int("Input x coordinate for ROI top left vertex:", 0, 10000, &(roi.point.x)) == -1)
964                 printf("Incorrect input! Try again.\n");
965
966         while (input_int("Input y coordinate for ROI top left vertex:", 0, 10000, &(roi.point.y)) == -1)
967                 printf("Incorrect input! Try again.\n");
968
969         while (input_int("Input ROI width:", 0, 10000, &(roi.width)) == -1)
970                 printf("Incorrect input! Try again.\n");
971
972         while (input_int("Input ROI height:", 0, 10000, &(roi.height)) == -1)
973                 printf("Incorrect input! Try again.\n");
974
975         LOGI("Region of interest (ROI) to detect barcode into has been specified");
976
977         while (input_string("Input file name to be generated:", 1024, &(detect_model.out_file_name)) == -1)
978                 printf("Incorrect input! Try again.\n");
979
980         LOGI("Barcode output image has been specified");
981
982         const int options[11] = { MEDIA_VISION_COLORSPACE_Y800,
983                                                                 MEDIA_VISION_COLORSPACE_I420,
984                                                                 MEDIA_VISION_COLORSPACE_NV12,
985                                                                 MEDIA_VISION_COLORSPACE_YV12,
986                                                                 MEDIA_VISION_COLORSPACE_NV21,
987                                                                 MEDIA_VISION_COLORSPACE_YUYV,
988                                                                 MEDIA_VISION_COLORSPACE_UYVY,
989                                                                 MEDIA_VISION_COLORSPACE_422P,
990                                                                 MEDIA_VISION_COLORSPACE_RGB565,
991                                                                 MEDIA_VISION_COLORSPACE_RGB888,
992                                                                 MEDIA_VISION_COLORSPACE_RGBA };
993         const char *names[11] = { "Y800", "I420", "NV12", "YV12", "NV21",
994                                                                 "YUYV", "UYVY", "422P", "RGB565",
995                                                                 "RGB888", "RGBA" };
996
997         while (true) {
998                 int sel_opt = show_menu("Select colorspace to test detector on:", options, names, 11);
999                 if (sel_opt < MEDIA_VISION_COLORSPACE_Y800 ||
1000                         sel_opt > MEDIA_VISION_COLORSPACE_RGBA) {
1001                         continue;
1002                 }
1003                 detect_model.colorspace = (mv_colorspace_e)sel_opt;
1004                 LOGI("User selection is %i", sel_opt);
1005                 break;
1006         }
1007
1008         int err = detect_barcode(detect_model, roi);
1009
1010         if (detect_model.file_name != NULL)
1011                 free(detect_model.file_name);
1012
1013         if (detect_model.out_file_name != NULL)
1014                 free(detect_model.out_file_name);
1015
1016         if (err != MEDIA_VISION_ERROR_NONE)
1017                 LOGE("Barcode detection failed with error code (0x%08x)", err);
1018
1019         MEDIA_VISION_FUNCTION_LEAVE();
1020
1021         return err;
1022 }
1023
1024 int perform_generate(void)
1025 {
1026         MEDIA_VISION_FUNCTION_ENTER();
1027
1028         barcode_model_s generate_model = {
1029                         MV_BARCODE_UNDEFINED,
1030                         MV_BARCODE_QR_ECC_UNAVAILABLE,
1031                         MV_BARCODE_QR_MODE_UNAVAILABLE,
1032                         0, 0, 0,
1033                         MV_BARCODE_IMAGE_FORMAT_PNG,
1034                         MEDIA_VISION_COLORSPACE_INVALID,
1035                         NULL, NULL, NULL, NULL };
1036
1037         generation_fcn_e gen_fcn = select_gen_function();
1038         generate_model.type = select_type();
1039         LOGI("Barcode type has been selected");
1040
1041         if (generate_model.type == MV_BARCODE_QR) {
1042                 generate_model.mode = select_mode();
1043                 LOGI("Barcode encoding mode has been selected");
1044                 generate_model.ecc = select_ecc();
1045                 LOGI("Barcode ecc level has been selected");
1046                 generate_model.version = select_version();
1047                 LOGI("Barcode version has been selected");
1048         }
1049
1050         if (gen_fcn == MV_TS_GENERATE_TO_IMAGE_FCN) {
1051                 generate_model.out_image_format = select_file_format();
1052                 LOGI("Barcode output image format has been selected");
1053         }
1054
1055         while (input_string("Input message:", 7089, &generate_model.message) == -1)
1056                 printf("Incorrect input! Try again.\n");
1057
1058         LOGI("Barcode message has been specified");
1059
1060         while (input_string("Input file name:", 1024, &generate_model.file_name) == -1)
1061                 printf("Incorrect input! Try again.\n");
1062
1063         LOGI("Barcode output file name has been specified");
1064
1065         if (gen_fcn == MV_TS_GENERATE_TO_IMAGE_FCN) {
1066                 while (input_size("Input image width:", 10000, &generate_model.width) == -1)
1067                         printf("Incorrect input! Try again.\n");
1068
1069                 LOGI("Barcode output file width has been specified");
1070
1071                 while (input_size("Input image height:", 10000, &generate_model.height) == -1)
1072                         printf("Incorrect input! Try again.\n");
1073
1074                 LOGI("Barcode output file height has been specified");
1075         }
1076
1077         const int err =
1078                         gen_fcn == MV_TS_GENERATE_TO_IMAGE_FCN ?
1079                         generate_barcode_to_image(generate_model) :
1080                         generate_barcode_to_source(generate_model);
1081
1082         if (generate_model.message != NULL)
1083                 free(generate_model.message);
1084
1085         if (generate_model.file_name != NULL)
1086                 free(generate_model.file_name);
1087
1088         if (err != MEDIA_VISION_ERROR_NONE) {
1089                 LOGE("Barcode generation failed with error code (0x%08x)", err);
1090                 printf("ERROR: Errors were occurred during barcode generation!!!\n");
1091                 MEDIA_VISION_FUNCTION_LEAVE();
1092                 return err;
1093         }
1094
1095         LOGI("Barcode output file has been generated");
1096         printf("\nBarcode image was successfully generated.\n");
1097
1098         MEDIA_VISION_FUNCTION_LEAVE();
1099
1100         return 0;
1101 }
1102
1103 int main(void)
1104 {
1105         LOGI("Media Vision Testsuite is launched.");
1106
1107         int err = MEDIA_VISION_ERROR_NONE;
1108
1109         int sel_opt = 0;
1110         const int options[2] = { 1, 2 };
1111         const char *names[2] = { "Generate", "Detect" };
1112
1113         while (sel_opt == 0) {
1114                 sel_opt = show_menu("Select action:", options, names, 2);
1115                 switch (sel_opt) {
1116                 case 1:
1117                         LOGI("Start the barcode generation flow");
1118                         err = perform_generate();
1119                         break;
1120                 case 2:
1121                         LOGI("Start the barcode detection flow");
1122                         err = perform_detect();
1123                         break;
1124                 default:
1125                         sel_opt = 0;
1126                         continue;
1127                 }
1128
1129                 int do_another = 0;
1130
1131                 if (err != MEDIA_VISION_ERROR_NONE)
1132                         printf("ERROR: Action is finished with error code: %i\n", err);
1133
1134                 sel_opt = 0;
1135                 const int options_last[2] = { 1, 2 };
1136                 const char *names_last[2] = { "YES", "NO" };
1137
1138                 while (sel_opt == 0) {
1139                         sel_opt = show_menu("Perform another action?", options_last, names_last, 2);
1140                         switch (sel_opt) {
1141                         case 1:
1142                                 do_another = 1;
1143                                 break;
1144                         case 2:
1145                                 do_another = 0;
1146                                 break;
1147                         default:
1148                                 sel_opt = 0;
1149                                 break;
1150                         }
1151                 }
1152                 LOGI("User selection is %i", sel_opt);
1153
1154                 sel_opt = (do_another == 1 ? 0 : sel_opt);
1155         }
1156
1157         LOGI("Media Vision Testsuite is closed.");
1158
1159         return err;
1160 }