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