1 /*
2  * cl_yuv_pipe_handler.cpp - CL YuvPipe 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: Wangfei <feix.w.wang@intel.com>
19  * Author: Wind Yuan <feng.yuan@intel.com>
20  */
21 
22 #include "cl_utils.h"
23 #include "cl_yuv_pipe_handler.h"
24 
25 #define USE_BUFFER_OBJECT 0
26 
27 namespace XCam {
28 
29 static const XCamKernelInfo kernel_yuv_pipe_info = {
30     "kernel_yuv_pipe",
31 #include "kernel_yuv_pipe.clx"
32     , 0,
33 };
34 
35 float default_matrix[XCAM_COLOR_MATRIX_SIZE] = {
36     0.299f, 0.587f, 0.114f,
37     -0.14713f, -0.28886f, 0.436f,
38     0.615f, -0.51499f, -0.10001f,
39 };
40 float default_macc[XCAM_CHROMA_AXIS_SIZE * XCAM_CHROMA_MATRIX_SIZE] = {
41     1.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 1.000000f,
42     1.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 1.000000f,
43     1.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 1.000000f,
44     1.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 1.000000f,
45     1.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 1.000000f,
46     1.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 1.000000f,
47     1.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 1.000000f,
48     1.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 1.000000f,
49 };
50 
CLYuvPipeImageKernel(const SmartPtr<CLContext> & context)51 CLYuvPipeImageKernel::CLYuvPipeImageKernel (const SmartPtr<CLContext> &context)
52     : CLImageKernel (context, "kernel_yuv_pipe")
53 
54 {
55 }
56 
CLYuvPipeImageHandler(const SmartPtr<CLContext> & context,const char * name)57 CLYuvPipeImageHandler::CLYuvPipeImageHandler (const SmartPtr<CLContext> &context, const char *name)
58     : CLImageHandler (context, name)
59     , _output_format(V4L2_PIX_FMT_NV12)
60     , _enable_tnr_yuv (0)
61     , _gain_yuv (1.0)
62     , _thr_y (0.05)
63     , _thr_uv (0.05)
64     ,  _enable_tnr_yuv_state (0)
65 
66 {
67     memcpy(_macc_table, default_macc, sizeof(float)*XCAM_CHROMA_AXIS_SIZE * XCAM_CHROMA_MATRIX_SIZE);
68     memcpy(_rgbtoyuv_matrix, default_matrix, sizeof(float)*XCAM_COLOR_MATRIX_SIZE);
69 }
70 
71 bool
set_macc_table(const XCam3aResultMaccMatrix & macc)72 CLYuvPipeImageHandler::set_macc_table (const XCam3aResultMaccMatrix &macc)
73 {
74     for(int i = 0; i < XCAM_CHROMA_AXIS_SIZE * XCAM_CHROMA_MATRIX_SIZE; i++)
75         _macc_table[i] = (float)macc.table[i];
76     return true;
77 }
78 
79 bool
set_rgbtoyuv_matrix(const XCam3aResultColorMatrix & matrix)80 CLYuvPipeImageHandler::set_rgbtoyuv_matrix (const XCam3aResultColorMatrix &matrix)
81 {
82     for (int i = 0; i < XCAM_COLOR_MATRIX_SIZE; i++)
83         _rgbtoyuv_matrix[i] = (float)matrix.matrix[i];
84     return true;
85 }
86 
87 XCamReturn
prepare_buffer_pool_video_info(const VideoBufferInfo & input,VideoBufferInfo & output)88 CLYuvPipeImageHandler::prepare_buffer_pool_video_info (
89     const VideoBufferInfo &input,
90     VideoBufferInfo &output)
91 {
92     bool format_inited = output.init (_output_format, input.width, input.height);
93 
94     XCAM_FAIL_RETURN (
95         WARNING,
96         format_inited,
97         XCAM_RETURN_ERROR_PARAM,
98         "CL image handler(%s) output format(%s) unsupported",
99         get_name (), xcam_fourcc_to_string (_output_format));
100 
101     return XCAM_RETURN_NO_ERROR;
102 }
103 
104 XCamReturn
prepare_parameters(SmartPtr<VideoBuffer> & input,SmartPtr<VideoBuffer> & output)105 CLYuvPipeImageHandler::prepare_parameters (
106     SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
107 {
108     SmartPtr<CLContext> context = get_context ();
109     const VideoBufferInfo & video_info_in = input->get_video_info ();
110     const VideoBufferInfo & video_info_out = output->get_video_info ();
111     CLArgList args;
112     CLWorkSize work_size;
113 
114     XCAM_ASSERT (_yuv_pipe_kernel.ptr ());
115     SmartPtr<CLMemory> buffer_in, buffer_out, buffer_out_UV;
116 
117 #if !USE_BUFFER_OBJECT
118     CLImageDesc in_image_info;
119     in_image_info.format.image_channel_order = CL_RGBA;
120     in_image_info.format.image_channel_data_type = CL_UNSIGNED_INT32;
121     in_image_info.width = video_info_in.aligned_width / 8;
122     in_image_info.height = video_info_in.aligned_height * 3;
123     in_image_info.row_pitch = video_info_in.strides[0];
124 
125     CLImageDesc out_image_info;
126     out_image_info.format.image_channel_order = CL_RGBA;
127     out_image_info.format.image_channel_data_type = CL_UNSIGNED_INT16;
128     out_image_info.width = video_info_out.width / 8;
129     out_image_info.height = video_info_out.aligned_height;
130     out_image_info.row_pitch = video_info_out.strides[0];
131 
132     buffer_in = convert_to_climage (context, input, in_image_info);
133     buffer_out = convert_to_climage (context, output, out_image_info, video_info_out.offsets[0]);
134 
135     out_image_info.height = video_info_out.aligned_height / 2;
136     out_image_info.row_pitch = video_info_out.strides[1];
137     buffer_out_UV = convert_to_climage (context, output, out_image_info, video_info_out.offsets[1]);
138 #else
139     buffer_in = convert_to_clbuffer (context, input);
140     buffer_out = convert_to_clbuffer (context, output);
141 #endif
142     SmartPtr<CLBuffer> matrix_buffer = new CLBuffer (
143         context, sizeof(float)*XCAM_COLOR_MATRIX_SIZE,
144         CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR , &_rgbtoyuv_matrix);
145     SmartPtr<CLBuffer> macc_table_buffer = new CLBuffer(
146         context, sizeof(float)*XCAM_CHROMA_AXIS_SIZE * XCAM_CHROMA_MATRIX_SIZE,
147         CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR , &_macc_table);
148 
149     uint32_t plannar_offset = video_info_in.aligned_height;
150 
151     if (!_buffer_out_prev.ptr ()) {
152         _buffer_out_prev = buffer_out;
153         _buffer_out_prev_UV = buffer_out_UV;
154         _enable_tnr_yuv_state = _enable_tnr_yuv;
155         _enable_tnr_yuv = 0;
156     }
157     else {
158         if (_enable_tnr_yuv == 0)
159             _enable_tnr_yuv = _enable_tnr_yuv_state;
160     }
161     XCAM_FAIL_RETURN (
162         WARNING,
163         buffer_in->is_valid () && buffer_out->is_valid (),
164         XCAM_RETURN_ERROR_MEM,
165         "cl image handler(%s) in/out memory not available", XCAM_STR (get_name ()));
166 
167     //set args;
168     args.push_back (new CLMemArgument (buffer_out));
169 
170 #if !USE_BUFFER_OBJECT
171     args.push_back (new CLMemArgument (buffer_out_UV));
172 #endif
173 
174     args.push_back (new CLMemArgument (_buffer_out_prev));
175 
176 #if !USE_BUFFER_OBJECT
177     args.push_back (new CLMemArgument (_buffer_out_prev_UV));
178 #else
179     uint32_t vertical_offset = video_info_out.aligned_height;
180     args.push_back (new CLArgumentT<uint32_t> (vertical_offset));
181 #endif
182     args.push_back (new CLArgumentT<uint32_t> (plannar_offset));
183     args.push_back (new CLMemArgument (matrix_buffer));
184     args.push_back (new CLMemArgument (macc_table_buffer));
185     args.push_back (new CLArgumentT<float> (_gain_yuv));
186     args.push_back (new CLArgumentT<float> (_thr_y));
187     args.push_back (new CLArgumentT<float> (_thr_uv));
188     args.push_back (new CLArgumentT<uint32_t> (_enable_tnr_yuv));
189     args.push_back (new CLMemArgument (buffer_in));
190 
191     work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
192     work_size.global[0] = video_info_out.width / 8 ;
193     work_size.global[1] = video_info_out.aligned_height / 2 ;
194     work_size.local[0] = 8;
195     work_size.local[1] = 4;
196 
197     XCAM_ASSERT (_yuv_pipe_kernel.ptr ());
198     XCamReturn ret = _yuv_pipe_kernel->set_arguments (args, work_size);
199     XCAM_FAIL_RETURN (
200         WARNING, ret == XCAM_RETURN_NO_ERROR, ret,
201         "yuv pipe kernel set arguments failed.");
202 
203     if (buffer_out->is_valid ()) {
204         _buffer_out_prev = buffer_out;
205         _buffer_out_prev_UV = buffer_out_UV;
206     }
207 
208     return XCAM_RETURN_NO_ERROR;
209 }
210 
211 bool
set_yuv_pipe_kernel(SmartPtr<CLYuvPipeImageKernel> & kernel)212 CLYuvPipeImageHandler::set_yuv_pipe_kernel(SmartPtr<CLYuvPipeImageKernel> &kernel)
213 {
214     SmartPtr<CLImageKernel> image_kernel = kernel;
215     add_kernel (image_kernel);
216     _yuv_pipe_kernel = kernel;
217     return true;
218 }
219 
220 bool
set_tnr_yuv_config(const XCam3aResultTemporalNoiseReduction & config)221 CLYuvPipeImageHandler::set_tnr_yuv_config (const XCam3aResultTemporalNoiseReduction& config)
222 {
223     if (!_yuv_pipe_kernel->is_valid ()) {
224         XCAM_LOG_ERROR ("set config error, invalid YUV-Pipe kernel !");
225     }
226 
227     _gain_yuv = (float)config.gain;
228     _thr_y = (float)config.threshold[0];
229     _thr_uv = (float)config.threshold[1];
230     XCAM_LOG_DEBUG ("set TNR YUV config: _gain(%f), _thr_y(%f), _thr_uv(%f)",
231                     _gain_yuv, _thr_y, _thr_uv);
232     return true;
233 }
234 
235 bool
set_tnr_enable(bool enable_tnr_yuv)236 CLYuvPipeImageHandler::set_tnr_enable (bool enable_tnr_yuv)
237 {
238     _enable_tnr_yuv = (enable_tnr_yuv ? 1 : 0);
239     return true;
240 }
241 
242 SmartPtr<CLImageHandler>
create_cl_yuv_pipe_image_handler(const SmartPtr<CLContext> & context)243 create_cl_yuv_pipe_image_handler (const SmartPtr<CLContext> &context)
244 {
245     SmartPtr<CLYuvPipeImageHandler> yuv_pipe_handler;
246     SmartPtr<CLYuvPipeImageKernel> yuv_pipe_kernel;
247 
248     yuv_pipe_kernel = new CLYuvPipeImageKernel (context);
249     XCAM_ASSERT (yuv_pipe_kernel.ptr ());
250     const char * options = USE_BUFFER_OBJECT ? "-DUSE_BUFFER_OBJECT=1" : "-DUSE_BUFFER_OBJECT=0";
251     XCAM_FAIL_RETURN (
252         ERROR, yuv_pipe_kernel->build_kernel (kernel_yuv_pipe_info, options) == XCAM_RETURN_NO_ERROR, NULL,
253         "build yuv-pipe kernel(%s) failed", kernel_yuv_pipe_info.kernel_name);
254 
255     XCAM_ASSERT (yuv_pipe_kernel->is_valid ());
256     yuv_pipe_handler = new CLYuvPipeImageHandler (context, "cl_handler_pipe_yuv");
257     yuv_pipe_handler->set_yuv_pipe_kernel (yuv_pipe_kernel);
258 
259     return yuv_pipe_handler;
260 }
261 
262 };
263