blob: efc253613fce0710be9a63e5ccceebbc085767a8 [file] [log] [blame]
/*
* cl_bayer_basic_handler.cpp - CL bayer basic 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: Wind Yuan <feng.yuan@intel.com>
*/
#include "cl_utils.h"
#include "cl_bayer_basic_handler.h"
#include "xcam_thread.h"
#define GROUP_CELL_X_SIZE 64
#define GROUP_CELL_Y_SIZE 4
#define STATS_3A_CELL_X_SIZE 8
#define STATS_3A_CELL_Y_SIZE GROUP_CELL_Y_SIZE
#define STANDARD_3A_STATS_SIZE 8
#define ENABLE_IMAGE_2D_INPUT 0
namespace XCam {
static const XCamKernelInfo kernel_bayer_basic_info = {
"kernel_bayer_basic",
#include "kernel_bayer_basic.clx"
, 0,
};
struct BayerPostData {
SmartPtr<VideoBuffer> image_buffer;
SmartPtr<CLBuffer> stats_cl_buf;
};
class CLBayer3AStatsThread
: public Thread
{
public:
CLBayer3AStatsThread (CLBayerBasicImageHandler *handler)
: Thread ("CLBayer3AStatsThread")
, _handler (handler)
{}
~CLBayer3AStatsThread () {}
virtual bool emit_stop ();
bool queue_stats (SmartPtr<VideoBuffer> &buf, SmartPtr<CLBuffer> &stats);
SmartPtr<VideoBuffer> pop_buf ();
protected:
virtual bool loop ();
virtual void stopped ();
private:
CLBayerBasicImageHandler *_handler;
SafeList<BayerPostData> _stats_process_list;
SafeList<VideoBuffer> _buffer_done_list;
};
bool
CLBayer3AStatsThread::emit_stop ()
{
_stats_process_list.pause_pop ();
_buffer_done_list.pause_pop ();
_stats_process_list.wakeup ();
_buffer_done_list.wakeup ();
return Thread::emit_stop ();
}
bool
CLBayer3AStatsThread::queue_stats (SmartPtr<VideoBuffer> &buf, SmartPtr<CLBuffer> &stats)
{
XCAM_FAIL_RETURN (
WARNING,
buf.ptr () && stats.ptr (),
false,
"cl bayer 3a-stats thread has error buffer/stats to queue");
SmartPtr<BayerPostData> data = new BayerPostData;
XCAM_ASSERT (data.ptr ());
data->image_buffer = buf;
data->stats_cl_buf = stats;
return _stats_process_list.push (data);
}
SmartPtr<VideoBuffer>
CLBayer3AStatsThread::pop_buf ()
{
return _buffer_done_list.pop ();
}
void
CLBayer3AStatsThread::stopped ()
{
_stats_process_list.clear ();
_buffer_done_list.clear ();
}
bool
CLBayer3AStatsThread::loop ()
{
XCamReturn ret = XCAM_RETURN_NO_ERROR;
SmartPtr<BayerPostData> data;
data = _stats_process_list.pop ();
if (!data.ptr ()) {
XCAM_LOG_INFO ("cl bayer 3a-stats thread is going to stop, processing data empty");
return false;
}
XCAM_ASSERT (data->image_buffer.ptr ());
XCAM_ASSERT (data->stats_cl_buf.ptr ());
XCAM_ASSERT (_handler);
ret = _handler->process_stats_buffer (data->image_buffer, data->stats_cl_buf);
XCAM_FAIL_RETURN (
WARNING,
ret == XCAM_RETURN_NO_ERROR,
false,
"cl bayer 3a-stats thread has error buffer on kernel post processing");
XCAM_FAIL_RETURN (
ERROR,
_buffer_done_list.push (data->image_buffer),
false,
"cl bayer 3a-stats thread failed to queue done-buffers");
return true;
}
CLBayerBasicImageKernel::CLBayerBasicImageKernel (const SmartPtr<CLContext> &context)
: CLImageKernel (context, "kernel_bayer_basic")
{
}
XCamReturn
CLBayerBasicImageHandler::process_stats_buffer (SmartPtr<VideoBuffer> &buffer, SmartPtr<CLBuffer> &cl_stats)
{
SmartPtr<X3aStats> stats_3a;
SmartPtr<CLContext> context = get_context ();
XCAM_OBJ_PROFILING_START;
context->finish ();
stats_3a = _3a_stats_context->copy_stats_out (cl_stats);
if (!stats_3a.ptr ()) {
XCAM_LOG_DEBUG ("copy 3a stats failed, maybe handler stopped");
return XCAM_RETURN_ERROR_CL;
}
stats_3a->set_timestamp (buffer->get_timestamp ());
buffer->attach_buffer (stats_3a);
if (cl_stats.ptr ())
_3a_stats_context->release_buffer (cl_stats);
XCAM_OBJ_PROFILING_END ("3a_stats_cpu_copy(async)", XCAM_OBJ_DUR_FRAME_NUM);
return post_stats (stats_3a);
}
CLBayerBasicImageHandler::CLBayerBasicImageHandler (
const SmartPtr<CLContext> &context, const char *name)
: CLImageHandler (context, name)
, _is_first_buf (true)
{
_blc_config.level_gr = XCAM_CL_BLC_DEFAULT_LEVEL;
_blc_config.level_r = XCAM_CL_BLC_DEFAULT_LEVEL;
_blc_config.level_b = XCAM_CL_BLC_DEFAULT_LEVEL;
_blc_config.level_gb = XCAM_CL_BLC_DEFAULT_LEVEL;
_blc_config.color_bits = 10;
_wb_config.r_gain = 1.0;
_wb_config.gr_gain = 1.0;
_wb_config.gb_gain = 1.0;
_wb_config.b_gain = 1.0;
for(int i = 0; i < XCAM_GAMMA_TABLE_SIZE; i++)
_gamma_table[i] = (float)i / 256.0f;
_gamma_table[XCAM_GAMMA_TABLE_SIZE] = 0.9999f;
_3a_stats_context = new CL3AStatsCalculatorContext (context);
XCAM_ASSERT (_3a_stats_context.ptr ());
_3a_stats_thread = new CLBayer3AStatsThread (this);
XCAM_ASSERT (_3a_stats_thread.ptr ());
XCAM_OBJ_PROFILING_INIT;
}
CLBayerBasicImageHandler::~CLBayerBasicImageHandler ()
{
_3a_stats_thread->stop ();
_3a_stats_context->clean_up_data ();
}
void
CLBayerBasicImageHandler::set_stats_bits (uint32_t stats_bits)
{
XCAM_ASSERT (_3a_stats_context.ptr ());
_3a_stats_context->set_bit_depth (stats_bits);
}
bool
CLBayerBasicImageHandler::set_bayer_kernel (SmartPtr<CLBayerBasicImageKernel> &kernel)
{
SmartPtr<CLImageKernel> image_kernel = kernel;
add_kernel (image_kernel);
_bayer_kernel = kernel;
return true;
}
bool
CLBayerBasicImageHandler::set_blc_config (const XCam3aResultBlackLevel &blc)
{
_blc_config.level_r = (float)blc.r_level;
_blc_config.level_gr = (float)blc.gr_level;
_blc_config.level_gb = (float)blc.gb_level;
_blc_config.level_b = (float)blc.b_level;
//_blc_config.color_bits = 0;
return true;
}
bool
CLBayerBasicImageHandler::set_wb_config (const XCam3aResultWhiteBalance &wb)
{
_wb_config.r_gain = (float)wb.r_gain;
_wb_config.gr_gain = (float)wb.gr_gain;
_wb_config.gb_gain = (float)wb.gb_gain;
_wb_config.b_gain = (float)wb.b_gain;
return true;
}
bool
CLBayerBasicImageHandler::set_gamma_table (const XCam3aResultGammaTable &gamma)
{
for(int i = 0; i < XCAM_GAMMA_TABLE_SIZE; i++)
_gamma_table[i] = (float)gamma.table[i] / 256.0f;
return true;
}
void
CLBayerBasicImageHandler::emit_stop ()
{
_3a_stats_context->pre_stop ();
_3a_stats_thread->emit_stop ();
}
XCamReturn
CLBayerBasicImageHandler::prepare_buffer_pool_video_info (
const VideoBufferInfo &input,
VideoBufferInfo &output)
{
uint32_t format = XCAM_PIX_FMT_SGRBG16_planar;
bool format_inited = output.init (format, input.width / 2 , input.height / 2);
XCAM_FAIL_RETURN (
WARNING,
format_inited,
XCAM_RETURN_ERROR_PARAM,
"CL image handler(%s) output format(%s) unsupported",
get_name (), xcam_fourcc_to_string (format));
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
CLBayerBasicImageHandler::prepare_parameters (
SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
{
SmartPtr<CLContext> context = get_context ();
const VideoBufferInfo & in_video_info = input->get_video_info ();
const VideoBufferInfo & out_video_info = output->get_video_info ();
CLImageDesc in_image_info;
CLImageDesc out_image_info;
CLArgList args;
CLWorkSize work_size;
XCAM_ASSERT (_bayer_kernel.ptr ());
if (!_3a_stats_context->is_ready () &&
!_3a_stats_context->allocate_data (
in_video_info,
STANDARD_3A_STATS_SIZE / STATS_3A_CELL_X_SIZE,
STANDARD_3A_STATS_SIZE / STATS_3A_CELL_Y_SIZE)) {
XCAM_LOG_WARNING ("CL3AStatsCalculatorContext allocate data failed");
return XCAM_RETURN_ERROR_MEM;
}
if (_is_first_buf) {
XCAM_FAIL_RETURN (
WARNING, _3a_stats_thread->start (), XCAM_RETURN_ERROR_THREAD,
"cl bayer basic handler start 3a stats thread failed");
}
in_image_info.format.image_channel_order = CL_RGBA;
in_image_info.format.image_channel_data_type = CL_UNSIGNED_INT32; //CL_UNORM_INT16;
in_image_info.width = in_video_info.aligned_width / 8;
in_image_info.height = in_video_info.height;
in_image_info.row_pitch = in_video_info.strides[0];
out_image_info.format.image_channel_order = CL_RGBA;
out_image_info.format.image_channel_data_type = CL_UNSIGNED_INT32; //CL_UNORM_INT16;
out_image_info.width = out_video_info.width / 8;
out_image_info.height = out_video_info.aligned_height * 4;
out_image_info.row_pitch = out_video_info.strides[0];
#if ENABLE_IMAGE_2D_INPUT
SmartPtr<CLImage> image_in = convert_to_climage (context, input, in_image_info);
#else
SmartPtr<CLBuffer> buffer_in = convert_to_clbuffer (context, input);
#endif
uint32_t input_aligned_width = in_video_info.strides[0] / (2 * 8); // ushort8
SmartPtr<CLImage> image_out = convert_to_climage (context, output, out_image_info);
uint32_t out_aligned_height = out_video_info.aligned_height;
_blc_config.color_bits = in_video_info.color_bits;
SmartPtr<CLBuffer> gamma_table_buffer = new CLBuffer(
context, sizeof(float) * (XCAM_GAMMA_TABLE_SIZE + 1),
CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, &_gamma_table);
_stats_cl_buffer = _3a_stats_context->get_buffer ();
XCAM_FAIL_RETURN (
WARNING,
_stats_cl_buffer.ptr () && _stats_cl_buffer->is_valid (),
XCAM_RETURN_ERROR_PARAM,
"CLBayerBasic handler get 3a stats buffer failed");
XCAM_FAIL_RETURN (
WARNING,
image_out->is_valid (),
XCAM_RETURN_ERROR_MEM,
"cl image handler(%s) out memory not available", XCAM_STR(get_name ()));
//set args;
#if ENABLE_IMAGE_2D_INPUT
args.push_back (new CLMemArgument (image_in));
#else
args.push_back (new CLMemArgument (buffer_in));
#endif
args.push_back (new CLArgumentT<uint32_t> (input_aligned_width));
args.push_back (new CLMemArgument (image_out));
args.push_back (new CLArgumentT<uint32_t> (out_aligned_height));
args.push_back (new CLArgumentT<CLBLCConfig> (_blc_config));
args.push_back (new CLArgumentT<CLWBConfig> (_wb_config));
args.push_back (new CLMemArgument (gamma_table_buffer));
args.push_back (new CLMemArgument (_stats_cl_buffer));
work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
work_size.local[0] = 16;
work_size.local[1] = 2;
work_size.global[0] = XCAM_ALIGN_UP(out_video_info.width, GROUP_CELL_X_SIZE) / GROUP_CELL_X_SIZE * work_size.local[0];
work_size.global[1] = XCAM_ALIGN_UP(out_video_info.aligned_height, GROUP_CELL_Y_SIZE) / GROUP_CELL_Y_SIZE * work_size.local[1];
//printf ("work_size:g(%d, %d), l(%d, %d)\n", work_size.global[0], work_size.global[1], work_size.local[0], work_size.local[1]);
XCAM_ASSERT (_bayer_kernel.ptr ());
XCamReturn ret = _bayer_kernel->set_arguments (args, work_size);
XCAM_FAIL_RETURN (
WARNING, ret == XCAM_RETURN_NO_ERROR, ret,
"bayer basic kernel set arguments failed.");
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
CLBayerBasicImageHandler::execute_done (SmartPtr<VideoBuffer> &output)
{
XCAM_FAIL_RETURN (
ERROR, _3a_stats_thread->queue_stats (output, _stats_cl_buffer), XCAM_RETURN_ERROR_UNKNOWN,
"cl bayer basic handler(%s) process 3a stats failed", XCAM_STR (get_name ()));
_stats_cl_buffer.release ();
if (_is_first_buf) {
_is_first_buf = false;
return XCAM_RETURN_BYPASS;
}
SmartPtr<VideoBuffer> done_buf = _3a_stats_thread->pop_buf ();
XCAM_FAIL_RETURN (
WARNING,
done_buf.ptr (),
XCAM_RETURN_ERROR_MEM,
"cl bayer handler(%s) failed to get done buffer", get_name ());
output = done_buf;
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
CLBayerBasicImageHandler::post_stats (const SmartPtr<X3aStats> &stats)
{
if (_stats_callback.ptr ())
return _stats_callback->x3a_stats_ready (stats);
return XCAM_RETURN_NO_ERROR;
}
SmartPtr<CLImageHandler>
create_cl_bayer_basic_image_handler (const SmartPtr<CLContext> &context, bool enable_gamma, uint32_t stats_bits)
{
SmartPtr<CLBayerBasicImageHandler> bayer_planar_handler;
SmartPtr<CLBayerBasicImageKernel> basic_kernel;
char build_options[1024];
bayer_planar_handler = new CLBayerBasicImageHandler (context, "cl_handler_bayer_basic");
bayer_planar_handler->set_stats_bits (stats_bits);
basic_kernel = new CLBayerBasicImageKernel (context);
XCAM_ASSERT (basic_kernel.ptr ());
xcam_mem_clear (build_options);
snprintf (build_options, sizeof (build_options),
" -DENABLE_GAMMA=%d "
" -DENABLE_IMAGE_2D_INPUT=%d "
" -DSTATS_BITS=%d ",
(enable_gamma ? 1 : 0),
ENABLE_IMAGE_2D_INPUT,
stats_bits);
XCAM_FAIL_RETURN (
ERROR, basic_kernel->build_kernel (kernel_bayer_basic_info, build_options) == XCAM_RETURN_NO_ERROR, NULL,
"build bayer-basic kernel(%s) failed", kernel_bayer_basic_info.kernel_name);
XCAM_ASSERT (basic_kernel->is_valid ());
bayer_planar_handler->set_bayer_kernel (basic_kernel);
return bayer_planar_handler;
}
};