Home | History | Annotate | Download | only in xcore
      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 (at) intel.com>
     19  */
     20 
     21 #include "image_processor.h"
     22 #include "xcam_thread.h"
     23 
     24 namespace XCam {
     25 
     26 void
     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
     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
     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:
     72     ImageProcessorThread (ImageProcessor *processor)
     73         : Thread ("image_processor")
     74         , _processor (processor)
     75     {}
     76     ~ImageProcessorThread () {}
     77 
     78     virtual bool loop ();
     79 
     80 private:
     81     ImageProcessor *_processor;
     82 };
     83 
     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:
     97     X3aResultsProcessThread (ImageProcessor *processor)
     98         : Thread ("x3a_results_process_thread")
     99         , _processor (processor)
    100     {}
    101     ~X3aResultsProcessThread () {}
    102 
    103     XCamReturn push_result (SmartPtr<X3aResult> &result) {
    104         _queue.push (result);
    105         return XCAM_RETURN_NO_ERROR;
    106     }
    107 
    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 
    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 }
    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 
    151 ImageProcessor::~ImageProcessor ()
    152 {
    153     if (_name)
    154         xcam_free (_name);
    155 }
    156 
    157 bool
    158 ImageProcessor::set_callback (ImageProcessCallback *callback)
    159 {
    160     XCAM_ASSERT (!_callback);
    161     _callback = callback;
    162     return true;
    163 }
    164 
    165 XCamReturn
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    348 ImageProcessor::emit_start ()
    349 {
    350     return XCAM_RETURN_NO_ERROR;
    351 }
    352 
    353 void
    354 ImageProcessor::emit_stop ()
    355 {
    356 }
    357 
    358 };
    359