| /* |
| * cl_wavelet_denoise_handler.cpp - CL wavelet denoise handler |
| * |
| * Copyright (c) 2015 Intel Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * Author: Wei Zong <[email protected]> |
| */ |
| #include "cl_utils.h" |
| #include "x3a_stats_pool.h" |
| #include "cl_context.h" |
| #include "cl_device.h" |
| #include "cl_wavelet_denoise_handler.h" |
| |
| #define WAVELET_DECOMPOSITION_LEVELS 4 |
| |
| namespace XCam { |
| |
| static const XCamKernelInfo kernel_wavelet_denoise_info = { |
| "kernel_wavelet_denoise", |
| #include "kernel_wavelet_denoise.clx" |
| , 0, |
| }; |
| |
| CLWaveletDenoiseImageKernel::CLWaveletDenoiseImageKernel ( |
| const SmartPtr<CLContext> &context, |
| const char *name, |
| SmartPtr<CLWaveletDenoiseImageHandler> &handler, |
| uint32_t channel, |
| uint32_t layer) |
| : CLImageKernel (context, name) |
| , _channel (channel) |
| , _current_layer (layer) |
| , _handler (handler) |
| { |
| } |
| |
| XCamReturn |
| CLWaveletDenoiseImageKernel::prepare_arguments ( |
| CLArgList &args, CLWorkSize &work_size) |
| { |
| SmartPtr<CLContext> context = get_context (); |
| SmartPtr<VideoBuffer> input = _handler->get_input_buf (); |
| SmartPtr<VideoBuffer> output = _handler->get_output_buf (); |
| |
| const VideoBufferInfo &video_info_in = input->get_video_info (); |
| const VideoBufferInfo &video_info_out = output->get_video_info (); |
| |
| SmartPtr<CLMemory> input_image = convert_to_clbuffer (context, input); |
| SmartPtr<CLMemory> reconstruct_image = convert_to_clbuffer (context, output); |
| |
| SmartPtr<CLMemory> details_image = _handler->get_details_image (); |
| SmartPtr<CLMemory> approx_image = _handler->get_approx_image (); |
| |
| uint32_t decomposition_levels = WAVELET_DECOMPOSITION_LEVELS; |
| float soft_threshold = _handler->get_denoise_config ().threshold[0]; |
| float hard_threshold = _handler->get_denoise_config ().threshold[1]; |
| |
| uint32_t input_y_offset = video_info_in.offsets[0] / 4; |
| uint32_t output_y_offset = video_info_out.offsets[0] / 4; |
| |
| uint32_t input_uv_offset = video_info_in.aligned_height; |
| uint32_t output_uv_offset = video_info_out.aligned_height; |
| |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| input_image->is_valid () && reconstruct_image->is_valid (), |
| XCAM_RETURN_ERROR_MEM, |
| "cl image kernel(%s) in/out memory not available", XCAM_STR(get_kernel_name ())); |
| |
| //set args; |
| work_size.dim = XCAM_DEFAULT_IMAGE_DIM; |
| work_size.local[0] = 8; |
| work_size.local[1] = 4; |
| |
| if (_current_layer % 2) { |
| args.push_back (new CLMemArgument (input_image)); |
| args.push_back (new CLMemArgument (approx_image)); |
| } else { |
| args.push_back (new CLMemArgument (approx_image)); |
| args.push_back (new CLMemArgument (input_image)); |
| } |
| args.push_back (new CLMemArgument (details_image)); |
| args.push_back (new CLMemArgument (reconstruct_image)); |
| args.push_back (new CLArgumentT<uint32_t> (input_y_offset)); |
| args.push_back (new CLArgumentT<uint32_t> (output_y_offset)); |
| args.push_back (new CLArgumentT<uint32_t> (input_uv_offset)); |
| args.push_back (new CLArgumentT<uint32_t> (output_uv_offset)); |
| args.push_back (new CLArgumentT<uint32_t> (_current_layer)); |
| args.push_back (new CLArgumentT<uint32_t> (decomposition_levels)); |
| args.push_back (new CLArgumentT<float> (hard_threshold)); |
| args.push_back (new CLArgumentT<float> (soft_threshold)); |
| |
| if (_channel & CL_IMAGE_CHANNEL_UV) { |
| work_size.global[0] = video_info_in.width / 16; |
| work_size.global[1] = video_info_in.height / 2; |
| } else { |
| work_size.global[0] = video_info_in.width / 16; |
| work_size.global[1] = video_info_in.height; |
| } |
| |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| CLWaveletDenoiseImageHandler::CLWaveletDenoiseImageHandler ( |
| const SmartPtr<CLContext> &context, const char *name) |
| : CLImageHandler (context, name) |
| { |
| _config.decomposition_levels = 5; |
| _config.threshold[0] = 0.5; |
| _config.threshold[1] = 5.0; |
| } |
| |
| XCamReturn |
| CLWaveletDenoiseImageHandler::prepare_output_buf (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output) |
| { |
| XCamReturn ret = XCAM_RETURN_NO_ERROR; |
| CLImageHandler::prepare_output_buf(input, output); |
| |
| if (!_approx_image.ptr ()) { |
| const VideoBufferInfo & video_info = input->get_video_info (); |
| uint32_t buffer_size = video_info.width * video_info.aligned_height; |
| |
| _approx_image = new CLBuffer (get_context (), buffer_size, |
| CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, NULL); |
| } |
| |
| if (!_details_image.ptr ()) { |
| const VideoBufferInfo & video_info = input->get_video_info (); |
| uint32_t buffer_size = sizeof(float) * video_info.width * video_info.height; |
| |
| _details_image = new CLBuffer (get_context (), buffer_size, |
| CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, NULL); |
| } |
| return ret; |
| } |
| |
| bool |
| CLWaveletDenoiseImageHandler::set_denoise_config (const XCam3aResultWaveletNoiseReduction& config) |
| |
| { |
| _config = config; |
| |
| return true; |
| } |
| |
| SmartPtr<CLImageHandler> |
| create_cl_wavelet_denoise_image_handler (const SmartPtr<CLContext> &context, uint32_t channel) |
| { |
| SmartPtr<CLWaveletDenoiseImageHandler> wavelet_handler; |
| SmartPtr<CLWaveletDenoiseImageKernel> wavelet_kernel; |
| |
| wavelet_handler = new CLWaveletDenoiseImageHandler (context, "cl_handler_wavelet_denoise"); |
| XCAM_ASSERT (wavelet_handler.ptr ()); |
| |
| for (int layer = 1; layer <= WAVELET_DECOMPOSITION_LEVELS; layer++) { |
| wavelet_kernel = new CLWaveletDenoiseImageKernel ( |
| context, "kernel_wavelet_denoise", wavelet_handler, channel, layer); |
| const char *build_options = |
| (channel & CL_IMAGE_CHANNEL_UV) ? "-DWAVELET_DENOISE_UV=1" : "-DWAVELET_DENOISE_UV=0"; |
| |
| XCAM_ASSERT (wavelet_kernel.ptr ()); |
| XCAM_FAIL_RETURN ( |
| ERROR, wavelet_kernel->build_kernel (kernel_wavelet_denoise_info, build_options) == XCAM_RETURN_NO_ERROR, NULL, |
| "build wavelet denoise kernel(%s) failed", kernel_wavelet_denoise_info.kernel_name); |
| XCAM_ASSERT (wavelet_kernel->is_valid ()); |
| |
| wavelet_handler->add_kernel (wavelet_kernel); |
| } |
| return wavelet_handler; |
| } |
| |
| }; |