Home | History | Annotate | Download | only in tests
      1 /*
      2  * test-image-blend.cpp - test cl image
      3  *
      4  *  Copyright (c) 2016 Intel Corporation
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  *
     18  * Author: Wind Yuan <feng.yuan (at) intel.com>
     19  */
     20 
     21 #include "test_common.h"
     22 #include "test_inline.h"
     23 #include <unistd.h>
     24 #include <getopt.h>
     25 #include <ocl/cl_device.h>
     26 #include <ocl/cl_context.h>
     27 #include <ocl/cl_blender.h>
     28 #include <image_file_handle.h>
     29 #include <ocl/cl_geo_map_handler.h>
     30 #if HAVE_LIBDRM
     31 #include <drm_display.h>
     32 #endif
     33 #include <dma_video_buffer.h>
     34 
     35 using namespace XCam;
     36 
     37 #define ENABLE_DMA_TEST 0
     38 
     39 static uint32_t input_format = V4L2_PIX_FMT_NV12;
     40 //static uint32_t output_format = V4L2_PIX_FMT_NV12;
     41 static uint32_t input_width0 = 1280, input_width1 = 1280;
     42 static uint32_t input_height = 960;
     43 static uint32_t output_width = 1920;
     44 static uint32_t output_height;
     45 static bool need_save_output = true;
     46 static bool enable_geo = false;
     47 static bool enable_seam = false;
     48 
     49 static int loop = 0;
     50 static uint32_t map_width = 51, map_height = 43;
     51 static const char *map0 = "fisheye0.csv";
     52 static const char *map1 = "fisheye1.csv";
     53 static char file_in0_name[XCAM_MAX_STR_SIZE], file_in1_name[XCAM_MAX_STR_SIZE], file_out_name[XCAM_MAX_STR_SIZE];
     54 
     55 static int read_map_data (const char* file, GeoPos *map, int width, int height);
     56 
     57 static void
     58 usage(const char* arg0)
     59 {
     60     printf ("Usage:\n"
     61             "%s --input0 file --input1 file --output file"
     62             " [--input-w0 width] [--input-w1 width] [--input-h height] [--output-w width] \n"
     63             "\t--input0, first image(NV12)\n"
     64             "\t--input1, second image(NV12)\n"
     65             "\t--output, output image(NV12) PREFIX\n"
     66             "\t--input-w0, optional, input width; default:1280\n"
     67             "\t--input-w1, optional, input width; default:1280\n"
     68             "\t--input-h,  optional, input height; default:960\n"
     69             "\t--output-w, optional, output width; default:1920, output height is same as input height.\n"
     70             "\t--loop,     optional, how many loops need to run for performance test, default 0; \n"
     71             "\t--save,     optional, save file or not, default true; select from [true/false]\n"
     72             "\t--enable-geo,  optional, enable geo map image frist. default: no\n"
     73             "\t--enable-seam, optional, enable seam finder in blending area. default: no\n"
     74             "\t--help,     usage\n",
     75             arg0);
     76 }
     77 
     78 static int
     79 geo_correct_image (
     80     SmartPtr<CLGeoMapHandler> geo_map_handler, SmartPtr<VideoBuffer> &in_out,
     81     GeoPos *geo_map0, uint32_t map_width, uint32_t map_height,
     82     char *file_name, bool need_save_output)
     83 {
     84     XCamReturn ret = XCAM_RETURN_NO_ERROR;
     85     SmartPtr<VideoBuffer> geo_out;
     86     geo_map_handler->set_map_data (geo_map0, map_width, map_height);
     87     ret = geo_map_handler->execute (in_out, geo_out);
     88     CHECK (ret, "geo map handler execute inpu0 failed");
     89     XCAM_ASSERT (geo_out.ptr ());
     90     in_out = geo_out;
     91 
     92     if (need_save_output) {
     93         char gdc_dump_name[1024];
     94         snprintf (gdc_dump_name, 1024, "gdc-%s", file_name);
     95         ImageFileHandle file_out;
     96         file_out.open (gdc_dump_name, "wb");
     97         file_out.write_buf (geo_out);
     98         file_out.close ();
     99         printf ("write gdc output buffer to: %s done\n", gdc_dump_name);
    100     }
    101     return 0;
    102 }
    103 
    104 #if (ENABLE_DMA_TEST) && (HAVE_LIBDRM)
    105 static SmartPtr<VideoBuffer>
    106 dma_buf_to_xcam_buf (
    107     SmartPtr<DrmDisplay> display, int dma_fd,
    108     uint32_t width, uint32_t height, uint32_t size,
    109     uint32_t aligned_width = 0, uint32_t aligned_height = 0)
    110 {
    111     /*
    112      *
    113      *  XCAM_ASSERT (native_handle_t.numFds == 1);
    114      *  XCAM_ASSERT (native_handle_t.data[0] > 0);
    115      * dma_fd = native_handle_t.data[0] ;
    116      */;
    117     VideoBufferInfo info;
    118     SmartPtr<VideoBuffer> dma_buf;
    119     SmartPtr<VideoBuffer> output;
    120 
    121     XCAM_ASSERT (dma_fd > 0);
    122 
    123     if (aligned_width == 0)
    124         aligned_width = XCAM_ALIGN_UP(width, 16);
    125     if (aligned_height == 0)
    126         aligned_height = XCAM_ALIGN_UP(height, 16);
    127 
    128     info.init (V4L2_PIX_FMT_NV12, width, height, aligned_width, aligned_height, size);
    129     dma_buf = new DmaVideoBuffer (info, dma_fd);
    130     output = display->convert_to_drm_bo_buf (display, dma_buf);
    131     if (!output.ptr ()) {
    132         XCAM_LOG_ERROR ("dma_buf(%d) convert to xcam_buf failed", dma_fd);
    133     }
    134 
    135     return output;
    136 }
    137 
    138 static SmartPtr<VideoBuffer>
    139 create_dma_buffer (SmartPtr<DrmDisplay> &display, const VideoBufferInfo &info)
    140 {
    141     SmartPtr<BufferPool> buf_pool = new DrmBoBufferPool (display);
    142     buf_pool->set_video_info (info);
    143     buf_pool->reserve (1);
    144     return buf_pool->get_buffer (buf_pool);
    145 }
    146 #endif
    147 
    148 static XCamReturn
    149 blend_images (
    150     SmartPtr<VideoBuffer> input0, SmartPtr<VideoBuffer> input1,
    151     SmartPtr<VideoBuffer> &output_buf,
    152     SmartPtr<CLBlender> blender)
    153 {
    154     blender->set_output_size (output_width, output_height);
    155     input0->attach_buffer (input1);
    156     return blender->execute (input0, output_buf);
    157 }
    158 
    159 int main (int argc, char *argv[])
    160 {
    161     GeoPos *geo_map0 = NULL, *geo_map1 = NULL;
    162     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    163     SmartPtr<CLImageHandler> image_handler;
    164     SmartPtr<CLGeoMapHandler> geo_map_handler;
    165     SmartPtr<CLBlender> blender;
    166     VideoBufferInfo input_buf_info0, input_buf_info1, output_buf_info;
    167     SmartPtr<CLContext> context;
    168     SmartPtr<BufferPool> buf_pool0, buf_pool1;
    169     ImageFileHandle file_in0, file_in1, file_out;
    170     SmartPtr<VideoBuffer> input0, input1;
    171     SmartPtr<VideoBuffer> output_buf;
    172     SmartPtr<VideoBuffer> read_buf;
    173 
    174 #define FAILED_GEO_FREE  { delete [] geo_map0; delete [] geo_map1; return -1; }
    175 
    176     const struct option long_opts[] = {
    177         {"input0", required_argument, NULL, 'i'},
    178         {"input1", required_argument, NULL, 'I'},
    179         {"output", required_argument, NULL, 'o'},
    180         {"input-w0", required_argument, NULL, 'w'},
    181         {"input-w1", required_argument, NULL, 'W'},
    182         {"input-h", required_argument, NULL, 'H'},
    183         {"output-w", required_argument, NULL, 'x'},
    184         {"loop", required_argument, NULL, 'l'},
    185         {"save", required_argument, NULL, 's'},
    186         {"enable-geo", no_argument, NULL, 'g'},
    187         {"enable-seam", no_argument, NULL, 'm'},
    188         {"help", no_argument, NULL, 'h'},
    189         {0, 0, 0, 0},
    190     };
    191 
    192     int opt = -1;
    193     while ((opt = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
    194         switch (opt) {
    195         case 'i':
    196             strncpy (file_in0_name, optarg, XCAM_MAX_STR_SIZE);
    197             break;
    198         case 'I':
    199             strncpy (file_in1_name, optarg, XCAM_MAX_STR_SIZE);
    200             break;
    201         case 'o':
    202             strncpy (file_out_name, optarg, XCAM_MAX_STR_SIZE);
    203             break;
    204         case 'w':
    205             input_width0 = atoi(optarg);
    206             break;
    207         case 'W':
    208             input_width1 = atoi(optarg);
    209             break;
    210         case 'H':
    211             input_height = atoi(optarg);
    212             break;
    213         case 'x':
    214             output_width = atoi(optarg);
    215             break;
    216         case 'l':
    217             loop = atoi(optarg);
    218             break;
    219         case 's':
    220             need_save_output = (strcasecmp (optarg, "false") == 0 ? false : true);
    221             break;
    222         case 'g':
    223             enable_geo = true;
    224             break;
    225         case 'm':
    226             enable_seam = true;
    227             break;
    228         case 'h':
    229             usage (argv[0]);
    230             return -1;
    231         default:
    232             printf ("getopt_long return unknown value:%c\n", opt);
    233             usage (argv[0]);
    234             return -1;
    235 
    236         }
    237     }
    238 
    239     if (optind < argc || argc < 2) {
    240         printf("unknown option %s\n", argv[optind]);
    241         usage (argv[0]);
    242         return -1;
    243     }
    244 
    245     printf ("Description-----------\n");
    246     printf ("input0 file:%s\n", file_in0_name);
    247     printf ("input1 file:%s\n", file_in1_name);
    248     printf ("output file PREFIX:%s\n", file_out_name);
    249     printf ("input0 width:%d\n", input_width0);
    250     printf ("input1 width:%d\n", input_width1);
    251     printf ("input/output height:%d\n", input_height);
    252     printf ("output width:%d\n", output_width);
    253     printf ("loop count:%d\n", loop);
    254     printf ("need save file:%s\n", need_save_output ? "true" : "false");
    255     printf ("enable seam mask:%s\n", (enable_seam ? "true" : "false"));
    256     printf ("----------------------\n");
    257 
    258     output_height = input_height;
    259     input_buf_info0.init (input_format, input_width0, input_height);
    260     input_buf_info1.init (input_format, input_width1, input_height);
    261     output_buf_info.init (input_format, output_width, output_height);
    262 #if (ENABLE_DMA_TEST) && (HAVE_LIBDRM)
    263     SmartPtr<DrmDisplay> display = DrmDisplay::instance ();
    264     buf_pool0 = new DrmBoBufferPool (display);
    265     buf_pool1 = new DrmBoBufferPool (display);
    266 #else
    267     buf_pool0 = new CLVideoBufferPool ();
    268     buf_pool1 = new CLVideoBufferPool ();
    269 #endif
    270     XCAM_ASSERT (buf_pool0.ptr () && buf_pool1.ptr ());
    271     buf_pool0->set_video_info (input_buf_info0);
    272     buf_pool1->set_video_info (input_buf_info1);
    273     if (!buf_pool0->reserve (2)) {
    274         XCAM_LOG_ERROR ("init buffer pool failed");
    275         return -1;
    276     }
    277     if (!buf_pool1->reserve (2)) {
    278         XCAM_LOG_ERROR ("init buffer pool failed");
    279         return -1;
    280     }
    281 
    282     context = CLDevice::instance ()->get_context ();
    283     blender = create_pyramid_blender (context, 2, true, enable_seam).dynamic_cast_ptr<CLBlender> ();
    284     XCAM_ASSERT (blender.ptr ());
    285 
    286 #if (ENABLE_DMA_TEST) && (HAVE_LIBDRM)
    287     int dma_fd0 = 30, dma_fd1 = 31, dma_fd_out = 32;
    288     input_buf_info0.init (
    289         input_format, input_width0, input_height, XCAM_ALIGN_UP (input_width0, 16), XCAM_ALIGN_UP(input_height, 16));
    290     input_buf_info1.init (
    291         input_format, input_width1, input_height, XCAM_ALIGN_UP (input_width1, 16), XCAM_ALIGN_UP(input_height, 16));
    292     output_buf_info.init (
    293         input_format, output_width, output_height, XCAM_ALIGN_UP (output_width, 16), XCAM_ALIGN_UP(output_height, 16));
    294     uint32_t in_size = input_buf_info0.aligned_width * input_buf_info0.aligned_height * 3 / 2;
    295     uint32_t out_size = output_buf_info.aligned_width * output_buf_info.aligned_height * 3 / 2;
    296     /* create dma fd, for buffer_handle_t just skip this segment, directly goto dma_buf_to_xcam_buf */
    297     SmartPtr<VideoBuffer> dma_buf0, dma_buf1, dma_buf_out;
    298     dma_buf0 = create_dma_buffer (display, input_buf_info0); //unit test
    299     dma_buf1 = create_dma_buffer (display, input_buf_info1); //unit test
    300     dma_buf_out = create_dma_buffer (display, output_buf_info); //unit test
    301     dma_fd0 = dma_buf0->get_fd (); //unit test
    302     dma_fd1 = dma_buf1->get_fd (); //unit test
    303     dma_fd_out = dma_buf_out->get_fd (); //unit test
    304     /*
    305       buffer_handle_t just go to here,
    306       dma_fd0 = native_handle_t.data[0];
    307       dma_fd1 = native_handle_t.data[0];
    308       dma_fd_out = native_handle_t.data[0];
    309      */
    310     printf ("DMA handles, buf0:%d, buf1:%d, buf_out:%d\n", dma_fd0, dma_fd1, dma_fd_out);
    311     input0 = dma_buf_to_xcam_buf (
    312                  display, dma_fd0, input_width0, input_height, in_size,
    313                  input_buf_info0.aligned_width, input_buf_info0.aligned_height);
    314     input1 = dma_buf_to_xcam_buf (
    315                  display, dma_fd1, input_width0, input_height, in_size,
    316                  input_buf_info1.aligned_width, input_buf_info1.aligned_height);
    317     output_buf = dma_buf_to_xcam_buf (
    318                      display, dma_fd_out, output_width, output_height, out_size,
    319                      output_buf_info.aligned_width, output_buf_info.aligned_height);
    320     blender->disable_buf_pool (true);
    321 #else
    322     input0 = buf_pool0->get_buffer (buf_pool0);
    323     input1 = buf_pool1->get_buffer (buf_pool1);
    324     XCAM_ASSERT (input0.ptr () && input1.ptr ());
    325 #endif
    326     //
    327     ret = file_in0.open (file_in0_name, "rb");
    328     CHECK_STATEMENT (ret, FAILED_GEO_FREE, "open input file(%s) failed", file_in0_name);
    329     read_buf = input0;
    330     ret = file_in0.read_buf (read_buf);
    331     CHECK_STATEMENT (ret, FAILED_GEO_FREE, "read buffer0 from (%s) failed", file_in0_name);
    332 
    333     ret = file_in1.open (file_in1_name, "rb");
    334     CHECK_STATEMENT (ret, FAILED_GEO_FREE, "open input file(%s) failed", file_in1_name);
    335     read_buf = input1;
    336     ret = file_in1.read_buf (read_buf);
    337     CHECK_STATEMENT (ret, FAILED_GEO_FREE, "read buffer1 from (%s) failed", file_in1_name);
    338 
    339     if (enable_geo) {
    340         geo_map_handler = create_geo_map_handler (context).dynamic_cast_ptr<CLGeoMapHandler> ();
    341         XCAM_ASSERT (geo_map_handler.ptr ());
    342 
    343         geo_map0 = new GeoPos[map_width * map_height];
    344         geo_map1 = new GeoPos[map_width * map_height];
    345         XCAM_ASSERT (geo_map0 && geo_map1);
    346         if (read_map_data (map0, geo_map0, map_width, map_height) <= 0 ||
    347                 read_map_data (map1, geo_map1, map_width, map_height) <= 0) {
    348             delete [] geo_map0;
    349             delete [] geo_map1;
    350             return -1;
    351         }
    352 
    353         geo_map_handler->set_map_uint (28.0f, 28.0f);
    354     }
    355 
    356     int i = 0;
    357     do {
    358         input0->clear_attached_buffers ();
    359         input1->clear_attached_buffers ();
    360 
    361         if (enable_geo) {
    362             geo_correct_image (geo_map_handler, input0, geo_map0, map_width, map_height, file_in0_name, need_save_output);
    363             geo_correct_image (geo_map_handler, input1, geo_map1, map_width, map_height, file_in1_name, need_save_output);
    364         }
    365 
    366         ret = blend_images (input0, input1, output_buf, blender);
    367         CHECK_STATEMENT (ret, FAILED_GEO_FREE, "blend_images execute failed");
    368         //printf ("DMA handles, output_buf:%d\n", output_buf->get_fd ());
    369 
    370         if (need_save_output) {
    371             char out_name[1024];
    372             snprintf (out_name, 1023, "%s.%02d", file_out_name, i);
    373 
    374             ret = file_out.open (out_name, "wb");
    375             CHECK_STATEMENT (ret, FAILED_GEO_FREE, "open output file(%s) failed", out_name);
    376             ret = file_out.write_buf (output_buf);
    377             CHECK_STATEMENT (ret, FAILED_GEO_FREE, "write buffer to (%s) failed", out_name);
    378             printf ("write output buffer to: %s done\n", out_name);
    379         } else {
    380             // check info
    381             ensure_gpu_buffer_done (output_buf);
    382         }
    383 
    384         FPS_CALCULATION (image_blend, XCAM_OBJ_DUR_FRAME_NUM);
    385         ++i;
    386     } while (i < loop);
    387 
    388     delete [] geo_map0;
    389     delete [] geo_map1;
    390 
    391     return ret;
    392 }
    393 
    394 //return count
    395 int read_map_data (const char* file, GeoPos *map, int width, int height)
    396 {
    397     char *ptr = NULL;
    398     FILE *p_f = fopen (file, "rb");
    399     CHECK_EXP (p_f, "open geo-map file(%s) failed", file);
    400 
    401 #define FAILED_READ_MAP { if (p_f) fclose(p_f); if (ptr) xcam_free (ptr); return -1; }
    402 
    403     CHECK_DECLARE (ERROR, fseek(p_f, 0L, SEEK_END) == 0, FAILED_READ_MAP, "seek to file(%s) end failed", file);
    404     size_t size = ftell (p_f);
    405     XCAM_ASSERT ((int)size != -1);
    406     fseek (p_f, 0L, SEEK_SET);
    407 
    408     ptr = (char*)xcam_malloc (size + 1);
    409     XCAM_ASSERT (ptr);
    410     CHECK_DECLARE (ERROR, fread (ptr, 1, size, p_f) == size, FAILED_READ_MAP, "read map file(%s)failed", file);
    411     ptr[size] = 0;
    412     fclose (p_f);
    413     p_f = NULL;
    414 
    415     char *str_num = NULL;
    416     char tokens[] = "\t ,\r\n";
    417     str_num = strtok (ptr, tokens);
    418     int count = 0;
    419     int x = 0, y = 0;
    420     while (str_num != NULL) {
    421         float num = strtof (str_num, NULL);
    422         //printf ("%.3f\n", num);
    423 
    424         x = count % width;
    425         y = count / (width * 2); // x,y
    426         if (y >= height)
    427             break;
    428 
    429         if (count % (width * 2) >= width)
    430             map[y * width + x].y = num;
    431         else
    432             map[y * width + x].x = num;
    433 
    434         ++count;
    435         str_num = strtok (NULL, tokens);
    436     }
    437     xcam_free (ptr);
    438     ptr = NULL;
    439     CHECK_EXP (y < height, "map data(%s) count larger than expected(%dx%dx2)", file, width, height);
    440     CHECK_EXP (count >= width * height * 2, "map data(%s) count less than expected(%dx%dx2)", file, width, height);
    441 
    442     printf ("read map(%s) x/y data count:%d\n", file, count);
    443     return count;
    444 }
    445 
    446