Home | History | Annotate | Download | only in ocl
      1 /*
      2  * cl_image_scaler.cpp - CL image scaler
      3  *
      4  *  Copyright (c) 2015 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_scaler.h"
     23 
     24 namespace XCam {
     25 
     26 static const XCamKernelInfo kernel_scale_info = {
     27     "kernel_image_scaler",
     28 #include "kernel_image_scaler.clx"
     29     , 0,
     30 };
     31 
     32 CLScalerKernel::CLScalerKernel (
     33     const SmartPtr<CLContext> &context,
     34     CLImageScalerMemoryLayout mem_layout
     35 )
     36     : CLImageKernel (context, "kernel_image_scaler")
     37     , _mem_layout (mem_layout)
     38 {
     39 }
     40 
     41 XCamReturn
     42 CLScalerKernel::prepare_arguments (CLArgList &args, CLWorkSize &work_size)
     43 {
     44     XCamReturn ret = XCAM_RETURN_NO_ERROR;
     45     SmartPtr<CLContext> context = get_context ();
     46 
     47     SmartPtr<VideoBuffer> input = get_input_buffer ();
     48     SmartPtr<VideoBuffer> output = get_output_buffer ();
     49     SmartPtr<CLImage> image_in, image_out;
     50 
     51     XCAM_FAIL_RETURN (
     52         WARNING,
     53         input.ptr () && output.ptr (),
     54         XCAM_RETURN_ERROR_MEM,
     55         "cl image kernel(%s) get input/output buffer failed", XCAM_STR(get_kernel_name ()));
     56 
     57     const VideoBufferInfo &input_info = input->get_video_info ();
     58     const VideoBufferInfo &output_info = output->get_video_info ();
     59 
     60     uint32_t output_width = 0, output_height = 0;
     61     CLImageDesc output_imageDesc;
     62 
     63     uint32_t channel_bits = XCAM_ALIGN_UP (output_info.color_bits, 8);
     64     if (channel_bits == 8)
     65         output_imageDesc.format.image_channel_data_type = CL_UNSIGNED_INT8;
     66     else if (channel_bits == 16)
     67         output_imageDesc.format.image_channel_data_type = CL_UNSIGNED_INT16;
     68 
     69     if ((CL_IMAGE_SCALER_NV12_UV == get_mem_layout ()) && (V4L2_PIX_FMT_NV12 == input_info.format)) {
     70         output_imageDesc.format.image_channel_order = CL_RG;
     71         output_imageDesc.width = output_info.width / 2;
     72         output_imageDesc.height = output_info.height / 2;
     73         output_imageDesc.row_pitch = output_info.strides[1];
     74 
     75         image_out = convert_to_climage (context, output, output_imageDesc, output_info.offsets[1]);
     76         output_width = output_info.width / 2;
     77         output_height = output_info.height / 2;
     78     } else {
     79         output_imageDesc.format.image_channel_order = CL_R;
     80         output_imageDesc.width = output_info.width;
     81         output_imageDesc.height = output_info.height;
     82         output_imageDesc.row_pitch = output_info.strides[0];
     83 
     84         image_out = convert_to_climage (context, output, output_imageDesc, output_info.offsets[0]);
     85         output_width = output_info.width;
     86         output_height = output_info.height;
     87     }
     88 
     89     CLImageDesc input_imageDesc;
     90     channel_bits = XCAM_ALIGN_UP (input_info.color_bits, 8);
     91     if (channel_bits == 8)
     92         input_imageDesc.format.image_channel_data_type = CL_UNSIGNED_INT8;
     93     else if (channel_bits == 16)
     94         input_imageDesc.format.image_channel_data_type = CL_UNSIGNED_INT16;
     95 
     96     if ((CL_IMAGE_SCALER_NV12_UV == get_mem_layout ()) && (V4L2_PIX_FMT_NV12 == input_info.format)) {
     97         input_imageDesc.format.image_channel_order = CL_RG;
     98         input_imageDesc.width = input_info.width / 2;
     99         input_imageDesc.height = input_info.height / 2;
    100         input_imageDesc.row_pitch = input_info.strides[1];
    101 
    102         image_in = convert_to_climage (context, input, input_imageDesc, input_info.offsets[1]);
    103     } else {
    104         input_imageDesc.format.image_channel_order = CL_R;
    105         input_imageDesc.width = input_info.width;
    106         input_imageDesc.height = input_info.height;
    107         input_imageDesc.row_pitch = input_info.strides[0];
    108 
    109         image_in = convert_to_climage (context, input, input_imageDesc, input_info.offsets[0]);
    110     }
    111 
    112     //set args;
    113     args.push_back (new CLMemArgument (image_in));
    114     args.push_back (new CLMemArgument (image_out));
    115     args.push_back (new CLArgumentT<uint32_t> (output_width));
    116     args.push_back (new CLArgumentT<uint32_t> (output_height));
    117 
    118     work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
    119     work_size.global[0] = XCAM_ALIGN_UP (output_width, XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE0);
    120     work_size.global[1] = XCAM_ALIGN_UP (output_height, XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE1);
    121     work_size.local[0] = XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE0;
    122     work_size.local[1] = XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE1;
    123 
    124     return ret;
    125 }
    126 
    127 CLImageScalerKernel::CLImageScalerKernel (
    128     const SmartPtr<CLContext> &context,
    129     CLImageScalerMemoryLayout mem_layout,
    130     SmartPtr<CLImageScaler> &scaler
    131 )
    132     : CLScalerKernel (context, mem_layout)
    133     , _scaler (scaler)
    134 {
    135 }
    136 
    137 SmartPtr<VideoBuffer>
    138 CLImageScalerKernel::get_input_buffer ()
    139 {
    140     return _scaler->get_input_buf ();
    141 }
    142 
    143 SmartPtr<VideoBuffer>
    144 CLImageScalerKernel::get_output_buffer ()
    145 {
    146     return _scaler->get_scaler_buf ();
    147 }
    148 
    149 CLImageScaler::CLImageScaler (const SmartPtr<CLContext> &context)
    150     : CLImageHandler (context, "CLImageScaler")
    151     , _h_scaler_factor (0.5)
    152     , _v_scaler_factor (0.5)
    153 {
    154 }
    155 
    156 void
    157 CLImageScaler::emit_stop ()
    158 {
    159     if (_scaler_buf_pool.ptr ())
    160         _scaler_buf_pool->stop ();
    161 }
    162 
    163 bool
    164 CLImageScaler::set_scaler_factor (const double h_factor, const double v_factor)
    165 {
    166     _h_scaler_factor = h_factor;
    167     _v_scaler_factor = v_factor;
    168 
    169     return true;
    170 }
    171 
    172 bool
    173 CLImageScaler::get_scaler_factor (double &h_factor, double &v_factor) const
    174 {
    175     h_factor = _h_scaler_factor;
    176     v_factor = _v_scaler_factor;
    177 
    178     return true;
    179 };
    180 
    181 XCamReturn
    182 CLImageScaler::prepare_output_buf (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
    183 {
    184     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    185     output = input;
    186 
    187     ret = prepare_scaler_buf (input->get_video_info (), _scaler_buf);
    188     XCAM_FAIL_RETURN(
    189         WARNING,
    190         ret == XCAM_RETURN_NO_ERROR,
    191         ret,
    192         "CLImageScalerKernel prepare scaled video buf failed");
    193 
    194     _scaler_buf->set_timestamp (input->get_timestamp ());
    195 
    196     return ret;
    197 }
    198 
    199 XCamReturn
    200 CLImageScaler::execute_done (SmartPtr<VideoBuffer> &output)
    201 {
    202     XCAM_UNUSED (output);
    203     get_context ()->finish();
    204     XCAM_ASSERT (_scaler_buf.ptr ());
    205 
    206     //post buffer out
    207     return post_buffer (_scaler_buf);
    208 }
    209 
    210 XCamReturn
    211 CLImageScaler::prepare_scaler_buf (const VideoBufferInfo &video_info, SmartPtr<VideoBuffer> &output)
    212 {
    213     if (!_scaler_buf_pool.ptr ()) {
    214         VideoBufferInfo scaler_video_info;
    215         uint32_t new_width = XCAM_ALIGN_UP ((uint32_t)(video_info.width * _h_scaler_factor),
    216                                             2 * XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE0);
    217         uint32_t new_height = XCAM_ALIGN_UP ((uint32_t)(video_info.height * _v_scaler_factor),
    218                                              2 * XCAM_CL_IMAGE_SCALER_KERNEL_LOCAL_WORK_SIZE1);
    219 
    220         scaler_video_info.init (video_info.format, new_width, new_height);
    221 
    222         _scaler_buf_pool = new CLVideoBufferPool ();
    223         XCAM_ASSERT (_scaler_buf_pool.ptr ());
    224         _scaler_buf_pool->set_video_info (scaler_video_info);
    225         _scaler_buf_pool->reserve (6);
    226     }
    227 
    228     output = _scaler_buf_pool->get_buffer (_scaler_buf_pool);
    229     XCAM_ASSERT (output.ptr ());
    230 
    231     return XCAM_RETURN_NO_ERROR;
    232 }
    233 
    234 XCamReturn
    235 CLImageScaler::post_buffer (const SmartPtr<VideoBuffer> &buffer)
    236 {
    237     if (_scaler_callback.ptr ())
    238         return _scaler_callback->scaled_image_ready (buffer);
    239 
    240     return XCAM_RETURN_NO_ERROR;
    241 }
    242 
    243 static SmartPtr<CLImageKernel>
    244 create_scale_kernel (
    245     const SmartPtr<CLContext> &context, SmartPtr<CLImageScaler> &handler, CLImageScalerMemoryLayout layout)
    246 {
    247     SmartPtr<CLImageKernel> kernel;
    248     kernel = new CLImageScalerKernel (context, layout, handler);
    249     XCAM_ASSERT (kernel.ptr ());
    250     XCAM_FAIL_RETURN (
    251         ERROR, kernel->build_kernel (kernel_scale_info, NULL) == XCAM_RETURN_NO_ERROR, NULL,
    252         "build scaler kernel(%s) failed", kernel_scale_info.kernel_name);
    253     XCAM_ASSERT (kernel->is_valid ());
    254     return kernel;
    255 }
    256 
    257 SmartPtr<CLImageHandler>
    258 create_cl_image_scaler_handler (const SmartPtr<CLContext> &context, const uint32_t format)
    259 {
    260     SmartPtr<CLImageScaler> scaler_handler;
    261     SmartPtr<CLImageKernel> scaler_kernel;
    262 
    263     scaler_handler = new CLImageScaler (context);
    264     XCAM_ASSERT (scaler_handler.ptr ());
    265 
    266     if (V4L2_PIX_FMT_NV12 == format) {
    267         //Y
    268         scaler_kernel = create_scale_kernel (context, scaler_handler, CL_IMAGE_SCALER_NV12_Y);
    269         XCAM_FAIL_RETURN (ERROR, scaler_kernel.ptr (), NULL, "build CL_IMAGE_SCALER_NV12_Y kernel failed");
    270         scaler_handler->add_kernel (scaler_kernel);
    271         //UV
    272         scaler_kernel = create_scale_kernel (context, scaler_handler, CL_IMAGE_SCALER_NV12_UV);
    273         XCAM_FAIL_RETURN (ERROR, scaler_kernel.ptr (), NULL, "build CL_IMAGE_SCALER_NV12_UV kernel failed");
    274         scaler_handler->add_kernel (scaler_kernel);
    275     } else if (XCAM_PIX_FMT_RGBA64 == format) {
    276         scaler_kernel = create_scale_kernel (context, scaler_handler, CL_IMAGE_SCALER_RGBA);
    277         XCAM_FAIL_RETURN (ERROR, scaler_kernel.ptr (), NULL, "build CL_IMAGE_SCALER_RGBA kernel failed");
    278         scaler_handler->add_kernel (scaler_kernel);
    279     } else {
    280         XCAM_LOG_ERROR ("create cl image scaler failed, unknown format:0x%08x", format);
    281         return NULL;
    282     }
    283 
    284     return scaler_handler;
    285 }
    286 
    287 };
    288