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