Home | History | Annotate | Download | only in ocl
      1 /*
      2  * cl_fisheye_handler.cpp - CL fisheye handler
      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 "cl_utils.h"
     22 #include "cl_fisheye_handler.h"
     23 #include "cl_device.h"
     24 
     25 #define XCAM_LSC_ARRAY_SIZE 64
     26 
     27 static const float max_gray_threshold = 220.0f;
     28 static const float min_gray_threshold = 80.0f;
     29 
     30 static const float lsc_array[XCAM_LSC_ARRAY_SIZE] = {
     31     1.000000f, 1.000150f, 1.000334f, 1.000523f, 1.000761f, 1.001317f, 1.002109f, 1.003472f,
     32     1.004502f, 1.008459f, 1.011816f, 1.014686f, 1.016767f, 1.018425f, 1.020455f, 1.022125f,
     33     1.023080f, 1.025468f, 1.029810f, 1.035422f, 1.041943f, 1.047689f, 1.054206f, 1.059395f,
     34     1.063541f, 1.068729f, 1.074158f, 1.082766f, 1.088606f, 1.095224f, 1.102773f, 1.112865f,
     35     1.117108f, 1.132849f, 1.140659f, 1.147847f, 1.157544f, 1.165002f, 1.175248f, 1.181730f,
     36     1.196203f, 1.205452f, 1.216974f, 1.236338f, 1.251963f, 1.269212f, 1.293479f, 1.311051f,
     37     1.336007f, 1.357711f, 1.385124f, 1.409937f, 1.448611f, 1.473716f, 1.501837f, 1.525721f,
     38     1.555186f, 1.602372f, 1.632105f, 1.698443f, 1.759641f, 1.836303f, 1.939085f, 2.066358f
     39 };
     40 
     41 namespace XCam {
     42 
     43 #define DEFAULT_FISHEYE_TABLE_SCALE 8.0f
     44 
     45 enum {
     46     KernelFisheye2GPS,
     47     KernelFisheyeTable,
     48     KernelLSCTable
     49 };
     50 
     51 const XCamKernelInfo kernel_fisheye_info[] = {
     52     {
     53         "kernel_fisheye_2_gps",
     54 #include "kernel_fisheye.clx"
     55         , 0,
     56     },
     57     {
     58         "kernel_fisheye_table",
     59 #include "kernel_fisheye.clx"
     60         , 0,
     61     },
     62     {
     63         "kernel_lsc_table",
     64 #include "kernel_fisheye.clx"
     65         , 0,
     66     },
     67 };
     68 
     69 CLFisheye2GPSKernel::CLFisheye2GPSKernel (
     70     const SmartPtr<CLContext> &context, SmartPtr<CLFisheyeHandler> &handler)
     71     : CLImageKernel (context)
     72     , _handler (handler)
     73 {
     74     XCAM_ASSERT (handler.ptr ());
     75 }
     76 
     77 XCamReturn
     78 CLFisheye2GPSKernel::prepare_arguments (CLArgList &args, CLWorkSize &work_size)
     79 {
     80     SmartPtr<CLImage> input_y = _handler->get_input_image (NV12PlaneYIdx);
     81     SmartPtr<CLImage> input_uv = _handler->get_input_image (NV12PlaneUVIdx);
     82     SmartPtr<CLImage> output_y = _handler->get_output_image (NV12PlaneYIdx);
     83     SmartPtr<CLImage> output_uv = _handler->get_output_image (NV12PlaneUVIdx);
     84     const CLImageDesc &input_y_desc = input_y->get_image_desc ();
     85     const CLImageDesc &outuv_desc = output_uv->get_image_desc ();
     86     FisheyeInfo fisheye_info;
     87     float input_y_size[2];
     88     float out_center[2]; //width/height
     89     float radian_per_pixel[2];
     90 
     91     input_y_size[0] = input_y_desc.width;
     92     input_y_size[1] = input_y_desc.height;
     93 
     94     uint32_t dst_w, dst_h;
     95     float dst_range_x, dst_range_y;
     96     _handler->get_output_size (dst_w, dst_h);
     97     out_center[0] = (float)dst_w / 2.0f;
     98     out_center[1] = (float)dst_h / 2.0f;
     99 
    100     _handler->get_dst_range (dst_range_x, dst_range_y);
    101     radian_per_pixel[0] = degree2radian (dst_range_x) / (float)dst_w;
    102     radian_per_pixel[1] = degree2radian (dst_range_y) / (float)dst_h;
    103 
    104     fisheye_info = _handler->get_fisheye_info ();
    105     fisheye_info.wide_angle = degree2radian (fisheye_info.wide_angle);
    106     fisheye_info.rotate_angle = degree2radian (fisheye_info.rotate_angle);
    107 
    108     XCAM_LOG_DEBUG ("@CLFisheye2GPSKernel input size(%d, %d), out_center:(%d, %d), range:(%d,%d)",
    109                     (int)input_y_size[0], (int)input_y_size[1],
    110                     (int)out_center[0], (int)out_center[1],
    111                     (int)dst_range_x, (int)dst_range_y);
    112 
    113     args.push_back (new CLMemArgument (input_y));
    114     args.push_back (new CLMemArgument (input_uv));
    115     args.push_back (new CLArgumentTArray<float, 2> (input_y_size));
    116     args.push_back (new CLArgumentT<FisheyeInfo> (fisheye_info));
    117     args.push_back (new CLMemArgument (output_y));
    118     args.push_back (new CLMemArgument (output_uv));
    119     args.push_back (new CLArgumentTArray<float, 2> (out_center));
    120     args.push_back (new CLArgumentTArray<float, 2> (radian_per_pixel));
    121 
    122     work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
    123     work_size.local[0] = 16;
    124     work_size.local[1] = 4;
    125     work_size.global[0] = XCAM_ALIGN_UP (outuv_desc.width, work_size.local[0]);
    126     work_size.global[1] = XCAM_ALIGN_UP (outuv_desc.height, work_size.local[1]);
    127 
    128     return XCAM_RETURN_NO_ERROR;
    129 }
    130 
    131 CLFisheyeHandler::CLFisheyeHandler (const SmartPtr<CLContext> &context, SurroundMode surround_mode, bool use_map, bool need_lsc)
    132     : CLImageHandler (context, "CLFisheyeHandler")
    133     , _output_width (0)
    134     , _output_height (0)
    135     , _range_longitude (180.0f)
    136     , _range_latitude (180.0f)
    137     , _map_factor (DEFAULT_FISHEYE_TABLE_SCALE)
    138     , _use_map (use_map)
    139     , _need_lsc (need_lsc ? 1 : 0)
    140     , _lsc_array_size (0)
    141     , _lsc_array (NULL)
    142     , _surround_mode (surround_mode)
    143 {
    144     xcam_mem_clear (_gray_threshold);
    145 }
    146 
    147 CLFisheyeHandler::~CLFisheyeHandler()
    148 {
    149     if (_lsc_array)
    150         xcam_free (_lsc_array);
    151 }
    152 
    153 void
    154 CLFisheyeHandler::set_output_size (uint32_t width, uint32_t height)
    155 {
    156     _output_width = width;
    157     _output_height = height;
    158 }
    159 
    160 void
    161 CLFisheyeHandler::get_output_size (uint32_t &width, uint32_t &height) const
    162 {
    163     width = _output_width;
    164     height = _output_height;
    165 }
    166 
    167 void
    168 CLFisheyeHandler::set_dst_range (float longitude, float latitude)
    169 {
    170     _range_longitude = longitude;
    171     _range_latitude = latitude;
    172 }
    173 
    174 void
    175 CLFisheyeHandler::get_dst_range (float &longitude, float &latitude) const
    176 {
    177     longitude = _range_longitude;
    178     latitude = _range_latitude;
    179 }
    180 
    181 void
    182 CLFisheyeHandler::set_fisheye_info (const FisheyeInfo &info)
    183 {
    184     _fisheye_info = info;
    185 }
    186 
    187 void
    188 CLFisheyeHandler::set_lsc_table (float *table, uint32_t table_size)
    189 {
    190     if (_lsc_array)
    191         xcam_free (_lsc_array);
    192 
    193     _lsc_array_size = table_size;
    194     _lsc_array = (float *) xcam_malloc0 (_lsc_array_size * sizeof (float));
    195     XCAM_ASSERT (_lsc_array);
    196     memcpy (_lsc_array, table, _lsc_array_size * sizeof (float));
    197 }
    198 
    199 void
    200 CLFisheyeHandler::set_lsc_gray_threshold (float min_threshold, float max_threshold)
    201 {
    202     _gray_threshold[0] = min_threshold;
    203     _gray_threshold[1] = max_threshold;
    204 }
    205 
    206 XCamReturn
    207 CLFisheyeHandler::prepare_buffer_pool_video_info (
    208     const VideoBufferInfo &input,
    209     VideoBufferInfo &output)
    210 {
    211     XCAM_FAIL_RETURN (
    212         WARNING, input.format == V4L2_PIX_FMT_NV12, XCAM_RETURN_ERROR_PARAM,
    213         "CLFisheyeHandler(%s) input buffer format(%s) is not supported, try NV12",
    214         get_name (), xcam_fourcc_to_string (input.format));
    215 
    216     if (!_output_width || !_output_height) {
    217         return XCAM_RETURN_ERROR_PARAM;
    218     }
    219     XCAM_FAIL_RETURN (
    220         WARNING, _output_width && _output_height, XCAM_RETURN_ERROR_PARAM,
    221         "CLFisheyeHandler output size(%d, %d) should > 0",
    222         _output_width, _output_height);
    223 
    224     output.init (
    225         input.format, _output_width, _output_height,
    226         XCAM_ALIGN_UP (_output_width, 16), XCAM_ALIGN_UP (_output_height, 16));
    227     return XCAM_RETURN_NO_ERROR;
    228 }
    229 
    230 XCamReturn
    231 CLFisheyeHandler::prepare_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
    232 {
    233     const VideoBufferInfo &in_info = input->get_video_info ();
    234     const VideoBufferInfo &out_info = output->get_video_info ();
    235     SmartPtr<CLContext> context = get_context ();
    236     uint32_t input_image_w = XCAM_ALIGN_DOWN (in_info.width, 2);
    237     uint32_t input_image_h = XCAM_ALIGN_DOWN (in_info.height, 2);
    238 
    239     XCAM_FAIL_RETURN (
    240         WARNING, _fisheye_info.is_valid (), XCAM_RETURN_ERROR_PARAM,
    241         "CLFisheyeHandler fisheye info is not valid, please check");
    242 
    243     CLImageDesc cl_desc;
    244     cl_desc.format.image_channel_data_type = CL_UNORM_INT8;
    245     cl_desc.format.image_channel_order = CL_R;
    246     cl_desc.width = input_image_w;
    247     cl_desc.height = input_image_h;
    248     cl_desc.row_pitch = in_info.strides[NV12PlaneYIdx];
    249     _input[NV12PlaneYIdx] = convert_to_climage (context, input, cl_desc, in_info.offsets[NV12PlaneYIdx]);
    250 
    251     cl_desc.format.image_channel_data_type = CL_UNORM_INT8;
    252     cl_desc.format.image_channel_order = CL_RG;
    253     cl_desc.width = input_image_w / 2;
    254     cl_desc.height = input_image_h / 2;
    255     cl_desc.row_pitch = in_info.strides[NV12PlaneUVIdx];
    256     _input[NV12PlaneUVIdx] = convert_to_climage (context, input, cl_desc, in_info.offsets[NV12PlaneUVIdx]);
    257 
    258     if (_use_map) {
    259         cl_desc.format.image_channel_data_type = CL_UNSIGNED_INT16;
    260         cl_desc.format.image_channel_order = CL_RGBA;
    261         cl_desc.width = XCAM_ALIGN_DOWN (out_info.width, 8) / 8; //CL_RGBA * CL_UNSIGNED_INT16 = 8
    262         cl_desc.height = XCAM_ALIGN_DOWN (out_info.height, 2);
    263         cl_desc.row_pitch = out_info.strides[NV12PlaneYIdx];
    264         _output[NV12PlaneYIdx] = convert_to_climage (context, output, cl_desc, out_info.offsets[NV12PlaneYIdx]);
    265         cl_desc.height /= 2;
    266         cl_desc.row_pitch = out_info.strides[NV12PlaneUVIdx];
    267         _output[NV12PlaneUVIdx] = convert_to_climage (context, output, cl_desc, out_info.offsets[NV12PlaneUVIdx]);
    268     } else {
    269         cl_desc.format.image_channel_data_type = CL_UNSIGNED_INT8;
    270         cl_desc.format.image_channel_order = CL_RGBA;
    271         cl_desc.width = XCAM_ALIGN_DOWN (out_info.width, 4) / 4; //CL_RGBA * CL_UNSIGNED_INT8 = 4
    272         cl_desc.height = XCAM_ALIGN_DOWN (out_info.height, 2);
    273         cl_desc.row_pitch = out_info.strides[NV12PlaneYIdx];
    274         _output[NV12PlaneYIdx] = convert_to_climage (context, output, cl_desc, out_info.offsets[NV12PlaneYIdx]);
    275         cl_desc.height /= 2;
    276         cl_desc.row_pitch = out_info.strides[NV12PlaneUVIdx];
    277         _output[NV12PlaneUVIdx] = convert_to_climage (context, output, cl_desc, out_info.offsets[NV12PlaneUVIdx]);
    278     }
    279 
    280     XCAM_ASSERT (
    281         _input[NV12PlaneYIdx].ptr () && _input[NV12PlaneYIdx]->is_valid () &&
    282         _input[NV12PlaneUVIdx].ptr () && _input[NV12PlaneUVIdx]->is_valid () &&
    283         _output[NV12PlaneYIdx].ptr () && _output[NV12PlaneYIdx]->is_valid () &&
    284         _output[NV12PlaneUVIdx].ptr () && _output[NV12PlaneUVIdx]->is_valid ());
    285 
    286     if (_use_map && !_geo_table.ptr ()) {
    287         generate_fisheye_table (input_image_w, input_image_h, _fisheye_info);
    288     }
    289 
    290     if (!_lsc_table.ptr () && _need_lsc)
    291         generate_lsc_table (input_image_w, input_image_h, _fisheye_info);
    292 
    293     return XCAM_RETURN_NO_ERROR;
    294 }
    295 
    296 SmartPtr<CLImage>
    297 CLFisheyeHandler::create_cl_image (
    298     uint32_t width, uint32_t height, cl_channel_order order, cl_channel_type type)
    299 {
    300     CLImageDesc cl_desc;
    301     cl_desc.format.image_channel_data_type = type;
    302     cl_desc.format.image_channel_order = order;
    303     cl_desc.width = width;
    304     cl_desc.height = height;
    305 
    306     SmartPtr<CLContext> context = get_context ();
    307     XCAM_ASSERT (context.ptr ());
    308     SmartPtr<CLImage> image = new CLImage2D (context, cl_desc);
    309     XCAM_FAIL_RETURN (
    310         ERROR, image.ptr () && image->is_valid (),
    311         NULL, "[%s] create cl image failed", get_name ());
    312     return image;
    313 }
    314 
    315 #if 0
    316 static void
    317 dump_geo_table (SmartPtr<CLImage> table)
    318 {
    319     const CLImageDesc &desc = table->get_image_desc ();
    320     void *ptr = NULL;
    321     size_t origin[3] = {0, 0, 0};
    322     size_t region[3] = {desc.width, desc.height, 1};
    323     size_t row_pitch;
    324     size_t slice_pitch;
    325 
    326     char name[1024];
    327     snprintf (name, 1024, "geo_table_x_%dx%d.x", desc.width, desc.height);
    328     FILE *fp = fopen (name, "wb");
    329     XCamReturn ret = table->enqueue_map (ptr, origin, region, &row_pitch, &slice_pitch, CL_MAP_READ);
    330     XCAM_ASSERT (ret == XCAM_RETURN_NO_ERROR);
    331 
    332     for (uint32_t i = 0; i < desc.height; ++i) {
    333         float * line = (float*)((uint8_t*)ptr + row_pitch * i);
    334         for (uint32_t j = 0; j < desc.width; ++j) {
    335             float *buf = line + j * 4;
    336             if (i == 120)
    337                 printf ("%.02f,", *buf);
    338             uint8_t val = *buf * 255;
    339             fwrite (&val, sizeof (val), 1, fp);
    340         }
    341     }
    342     printf ("\n");
    343     fclose (fp);
    344     table->enqueue_unmap (ptr);
    345 }
    346 #endif
    347 
    348 XCamReturn
    349 CLFisheyeHandler::generate_fisheye_table (
    350     uint32_t fisheye_width, uint32_t fisheye_height, const FisheyeInfo &fisheye_info)
    351 {
    352     SmartPtr<CLContext> context = get_context ();
    353     XCAM_ASSERT (context.ptr ());
    354     SmartPtr<CLKernel> table_kernel = new CLKernel (context, "fisheye_table_temp");
    355     XCAM_FAIL_RETURN (
    356         ERROR, table_kernel->build_kernel (kernel_fisheye_info[KernelFisheyeTable], NULL) == XCAM_RETURN_NO_ERROR,
    357         XCAM_RETURN_ERROR_CL, "[%s] build fisheye table kernel failed", get_name ());
    358 
    359     float longitude, latitude;
    360     get_dst_range (longitude, latitude);
    361     XCAM_FAIL_RETURN (
    362         ERROR, longitude > 0.0f && latitude > 0.0f,
    363         XCAM_RETURN_ERROR_PARAM, "[%s] dest latitude and longitude were not set", get_name ());
    364 
    365     uint32_t output_width, output_height;
    366     get_output_size (output_width, output_height);
    367 
    368     uint32_t table_width, table_height;
    369     table_width = output_width / _map_factor;
    370     table_width = XCAM_ALIGN_UP (table_width, 4);
    371     table_height = output_height / _map_factor;
    372     table_height = XCAM_ALIGN_UP (table_height, 2);
    373     _geo_table = create_cl_image (table_width, table_height, CL_RGBA, CL_FLOAT);
    374     XCAM_FAIL_RETURN (
    375         ERROR, _geo_table.ptr () && _geo_table->is_valid (),
    376         XCAM_RETURN_ERROR_MEM, "[%s] check geo map buffer failed", get_name ());
    377 
    378     if(_surround_mode == BowlView) {
    379         BowlDataConfig bowl_data_config = get_bowl_config();
    380         IntrinsicParameter intrinsic_param = get_intrinsic_param();
    381         ExtrinsicParameter extrinsic_param = get_extrinsic_param();
    382 
    383         SurViewFisheyeDewarp::MapTable map_table(table_width * table_height * 2);
    384         PolyFisheyeDewarp fd;
    385         fd.set_intrinsic_param(intrinsic_param);
    386         fd.set_extrinsic_param(extrinsic_param);
    387 
    388         fd.fisheye_dewarp(map_table, table_width, table_height, output_width, output_height, bowl_data_config);
    389 
    390         float *map_ptr = NULL;
    391         size_t origin[3] = {0, 0, 0};
    392         size_t region[3] = {table_width, table_height, 1};
    393         size_t row_pitch;
    394         size_t slice_pitch;
    395         XCamReturn ret = _geo_table->enqueue_map ((void *&)map_ptr, origin, region, &row_pitch, &slice_pitch, CL_MAP_WRITE);
    396         XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "CLFisheyeHandler mesh table failed in enqueue_map");
    397 
    398         for (uint32_t row = 0; row < table_height; row++) {
    399             for(uint32_t col = 0; col < table_width; col++) {
    400                 map_ptr[row * row_pitch / 4 + col * 4] = map_table[row * table_width + col].x / fisheye_width;
    401                 map_ptr[row * row_pitch / 4 + col * 4 + 1] = map_table[row * table_width + col].y / fisheye_height;
    402             }
    403         }
    404         _geo_table->enqueue_unmap ((void *&)map_ptr);
    405     } else {
    406         CLArgList args;
    407         CLWorkSize work_size;
    408 
    409         FisheyeInfo fisheye_arg1 = fisheye_info;
    410         fisheye_arg1.wide_angle = degree2radian (fisheye_info.wide_angle);
    411         fisheye_arg1.rotate_angle = degree2radian (fisheye_info.rotate_angle);
    412         args.push_back (new CLArgumentT<FisheyeInfo> (fisheye_arg1));
    413 
    414         float fisheye_image_size[2];
    415         fisheye_image_size[0] = fisheye_width;
    416         fisheye_image_size[1] = fisheye_height;
    417         args.push_back (new CLArgumentTArray<float, 2> (fisheye_image_size));
    418         args.push_back (new CLMemArgument (_geo_table));
    419 
    420         float radian_per_pixel[2];
    421         radian_per_pixel[0] = degree2radian (longitude / table_width);
    422         radian_per_pixel[1] = degree2radian (latitude / table_height);
    423         args.push_back (new CLArgumentTArray<float, 2> (radian_per_pixel));
    424 
    425         float table_center[2];
    426         table_center[0] = table_width / 2.0f;
    427         table_center[1] = table_height / 2.0f;
    428         args.push_back (new CLArgumentTArray<float, 2> (table_center));
    429 
    430         work_size.dim = 2;
    431         work_size.local[0] = 8;
    432         work_size.local[1] = 4;
    433         work_size.global[0] = XCAM_ALIGN_UP (table_width, work_size.local[0]);
    434         work_size.global[1] = XCAM_ALIGN_UP (table_height, work_size.local[1]);
    435 
    436         XCAM_FAIL_RETURN (
    437             ERROR, table_kernel->set_arguments (args, work_size) == XCAM_RETURN_NO_ERROR,
    438             XCAM_RETURN_ERROR_CL, "kernel_fisheye_table set arguments failed");
    439 
    440         XCAM_FAIL_RETURN (
    441             ERROR, table_kernel->execute (table_kernel, true) == XCAM_RETURN_NO_ERROR,
    442             XCAM_RETURN_ERROR_CL, "[%s] execute kernel_fisheye_table failed", get_name ());
    443     }
    444     //dump_geo_table (_geo_table);
    445 
    446     return XCAM_RETURN_NO_ERROR;
    447 }
    448 
    449 void
    450 CLFisheyeHandler::ensure_lsc_params ()
    451 {
    452     if (_lsc_array)
    453         return;
    454 
    455     _lsc_array_size = XCAM_LSC_ARRAY_SIZE;
    456     _lsc_array = (float *) xcam_malloc0 (_lsc_array_size * sizeof (float));
    457     XCAM_ASSERT (_lsc_array);
    458     memcpy (_lsc_array, lsc_array, _lsc_array_size * sizeof (float));
    459 
    460     _gray_threshold[1] = max_gray_threshold;
    461     _gray_threshold[0] = min_gray_threshold;
    462 }
    463 
    464 XCamReturn
    465 CLFisheyeHandler::generate_lsc_table (
    466     uint32_t fisheye_width, uint32_t fisheye_height, FisheyeInfo &fisheye_info)
    467 {
    468     if (!_need_lsc) {
    469         XCAM_LOG_WARNING ("lsc is not needed, don't generate lsc table");
    470         return XCAM_RETURN_NO_ERROR;
    471     }
    472 
    473     if (!_geo_table.ptr ()) {
    474         XCAM_LOG_ERROR ("generate lsc table failed, need generate fisheye table first");
    475         return XCAM_RETURN_ERROR_MEM;
    476     }
    477 
    478     ensure_lsc_params ();
    479 
    480     SmartPtr<CLContext> context = get_context ();
    481     XCAM_ASSERT (context.ptr ());
    482     SmartPtr<CLKernel> table_kernel = new CLKernel (context, "lsc_table");
    483     XCAM_FAIL_RETURN (
    484         ERROR, table_kernel->build_kernel (kernel_fisheye_info[KernelLSCTable], NULL) == XCAM_RETURN_NO_ERROR,
    485         XCAM_RETURN_ERROR_CL, "[%s] build lsc table kernel failed", get_name ());
    486 
    487     SmartPtr<CLBuffer> array_buf = new CLBuffer (
    488         context, _lsc_array_size * sizeof (float),
    489         CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, _lsc_array);
    490     xcam_free (_lsc_array);
    491 
    492     CLImageDesc desc = _geo_table->get_image_desc ();
    493     _lsc_table = create_cl_image (desc.width, desc.height, CL_R, CL_FLOAT);
    494     XCAM_FAIL_RETURN (
    495         ERROR, _lsc_table.ptr () && _lsc_table->is_valid (),
    496         XCAM_RETURN_ERROR_MEM, "[%s] create lsc image failed", get_name ());
    497 
    498     CLArgList args;
    499     args.push_back (new CLMemArgument (_geo_table));
    500     args.push_back (new CLMemArgument (_lsc_table));
    501     args.push_back (new CLMemArgument (array_buf));
    502     args.push_back (new CLArgumentT<uint32_t> (_lsc_array_size));
    503     args.push_back (new CLArgumentT<FisheyeInfo> (fisheye_info));
    504 
    505     float fisheye_image_size[2];
    506     fisheye_image_size[0] = fisheye_width;
    507     fisheye_image_size[1] = fisheye_height;
    508     args.push_back (new CLArgumentTArray<float, 2> (fisheye_image_size));
    509 
    510     CLWorkSize work_size;
    511     work_size.dim = 2;
    512     work_size.local[0] = 8;
    513     work_size.local[1] = 4;
    514     work_size.global[0] = XCAM_ALIGN_UP (desc.width, work_size.local[0]);
    515     work_size.global[1] = XCAM_ALIGN_UP (desc.height, work_size.local[1]);
    516 
    517     XCAM_FAIL_RETURN (
    518         ERROR, table_kernel->set_arguments (args, work_size) == XCAM_RETURN_NO_ERROR,
    519         XCAM_RETURN_ERROR_CL, "kernel_lsc_table set arguments failed");
    520 
    521     XCAM_FAIL_RETURN (
    522         ERROR, table_kernel->execute (table_kernel, true) == XCAM_RETURN_NO_ERROR,
    523         XCAM_RETURN_ERROR_CL, "[%s] execute kernel_lsc_table failed", get_name ());
    524 
    525     return XCAM_RETURN_NO_ERROR;
    526 }
    527 
    528 XCamReturn
    529 CLFisheyeHandler::execute_done (SmartPtr<VideoBuffer> &output)
    530 {
    531     XCAM_UNUSED (output);
    532 
    533     for (int i = 0; i < NV12PlaneMax; ++i) {
    534         _input[i].release ();
    535         _output[i].release ();
    536     }
    537 
    538     return XCAM_RETURN_NO_ERROR;
    539 }
    540 
    541 SmartPtr<CLImage>
    542 CLFisheyeHandler::get_geo_input_image (NV12PlaneIdx index) {
    543     return get_input_image(index);
    544 }
    545 
    546 SmartPtr<CLImage>
    547 CLFisheyeHandler::get_geo_output_image (NV12PlaneIdx index) {
    548     return get_output_image (index);
    549 }
    550 
    551 void
    552 CLFisheyeHandler::get_geo_equivalent_out_size (float &width, float &height)
    553 {
    554     width = _output_width;
    555     height = _output_height;
    556 }
    557 
    558 void
    559 CLFisheyeHandler::get_geo_pixel_out_size (float &width, float &height)
    560 {
    561     width = _output_width;
    562     height = _output_height;
    563 }
    564 
    565 SmartPtr<CLImage>
    566 CLFisheyeHandler::get_lsc_table () {
    567     XCAM_ASSERT (_lsc_table.ptr ());
    568     return _lsc_table;
    569 }
    570 
    571 float*
    572 CLFisheyeHandler::get_lsc_gray_threshold () {
    573     return _gray_threshold;
    574 }
    575 
    576 static SmartPtr<CLImageKernel>
    577 create_fishey_gps_kernel (const SmartPtr<CLContext> &context, SmartPtr<CLFisheyeHandler> handler)
    578 {
    579     SmartPtr<CLImageKernel> kernel = new CLFisheye2GPSKernel (context, handler);
    580     XCAM_ASSERT (kernel.ptr ());
    581     XCAM_FAIL_RETURN (
    582         ERROR, kernel->build_kernel (kernel_fisheye_info[KernelFisheye2GPS], NULL) == XCAM_RETURN_NO_ERROR,
    583         NULL, "build fisheye kernel failed");
    584     return kernel;
    585 }
    586 
    587 SmartPtr<CLImageHandler>
    588 create_fisheye_handler (const SmartPtr<CLContext> &context, SurroundMode surround_mode, bool use_map, bool need_lsc)
    589 {
    590     SmartPtr<CLFisheyeHandler> handler;
    591     SmartPtr<CLImageKernel> kernel;
    592 
    593     handler = new CLFisheyeHandler (context, surround_mode, use_map, need_lsc);
    594     XCAM_ASSERT (handler.ptr ());
    595 
    596     if (use_map) {
    597         kernel = create_geo_map_kernel (context, handler, need_lsc);
    598     } else {
    599         kernel = create_fishey_gps_kernel (context, handler);
    600     }
    601     XCAM_FAIL_RETURN (
    602         ERROR, kernel.ptr (), NULL, "Fisheye handler create kernel failed.");
    603 
    604     handler->add_kernel (kernel);
    605     return handler;
    606 }
    607 
    608 
    609 }
    610