1 /*
2  * cl_bayer_pipe_handler.cpp - CL bayer pipe handler
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: Wind Yuan <feng.yuan@intel.com>
19  * Author: wangfei <feix.w.wang@intel.com>
20  * Author: Shincy Tu <shincy.tu@intel.com>
21  */
22 
23 #include "cl_utils.h"
24 #include "cl_bayer_pipe_handler.h"
25 
26 #define WORKGROUP_PIXEL_WIDTH 128
27 #define WORKGROUP_PIXEL_HEIGHT 8
28 
29 #define BAYER_LOCAL_X_SIZE 64
30 #define BAYER_LOCAL_Y_SIZE 2
31 
32 namespace XCam {
33 
34 static const float table [XCAM_BNR_TABLE_SIZE] = {
35     63.661991f, 60.628166f, 52.366924f, 41.023067f, 29.146584f, 18.781729f, 10.976704f,
36     6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f,
37     6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f,
38     6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f,
39     6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f,
40     6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f,
41     6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f,
42     6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f, 6.000000f,
43     6.000000f,
44 };
45 
46 static const XCamKernelInfo kernel_bayer_pipe_info = {
47     "kernel_bayer_pipe",
48 #include "kernel_bayer_pipe.clx"
49     , 0,
50 };
51 
CLBayerPipeImageKernel(const SmartPtr<CLContext> & context,SmartPtr<CLBayerPipeImageHandler> & handler)52 CLBayerPipeImageKernel::CLBayerPipeImageKernel (
53     const SmartPtr<CLContext> &context,
54     SmartPtr<CLBayerPipeImageHandler> &handler)
55     : CLImageKernel (context, "kernel_bayer_pipe")
56     , _handler (handler)
57 {
58 
59 }
60 
CLBayerPipeImageHandler(const SmartPtr<CLContext> & context,const char * name)61 CLBayerPipeImageHandler::CLBayerPipeImageHandler (const SmartPtr<CLContext> &context, const char *name)
62     : CLImageHandler (context, name)
63     , _output_format (XCAM_PIX_FMT_RGB48_planar)
64     , _enable_denoise (0)
65 {
66     memcpy(_bnr_table, table, sizeof(float)*XCAM_BNR_TABLE_SIZE);
67     _ee_config.ee_gain = 0.8;
68     _ee_config.ee_threshold = 0.025;
69 }
70 
71 bool
set_output_format(uint32_t fourcc)72 CLBayerPipeImageHandler::set_output_format (uint32_t fourcc)
73 {
74     XCAM_FAIL_RETURN (
75         WARNING,
76         XCAM_PIX_FMT_RGB48_planar == fourcc || XCAM_PIX_FMT_RGB24_planar == fourcc,
77         false,
78         "CL image handler(%s) doesn't support format(%s) settings",
79         get_name (), xcam_fourcc_to_string (fourcc));
80 
81     _output_format = fourcc;
82     return true;
83 }
84 
85 bool
set_bayer_kernel(SmartPtr<CLBayerPipeImageKernel> & kernel)86 CLBayerPipeImageHandler::set_bayer_kernel (SmartPtr<CLBayerPipeImageKernel> &kernel)
87 {
88     SmartPtr<CLImageKernel> image_kernel = kernel;
89     add_kernel (image_kernel);
90     _bayer_kernel = kernel;
91     return true;
92 }
93 
94 bool
enable_denoise(bool enable)95 CLBayerPipeImageHandler::enable_denoise (bool enable)
96 {
97     _enable_denoise = (enable ? 1 : 0);
98     return true;
99 
100 }
101 
102 bool
set_ee_config(const XCam3aResultEdgeEnhancement & ee)103 CLBayerPipeImageHandler::set_ee_config (const XCam3aResultEdgeEnhancement &ee)
104 {
105     _ee_config.ee_gain = (float)ee.gain;
106     _ee_config.ee_threshold = (float)ee.threshold;
107     return true;
108 }
109 bool
set_bnr_config(const XCam3aResultBayerNoiseReduction & bnr)110 CLBayerPipeImageHandler::set_bnr_config (const XCam3aResultBayerNoiseReduction &bnr)
111 {
112     for(int i = 0; i < XCAM_BNR_TABLE_SIZE; i++)
113         _bnr_table[i] = (float)bnr.table[i];
114     return true;
115 }
116 
117 XCamReturn
prepare_buffer_pool_video_info(const VideoBufferInfo & input,VideoBufferInfo & output)118 CLBayerPipeImageHandler::prepare_buffer_pool_video_info (
119     const VideoBufferInfo &input,
120     VideoBufferInfo &output)
121 {
122     uint32_t format = _output_format;
123     uint32_t width = input.width;
124     uint32_t height = input.height;
125     if (input.format == XCAM_PIX_FMT_SGRBG16_planar) {
126         width *= 2;
127         height *= 2;
128     }
129     bool format_inited = output.init (format, width, height);
130 
131     XCAM_FAIL_RETURN (
132         WARNING,
133         format_inited,
134         XCAM_RETURN_ERROR_PARAM,
135         "CL image handler(%s) output format(%s) unsupported",
136         get_name (), xcam_fourcc_to_string (format));
137 
138     return XCAM_RETURN_NO_ERROR;
139 }
140 
141 XCamReturn
prepare_parameters(SmartPtr<VideoBuffer> & input,SmartPtr<VideoBuffer> & output)142 CLBayerPipeImageHandler::prepare_parameters (
143     SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
144 {
145     SmartPtr<CLContext> context = get_context ();
146     const VideoBufferInfo & in_video_info = input->get_video_info ();
147     const VideoBufferInfo & out_video_info = output->get_video_info ();
148     CLArgList args;
149     CLWorkSize work_size;
150 
151     XCAM_ASSERT (_bayer_kernel.ptr ());
152 
153     CLImageDesc in_desc;
154     in_desc.format.image_channel_order = CL_RGBA;
155     in_desc.format.image_channel_data_type = CL_UNORM_INT16; //CL_UNSIGNED_INT32;
156     in_desc.width = in_video_info.width / 4; // 960/4
157     in_desc.height = in_video_info.aligned_height * 4;  //540
158     in_desc.row_pitch = in_video_info.strides[0];
159 
160     SmartPtr<CLImage> image_in = convert_to_climage (context, input, in_desc);
161 
162     CLImageDesc out_desc;
163     out_desc.format.image_channel_order = CL_RGBA;
164     if (XCAM_PIX_FMT_RGB48_planar == out_video_info.format)
165         out_desc.format.image_channel_data_type = CL_UNORM_INT16;
166     else
167         out_desc.format.image_channel_data_type = CL_UNORM_INT8;
168     out_desc.width = out_video_info.aligned_width / 4;
169     out_desc.height = out_video_info.aligned_height * 3;
170     out_desc.row_pitch = out_video_info.strides[0];
171     out_desc.array_size = 3;
172     out_desc.slice_pitch = out_video_info.strides [0] * out_video_info.aligned_height;
173 
174     SmartPtr<CLImage> image_out = convert_to_climage (context, output, out_desc);
175 
176     uint input_height = in_video_info.aligned_height;
177     uint output_height = out_video_info.aligned_height;
178 
179     XCAM_ASSERT (image_in.ptr () && image_out.ptr ());
180     XCAM_FAIL_RETURN (
181         WARNING,
182         image_in->is_valid () && image_out->is_valid (),
183         XCAM_RETURN_ERROR_MEM,
184         "cl image kernel(%s) in/out memory not available", _bayer_kernel->get_kernel_name ());
185 
186     SmartPtr<CLBuffer> bnr_table_buffer = new CLBuffer(
187         context, sizeof(float) * XCAM_BNR_TABLE_SIZE,
188         CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, &_bnr_table);
189 
190     //set args;
191     args.push_back (new CLMemArgument (image_in));
192     args.push_back (new CLArgumentT<uint> (input_height));
193     args.push_back (new CLMemArgument (image_out));
194     args.push_back (new CLArgumentT<uint> (output_height));
195     args.push_back (new CLMemArgument (bnr_table_buffer));
196     args.push_back (new CLArgumentT<uint32_t> (_enable_denoise));
197     args.push_back (new CLArgumentT<CLEeConfig> (_ee_config));
198 
199     work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
200     work_size.local[0] = BAYER_LOCAL_X_SIZE;
201     work_size.local[1] = BAYER_LOCAL_Y_SIZE;
202     work_size.global[0] = (XCAM_ALIGN_UP(out_video_info.width, WORKGROUP_PIXEL_WIDTH) / WORKGROUP_PIXEL_WIDTH) *
203                           work_size.local[0];
204     work_size.global[1] = (XCAM_ALIGN_UP(out_video_info.height, WORKGROUP_PIXEL_HEIGHT) / WORKGROUP_PIXEL_HEIGHT) *
205                           work_size.local[1];
206 
207     XCAM_ASSERT (_bayer_kernel.ptr ());
208     XCamReturn ret = _bayer_kernel->set_arguments (args, work_size);
209     XCAM_FAIL_RETURN (
210         WARNING, ret == XCAM_RETURN_NO_ERROR, ret,
211         "bayer pipe kernel set arguments failed.");
212 
213     return XCAM_RETURN_NO_ERROR;
214 }
215 
216 
217 SmartPtr<CLImageHandler>
create_cl_bayer_pipe_image_handler(const SmartPtr<CLContext> & context)218 create_cl_bayer_pipe_image_handler (const SmartPtr<CLContext> &context)
219 {
220     SmartPtr<CLBayerPipeImageHandler> bayer_pipe_handler;
221     SmartPtr<CLBayerPipeImageKernel> bayer_pipe_kernel;
222 
223     bayer_pipe_handler = new CLBayerPipeImageHandler (context, "cl_handler_bayer_pipe");
224     bayer_pipe_kernel = new CLBayerPipeImageKernel (context, bayer_pipe_handler);
225     XCAM_ASSERT (bayer_pipe_kernel.ptr ());
226     XCAM_FAIL_RETURN (
227         ERROR, bayer_pipe_kernel->build_kernel (kernel_bayer_pipe_info, NULL) == XCAM_RETURN_NO_ERROR, NULL,
228         "build bayer-pipe kernel(%s) failed", kernel_bayer_pipe_info.kernel_name);
229 
230     XCAM_ASSERT (bayer_pipe_kernel->is_valid ());
231     bayer_pipe_handler->set_bayer_kernel (bayer_pipe_kernel);
232 
233     return bayer_pipe_handler;
234 }
235 
236 };
237