• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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