Home | History | Annotate | Download | only in tests
      1 /*
      2  * test-image-stitching.cpp - test image stitching
      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: Yinhang Liu <yinhangx.liu (at) intel.com>
     19  * Author: Wind Yuan <feng.yuan (at) intel.com>
     20  */
     21 
     22 #include "test_common.h"
     23 #include "test_inline.h"
     24 #include <unistd.h>
     25 #include <getopt.h>
     26 #include <image_file_handle.h>
     27 #include <calibration_parser.h>
     28 #include <ocl/cl_device.h>
     29 #include <ocl/cl_context.h>
     30 #include <ocl/cl_fisheye_handler.h>
     31 #include <ocl/cl_image_360_stitch.h>
     32 #include <ocl/cl_utils.h>
     33 #if HAVE_OPENCV
     34 #include <ocl/cv_base_class.h>
     35 #endif
     36 
     37 #define XCAM_TEST_STITCH_DEBUG 0
     38 #define XCAM_ALIGNED_WIDTH 16
     39 
     40 #define CHECK_ACCESS(fliename) \
     41     if (access (fliename, F_OK) != 0) {            \
     42         XCAM_LOG_ERROR ("%s not found", fliename); \
     43         return false;                              \
     44     }
     45 
     46 using namespace XCam;
     47 
     48 #if XCAM_TEST_STITCH_DEBUG
     49 static void dbg_write_image (
     50     SmartPtr<CLContext> context, SmartPtr<CLImage360Stitch> image_360,
     51     SmartPtr<VideoBuffer> input_bufs[], SmartPtr<VideoBuffer> output_buf,
     52     SmartPtr<VideoBuffer> top_view_buf, SmartPtr<VideoBuffer> rectified_view_buf,
     53     bool all_in_one, int fisheye_num, int input_count);
     54 #endif
     55 
     56 static bool
     57 parse_calibration_params (
     58     IntrinsicParameter intrinsic_param[],
     59     ExtrinsicParameter extrinsic_param[],
     60     int fisheye_num)
     61 {
     62     CalibrationParser calib_parser;
     63 
     64     char intrinsic_path[1024], extrinsic_path[1024];
     65     for(int index = 0; index < fisheye_num; index++) {
     66         switch (index) {
     67         case 0:
     68             strncpy (intrinsic_path, "./calib_params/intrinsic_camera_front.txt", 1023);
     69             strncpy (extrinsic_path, "./calib_params/extrinsic_camera_front.txt", 1023);
     70             break;
     71         case 1:
     72             strncpy (intrinsic_path, "./calib_params/intrinsic_camera_right.txt", 1023);
     73             strncpy (extrinsic_path, "./calib_params/extrinsic_camera_right.txt", 1023);
     74             break;
     75         case 2:
     76             strncpy (intrinsic_path, "./calib_params/intrinsic_camera_rear.txt", 1023);
     77             strncpy (extrinsic_path, "./calib_params/extrinsic_camera_rear.txt", 1023);
     78             break;
     79         case 3:
     80             strncpy (intrinsic_path, "./calib_params/intrinsic_camera_left.txt", 1023);
     81             strncpy (extrinsic_path, "./calib_params/extrinsic_camera_left.txt", 1023);
     82             break;
     83         default:
     84             XCAM_LOG_ERROR ("bowl view only support 4-camera mode");
     85             return false;
     86         }
     87 
     88         CHECK_ACCESS (intrinsic_path);
     89         CHECK_ACCESS (extrinsic_path);
     90 
     91         if (!xcam_ret_is_ok (
     92                     calib_parser.parse_intrinsic_file (intrinsic_path, intrinsic_param[index]))) {
     93             XCAM_LOG_ERROR ("parse fisheye:%d intrinsic file:%s failed.", index, intrinsic_path);
     94             return false;
     95         }
     96         if (!xcam_ret_is_ok (
     97                     calib_parser.parse_extrinsic_file (extrinsic_path, extrinsic_param[index]))) {
     98             XCAM_LOG_ERROR ("parse fisheye:%d extrinsic file:%s failed.", index, extrinsic_path);
     99             return false;
    100         }
    101 
    102         extrinsic_param[index].trans_x += TEST_CAMERA_POSITION_OFFSET_X;
    103     }
    104 
    105     return true;
    106 }
    107 
    108 XCamReturn
    109 read_file_to_video_buffer (
    110     ImageFileHandle &file,
    111     uint32_t width,
    112     uint32_t height,
    113     uint32_t row_pitch,
    114     SmartPtr<VideoBuffer> &buf)
    115 {
    116     size_t size = row_pitch * height / 2 * 3;
    117     uint8_t *nv12_mem = (uint8_t *) xcam_malloc0 (sizeof (uint8_t) * size);
    118     XCAM_ASSERT (nv12_mem);
    119 
    120     XCamReturn ret = file.read_file (nv12_mem, size);
    121     if (ret != XCAM_RETURN_NO_ERROR) {
    122         xcam_free (nv12_mem);
    123         return ret;
    124     }
    125 
    126     uint32_t offset_uv = row_pitch * height;
    127     convert_nv12_mem_to_video_buffer (nv12_mem, width, height, row_pitch, offset_uv, buf);
    128     XCAM_ASSERT (buf.ptr ());
    129 
    130     xcam_free (nv12_mem);
    131     return XCAM_RETURN_NO_ERROR;
    132 }
    133 
    134 void usage(const char* arg0)
    135 {
    136     printf ("Usage:\n"
    137             "%s --input file --output file\n"
    138             "\t--input             input image(NV12)\n"
    139             "\t--output            output image(NV12)\n"
    140             "\t--input-w           optional, input width, default: 1920\n"
    141             "\t--input-h           optional, input height, default: 1080\n"
    142             "\t--output-w          optional, output width, default: 1920\n"
    143             "\t--output-h          optional, output width, default: 960\n"
    144             "\t--res-mode          optional, image resolution mode, select from [1080p/1080p4/4k], default: 1080p\n"
    145             "\t--surround-mode     optional, stitching surround mode, select from [sphere, bowl], default: sphere\n"
    146             "\t--scale-mode        optional, image scaling mode, select from [local/global], default: local\n"
    147             "\t--enable-seam       optional, enable seam finder in blending area, default: no\n"
    148             "\t--enable-fisheyemap optional, enable fisheye map, default: no\n"
    149             "\t--enable-lsc        optional, enable lens shading correction, default: no\n"
    150 #if HAVE_OPENCV
    151             "\t--fm-ocl            optional, enable ocl for feature match, select from [true/false], default: false\n"
    152 #endif
    153             "\t--fisheye-num       optional, the number of fisheye lens, default: 2\n"
    154             "\t--all-in-one        optional, all fisheye in one image, select from [true/false], default: true\n"
    155             "\t--save              optional, save file or not, select from [true/false], default: true\n"
    156             "\t--framerate         optional, framerate of saved video, default: 30.0\n"
    157             "\t--loop              optional, how many loops need to run for performance test, default: 1\n"
    158             "\t--help              usage\n",
    159             arg0);
    160 }
    161 
    162 int main (int argc, char *argv[])
    163 {
    164     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    165     SmartPtr<CLContext> context;
    166     SmartPtr<BufferPool> buf_pool[XCAM_STITCH_FISHEYE_MAX_NUM];
    167     ImageFileHandle file_in[XCAM_STITCH_FISHEYE_MAX_NUM];
    168     ImageFileHandle file_out;
    169     SmartPtr<VideoBuffer> input_buf, output_buf, top_view_buf, rectified_view_buf;
    170     VideoBufferInfo input_buf_info, output_buf_info, top_view_buf_info, rectified_view_buf_info;
    171     SmartPtr<CLImage360Stitch> image_360;
    172 
    173     uint32_t input_format = V4L2_PIX_FMT_NV12;
    174     uint32_t input_width = 1920;
    175     uint32_t input_height = 1080;
    176     uint32_t output_height = 960;
    177     uint32_t output_width = output_height * 2;
    178 
    179     uint32_t top_view_width = 1920;
    180     uint32_t top_view_height = 1080;
    181 
    182     uint32_t rectified_view_width = 1920;
    183     uint32_t rectified_view_height = 1080;
    184 
    185     int loop = 1;
    186     bool enable_seam = false;
    187     bool enable_fisheye_map = false;
    188     bool enable_lsc = false;
    189     CLBlenderScaleMode scale_mode = CLBlenderScaleLocal;
    190     StitchResMode res_mode = StitchRes1080P;
    191     SurroundMode surround_mode = BowlView;
    192 
    193     IntrinsicParameter intrinsic_param[XCAM_STITCH_FISHEYE_MAX_NUM];
    194     ExtrinsicParameter extrinsic_param[XCAM_STITCH_FISHEYE_MAX_NUM];
    195 
    196 #if HAVE_OPENCV
    197     bool fm_ocl = false;
    198 #endif
    199     int fisheye_num = 2;
    200     bool all_in_one = true;
    201     bool need_save_output = true;
    202     double framerate = 30.0;
    203 
    204     const char *file_in_name[XCAM_STITCH_FISHEYE_MAX_NUM] = {NULL};
    205     const char *file_out_name = NULL;
    206     const char *top_view_filename = "top_view.mp4";
    207     const char *rectified_view_filename = "rectified_view.mp4";
    208 
    209     int input_count = 0;
    210 
    211     const struct option long_opts[] = {
    212         {"input", required_argument, NULL, 'i'},
    213         {"output", required_argument, NULL, 'o'},
    214         {"input-w", required_argument, NULL, 'w'},
    215         {"input-h", required_argument, NULL, 'h'},
    216         {"output-w", required_argument, NULL, 'W'},
    217         {"output-h", required_argument, NULL, 'H'},
    218         {"res-mode", required_argument, NULL, 'R'},
    219         {"surround-mode", required_argument, NULL, 'r'},
    220         {"scale-mode", required_argument, NULL, 'c'},
    221         {"enable-seam", no_argument, NULL, 'S'},
    222         {"enable-fisheyemap", no_argument, NULL, 'F'},
    223         {"enable-lsc", no_argument, NULL, 'L'},
    224 #if HAVE_OPENCV
    225         {"fm-ocl", required_argument, NULL, 'O'},
    226 #endif
    227         {"fisheye-num", required_argument, NULL, 'N'},
    228         {"all-in-one", required_argument, NULL, 'A'},
    229         {"save", required_argument, NULL, 's'},
    230         {"framerate", required_argument, NULL, 'f'},
    231         {"loop", required_argument, NULL, 'l'},
    232         {"help", no_argument, NULL, 'e'},
    233         {NULL, 0, NULL, 0},
    234     };
    235 
    236     int opt = -1;
    237     while ((opt = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
    238         switch (opt) {
    239         case 'i':
    240             XCAM_ASSERT (optarg);
    241             file_in_name[input_count] = optarg;
    242             input_count++;
    243             break;
    244         case 'o':
    245             XCAM_ASSERT (optarg);
    246             file_out_name = optarg;
    247             break;
    248         case 'w':
    249             input_width = atoi(optarg);
    250             break;
    251         case 'h':
    252             input_height = atoi(optarg);
    253             break;
    254         case 'W':
    255             output_width = atoi(optarg);
    256             break;
    257         case 'H':
    258             output_height = atoi(optarg);
    259             break;
    260         case 'R':
    261             if (!strcasecmp (optarg, "1080p"))
    262                 res_mode = StitchRes1080P;
    263             else if (!strcasecmp (optarg, "1080p4"))
    264                 res_mode = StitchRes1080P4;
    265             else if (!strcasecmp (optarg, "4k"))
    266                 res_mode = StitchRes4K;
    267             else {
    268                 XCAM_LOG_ERROR ("incorrect resolution mode");
    269                 return -1;
    270             }
    271             break;
    272         case 'r':
    273             if (!strcasecmp (optarg, "sphere"))
    274                 surround_mode = SphereView;
    275             else if(!strcasecmp (optarg, "bowl"))
    276                 surround_mode = BowlView;
    277             else {
    278                 XCAM_LOG_ERROR ("incorrect surround mode");
    279                 return -1;
    280             }
    281             break;
    282         case 'c':
    283             if (!strcasecmp (optarg, "local"))
    284                 scale_mode = CLBlenderScaleLocal;
    285             else if (!strcasecmp (optarg, "global"))
    286                 scale_mode = CLBlenderScaleGlobal;
    287             else {
    288                 XCAM_LOG_ERROR ("incorrect scaling mode");
    289                 return -1;
    290             }
    291             break;
    292         case 'S':
    293             enable_seam = true;
    294             break;
    295         case 'F':
    296             enable_fisheye_map = true;
    297             break;
    298         case 'L':
    299             enable_lsc = true;
    300             break;
    301 #if HAVE_OPENCV
    302         case 'O':
    303             fm_ocl = (strcasecmp (optarg, "true") == 0 ? true : false);
    304             break;
    305 #endif
    306         case 'N':
    307             fisheye_num = atoi(optarg);
    308             if (fisheye_num > XCAM_STITCH_FISHEYE_MAX_NUM) {
    309                 XCAM_LOG_ERROR ("fisheye number should not be greater than %d\n", XCAM_STITCH_FISHEYE_MAX_NUM);
    310                 return -1;
    311             }
    312             break;
    313         case 'A':
    314             all_in_one = (strcasecmp (optarg, "false") == 0 ? false : true);
    315             break;
    316         case 's':
    317             need_save_output = (strcasecmp (optarg, "false") == 0 ? false : true);
    318             break;
    319         case 'f':
    320             framerate = atof(optarg);
    321             break;
    322         case 'l':
    323             loop = atoi(optarg);
    324             break;
    325         case 'e':
    326             usage (argv[0]);
    327             return -1;
    328         default:
    329             XCAM_LOG_ERROR ("getopt_long return unknown value:%c", opt);
    330             usage (argv[0]);
    331             return -1;
    332         }
    333     }
    334 
    335     if (optind < argc || argc < 2) {
    336         XCAM_LOG_ERROR ("unknown option %s", argv[optind]);
    337         usage (argv[0]);
    338         return -1;
    339     }
    340 
    341     if (!all_in_one && input_count != fisheye_num) {
    342         XCAM_LOG_ERROR ("multiple-input mode: conflicting input number(%d) and fisheye number(%d)",
    343                         input_count, fisheye_num);
    344         return -1;
    345     }
    346 
    347     for (int i = 0; i < input_count; i++) {
    348         if (!file_in_name[i]) {
    349             XCAM_LOG_ERROR ("input[%d] path is NULL", i);
    350             return -1;
    351         }
    352     }
    353 
    354     if (!file_out_name) {
    355         XCAM_LOG_ERROR ("output path is NULL");
    356         return -1;
    357     }
    358 
    359     output_width = XCAM_ALIGN_UP (output_width, XCAM_ALIGNED_WIDTH);
    360     output_height = XCAM_ALIGN_UP (output_height, XCAM_ALIGNED_WIDTH);
    361     // if (output_width != output_height * 2) {
    362     //     XCAM_LOG_ERROR ("incorrect output size width:%d height:%d", output_width, output_height);
    363     //     return -1;
    364     // }
    365 
    366 #if !HAVE_OPENCV
    367     if (need_save_output) {
    368         XCAM_LOG_WARNING ("non-OpenCV mode, can't save video");
    369         need_save_output = false;
    370     }
    371 #endif
    372 
    373     printf ("Description------------------------\n");
    374     if (all_in_one)
    375         printf ("input file:\t\t%s\n", file_in_name[0]);
    376     else {
    377         for (int i = 0; i < input_count; i++)
    378             printf ("input file %d:\t\t%s\n", i, file_in_name[i]);
    379     }
    380     printf ("output file:\t\t%s\n", file_out_name);
    381     printf ("input width:\t\t%d\n", input_width);
    382     printf ("input height:\t\t%d\n", input_height);
    383     printf ("output width:\t\t%d\n", output_width);
    384     printf ("output height:\t\t%d\n", output_height);
    385     printf ("resolution mode:\t%s\n",
    386             res_mode == StitchRes1080P ? "1080P" : (res_mode == StitchRes1080P4 ? "1080P4" : "4K"));
    387     printf ("surround mode: \t\t%s\n",
    388             surround_mode == SphereView ? "sphere view" : "bowl view");
    389     printf ("scale mode:\t\t%s\n", scale_mode == CLBlenderScaleLocal ? "local" : "global");
    390     printf ("seam mask:\t\t%s\n", enable_seam ? "true" : "false");
    391     printf ("fisheye map:\t\t%s\n", enable_fisheye_map ? "true" : "false");
    392     printf ("shading correction:\t%s\n", enable_lsc ? "true" : "false");
    393 #if HAVE_OPENCV
    394     printf ("feature match ocl:\t%s\n", fm_ocl ? "true" : "false");
    395 #endif
    396     printf ("fisheye number:\t\t%d\n", fisheye_num);
    397     printf ("all in one:\t\t%s\n", all_in_one ? "true" : "false");
    398     printf ("save file:\t\t%s\n", need_save_output ? "true" : "false");
    399     printf ("framerate:\t\t%.3lf\n", framerate);
    400     printf ("loop count:\t\t%d\n", loop);
    401     printf ("-----------------------------------\n");
    402 
    403     context = CLDevice::instance ()->get_context ();
    404     image_360 =
    405         create_image_360_stitch (
    406             context, enable_seam, scale_mode, enable_fisheye_map, enable_lsc, surround_mode,
    407             res_mode, fisheye_num, all_in_one).dynamic_cast_ptr<CLImage360Stitch> ();
    408     XCAM_ASSERT (image_360.ptr ());
    409     image_360->set_output_size (output_width, output_height);
    410 #if HAVE_OPENCV
    411     image_360->set_feature_match_ocl (fm_ocl);
    412 #endif
    413     image_360->set_pool_type (CLImageHandler::CLVideoPoolType);
    414 
    415     if (surround_mode == BowlView) {
    416         parse_calibration_params (intrinsic_param, extrinsic_param, fisheye_num);
    417 
    418         for (int i = 0; i < fisheye_num; i++) {
    419             image_360->set_fisheye_intrinsic (intrinsic_param[i], i);
    420             image_360->set_fisheye_extrinsic (extrinsic_param[i], i);
    421         }
    422     }
    423 
    424     input_buf_info.init (input_format, input_width, input_height);
    425     output_buf_info.init (input_format, output_width, output_height);
    426     top_view_buf_info.init (input_format, top_view_width, top_view_height);
    427     rectified_view_buf_info.init (input_format, rectified_view_width, rectified_view_height);
    428     for (int i = 0; i < input_count; i++) {
    429         buf_pool[i] = new CLVideoBufferPool ();
    430         XCAM_ASSERT (buf_pool[i].ptr ());
    431         buf_pool[i]->set_video_info (input_buf_info);
    432         if (!buf_pool[i]->reserve (6)) {
    433             XCAM_LOG_ERROR ("init buffer pool failed");
    434             return -1;
    435         }
    436     }
    437 
    438     SmartPtr<BufferPool> top_view_pool = new CLVideoBufferPool ();
    439     XCAM_ASSERT (top_view_pool.ptr ());
    440     top_view_pool->set_video_info (top_view_buf_info);
    441     if (!top_view_pool->reserve (6)) {
    442         XCAM_LOG_ERROR ("top-view-buffer pool reserve failed");
    443         return -1;
    444     }
    445     top_view_buf = top_view_pool->get_buffer (top_view_pool);
    446 
    447     SmartPtr<BufferPool> rectified_view_pool = new CLVideoBufferPool ();
    448     XCAM_ASSERT (rectified_view_pool.ptr ());
    449     rectified_view_pool->set_video_info (rectified_view_buf_info);
    450     if (!rectified_view_pool->reserve (6)) {
    451         XCAM_LOG_ERROR ("top-view-buffer pool reserve failed");
    452         return -1;
    453     }
    454     rectified_view_buf = rectified_view_pool->get_buffer (rectified_view_pool);
    455 
    456     for (int i = 0; i < input_count; i++) {
    457         ret = file_in[i].open (file_in_name[i], "rb");
    458         CHECK (ret, "open %s failed", file_in_name[i]);
    459     }
    460 
    461 #if HAVE_OPENCV
    462     cv::VideoWriter writer;
    463     cv::VideoWriter top_view_writer;
    464     cv::VideoWriter rectified_view_writer;
    465     if (need_save_output) {
    466         cv::Size dst_size = cv::Size (output_width, output_height);
    467         if (!writer.open (file_out_name, CV_FOURCC('X', '2', '6', '4'), framerate, dst_size)) {
    468             XCAM_LOG_ERROR ("open file %s failed", file_out_name);
    469             return -1;
    470         }
    471 
    472         dst_size = cv::Size (top_view_width, top_view_height);
    473         if (!top_view_writer.open (top_view_filename, CV_FOURCC('X', '2', '6', '4'), framerate, dst_size)) {
    474             XCAM_LOG_ERROR ("open file %s failed", top_view_filename);
    475             return -1;
    476         }
    477 
    478         dst_size = cv::Size (rectified_view_width, rectified_view_height);
    479         if (!rectified_view_writer.open (rectified_view_filename, CV_FOURCC('X', '2', '6', '4'), framerate, dst_size)) {
    480             XCAM_LOG_ERROR ("open file %s failed", rectified_view_filename);
    481             return -1;
    482         }
    483     }
    484 #endif
    485 
    486     SmartPtr<VideoBuffer> pre_buf, cur_buf;
    487 #if (HAVE_OPENCV) && (XCAM_TEST_STITCH_DEBUG)
    488     SmartPtr<VideoBuffer> input_bufs[XCAM_STITCH_FISHEYE_MAX_NUM];
    489 #endif
    490     int frame_id = 0;
    491     std::vector<PointFloat2> top_view_map_table;
    492     std::vector<PointFloat2> rectified_view_map_table;
    493     float rectified_start_angle = -45.0f, rectified_end_angle = 45.0f;
    494 
    495     while (loop--) {
    496         for (int i = 0; i < input_count; i++) {
    497             ret = file_in[i].rewind ();
    498             CHECK (ret, "image_360 stitch rewind file(%s) failed", file_in_name[i]);
    499         }
    500 
    501         do {
    502             for (int i = 0; i < input_count; i++) {
    503                 cur_buf = buf_pool[i]->get_buffer (buf_pool[i]);
    504                 XCAM_ASSERT (cur_buf.ptr ());
    505                 ret = file_in[i].read_buf (cur_buf);
    506                 // ret = read_file_to_video_buffer (file_in[i], input_width, input_height, input_width, cur_buf);
    507                 if (ret == XCAM_RETURN_BYPASS)
    508                     break;
    509                 if (ret == XCAM_RETURN_ERROR_FILE) {
    510                     XCAM_LOG_ERROR ("read buffer from %s failed", file_in_name[i]);
    511                     return -1;
    512                 }
    513 
    514                 if (i == 0)
    515                     input_buf = cur_buf;
    516                 else
    517                     pre_buf->attach_buffer (cur_buf);
    518 
    519                 pre_buf = cur_buf;
    520 #if (HAVE_OPENCV) && (XCAM_TEST_STITCH_DEBUG)
    521                 input_bufs[i] = cur_buf;
    522 #endif
    523             }
    524             if (ret == XCAM_RETURN_BYPASS)
    525                 break;
    526 
    527             ret = image_360->execute (input_buf, output_buf);
    528             CHECK (ret, "image_360 stitch execute failed");
    529 
    530 #if HAVE_OPENCV
    531             if (need_save_output) {
    532                 cv::Mat out_mat;
    533                 convert_to_mat (output_buf, out_mat);
    534                 writer.write (out_mat);
    535 
    536                 BowlDataConfig config = image_360->get_fisheye_bowl_config ();
    537                 cv::Mat top_view_mat;
    538                 sample_generate_top_view (output_buf, top_view_buf, config, top_view_map_table);
    539                 convert_to_mat (top_view_buf, top_view_mat);
    540                 top_view_writer.write (top_view_mat);
    541 
    542                 cv::Mat rectified_view_mat;
    543                 sample_generate_rectified_view (output_buf, rectified_view_buf, config, rectified_start_angle,
    544                                                 rectified_end_angle, rectified_view_map_table);
    545                 convert_to_mat (rectified_view_buf, rectified_view_mat);
    546                 rectified_view_writer.write (rectified_view_mat);
    547 
    548 #if XCAM_TEST_STITCH_DEBUG
    549                 dbg_write_image (context, image_360, input_bufs, output_buf, top_view_buf, rectified_view_buf,
    550                                  all_in_one, fisheye_num, input_count);
    551 #endif
    552             } else
    553 #endif
    554                 ensure_gpu_buffer_done (output_buf);
    555 
    556             frame_id++;
    557             FPS_CALCULATION (image_stitching, XCAM_OBJ_DUR_FRAME_NUM);
    558         } while (true);
    559     }
    560 
    561     return 0;
    562 }
    563 
    564 #if (HAVE_OPENCV) && (XCAM_TEST_STITCH_DEBUG)
    565 static void dbg_write_image (
    566     SmartPtr<CLContext> context, SmartPtr<CLImage360Stitch> image_360,
    567     SmartPtr<VideoBuffer> input_bufs[], SmartPtr<VideoBuffer> output_buf,
    568     SmartPtr<VideoBuffer> top_view_buf, SmartPtr<VideoBuffer> rectified_view_buf,
    569     bool all_in_one, int fisheye_num, int input_count)
    570 {
    571     cv::Mat mat;
    572     static int frame_count = 0;
    573     char file_name [1024];
    574     StitchInfo stitch_info = image_360->get_stitch_info ();
    575 
    576     std::snprintf (file_name, 1023, "orig_fisheye_%d.jpg", frame_count);
    577     for (int i = 0; i < input_count; i++) {
    578         if (!all_in_one)
    579             std::snprintf (file_name, 1023, "orig_fisheye_%d_%d.jpg", frame_count, i);
    580 
    581         convert_to_mat (input_bufs[i], mat);
    582         int fisheye_per_frame = all_in_one ? fisheye_num : 1;
    583         for (int i = 0; i < fisheye_per_frame; i++) {
    584             cv::circle (mat, cv::Point(stitch_info.fisheye_info[i].center_x, stitch_info.fisheye_info[i].center_y),
    585                         stitch_info.fisheye_info[i].radius, cv::Scalar(0, 0, 255), 2);
    586         }
    587         cv::imwrite (file_name, mat);
    588     }
    589 
    590     char frame_str[1024];
    591     std::snprintf (frame_str, 1023, "%d", frame_count);
    592 
    593     convert_to_mat (output_buf, mat);
    594     cv::putText (mat, frame_str, cv::Point(120, 120), cv::FONT_HERSHEY_COMPLEX, 2.0,
    595                  cv::Scalar(0, 0, 255), 2, 8, false);
    596     std::snprintf (file_name, 1023, "stitched_img_%d.jpg", frame_count);
    597     cv::imwrite (file_name, mat);
    598 
    599     convert_to_mat (top_view_buf, mat);
    600     cv::putText (mat, frame_str, cv::Point(120, 120), cv::FONT_HERSHEY_COMPLEX, 2.0,
    601                  cv::Scalar(0, 0, 255), 2, 8, false);
    602     std::snprintf (file_name, 1023, "top_view_img_%d.jpg", frame_count);
    603     cv::imwrite (file_name, mat);
    604 
    605     convert_to_mat (rectified_view_buf, mat);
    606     cv::putText (mat, frame_str, cv::Point(120, 120), cv::FONT_HERSHEY_COMPLEX, 2.0,
    607                  cv::Scalar(0, 0, 255), 2, 8, false);
    608     std::snprintf (file_name, 1023, "rectified_view_img_%d.jpg", frame_count);
    609     cv::imwrite (file_name, mat);
    610 
    611     frame_count++;
    612 }
    613 #endif
    614 
    615