• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
CLScalerKernel(const SmartPtr<CLContext> & context,CLImageScalerMemoryLayout mem_layout)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
prepare_arguments(CLArgList & args,CLWorkSize & work_size)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 
CLImageScalerKernel(const SmartPtr<CLContext> & context,CLImageScalerMemoryLayout mem_layout,SmartPtr<CLImageScaler> & scaler)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>
get_input_buffer()138 CLImageScalerKernel::get_input_buffer ()
139 {
140     return _scaler->get_input_buf ();
141 }
142 
143 SmartPtr<VideoBuffer>
get_output_buffer()144 CLImageScalerKernel::get_output_buffer ()
145 {
146     return _scaler->get_scaler_buf ();
147 }
148 
CLImageScaler(const SmartPtr<CLContext> & context)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
emit_stop()157 CLImageScaler::emit_stop ()
158 {
159     if (_scaler_buf_pool.ptr ())
160         _scaler_buf_pool->stop ();
161 }
162 
163 bool
set_scaler_factor(const double h_factor,const double v_factor)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
get_scaler_factor(double & h_factor,double & v_factor) const173 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
prepare_output_buf(SmartPtr<VideoBuffer> & input,SmartPtr<VideoBuffer> & output)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
execute_done(SmartPtr<VideoBuffer> & output)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
prepare_scaler_buf(const VideoBufferInfo & video_info,SmartPtr<VideoBuffer> & output)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
post_buffer(const SmartPtr<VideoBuffer> & buffer)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>
create_scale_kernel(const SmartPtr<CLContext> & context,SmartPtr<CLImageScaler> & handler,CLImageScalerMemoryLayout layout)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>
create_cl_image_scaler_handler(const SmartPtr<CLContext> & context,const uint32_t format)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