1 /*
2 * cl_3a_stats_context.cpp - CL 3a stats context
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: Wind Yuan <feng.yuan@intel.com>
19 * Author: Jia Meng <jia.meng@intel.com>
20 */
21
22 #include <xcam_std.h>
23 #include "cl_3a_stats_context.h"
24
25 namespace XCam {
CL3AStatsCalculatorContext(const SmartPtr<CLContext> & context)26 CL3AStatsCalculatorContext::CL3AStatsCalculatorContext (const SmartPtr<CLContext> &context)
27 : _context (context)
28 , _width_factor (1)
29 , _height_factor (1)
30 , _factor_shift (0)
31 , _data_allocated (false)
32 {
33 _stats_pool = new X3aStatsPool ();
34 }
35
~CL3AStatsCalculatorContext()36 CL3AStatsCalculatorContext::~CL3AStatsCalculatorContext ()
37 {
38 clean_up_data ();
39 }
40
41 void
set_bit_depth(uint32_t bits)42 CL3AStatsCalculatorContext::set_bit_depth (uint32_t bits)
43 {
44 XCAM_ASSERT (_stats_pool.ptr ());
45 _stats_pool->set_bit_depth (bits);
46 }
47
48 bool
allocate_data(const VideoBufferInfo & buffer_info,uint32_t width_factor,uint32_t height_factor)49 CL3AStatsCalculatorContext::allocate_data (const VideoBufferInfo &buffer_info, uint32_t width_factor, uint32_t height_factor)
50 {
51 uint32_t multiply_factor = 0;
52
53 _stats_pool->set_video_info (buffer_info);
54
55 XCAM_FAIL_RETURN (
56 WARNING,
57 _stats_pool->reserve (32), // need reserve more if as attachement
58 false,
59 "reserve cl stats buffer failed");
60
61 _stats_info = _stats_pool->get_stats_info ();
62 XCAM_ASSERT ((width_factor & (width_factor - 1)) == 0 &&
63 (height_factor & (height_factor - 1)) == 0);
64 _width_factor = width_factor;
65 _height_factor = height_factor;
66 multiply_factor = width_factor * height_factor;
67 _factor_shift = 0;
68 while ((multiply_factor >>= 1) != 0) {
69 ++_factor_shift;
70 }
71
72 _stats_mem_size =
73 _stats_info.aligned_width * _width_factor *
74 _stats_info.aligned_height * _height_factor * sizeof (CL3AStatsStruct);
75
76 for (uint32_t i = 0; i < XCAM_CL_3A_STATS_BUFFER_COUNT; ++i) {
77 SmartPtr<CLBuffer> buf_new = new CLBuffer (
78 _context, _stats_mem_size);
79
80 XCAM_ASSERT (buf_new.ptr ());
81 XCAM_FAIL_RETURN (
82 WARNING,
83 buf_new->is_valid (),
84 false,
85 "allocate cl stats buffer failed");
86 _stats_cl_buffers.push (buf_new);
87 }
88 _data_allocated = true;
89
90 return true;
91 }
92
93 void
pre_stop()94 CL3AStatsCalculatorContext::pre_stop ()
95 {
96 if (_stats_pool.ptr ())
97 _stats_pool->stop ();
98 _stats_cl_buffers.pause_pop ();
99 _stats_cl_buffers.wakeup ();
100 }
101
102 void
clean_up_data()103 CL3AStatsCalculatorContext::clean_up_data ()
104 {
105 _data_allocated = false;
106
107 _stats_cl_buffers.pause_pop ();
108 _stats_cl_buffers.wakeup ();
109 _stats_cl_buffers.clear ();
110 }
111
112 SmartPtr<CLBuffer>
get_buffer()113 CL3AStatsCalculatorContext::get_buffer ()
114 {
115 SmartPtr<CLBuffer> buf = _stats_cl_buffers.pop ();
116 return buf;
117 }
118
119 bool
release_buffer(SmartPtr<CLBuffer> & buf)120 CL3AStatsCalculatorContext::release_buffer (SmartPtr<CLBuffer> &buf)
121 {
122 XCAM_ASSERT (buf.ptr ());
123 if (!buf.ptr ())
124 return false;
125 return _stats_cl_buffers.push (buf);
126 }
127
debug_print_3a_stats(XCam3AStats * stats_ptr)128 void debug_print_3a_stats (XCam3AStats *stats_ptr)
129 {
130 static int frames = 0;
131 frames++;
132 printf ("********frame(%d) debug 3a stats(%dbits) \n", frames, stats_ptr->info.bit_depth);
133 for (int y = 30; y < 60; ++y) {
134 printf ("---- y ");
135 for (int x = 40; x < 80; ++x)
136 printf ("%4d ", stats_ptr->stats[y * stats_ptr->info.aligned_width + x].avg_y);
137 printf ("\n");
138 }
139
140 #if 0
141 #define DUMP_STATS(ch, w, h, aligned_w, stats) do { \
142 printf ("stats " #ch ":"); \
143 for (uint32_t y = 0; y < h; ++y) { \
144 for (uint32_t x = 0; x < w; ++x) \
145 printf ("%3d ", stats[y * aligned_w + x].avg_##ch); \
146 } \
147 printf ("\n"); \
148 } while (0)
149 DUMP_STATS (r, stats_ptr->info.width, stats_ptr->info.height,
150 stats_ptr->info.aligned_width, stats_ptr->stats);
151 DUMP_STATS (gr, stats_ptr->info.width, stats_ptr->info.height,
152 stats_ptr->info.aligned_width, stats_ptr->stats);
153 DUMP_STATS (gb, stats_ptr->info.width, stats_ptr->info.height,
154 stats_ptr->info.aligned_width, stats_ptr->stats);
155 DUMP_STATS (b, stats_ptr->info.width, stats_ptr->info.height,
156 stats_ptr->info.aligned_width, stats_ptr->stats);
157 DUMP_STATS (y, stats_ptr->info.width, stats_ptr->info.height,
158 stats_ptr->info.aligned_width, stats_ptr->stats);
159 #endif
160 }
161
debug_print_histogram(XCam3AStats * stats_ptr)162 void debug_print_histogram (XCam3AStats *stats_ptr)
163 {
164 #define DUMP_HISTOGRAM(ch, bins, hist) do { \
165 printf ("histogram " #ch ":"); \
166 for (uint32_t i = 0; i < bins; i++) { \
167 if (i % 16 == 0) printf ("\n"); \
168 printf ("%4d ", hist[i].ch); \
169 } \
170 printf ("\n"); \
171 } while (0)
172
173 DUMP_HISTOGRAM (r, stats_ptr->info.histogram_bins, stats_ptr->hist_rgb);
174 DUMP_HISTOGRAM (gr, stats_ptr->info.histogram_bins, stats_ptr->hist_rgb);
175 DUMP_HISTOGRAM (gb, stats_ptr->info.histogram_bins, stats_ptr->hist_rgb);
176 DUMP_HISTOGRAM (b, stats_ptr->info.histogram_bins, stats_ptr->hist_rgb);
177
178 printf ("histogram y:");
179 for (uint32_t i = 0; i < stats_ptr->info.histogram_bins; i++) {
180 if (i % 16 == 0) printf ("\n");
181 printf ("%4d ", stats_ptr->hist_y[i]);
182 }
183 printf ("\n");
184 }
185
186 SmartPtr<X3aStats>
copy_stats_out(const SmartPtr<CLBuffer> & stats_cl_buf)187 CL3AStatsCalculatorContext::copy_stats_out (const SmartPtr<CLBuffer> &stats_cl_buf)
188 {
189 SmartPtr<VideoBuffer> buffer;
190 SmartPtr<X3aStats> stats;
191 SmartPtr<CLEvent> event = new CLEvent;
192 XCam3AStats *stats_ptr = NULL;
193 XCamReturn ret = XCAM_RETURN_NO_ERROR;
194 void *buf_ptr = NULL;
195 const CL3AStatsStruct *cl_buf_ptr = NULL;
196
197 XCAM_ASSERT (stats_cl_buf.ptr ());
198
199 buffer = _stats_pool->get_buffer (_stats_pool);
200 XCAM_FAIL_RETURN (WARNING, buffer.ptr (), NULL, "3a stats pool stopped.");
201
202 stats = buffer.dynamic_cast_ptr<X3aStats> ();
203 XCAM_ASSERT (stats.ptr ());
204 stats_ptr = stats->get_stats ();
205
206 ret = stats_cl_buf->enqueue_map (
207 buf_ptr,
208 0, _stats_mem_size,
209 CL_MAP_READ,
210 CLEvent::EmptyList,
211 event);
212 XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, NULL, "3a stats enqueue read buffer failed.");
213 XCAM_ASSERT (event->get_event_id ());
214 ret = event->wait ();
215 XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, NULL, "3a stats buffer enqueue event wait failed");
216
217 cl_buf_ptr = (const CL3AStatsStruct*)buf_ptr;
218
219 XCAM_ASSERT (stats_ptr);
220 memset (stats_ptr->stats, 0, sizeof (XCamGridStat) * _stats_info.aligned_width * _stats_info.aligned_height);
221 //uint32_t avg_factor = _width_factor * _height_factor;
222 //uint32_t avg_round_pading = avg_factor / 2;
223 uint32_t cl_stats_width = _stats_info.aligned_width * _width_factor;
224
225 for (uint32_t h = 0; h < _stats_info.height; ++h) {
226 XCamGridStat *grid_stats_line = &stats_ptr->stats[_stats_info.aligned_width * h];
227 uint32_t end_i_h = (h + 1) * _height_factor;
228 for (uint32_t i_h = h * _height_factor; i_h < end_i_h; ++i_h) {
229 const CL3AStatsStruct *cl_stats_line = &cl_buf_ptr[cl_stats_width * i_h];
230 for (uint32_t w = 0; w < _stats_info.width; ++w) {
231 uint32_t end_i_w = (w + 1) * _width_factor;
232 for (uint32_t i_w = w * _width_factor; i_w < end_i_w; ++i_w) {
233 //grid_stats_line[w].avg_y += (cl_stats_line[i_w].avg_y + avg_round_pading) / avg_factor;
234 grid_stats_line[w].avg_y += (cl_stats_line[i_w].avg_y >> _factor_shift);
235 grid_stats_line[w].avg_r += (cl_stats_line[i_w].avg_r >> _factor_shift);
236 grid_stats_line[w].avg_gr += (cl_stats_line[i_w].avg_gr >> _factor_shift);
237 grid_stats_line[w].avg_gb += (cl_stats_line[i_w].avg_gb >> _factor_shift);
238 grid_stats_line[w].avg_b += (cl_stats_line[i_w].avg_b >> _factor_shift);
239 grid_stats_line[w].valid_wb_count += cl_stats_line[i_w].valid_wb_count;
240 grid_stats_line[w].f_value1 += cl_stats_line[i_w].f_value1;
241 grid_stats_line[w].f_value2 += cl_stats_line[i_w].f_value2;
242 }
243 }
244 }
245 }
246
247 event.release ();
248
249 SmartPtr<CLEvent> unmap_event = new CLEvent;
250 ret = stats_cl_buf->enqueue_unmap (buf_ptr, CLEvent::EmptyList, unmap_event);
251 XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, NULL, "3a stats buffer enqueue unmap failed");
252 ret = unmap_event->wait ();
253 XCAM_FAIL_RETURN (WARNING, ret == XCAM_RETURN_NO_ERROR, NULL, "3a stats buffer enqueue unmap event wait failed");
254 unmap_event.release ();
255 //debug_print_3a_stats (stats_ptr);
256 fill_histogram (stats_ptr);
257 //debug_print_histogram (stats_ptr);
258
259 return stats;
260 }
261
262 bool
fill_histogram(XCam3AStats * stats)263 CL3AStatsCalculatorContext::fill_histogram (XCam3AStats * stats)
264 {
265 const XCam3AStatsInfo &stats_info = stats->info;
266 const XCamGridStat *grid_stat;
267 XCamHistogram *hist_rgb = stats->hist_rgb;
268 uint32_t *hist_y = stats->hist_y;
269
270 memset (hist_rgb, 0, sizeof(XCamHistogram) * stats_info.histogram_bins);
271 memset (hist_y, 0, sizeof(uint32_t) * stats_info.histogram_bins);
272 for (uint32_t i = 0; i < stats_info.width; i++) {
273 for (uint32_t j = 0; j < stats_info.height; j++) {
274 grid_stat = &stats->stats[j * stats_info.aligned_width + i];
275 hist_rgb[grid_stat->avg_r].r++;
276 hist_rgb[grid_stat->avg_gr].gr++;
277 hist_rgb[grid_stat->avg_gb].gb++;
278 hist_rgb[grid_stat->avg_b].b++;
279 hist_y[grid_stat->avg_y]++;
280 }
281 }
282 return true;
283 }
284
285 }
286