1 /*
2 * image_processor.h - 3a image processor
3 *
4 * Copyright (c) 2014-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 */
20
21 #include "image_processor.h"
22 #include "xcam_thread.h"
23
24 namespace XCam {
25
26 void
process_buffer_done(ImageProcessor * processor,const SmartPtr<VideoBuffer> & buf)27 ImageProcessCallback::process_buffer_done (ImageProcessor *processor, const SmartPtr<VideoBuffer> &buf) {
28 XCAM_UNUSED (processor);
29 XCAM_ASSERT (buf.ptr() && processor);
30
31 int64_t ts = buf->get_timestamp();
32 XCAM_UNUSED (ts);
33 XCAM_LOG_DEBUG (
34 "processor(%s) handled buffer(" XCAM_TIMESTAMP_FORMAT ") successfully",
35 XCAM_STR(processor->get_name()),
36 XCAM_TIMESTAMP_ARGS (ts));
37 }
38
39 void
process_buffer_failed(ImageProcessor * processor,const SmartPtr<VideoBuffer> & buf)40 ImageProcessCallback::process_buffer_failed (ImageProcessor *processor, const SmartPtr<VideoBuffer> &buf)
41 {
42 XCAM_ASSERT (buf.ptr() && processor);
43
44 int64_t ts = buf->get_timestamp();
45 XCAM_UNUSED (ts);
46 XCAM_LOG_WARNING (
47 "processor(%s) handled buffer(" XCAM_TIMESTAMP_FORMAT ") failed",
48 XCAM_STR(processor->get_name()),
49 XCAM_TIMESTAMP_ARGS (ts));
50 }
51
52 void
process_image_result_done(ImageProcessor * processor,const SmartPtr<X3aResult> & result)53 ImageProcessCallback::process_image_result_done (ImageProcessor *processor, const SmartPtr<X3aResult> &result)
54 {
55 XCAM_UNUSED (processor);
56 XCAM_ASSERT (result.ptr() && processor);
57
58 int64_t ts = result->get_timestamp();
59 XCAM_UNUSED (ts);
60
61 XCAM_LOG_DEBUG (
62 "processor(%s) processed result(type:%d, timestamp:" XCAM_TIMESTAMP_FORMAT ") done",
63 XCAM_STR(processor->get_name()),
64 (int)result->get_type(),
65 XCAM_TIMESTAMP_ARGS (ts));
66 }
67
68 class ImageProcessorThread
69 : public Thread
70 {
71 public:
ImageProcessorThread(ImageProcessor * processor)72 ImageProcessorThread (ImageProcessor *processor)
73 : Thread ("image_processor")
74 , _processor (processor)
75 {}
~ImageProcessorThread()76 ~ImageProcessorThread () {}
77
78 virtual bool loop ();
79
80 private:
81 ImageProcessor *_processor;
82 };
83
loop()84 bool ImageProcessorThread::loop ()
85 {
86 XCamReturn ret = _processor->buffer_process_loop ();
87 if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_ERROR_TIMEOUT)
88 return true;
89 return false;
90 }
91
92 class X3aResultsProcessThread
93 : public Thread
94 {
95 typedef SafeList<X3aResult> ResultQueue;
96 public:
X3aResultsProcessThread(ImageProcessor * processor)97 X3aResultsProcessThread (ImageProcessor *processor)
98 : Thread ("x3a_results_process_thread")
99 , _processor (processor)
100 {}
~X3aResultsProcessThread()101 ~X3aResultsProcessThread () {}
102
push_result(SmartPtr<X3aResult> & result)103 XCamReturn push_result (SmartPtr<X3aResult> &result) {
104 _queue.push (result);
105 return XCAM_RETURN_NO_ERROR;
106 }
107
triger_stop()108 void triger_stop () {
109 _queue.pause_pop ();
110 }
111
112 virtual bool loop ();
113
114 private:
115 ImageProcessor *_processor;
116 ResultQueue _queue;
117 };
118
loop()119 bool X3aResultsProcessThread::loop ()
120 {
121 X3aResultList result_list;
122 SmartPtr<X3aResult> result;
123
124 result = _queue.pop (-1);
125 if (!result.ptr ())
126 return false;
127
128 result_list.push_back (result);
129 while ((result = _queue.pop (0)).ptr ()) {
130 result_list.push_back (result);
131 }
132
133 XCamReturn ret = _processor->process_3a_results (result_list);
134 if (ret != XCAM_RETURN_NO_ERROR) {
135 XCAM_LOG_DEBUG ("processing 3a result failed");
136 }
137
138 return true;
139 }
ImageProcessor(const char * name)140 ImageProcessor::ImageProcessor (const char* name)
141 : _name (NULL)
142 , _callback (NULL)
143 {
144 if (name)
145 _name = strndup (name, XCAM_MAX_STR_SIZE);
146
147 _processor_thread = new ImageProcessorThread (this);
148 _results_thread = new X3aResultsProcessThread (this);
149 }
150
~ImageProcessor()151 ImageProcessor::~ImageProcessor ()
152 {
153 if (_name)
154 xcam_free (_name);
155 }
156
157 bool
set_callback(ImageProcessCallback * callback)158 ImageProcessor::set_callback (ImageProcessCallback *callback)
159 {
160 XCAM_ASSERT (!_callback);
161 _callback = callback;
162 return true;
163 }
164
165 XCamReturn
start()166 ImageProcessor::start()
167 {
168 XCamReturn ret = XCAM_RETURN_NO_ERROR;
169 if (!_results_thread->start ()) {
170 return XCAM_RETURN_ERROR_THREAD;
171 }
172 if (!_processor_thread->start ()) {
173 return XCAM_RETURN_ERROR_THREAD;
174 }
175 ret = emit_start ();
176 if (ret != XCAM_RETURN_NO_ERROR) {
177 XCAM_LOG_WARNING ("ImageProcessor(%s) emit start failed", XCAM_STR (_name));
178 _video_buf_queue.pause_pop ();
179 _results_thread->triger_stop ();
180 _processor_thread->stop ();
181 _results_thread->stop ();
182 return ret;
183 }
184 XCAM_LOG_INFO ("ImageProcessor(%s) started", XCAM_STR (_name));
185 return XCAM_RETURN_NO_ERROR;
186 }
187
188 XCamReturn
stop()189 ImageProcessor::stop()
190 {
191 _video_buf_queue.pause_pop ();
192 _results_thread->triger_stop ();
193
194 emit_stop ();
195
196 _processor_thread->stop ();
197 _results_thread->stop ();
198 XCAM_LOG_DEBUG ("ImageProcessor(%s) stopped", XCAM_STR (_name));
199 return XCAM_RETURN_NO_ERROR;
200 }
201
202 XCamReturn
push_buffer(SmartPtr<VideoBuffer> & buf)203 ImageProcessor::push_buffer (SmartPtr<VideoBuffer> &buf)
204 {
205 if (_video_buf_queue.push (buf))
206 return XCAM_RETURN_NO_ERROR;
207
208 XCAM_LOG_DEBUG ("processor push buffer failed");
209 return XCAM_RETURN_ERROR_UNKNOWN;
210 }
211
212 XCamReturn
push_3a_results(X3aResultList & results)213 ImageProcessor::push_3a_results (X3aResultList &results)
214 {
215 XCAM_ASSERT (!results.empty ());
216 XCamReturn ret = XCAM_RETURN_NO_ERROR;
217 for (X3aResultList::iterator i_res = results.begin();
218 i_res != results.end(); ++i_res) {
219 SmartPtr<X3aResult> &res = *i_res;
220
221 ret = _results_thread->push_result (res);
222 if (ret != XCAM_RETURN_NO_ERROR)
223 break;
224 }
225
226 XCAM_FAIL_RETURN(
227 WARNING,
228 ret == XCAM_RETURN_NO_ERROR,
229 ret,
230 "processor(%s) push 3a results failed", XCAM_STR(get_name()));
231 return XCAM_RETURN_NO_ERROR;
232 }
233
234 XCamReturn
push_3a_result(SmartPtr<X3aResult> & result)235 ImageProcessor::push_3a_result (SmartPtr<X3aResult> &result)
236 {
237 XCamReturn ret = _results_thread->push_result (result);
238 XCAM_FAIL_RETURN(
239 WARNING,
240 ret == XCAM_RETURN_NO_ERROR,
241 ret,
242 "processor(%s) push 3a result failed", XCAM_STR(get_name()));
243 return XCAM_RETURN_NO_ERROR;
244 }
245
246 XCamReturn
process_3a_results(X3aResultList & results)247 ImageProcessor::process_3a_results (X3aResultList &results)
248 {
249 X3aResultList valid_results;
250 XCamReturn ret = XCAM_RETURN_NO_ERROR;
251
252 filter_valid_results (results, valid_results);
253 if (valid_results.empty())
254 return XCAM_RETURN_BYPASS;
255
256 ret = apply_3a_results (valid_results);
257
258 if (ret != XCAM_RETURN_NO_ERROR && ret != XCAM_RETURN_BYPASS) {
259 XCAM_LOG_WARNING ("processor(%s) apply results failed", XCAM_STR(get_name()));
260 return ret;
261 }
262
263 if (_callback) {
264 for (X3aResultList::iterator i_res = valid_results.begin();
265 i_res != valid_results.end(); ++i_res) {
266 SmartPtr<X3aResult> &res = *i_res;
267 _callback->process_image_result_done (this, res);
268 }
269 }
270
271 return ret;
272 }
273
274 XCamReturn
process_3a_result(SmartPtr<X3aResult> & result)275 ImageProcessor::process_3a_result (SmartPtr<X3aResult> &result)
276 {
277 X3aResultList valid_results;
278 XCamReturn ret = XCAM_RETURN_NO_ERROR;
279
280 if (!can_process_result(result))
281 return XCAM_RETURN_BYPASS;
282
283 ret = apply_3a_result (result);
284
285 if (ret != XCAM_RETURN_NO_ERROR && ret != XCAM_RETURN_BYPASS) {
286 XCAM_LOG_WARNING ("processor(%s) apply result failed", XCAM_STR(get_name()));
287 return ret;
288 }
289
290 if (_callback) {
291 _callback->process_image_result_done (this, result);
292 }
293
294 return ret;
295 }
296
297 void
filter_valid_results(X3aResultList & input,X3aResultList & valid_results)298 ImageProcessor::filter_valid_results (X3aResultList &input, X3aResultList &valid_results)
299 {
300 for (X3aResultList::iterator i_res = input.begin(); i_res != input.end(); ) {
301 SmartPtr<X3aResult> &res = *i_res;
302 if (can_process_result(res)) {
303 valid_results.push_back (res);
304 input.erase (i_res++);
305 } else
306 ++i_res;
307 }
308 }
309
310 void
notify_process_buffer_done(const SmartPtr<VideoBuffer> & buf)311 ImageProcessor::notify_process_buffer_done (const SmartPtr<VideoBuffer> &buf)
312 {
313 if (_callback)
314 _callback->process_buffer_done (this, buf);
315 }
316
317 void
notify_process_buffer_failed(const SmartPtr<VideoBuffer> & buf)318 ImageProcessor::notify_process_buffer_failed (const SmartPtr<VideoBuffer> &buf)
319 {
320 if (_callback)
321 _callback->process_buffer_failed (this, buf);
322 }
323
324 XCamReturn
buffer_process_loop()325 ImageProcessor::buffer_process_loop ()
326 {
327 XCamReturn ret = XCAM_RETURN_NO_ERROR;
328 SmartPtr<VideoBuffer> new_buf;
329 SmartPtr<VideoBuffer> buf = _video_buf_queue.pop();
330
331 if (!buf.ptr())
332 return XCAM_RETURN_ERROR_MEM;
333
334 ret = this->process_buffer (buf, new_buf);
335 if (ret < XCAM_RETURN_NO_ERROR) {
336 XCAM_LOG_DEBUG ("processing buffer failed");
337 notify_process_buffer_failed (buf);
338 return ret;
339 }
340
341 if (new_buf.ptr ())
342 notify_process_buffer_done (new_buf);
343
344 return XCAM_RETURN_NO_ERROR;
345 }
346
347 XCamReturn
emit_start()348 ImageProcessor::emit_start ()
349 {
350 return XCAM_RETURN_NO_ERROR;
351 }
352
353 void
emit_stop()354 ImageProcessor::emit_stop ()
355 {
356 }
357
358 };
359