1/*
2 * cl_csc_handler.cpp - CL csc 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#include "cl_utils.h"
22#include "cl_csc_handler.h"
23#include "cl_device.h"
24#include "cl_kernel.h"
25
26static const XCamKernelInfo kernel_csc_info[] = {
27    {
28        "kernel_csc_rgbatonv12",
29#include "kernel_csc.clx"
30        , 0,
31    },
32    {
33        "kernel_csc_rgbatolab",
34#include "kernel_csc.clx"
35        , 0,
36    },
37    {
38        "kernel_csc_rgba64torgba",
39#include "kernel_csc.clx"
40        , 0,
41    },
42    {
43        "kernel_csc_yuyvtorgba",
44#include "kernel_csc.clx"
45        , 0,
46    },
47    {
48        "kernel_csc_nv12torgba",
49#include "kernel_csc.clx"
50        , 0,
51    },
52};
53
54
55float default_rgbtoyuv_matrix[XCAM_COLOR_MATRIX_SIZE] = {
56    0.299f, 0.587f, 0.114f,
57    -0.14713f, -0.28886f, 0.436f,
58    0.615f, -0.51499f, -0.10001f
59};
60
61namespace XCam {
62
63CLCscImageKernel::CLCscImageKernel (const SmartPtr<CLContext> &context, CLCscType type)
64    : CLImageKernel (context)
65    , _kernel_csc_type (type)
66{
67}
68
69CLCscImageHandler::CLCscImageHandler (
70    const SmartPtr<CLContext> &context, const char *name, CLCscType type)
71    : CLImageHandler (context, name)
72    , _output_format (V4L2_PIX_FMT_NV12)
73    , _csc_type (type)
74{
75    memcpy (_rgbtoyuv_matrix, default_rgbtoyuv_matrix, sizeof (_rgbtoyuv_matrix));
76
77    switch (type) {
78    case CL_CSC_TYPE_RGBATONV12:
79        _output_format = V4L2_PIX_FMT_NV12;
80        break;
81    case CL_CSC_TYPE_RGBATOLAB:
82        _output_format = XCAM_PIX_FMT_LAB;
83        break;
84    case CL_CSC_TYPE_RGBA64TORGBA:
85    case CL_CSC_TYPE_YUYVTORGBA:
86    case CL_CSC_TYPE_NV12TORGBA:
87        _output_format = V4L2_PIX_FMT_RGBA32;
88        break;
89    default:
90        break;
91    }
92}
93
94bool
95CLCscImageHandler::set_csc_kernel (SmartPtr<CLCscImageKernel> &kernel)
96{
97    SmartPtr<CLImageKernel> image_kernel = kernel;
98    add_kernel (image_kernel);
99    _csc_kernel = kernel;
100    return true;
101}
102
103bool
104CLCscImageHandler::set_matrix (const XCam3aResultColorMatrix &matrix)
105{
106    for (int i = 0; i < XCAM_COLOR_MATRIX_SIZE; i++)
107        _rgbtoyuv_matrix[i] = (float)matrix.matrix[i];
108    return true;
109}
110
111bool
112CLCscImageHandler::set_output_format (uint32_t fourcc)
113{
114    XCAM_FAIL_RETURN (
115        WARNING,
116        V4L2_PIX_FMT_XBGR32 == fourcc || V4L2_PIX_FMT_NV12 == fourcc,
117        false,
118        "CL csc handler doesn't support format: (%s)",
119        xcam_fourcc_to_string (fourcc));
120
121    _output_format = fourcc;
122    return true;
123}
124
125XCamReturn
126CLCscImageHandler::prepare_buffer_pool_video_info (
127    const VideoBufferInfo &input,
128    VideoBufferInfo &output)
129{
130    bool format_inited = output.init (_output_format, input.width, input.height);
131
132    XCAM_FAIL_RETURN (
133        WARNING,
134        format_inited,
135        XCAM_RETURN_ERROR_PARAM,
136        "CL image handler(%s) output format(%s) unsupported",
137        get_name (), xcam_fourcc_to_string (_output_format));
138
139    return XCAM_RETURN_NO_ERROR;
140}
141
142static bool
143ensure_image_desc (const VideoBufferInfo &info, CLImageDesc &desc)
144{
145    desc.array_size = 0;
146    desc.slice_pitch = 0;
147    if (info.format == XCAM_PIX_FMT_RGB48_planar || info.format == XCAM_PIX_FMT_RGB24_planar)
148        desc.height = info.aligned_height * 3;
149
150    return true;
151}
152
153XCamReturn
154CLCscImageHandler::prepare_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
155{
156    SmartPtr<CLContext> context = get_context ();
157
158    const VideoBufferInfo &in_video_info = input->get_video_info ();
159    const VideoBufferInfo &out_video_info = output->get_video_info ();
160    CLArgList args;
161    CLWorkSize work_size;
162    XCamReturn ret = XCAM_RETURN_NO_ERROR;
163
164    XCAM_ASSERT (_csc_kernel.ptr ());
165
166    CLImageDesc in_desc, out_desc;
167    CLImage::video_info_2_cl_image_desc (in_video_info, in_desc);
168    CLImage::video_info_2_cl_image_desc (out_video_info, out_desc);
169    ensure_image_desc (in_video_info, in_desc);
170    ensure_image_desc (out_video_info, out_desc);
171
172    SmartPtr<CLImage> image_in  = convert_to_climage (context, input, in_desc, in_video_info.offsets[0]);
173    SmartPtr<CLImage> image_out  = convert_to_climage (context, output, out_desc, out_video_info.offsets[0]);
174    SmartPtr<CLBuffer> matrix_buffer = new CLBuffer (
175        context, sizeof(float)*XCAM_COLOR_MATRIX_SIZE,
176        CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR , &_rgbtoyuv_matrix);
177
178    XCAM_FAIL_RETURN (
179        WARNING,
180        image_in->is_valid () && image_out->is_valid () && matrix_buffer->is_valid(),
181        XCAM_RETURN_ERROR_MEM,
182        "cl image kernel(%s) in/out memory not available", _csc_kernel->get_kernel_name ());
183
184    work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
185    work_size.local[0] = 4;
186    work_size.local[1] = 4;
187
188    args.push_back (new CLMemArgument (image_in));
189    args.push_back (new CLMemArgument (image_out));
190
191    do {
192        if ((_csc_type == CL_CSC_TYPE_RGBATOLAB)
193                || (_csc_type == CL_CSC_TYPE_RGBA64TORGBA)
194                || (_csc_type == CL_CSC_TYPE_YUYVTORGBA)) {
195            work_size.global[0] = out_video_info.width;
196            work_size.global[1] = out_video_info.height;
197            break;
198        }
199
200        SmartPtr<CLImage> image_uv;
201        if(_csc_type == CL_CSC_TYPE_NV12TORGBA) {
202            in_desc.height /= 2;
203            image_uv = convert_to_climage (context, input, in_desc, in_video_info.offsets[1]);
204            args.push_back (new CLMemArgument (image_uv));
205
206            work_size.global[0] = out_video_info.width / 2;
207            work_size.global[1] = out_video_info.height / 2;
208            break;
209        }
210
211        if (_csc_type == CL_CSC_TYPE_RGBATONV12) {
212            out_desc.height /= 2;
213            image_uv = convert_to_climage (context, output, out_desc, out_video_info.offsets[1]);
214            args.push_back (new CLMemArgument (image_uv));
215            args.push_back (new CLMemArgument (matrix_buffer));
216
217            work_size.global[0] = out_video_info.width / 2;
218            work_size.global[1] = out_video_info.height / 2;
219            break;
220        }
221    } while (0);
222
223    XCAM_ASSERT (_csc_kernel.ptr ());
224    ret = _csc_kernel->set_arguments (args, work_size);
225    XCAM_FAIL_RETURN (
226        WARNING, ret == XCAM_RETURN_NO_ERROR, ret,
227        "csc kernel set arguments failed.");
228
229    return XCAM_RETURN_NO_ERROR;
230}
231
232SmartPtr<CLImageHandler>
233create_cl_csc_image_handler (const SmartPtr<CLContext> &context, CLCscType type)
234{
235    SmartPtr<CLCscImageHandler> csc_handler;
236    SmartPtr<CLCscImageKernel> csc_kernel;
237
238    XCAM_ASSERT (type < CL_CSC_TYPE_MAX);
239    csc_kernel = new CLCscImageKernel (context, type);
240    XCAM_ASSERT (csc_kernel.ptr ());
241    XCAM_FAIL_RETURN (
242        ERROR, csc_kernel->build_kernel (kernel_csc_info[type], NULL) == XCAM_RETURN_NO_ERROR, NULL,
243        "build csc kernel(%s) failed", kernel_csc_info[type].kernel_name);
244
245    XCAM_ASSERT (csc_kernel->is_valid ());
246
247    csc_handler = new CLCscImageHandler (context, "cl_handler_csc", type);
248    csc_handler->set_csc_kernel (csc_kernel);
249
250    return csc_handler;
251}
252
253};
254