Home | History | Annotate | Download | only in ocl
      1 /*
      2  * cl_image_warp_handler.cpp - CL image warping 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: Zong Wei <wei.zong (at) intel.com>
     19  */
     20 
     21 #include "cl_utils.h"
     22 #include "cl_image_warp_handler.h"
     23 
     24 namespace XCam {
     25 
     26 #define CL_IMAGE_WARP_WG_WIDTH   8
     27 #define CL_IMAGE_WARP_WG_HEIGHT  4
     28 
     29 
     30 static const XCamKernelInfo kernel_image_warp_info [] = {
     31     {
     32         "kernel_image_warp_8_pixel",
     33 #include "kernel_image_warp.clx"
     34         , 0,
     35     },
     36     {
     37         "kernel_image_warp_1_pixel",
     38 #include "kernel_image_warp.clx"
     39         , 0,
     40     }
     41 };
     42 
     43 CLImageWarpKernel::CLImageWarpKernel (
     44     const SmartPtr<CLContext> &context,
     45     const char *name,
     46     uint32_t channel,
     47     SmartPtr<CLImageHandler> &handler)
     48     : CLImageKernel (context, name)
     49     , _channel (channel)
     50 {
     51     _handler = handler.dynamic_cast_ptr<CLImageWarpHandler> ();
     52 }
     53 
     54 XCamReturn
     55 CLImageWarpKernel::prepare_arguments (
     56     CLArgList &args, CLWorkSize &work_size)
     57 {
     58     SmartPtr<CLContext> context = get_context ();
     59     SmartPtr<VideoBuffer> input = _handler->get_warp_input_buf ();
     60     SmartPtr<VideoBuffer> output = _handler->get_output_buf ();
     61 
     62     const VideoBufferInfo & video_info_in = input->get_video_info ();
     63     const VideoBufferInfo & video_info_out = output->get_video_info ();
     64 
     65     uint32_t info_index = 0;
     66     if (_channel == CL_IMAGE_CHANNEL_Y) {
     67         info_index = 0;
     68     } else if (_channel == CL_IMAGE_CHANNEL_UV) {
     69         info_index = 1;
     70     }
     71 
     72     CLImageDesc cl_desc_in, cl_desc_out;
     73     cl_desc_in.format.image_channel_order = info_index == 0 ? CL_R : CL_RG;
     74     cl_desc_in.format.image_channel_data_type = CL_UNORM_INT8;
     75     cl_desc_in.width = video_info_in.width >> info_index;
     76     cl_desc_in.height = video_info_in.height >> info_index;
     77     cl_desc_in.row_pitch = video_info_in.strides[info_index];
     78 
     79 #if CL_IMAGE_WARP_WRITE_UINT
     80     cl_desc_out.format.image_channel_data_type = info_index == 0 ? CL_UNSIGNED_INT16 : CL_UNSIGNED_INT32;
     81     cl_desc_out.format.image_channel_order = CL_RGBA;
     82     cl_desc_out.width = XCAM_ALIGN_DOWN (video_info_out.width >> info_index, 8) / 8;
     83     cl_desc_out.height = video_info_out.height >> info_index;
     84 #else
     85     cl_desc_out.format.image_channel_order = info_index == 0 ? CL_R : CL_RG;
     86     cl_desc_out.format.image_channel_data_type = CL_UNORM_INT8;
     87     cl_desc_out.width = video_info_out.width >> info_index;
     88     cl_desc_out.height = video_info_out.height >> info_index;
     89 #endif
     90 
     91     cl_desc_out.row_pitch = video_info_out.strides[info_index];
     92     SmartPtr<CLImage> image_in = convert_to_climage (context, input, cl_desc_in, video_info_in.offsets[info_index]);
     93 
     94     CLWarpConfig warp_config = _handler->get_warp_config ();
     95     if ((warp_config.trim_ratio > 0.5f) || (warp_config.trim_ratio < 0.0f)) {
     96         warp_config.trim_ratio = 0.0f;
     97     }
     98 
     99     float sample_rate_x = (float)warp_config.width / (float)video_info_in.width;
    100     float sample_rate_y = (float)warp_config.height / (float)video_info_in.height;
    101     XCAM_LOG_DEBUG ("warp analyze image sample rate(%fx%f)", sample_rate_x, sample_rate_y);
    102     warp_config.proj_mat[2] = warp_config.proj_mat[2] / sample_rate_x;
    103     warp_config.proj_mat[5] = warp_config.proj_mat[5] / sample_rate_y;
    104     warp_config.proj_mat[6] = warp_config.proj_mat[6] * sample_rate_x;
    105     warp_config.proj_mat[7] = warp_config.proj_mat[7] * sample_rate_y;
    106 
    107     /*
    108        For NV12 image (YUV420), UV plane has half horizontal & vertical coordinate size of Y plane,
    109        need to adjust the projection matrix as:
    110        H(uv) = [0.5, 0, 0; 0, 0.5, 0; 0, 0, 1] * H(y) * [2, 0, 0; 0, 2, 0; 0, 0, 1]
    111     */
    112     if (_channel == CL_IMAGE_CHANNEL_UV) {
    113         warp_config.proj_mat[2] = 0.5 * warp_config.proj_mat[2];
    114         warp_config.proj_mat[5] = 0.5 * warp_config.proj_mat[5];
    115         warp_config.proj_mat[6] = 2.0 * warp_config.proj_mat[6];
    116         warp_config.proj_mat[7] = 2.0 * warp_config.proj_mat[7];
    117     }
    118 
    119     /*
    120       Trim image: shift toward origin then scale up
    121       Trim Matrix (TMat)
    122       TMat = [ scale_x, 0.0f,    shift_x;
    123                0.0f,    scale_y, shift_y;
    124                1.0f,    1.0f,    1.0f;   ]
    125 
    126       Warp Perspective Matrix = TMat * HMat
    127     */
    128 #if CL_IMAGE_WARP_WRITE_UINT
    129     float shift_x = warp_config.trim_ratio * cl_desc_out.width * 8.0f;
    130 #else
    131     float shift_x = warp_config.trim_ratio * cl_desc_out.width;
    132 #endif
    133     float shift_y = warp_config.trim_ratio * cl_desc_out.height;
    134     float scale_x = 1.0f - 2.0f * warp_config.trim_ratio;
    135     float scale_y = 1.0f - 2.0f * warp_config.trim_ratio;
    136 
    137     warp_config.proj_mat[0] = scale_x * warp_config.proj_mat[0] + shift_x * warp_config.proj_mat[6];
    138     warp_config.proj_mat[1] = scale_x * warp_config.proj_mat[1] + shift_x * warp_config.proj_mat[7];
    139     warp_config.proj_mat[2] = scale_x * warp_config.proj_mat[2] + shift_x * warp_config.proj_mat[8];
    140     warp_config.proj_mat[3] = scale_y * warp_config.proj_mat[3] + shift_y * warp_config.proj_mat[6];
    141     warp_config.proj_mat[4] = scale_y * warp_config.proj_mat[4] + shift_y * warp_config.proj_mat[7];
    142     warp_config.proj_mat[5] = scale_y * warp_config.proj_mat[5] + shift_y * warp_config.proj_mat[8];
    143 
    144     XCAM_LOG_DEBUG ("warp config image size(%dx%d)", warp_config.width, warp_config.height);
    145     XCAM_LOG_DEBUG ("proj_mat[%d]=(%f, %f, %f, %f, %f, %f, %f, %f, %f);", warp_config.frame_id,
    146                     warp_config.proj_mat[0], warp_config.proj_mat[1], warp_config.proj_mat[2],
    147                     warp_config.proj_mat[3], warp_config.proj_mat[4], warp_config.proj_mat[5],
    148                     warp_config.proj_mat[6], warp_config.proj_mat[7], warp_config.proj_mat[8]);
    149 
    150     SmartPtr<CLImage> image_out = convert_to_climage (context, output, cl_desc_out, video_info_out.offsets[info_index]);
    151     XCAM_FAIL_RETURN (
    152         WARNING,
    153         image_in->is_valid () && image_out->is_valid (),
    154         XCAM_RETURN_ERROR_MEM,
    155         "cl image kernel(%s) in/out memory not available", get_kernel_name ());
    156 
    157     //set args;
    158     work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
    159     work_size.local[0] = CL_IMAGE_WARP_WG_WIDTH;
    160     work_size.local[1] = CL_IMAGE_WARP_WG_HEIGHT;
    161     work_size.global[0] = XCAM_ALIGN_UP (cl_desc_out.width, work_size.local[0]);
    162     work_size.global[1] = XCAM_ALIGN_UP(cl_desc_out.height, work_size.local[1]);
    163 
    164     args.push_back (new CLMemArgument (image_in));
    165     args.push_back (new CLMemArgument (image_out));
    166     args.push_back (new CLArgumentT<CLWarpConfig> (warp_config));
    167 
    168     return XCAM_RETURN_NO_ERROR;
    169 }
    170 
    171 CLImageWarpHandler::CLImageWarpHandler (const SmartPtr<CLContext> &context, const char *name)
    172     : CLImageHandler (context, name)
    173 {
    174 }
    175 
    176 bool
    177 CLImageWarpHandler::is_ready ()
    178 {
    179     bool ret = !_warp_config_list.empty ();
    180     return ret && CLImageHandler::is_ready ();
    181 }
    182 
    183 XCamReturn
    184 CLImageWarpHandler::execute_done (SmartPtr<VideoBuffer> &output)
    185 {
    186     XCAM_UNUSED (output);
    187     if (!_warp_config_list.empty ()) {
    188         _warp_config_list.pop_front ();
    189     }
    190 
    191     return XCAM_RETURN_NO_ERROR;
    192 }
    193 
    194 SmartPtr<VideoBuffer>
    195 CLImageWarpHandler::get_warp_input_buf ()
    196 {
    197     return CLImageHandler::get_input_buf ();
    198 }
    199 
    200 bool
    201 CLImageWarpHandler::set_warp_config (const XCamDVSResult& config)
    202 {
    203     CLWarpConfig warp_config;
    204     warp_config.frame_id = config.frame_id;
    205     warp_config.width = config.frame_width;
    206     warp_config.height = config.frame_height;
    207     for( int i = 0; i < 9; i++ ) {
    208         warp_config.proj_mat[i] = config.proj_mat[i];
    209     }
    210     XCAM_LOG_DEBUG ("warp_mat{%d}=[%f, %f, %f; %f, %f, %f; %f, %f, %f]", warp_config.frame_id + 1,
    211                     warp_config.proj_mat[0], warp_config.proj_mat[1], warp_config.proj_mat[2],
    212                     warp_config.proj_mat[3], warp_config.proj_mat[4], warp_config.proj_mat[5],
    213                     warp_config.proj_mat[6], warp_config.proj_mat[7], warp_config.proj_mat[8]);
    214 #if 0
    215     printf ("warp_mat{%d}=[%f, %f, %f; %f, %f, %f; %f, %f, %f]; \n", warp_config.frame_id + 1,
    216             warp_config.proj_mat[0], warp_config.proj_mat[1], warp_config.proj_mat[2],
    217             warp_config.proj_mat[3], warp_config.proj_mat[4], warp_config.proj_mat[5],
    218             warp_config.proj_mat[6], warp_config.proj_mat[7], warp_config.proj_mat[8]);
    219 #endif
    220     _warp_config_list.push_back (warp_config);
    221 
    222     return true;
    223 }
    224 
    225 CLWarpConfig
    226 CLImageWarpHandler::get_warp_config ()
    227 {
    228     CLWarpConfig warp_config;
    229 
    230     if (_warp_config_list.size () > 0) {
    231         warp_config = *(_warp_config_list.begin ());
    232     } else {
    233         warp_config.frame_id = -1;
    234         warp_config.proj_mat[0] = 1.0f;
    235         warp_config.proj_mat[1] = 0.0f;
    236         warp_config.proj_mat[2] = 0.0f;
    237         warp_config.proj_mat[3] = 0.0f;
    238         warp_config.proj_mat[4] = 1.0f;
    239         warp_config.proj_mat[5] = 0.0f;
    240         warp_config.proj_mat[6] = 0.0f;
    241         warp_config.proj_mat[7] = 0.0f;
    242         warp_config.proj_mat[8] = 1.0f;
    243     }
    244 
    245     return warp_config;
    246 }
    247 
    248 static SmartPtr<CLImageWarpKernel>
    249 create_kernel_image_warp (
    250     const SmartPtr<CLContext> &context,
    251     uint32_t channel,
    252     SmartPtr<CLImageHandler> handler)
    253 {
    254     SmartPtr<CLImageWarpKernel> warp_kernel;
    255 
    256     const char *name = (channel == CL_IMAGE_CHANNEL_Y ? "kernel_image_warp_y" : "kernel_image_warp_uv");
    257     char build_options[1024];
    258     xcam_mem_clear (build_options);
    259 
    260     snprintf (build_options, sizeof (build_options),
    261               " -DWARP_Y=%d ",
    262               (channel == CL_IMAGE_CHANNEL_Y ? 1 : 0));
    263 
    264     warp_kernel = new CLImageWarpKernel (context, name, channel, handler);
    265     XCAM_ASSERT (warp_kernel.ptr ());
    266     XCAM_FAIL_RETURN (
    267         ERROR, warp_kernel->build_kernel (kernel_image_warp_info[KernelImageWarp], build_options) == XCAM_RETURN_NO_ERROR,
    268         NULL, "build image warp kernel failed");
    269     XCAM_ASSERT (warp_kernel->is_valid ());
    270 
    271     return warp_kernel;
    272 }
    273 
    274 SmartPtr<CLImageHandler>
    275 create_cl_image_warp_handler (const SmartPtr<CLContext> &context)
    276 {
    277     SmartPtr<CLImageWarpHandler> warp_handler;
    278     SmartPtr<CLImageKernel> warp_kernel;
    279 
    280     warp_handler = new CLImageWarpHandler (context);
    281     XCAM_ASSERT (warp_handler.ptr ());
    282 
    283     warp_kernel = create_kernel_image_warp (context, CL_IMAGE_CHANNEL_Y, warp_handler);
    284     XCAM_ASSERT (warp_kernel.ptr ());
    285     warp_handler->add_kernel (warp_kernel);
    286 
    287     warp_kernel = create_kernel_image_warp (context, CL_IMAGE_CHANNEL_UV, warp_handler);
    288     XCAM_ASSERT (warp_kernel.ptr ());
    289     warp_handler->add_kernel (warp_kernel);
    290 
    291     return warp_handler;
    292 }
    293 
    294 };
    295