• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
CLImageWarpKernel(const SmartPtr<CLContext> & context,const char * name,uint32_t channel,SmartPtr<CLImageHandler> & handler)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
prepare_arguments(CLArgList & args,CLWorkSize & work_size)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 
CLImageWarpHandler(const SmartPtr<CLContext> & context,const char * name)171 CLImageWarpHandler::CLImageWarpHandler (const SmartPtr<CLContext> &context, const char *name)
172     : CLImageHandler (context, name)
173 {
174 }
175 
176 bool
is_ready()177 CLImageWarpHandler::is_ready ()
178 {
179     bool ret = !_warp_config_list.empty ();
180     return ret && CLImageHandler::is_ready ();
181 }
182 
183 XCamReturn
execute_done(SmartPtr<VideoBuffer> & output)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>
get_warp_input_buf()195 CLImageWarpHandler::get_warp_input_buf ()
196 {
197     return CLImageHandler::get_input_buf ();
198 }
199 
200 bool
set_warp_config(const XCamDVSResult & config)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
get_warp_config()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>
create_kernel_image_warp(const SmartPtr<CLContext> & context,uint32_t channel,SmartPtr<CLImageHandler> handler)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>
create_cl_image_warp_handler(const SmartPtr<CLContext> & context)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