Home | History | Annotate | Download | only in ocl
      1 /*
      2  * cl_geo_map_handler.cpp - CL geometry map 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_geo_map_handler.h"
     23 #include "cl_device.h"
     24 
     25 namespace XCam {
     26 
     27 static const XCamKernelInfo kernel_geo_map_info = {
     28     "kernel_geo_map",
     29 #include "kernel_geo_map.clx"
     30     , 0,
     31 };
     32 
     33 // GEO_MAP_CHANNEL for CL_RGBA channel
     34 #define GEO_MAP_CHANNEL 4  /* only use channel_0, channel_1 */
     35 
     36 CLGeoMapKernel::CLGeoMapKernel (
     37     const SmartPtr<CLContext> &context, const SmartPtr<GeoKernelParamCallback> handler, bool need_lsc)
     38     : CLImageKernel (context)
     39     , _handler (handler)
     40     , _need_lsc (need_lsc)
     41 {
     42     XCAM_ASSERT (handler.ptr ());
     43 }
     44 
     45 XCamReturn
     46 CLGeoMapKernel::prepare_arguments (CLArgList &args, CLWorkSize &work_size)
     47 {
     48     SmartPtr<CLImage> input_y = _handler->get_geo_input_image (NV12PlaneYIdx);
     49     SmartPtr<CLImage> input_uv = _handler->get_geo_input_image (NV12PlaneUVIdx);
     50     SmartPtr<CLImage> output_y = _handler->get_geo_output_image (NV12PlaneYIdx);
     51     SmartPtr<CLImage> output_uv = _handler->get_geo_output_image (NV12PlaneUVIdx);
     52     const CLImageDesc &outuv_desc = output_uv->get_image_desc ();
     53     SmartPtr<CLImage> geo_image = _handler->get_geo_map_table ();
     54 
     55     float geo_scale_size[2]; //width/height
     56     float out_size[2];
     57     _handler->get_geo_equivalent_out_size (geo_scale_size[0], geo_scale_size[1]);
     58     _handler->get_geo_pixel_out_size (out_size[0], out_size[1]);
     59 
     60     args.push_back (new CLMemArgument (input_y));
     61     args.push_back (new CLMemArgument (input_uv));
     62     args.push_back (new CLMemArgument (geo_image));
     63     args.push_back (new CLArgumentTArray<float, 2> (geo_scale_size));
     64 
     65     if (_need_lsc) {
     66         SmartPtr<CLImage> lsc_image = _handler->get_lsc_table ();
     67         float *gray_threshold = _handler->get_lsc_gray_threshold ();
     68         XCAM_FAIL_RETURN (
     69             ERROR,
     70             lsc_image.ptr() && lsc_image->is_valid () && gray_threshold,
     71             XCAM_RETURN_ERROR_PARAM,
     72             "CLGeoMapHandler::lsc table or gray threshold was not found");
     73         args.push_back (new CLMemArgument (lsc_image));
     74         args.push_back (new CLArgumentTArray<float, 2> (gray_threshold));
     75     }
     76     args.push_back (new CLMemArgument (output_y));
     77     args.push_back (new CLMemArgument (output_uv));
     78     args.push_back (new CLArgumentTArray<float, 2> (out_size));
     79 
     80     work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
     81     work_size.local[0] = 16;
     82     work_size.local[1] = 4;
     83     work_size.global[0] = XCAM_ALIGN_UP (outuv_desc.width, work_size.local[0]);
     84     work_size.global[1] = XCAM_ALIGN_UP (outuv_desc.height, work_size.local[1]);
     85 
     86     return XCAM_RETURN_NO_ERROR;
     87 }
     88 
     89 CLGeoMapHandler::CLGeoMapHandler (const SmartPtr<CLContext> &context)
     90     : CLImageHandler (context, "CLGeoMapHandler")
     91     , _output_width (0)
     92     , _output_height (0)
     93     , _map_width (0)
     94     , _map_height (0)
     95     , _map_aligned_width (0)
     96     , _uint_x (0.0f)
     97     , _uint_y (0.0f)
     98     , _geo_map_normalized (false)
     99 {
    100 }
    101 
    102 void
    103 CLGeoMapHandler::get_geo_equivalent_out_size (float &width, float &height)
    104 {
    105     width = _map_width * _uint_x;
    106     height = _map_height * _uint_y;
    107 }
    108 
    109 void
    110 CLGeoMapHandler::get_geo_pixel_out_size (float &width, float &height)
    111 {
    112     width = _output_width;
    113     height = _output_height;
    114 }
    115 
    116 bool
    117 CLGeoMapHandler::set_map_uint (float uint_x, float uint_y)
    118 {
    119     _uint_x = uint_x;
    120     _uint_y = uint_y;
    121     return true;
    122 }
    123 
    124 bool
    125 CLGeoMapHandler::set_map_data (GeoPos *data, uint32_t width, uint32_t height)
    126 {
    127     uint32_t size = width * height * GEO_MAP_CHANNEL * sizeof (float); // 4 for CL_RGBA,
    128     float *map_ptr = NULL;
    129 
    130     XCAM_FAIL_RETURN (
    131         ERROR, check_geo_map_buf (width, height), false,
    132         "CLGeoMapKernel check geo map buffer failed");
    133 
    134     XCamReturn ret = _geo_map->enqueue_map ((void *&)map_ptr, 0, size);
    135     XCAM_FAIL_RETURN (
    136         WARNING, ret == XCAM_RETURN_NO_ERROR, false,
    137         "CLGeoMapKernel map buffer failed");
    138 
    139     uint32_t start, idx;
    140     for (uint32_t h = 0; h < height; ++h) {
    141         for (uint32_t w = 0; w < width; ++w) {
    142             start = (h * _map_aligned_width + w) * GEO_MAP_CHANNEL;
    143             idx = h * width + w;
    144 
    145             map_ptr [start] = data [idx].x;
    146             map_ptr [start + 1] = data [idx].y;
    147         }
    148     }
    149     _geo_map->enqueue_unmap ((void *&)map_ptr);
    150     _geo_map_normalized = false;
    151     return true;
    152 }
    153 
    154 bool
    155 CLGeoMapHandler::check_geo_map_buf (uint32_t width, uint32_t height)
    156 {
    157     XCAM_ASSERT (width && height);
    158     if (width == _map_width && height == _map_height && _geo_map.ptr ()) {
    159         return true; // geo memory already created
    160     }
    161 
    162     uint32_t aligned_width = XCAM_ALIGN_UP (width, XCAM_CL_IMAGE_ALIGNMENT_X);  // 4 channel for CL_RGBA, but only use RG
    163     uint32_t row_pitch = aligned_width * GEO_MAP_CHANNEL * sizeof (float);
    164     uint32_t size = row_pitch * height;
    165     SmartPtr<CLContext> context = get_context ();
    166     XCAM_ASSERT (context.ptr ());
    167     _geo_map = new CLBuffer (context, size);
    168 
    169     if (!_geo_map.ptr () || !_geo_map->is_valid ()) {
    170         XCAM_LOG_ERROR ("CLGeoMapKernel create geo map buffer failed.");
    171         _geo_map.release ();
    172         return false;
    173     }
    174 
    175     CLImageDesc cl_geo_desc;
    176     cl_geo_desc.format.image_channel_data_type = CL_FLOAT;
    177     cl_geo_desc.format.image_channel_order = CL_RGBA; // CL_FLOAT need co-work with CL_RGBA
    178     cl_geo_desc.width = width;
    179     cl_geo_desc.height = height;
    180     cl_geo_desc.row_pitch = row_pitch;
    181     _geo_image = new CLImage2D (context, cl_geo_desc, 0, _geo_map);
    182     if (!_geo_image.ptr () || !_geo_image->is_valid ()) {
    183         XCAM_LOG_ERROR ("CLGeoMapKernel convert geo map buffer to image2d failed.");
    184         _geo_map.release ();
    185         _geo_image.release ();
    186         return false;
    187     }
    188 
    189     _map_width = width;
    190     _map_height = height;
    191     _map_aligned_width = aligned_width;
    192     return true;
    193 }
    194 
    195 
    196 bool
    197 CLGeoMapHandler::normalize_geo_map (uint32_t image_w, uint32_t image_h)
    198 {
    199     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    200 
    201     uint32_t row_pitch = _map_aligned_width * GEO_MAP_CHANNEL * sizeof (float);  // 4 channel for CL_RGBA, but only use RG
    202     uint32_t size = row_pitch * _map_height;
    203     float *map_ptr = NULL;
    204 
    205     XCAM_ASSERT (image_w && image_h);
    206     XCAM_FAIL_RETURN (
    207         ERROR, _geo_map.ptr () && _geo_map->is_valid (),
    208         false, "CLGeoMapKernel geo_map was not initialized");
    209 
    210     ret = _geo_map->enqueue_map ((void *&)map_ptr, 0, size);
    211     XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, false, "CLGeoMapKernel map buffer failed");
    212     uint32_t idx = 0;
    213     for (uint32_t h = 0; h < _map_height; ++h) {
    214         for (uint32_t w = 0; w < _map_width; ++w) {
    215             idx = (h * _map_aligned_width + w) * GEO_MAP_CHANNEL;
    216 
    217             map_ptr [idx] /= image_w;
    218             map_ptr [idx + 1] /= image_h;
    219         }
    220     }
    221     _geo_map->enqueue_unmap ((void *&)map_ptr);
    222 
    223     return true;
    224 }
    225 
    226 XCamReturn
    227 CLGeoMapHandler::prepare_buffer_pool_video_info (
    228     const VideoBufferInfo &input, VideoBufferInfo &output)
    229 {
    230     XCAM_FAIL_RETURN (
    231         WARNING, input.format == V4L2_PIX_FMT_NV12, XCAM_RETURN_ERROR_PARAM,
    232         "CLGeoMapHandler(%s) input buffer format(%s) not NV12", get_name (), xcam_fourcc_to_string (input.format));
    233 
    234     if (!_output_width || !_output_height) {
    235         _output_width = input.width;
    236         _output_height = input.height;
    237     }
    238     output.init (
    239         input.format, _output_width, _output_height,
    240         XCAM_ALIGN_UP (_output_width, 16), XCAM_ALIGN_UP (_output_height, 16));
    241     return XCAM_RETURN_NO_ERROR;
    242 }
    243 
    244 XCamReturn
    245 CLGeoMapHandler::prepare_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
    246 {
    247     const VideoBufferInfo &in_info = input->get_video_info ();
    248     const VideoBufferInfo &out_info = output->get_video_info ();
    249     SmartPtr<CLContext> context = get_context ();
    250     uint32_t input_image_w = XCAM_ALIGN_DOWN (in_info.width, 2);
    251     uint32_t input_image_h = XCAM_ALIGN_DOWN (in_info.height, 2);
    252 
    253     CLImageDesc cl_desc;
    254     cl_desc.format.image_channel_data_type = CL_UNORM_INT8;
    255     cl_desc.format.image_channel_order = CL_R;
    256     cl_desc.width = input_image_w;
    257     cl_desc.height = input_image_h;
    258     cl_desc.row_pitch = in_info.strides[NV12PlaneYIdx];
    259     _input[NV12PlaneYIdx] = convert_to_climage (context, input, cl_desc, in_info.offsets[NV12PlaneYIdx]);
    260 
    261     cl_desc.format.image_channel_data_type = CL_UNORM_INT8;
    262     cl_desc.format.image_channel_order = CL_RG;
    263     cl_desc.width = input_image_w / 2;
    264     cl_desc.height = input_image_h / 2;
    265     cl_desc.row_pitch = in_info.strides[NV12PlaneUVIdx];
    266     _input[NV12PlaneUVIdx] = convert_to_climage (context, input, cl_desc, in_info.offsets[NV12PlaneUVIdx]);
    267 
    268     cl_desc.format.image_channel_data_type = CL_UNSIGNED_INT16;
    269     cl_desc.format.image_channel_order = CL_RGBA;
    270     cl_desc.width = XCAM_ALIGN_DOWN (out_info.width, 4) / 8; //CL_RGBA * CL_UNSIGNED_INT16 = 8
    271     cl_desc.height = XCAM_ALIGN_DOWN (out_info.height, 2);
    272     cl_desc.row_pitch = out_info.strides[NV12PlaneYIdx];
    273     _output[NV12PlaneYIdx] = convert_to_climage (context, output, cl_desc, out_info.offsets[NV12PlaneYIdx]);
    274     cl_desc.height /= 2;
    275     cl_desc.row_pitch = out_info.strides[NV12PlaneUVIdx];
    276     _output[NV12PlaneUVIdx] = convert_to_climage (context, output, cl_desc, out_info.offsets[NV12PlaneUVIdx]);
    277 
    278     XCAM_ASSERT (
    279         _input[NV12PlaneYIdx].ptr () && _input[NV12PlaneYIdx]->is_valid () &&
    280         _input[NV12PlaneUVIdx].ptr () && _input[NV12PlaneUVIdx]->is_valid () &&
    281         _output[NV12PlaneYIdx].ptr () && _output[NV12PlaneYIdx]->is_valid () &&
    282         _output[NV12PlaneUVIdx].ptr () && _output[NV12PlaneUVIdx]->is_valid ());
    283 
    284     XCAM_FAIL_RETURN (
    285         ERROR, _geo_map.ptr () && _geo_map->is_valid (),
    286         XCAM_RETURN_ERROR_PARAM, "CLGeoMapHandler map data was not set");
    287 
    288     //calculate kernel map unit_x, unit_y.
    289     float uint_x, uint_y;
    290     get_map_uint (uint_x, uint_y);
    291     if (uint_x < 1.0f && uint_y < 1.0f) {
    292         uint_x = out_info.width / (float)_map_width;
    293         uint_y = out_info.height / (float)_map_height;
    294         set_map_uint (uint_x, uint_y);
    295     }
    296 
    297     if (!_geo_map_normalized) {
    298         XCAM_FAIL_RETURN (
    299             ERROR, normalize_geo_map (input_image_w, input_image_h),
    300             XCAM_RETURN_ERROR_PARAM, "CLGeoMapHandler normalized geo map failed");
    301         _geo_map_normalized = true;
    302     }
    303 
    304     return XCAM_RETURN_NO_ERROR;
    305 }
    306 
    307 XCamReturn
    308 CLGeoMapHandler::execute_done (SmartPtr<VideoBuffer> &output)
    309 {
    310     XCAM_UNUSED (output);
    311 
    312     for (int i = 0; i < NV12PlaneMax; ++i) {
    313         _input[i].release ();
    314         _output[i].release ();
    315     }
    316 
    317     return XCAM_RETURN_NO_ERROR;
    318 }
    319 
    320 SmartPtr<CLImageKernel>
    321 create_geo_map_kernel (
    322     const SmartPtr<CLContext> &context, SmartPtr<GeoKernelParamCallback> param_cb, bool need_lsc)
    323 {
    324     SmartPtr<CLImageKernel> kernel;
    325     kernel = new CLGeoMapKernel (context, param_cb, need_lsc);
    326     XCAM_ASSERT (kernel.ptr ());
    327 
    328     char build_options[1024];
    329     snprintf (build_options, sizeof(build_options), "-DENABLE_LSC=%d", need_lsc ? 1 : 0);
    330     XCAM_FAIL_RETURN (
    331         ERROR, kernel->build_kernel (kernel_geo_map_info, build_options) == XCAM_RETURN_NO_ERROR,
    332         NULL, "build geo map kernel failed");
    333 
    334     return kernel;
    335 }
    336 
    337 SmartPtr<CLImageHandler>
    338 create_geo_map_handler (const SmartPtr<CLContext> &context, bool need_lsc)
    339 {
    340     SmartPtr<CLGeoMapHandler> handler;
    341     SmartPtr<CLImageKernel> kernel;
    342 
    343     handler = new CLGeoMapHandler (context);
    344     XCAM_ASSERT (handler.ptr ());
    345 
    346     kernel = create_geo_map_kernel (context, handler, need_lsc);
    347     XCAM_FAIL_RETURN (
    348         ERROR, kernel.ptr (), NULL, "CLMapHandler build geo map kernel failed");
    349     handler->add_kernel (kernel);
    350 
    351     return handler;
    352 }
    353 
    354 }
    355