/* * 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 * Author: Jia Meng */ #include #include "cl_3a_stats_context.h" namespace XCam { CL3AStatsCalculatorContext::CL3AStatsCalculatorContext (const SmartPtr &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 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 CL3AStatsCalculatorContext::get_buffer () { SmartPtr buf = _stats_cl_buffers.pop (); return buf; } bool CL3AStatsCalculatorContext::release_buffer (SmartPtr &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 CL3AStatsCalculatorContext::copy_stats_out (const SmartPtr &stats_cl_buf) { SmartPtr buffer; SmartPtr stats; SmartPtr 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 (); 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 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; } }