blob: 4d43e6ac29ce9ba140e1b403f5f6232d4ee5a463 [file] [log] [blame]
/*
* cl_3a_stats_context.cpp - CL 3a stats context
*
* 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>
* Author: Jia Meng <jia.meng@intel.com>
*/
#include <xcam_std.h>
#include "cl_3a_stats_context.h"
namespace XCam {
CL3AStatsCalculatorContext::CL3AStatsCalculatorContext (const SmartPtr<CLContext> &context)
: _context (context)
, _width_factor (1)
, _height_factor (1)
, _factor_shift (0)
, _data_allocated (false)
{
_stats_pool = new X3aStatsPool ();
}
CL3AStatsCalculatorContext::~CL3AStatsCalculatorContext ()
{
clean_up_data ();
}
void
CL3AStatsCalculatorContext::set_bit_depth (uint32_t bits)
{
XCAM_ASSERT (_stats_pool.ptr ());
_stats_pool->set_bit_depth (bits);
}
bool
CL3AStatsCalculatorContext::allocate_data (const VideoBufferInfo &buffer_info, uint32_t width_factor, uint32_t height_factor)
{
uint32_t multiply_factor = 0;
_stats_pool->set_video_info (buffer_info);
XCAM_FAIL_RETURN (
WARNING,
_stats_pool->reserve (32), // need reserve more if as attachement
false,
"reserve cl stats buffer failed");
_stats_info = _stats_pool->get_stats_info ();
XCAM_ASSERT ((width_factor & (width_factor - 1)) == 0 &&
(height_factor & (height_factor - 1)) == 0);
_width_factor = width_factor;
_height_factor = height_factor;
multiply_factor = width_factor * height_factor;
_factor_shift = 0;
while ((multiply_factor >>= 1) != 0) {
++_factor_shift;
}
_stats_mem_size =
_stats_info.aligned_width * _width_factor *
_stats_info.aligned_height * _height_factor * sizeof (CL3AStatsStruct);
for (uint32_t i = 0; i < XCAM_CL_3A_STATS_BUFFER_COUNT; ++i) {
SmartPtr<CLBuffer> buf_new = new CLBuffer (
_context, _stats_mem_size);
XCAM_ASSERT (buf_new.ptr ());
XCAM_FAIL_RETURN (
WARNING,
buf_new->is_valid (),
false,
"allocate cl stats buffer failed");
_stats_cl_buffers.push (buf_new);
}
_data_allocated = true;
return true;
}
void
CL3AStatsCalculatorContext::pre_stop ()
{
if (_stats_pool.ptr ())
_stats_pool->stop ();
_stats_cl_buffers.pause_pop ();
_stats_cl_buffers.wakeup ();
}
void
CL3AStatsCalculatorContext::clean_up_data ()
{
_data_allocated = false;
_stats_cl_buffers.pause_pop ();
_stats_cl_buffers.wakeup ();
_stats_cl_buffers.clear ();
}
SmartPtr<CLBuffer>
CL3AStatsCalculatorContext::get_buffer ()
{
SmartPtr<CLBuffer> buf = _stats_cl_buffers.pop ();
return buf;
}
bool
CL3AStatsCalculatorContext::release_buffer (SmartPtr<CLBuffer> &buf)
{
XCAM_ASSERT (buf.ptr ());
if (!buf.ptr ())
return false;
return _stats_cl_buffers.push (buf);
}
void debug_print_3a_stats (XCam3AStats *stats_ptr)
{
static int frames = 0;
frames++;
printf ("********frame(%d) debug 3a stats(%dbits) \n", frames, stats_ptr->info.bit_depth);
for (int y = 30; y < 60; ++y) {
printf ("---- y ");
for (int x = 40; x < 80; ++x)
printf ("%4d ", stats_ptr->stats[y * stats_ptr->info.aligned_width + x].avg_y);
printf ("\n");
}
#if 0
#define DUMP_STATS(ch, w, h, aligned_w, stats) do { \
printf ("stats " #ch ":"); \
for (uint32_t y = 0; y < h; ++y) { \
for (uint32_t x = 0; x < w; ++x) \
printf ("%3d ", stats[y * aligned_w + x].avg_##ch); \
} \
printf ("\n"); \
} while (0)
DUMP_STATS (r, stats_ptr->info.width, stats_ptr->info.height,
stats_ptr->info.aligned_width, stats_ptr->stats);
DUMP_STATS (gr, stats_ptr->info.width, stats_ptr->info.height,
stats_ptr->info.aligned_width, stats_ptr->stats);
DUMP_STATS (gb, stats_ptr->info.width, stats_ptr->info.height,
stats_ptr->info.aligned_width, stats_ptr->stats);
DUMP_STATS (b, stats_ptr->info.width, stats_ptr->info.height,
stats_ptr->info.aligned_width, stats_ptr->stats);
DUMP_STATS (y, stats_ptr->info.width, stats_ptr->info.height,
stats_ptr->info.aligned_width, stats_ptr->stats);
#endif
}
void debug_print_histogram (XCam3AStats *stats_ptr)
{
#define DUMP_HISTOGRAM(ch, bins, hist) do { \
printf ("histogram " #ch ":"); \
for (uint32_t i = 0; i < bins; i++) { \
if (i % 16 == 0) printf ("\n"); \
printf ("%4d ", hist[i].ch); \
} \
printf ("\n"); \
} while (0)
DUMP_HISTOGRAM (r, stats_ptr->info.histogram_bins, stats_ptr->hist_rgb);
DUMP_HISTOGRAM (gr, stats_ptr->info.histogram_bins, stats_ptr->hist_rgb);
DUMP_HISTOGRAM (gb, stats_ptr->info.histogram_bins, stats_ptr->hist_rgb);
DUMP_HISTOGRAM (b, stats_ptr->info.histogram_bins, stats_ptr->hist_rgb);
printf ("histogram y:");
for (uint32_t i = 0; i < stats_ptr->info.histogram_bins; i++) {
if (i % 16 == 0) printf ("\n");
printf ("%4d ", stats_ptr->hist_y[i]);
}
printf ("\n");
}
SmartPtr<X3aStats>
CL3AStatsCalculatorContext::copy_stats_out (const SmartPtr<CLBuffer> &stats_cl_buf)
{
SmartPtr<VideoBuffer> buffer;
SmartPtr<X3aStats> stats;
SmartPtr<CLEvent> event = new CLEvent;
XCam3AStats *stats_ptr = NULL;
XCamReturn ret = XCAM_RETURN_NO_ERROR;
void *buf_ptr = NULL;
const CL3AStatsStruct *cl_buf_ptr = NULL;
XCAM_ASSERT (stats_cl_buf.ptr ());
buffer = _stats_pool->get_buffer (_stats_pool);
XCAM_FAIL_RETURN (WARNING, buffer.ptr (), NULL, "3a stats pool stopped.");
stats = buffer.dynamic_cast_ptr<X3aStats> ();
XCAM_ASSERT (stats.ptr ());
stats_ptr = stats->get_stats ();
ret = stats_cl_buf->enqueue_map (
buf_ptr,
0, _stats_mem_size,
CL_MAP_READ,
CLEvent::EmptyList,
event);
XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, NULL, "3a stats enqueue read buffer failed.");
XCAM_ASSERT (event->get_event_id ());
ret = event->wait ();
XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, NULL, "3a stats buffer enqueue event wait failed");
cl_buf_ptr = (const CL3AStatsStruct*)buf_ptr;
XCAM_ASSERT (stats_ptr);
memset (stats_ptr->stats, 0, sizeof (XCamGridStat) * _stats_info.aligned_width * _stats_info.aligned_height);
//uint32_t avg_factor = _width_factor * _height_factor;
//uint32_t avg_round_pading = avg_factor / 2;
uint32_t cl_stats_width = _stats_info.aligned_width * _width_factor;
for (uint32_t h = 0; h < _stats_info.height; ++h) {
XCamGridStat *grid_stats_line = &stats_ptr->stats[_stats_info.aligned_width * h];
uint32_t end_i_h = (h + 1) * _height_factor;
for (uint32_t i_h = h * _height_factor; i_h < end_i_h; ++i_h) {
const CL3AStatsStruct *cl_stats_line = &cl_buf_ptr[cl_stats_width * i_h];
for (uint32_t w = 0; w < _stats_info.width; ++w) {
uint32_t end_i_w = (w + 1) * _width_factor;
for (uint32_t i_w = w * _width_factor; i_w < end_i_w; ++i_w) {
//grid_stats_line[w].avg_y += (cl_stats_line[i_w].avg_y + avg_round_pading) / avg_factor;
grid_stats_line[w].avg_y += (cl_stats_line[i_w].avg_y >> _factor_shift);
grid_stats_line[w].avg_r += (cl_stats_line[i_w].avg_r >> _factor_shift);
grid_stats_line[w].avg_gr += (cl_stats_line[i_w].avg_gr >> _factor_shift);
grid_stats_line[w].avg_gb += (cl_stats_line[i_w].avg_gb >> _factor_shift);
grid_stats_line[w].avg_b += (cl_stats_line[i_w].avg_b >> _factor_shift);
grid_stats_line[w].valid_wb_count += cl_stats_line[i_w].valid_wb_count;
grid_stats_line[w].f_value1 += cl_stats_line[i_w].f_value1;
grid_stats_line[w].f_value2 += cl_stats_line[i_w].f_value2;
}
}
}
}
event.release ();
SmartPtr<CLEvent> unmap_event = new CLEvent;
ret = stats_cl_buf->enqueue_unmap (buf_ptr, CLEvent::EmptyList, unmap_event);
XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, NULL, "3a stats buffer enqueue unmap failed");
ret = unmap_event->wait ();
XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, NULL, "3a stats buffer enqueue unmap event wait failed");
unmap_event.release ();
//debug_print_3a_stats (stats_ptr);
fill_histogram (stats_ptr);
//debug_print_histogram (stats_ptr);
return stats;
}
bool
CL3AStatsCalculatorContext::fill_histogram (XCam3AStats * stats)
{
const XCam3AStatsInfo &stats_info = stats->info;
const XCamGridStat *grid_stat;
XCamHistogram *hist_rgb = stats->hist_rgb;
uint32_t *hist_y = stats->hist_y;
memset (hist_rgb, 0, sizeof(XCamHistogram) * stats_info.histogram_bins);
memset (hist_y, 0, sizeof(uint32_t) * stats_info.histogram_bins);
for (uint32_t i = 0; i < stats_info.width; i++) {
for (uint32_t j = 0; j < stats_info.height; j++) {
grid_stat = &stats->stats[j * stats_info.aligned_width + i];
hist_rgb[grid_stat->avg_r].r++;
hist_rgb[grid_stat->avg_gr].gr++;
hist_rgb[grid_stat->avg_gb].gb++;
hist_rgb[grid_stat->avg_b].b++;
hist_y[grid_stat->avg_y]++;
}
}
return true;
}
}