Home | History | Annotate | Download | only in xcore
      1 /*
      2  * xcam_analyzer.cpp - libxcam analyzer
      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  *         Zong Wei <wei.zong (at) intel.com>
     20  *         Jia Meng <jia.meng (at) intel.com>
     21  */
     22 
     23 #include "xcam_analyzer.h"
     24 #include "x3a_stats_pool.h"
     25 
     26 namespace XCam {
     27 
     28 AnalyzerThread::AnalyzerThread (XAnalyzer *analyzer)
     29     : Thread ("AnalyzerThread")
     30     , _analyzer (analyzer)
     31 {}
     32 
     33 AnalyzerThread::~AnalyzerThread ()
     34 {
     35     _stats_queue.clear ();
     36 }
     37 
     38 bool
     39 AnalyzerThread::push_stats (const SmartPtr<VideoBuffer> &buffer)
     40 {
     41     _stats_queue.push (buffer);
     42     return true;
     43 }
     44 
     45 bool
     46 AnalyzerThread::started ()
     47 {
     48     XCamReturn ret = XCAM_RETURN_NO_ERROR;
     49 
     50     XCAM_ASSERT (_analyzer);
     51     ret = _analyzer->configure ();
     52     if (ret != XCAM_RETURN_NO_ERROR) {
     53         _analyzer->notify_calculation_failed (NULL, 0, "configure 3a failed");
     54         XCAM_LOG_WARNING ("analyzer(%s) configure 3a failed", XCAM_STR(_analyzer->get_name()));
     55         return false;
     56     }
     57 
     58     return true;
     59 }
     60 
     61 bool
     62 AnalyzerThread::loop ()
     63 {
     64     const static int32_t timeout = -1;
     65     SmartPtr<VideoBuffer> latest_stats;
     66     SmartPtr<VideoBuffer> stats = _stats_queue.pop (timeout);
     67     if (!stats.ptr()) {
     68         XCAM_LOG_DEBUG ("analyzer thread got empty stats, stop thread");
     69         return false;
     70     }
     71     //while ((latest_stats = _stats_queue.pop (0)).ptr ()) {
     72     //    stats = latest_stats;
     73     //    XCAM_LOG_WARNING ("lost 3a stats since 3a analyzer too slow");
     74     //}
     75 
     76     XCamReturn ret = _analyzer->analyze (stats);
     77     if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS)
     78         return true;
     79 
     80     XCAM_LOG_DEBUG ("analyzer(%s) failed to analyze 3a stats", XCAM_STR(_analyzer->get_name()));
     81     return false;
     82 }
     83 
     84 void
     85 AnalyzerCallback::x3a_calculation_done (XAnalyzer *analyzer, X3aResultList &results)
     86 {
     87     XCAM_UNUSED (analyzer);
     88 
     89     for (X3aResultList::iterator i_res = results.begin();
     90             i_res != results.end(); ++i_res) {
     91         SmartPtr<X3aResult> res = *i_res;
     92         if (res.ptr() == NULL) continue;
     93         XCAM_LOG_DEBUG (
     94             "calculated 3a result(type:0x%x, timestamp:" XCAM_TIMESTAMP_FORMAT ")",
     95             res->get_type (), XCAM_TIMESTAMP_ARGS (res->get_timestamp ()));
     96     }
     97 }
     98 
     99 void
    100 AnalyzerCallback::x3a_calculation_failed (XAnalyzer *analyzer, int64_t timestamp, const char *msg)
    101 {
    102     XCAM_UNUSED (analyzer);
    103 
    104     XCAM_LOG_WARNING (
    105         "Calculate 3a result failed, ts(" XCAM_TIMESTAMP_FORMAT "), msg:%s",
    106         XCAM_TIMESTAMP_ARGS (timestamp), XCAM_STR (msg));
    107 }
    108 
    109 XAnalyzer::XAnalyzer (const char *name)
    110     : _name (NULL)
    111     , _sync (false)
    112     , _started (false)
    113     , _width (0)
    114     , _height (0)
    115     , _framerate (30.0)
    116     , _callback (NULL)
    117 {
    118     if (name)
    119         _name = strndup (name, XCAM_MAX_STR_SIZE);
    120 
    121     _analyzer_thread  = new AnalyzerThread (this);
    122 }
    123 
    124 XAnalyzer::~XAnalyzer()
    125 {
    126     if (_name)
    127         xcam_free (_name);
    128 }
    129 
    130 bool
    131 XAnalyzer::set_results_callback (AnalyzerCallback *callback)
    132 {
    133     XCAM_ASSERT (!_callback);
    134     _callback = callback;
    135     return true;
    136 }
    137 
    138 XCamReturn
    139 XAnalyzer::prepare_handlers ()
    140 {
    141     return create_handlers ();
    142 }
    143 
    144 XCamReturn
    145 XAnalyzer::init (uint32_t width, uint32_t height, double framerate)
    146 {
    147     XCAM_LOG_DEBUG ("Analyzer(%s) init.", XCAM_STR(get_name()));
    148     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    149 
    150     XCAM_ASSERT (!_width && !_height);
    151     _width = width;
    152     _height = height;
    153     _framerate = framerate;
    154 
    155     ret = internal_init (width, height, _framerate);
    156     if (ret != XCAM_RETURN_NO_ERROR) {
    157         XCAM_LOG_WARNING ("analyzer init failed");
    158         deinit ();
    159         return ret;
    160     }
    161 
    162     XCAM_LOG_INFO (
    163         "Analyzer(%s) initialized(w:%d, h:%d).",
    164         XCAM_STR(get_name()), _width, _height);
    165     return XCAM_RETURN_NO_ERROR;
    166 }
    167 
    168 XCamReturn
    169 XAnalyzer::deinit ()
    170 {
    171     internal_deinit ();
    172 
    173     release_handlers ();
    174 
    175     _width = 0;
    176     _height = 0;
    177 
    178     XCAM_LOG_INFO ("Analyzer(%s) deinited.", XCAM_STR(get_name()));
    179     return XCAM_RETURN_NO_ERROR;
    180 }
    181 
    182 XCamReturn
    183 XAnalyzer::set_sync_mode (bool sync)
    184 {
    185     if (_started) {
    186         XCAM_LOG_ERROR ("can't set_sync_mode after analyzer started");
    187         return XCAM_RETURN_ERROR_PARAM;
    188     }
    189     _sync = sync;
    190     return XCAM_RETURN_NO_ERROR;
    191 }
    192 
    193 XCamReturn
    194 XAnalyzer::start ()
    195 {
    196     if (_sync) {
    197         XCamReturn ret = configure ();
    198         if (ret != XCAM_RETURN_NO_ERROR) {
    199             XCAM_LOG_ERROR ("analyzer failed to start in sync mode");
    200             stop ();
    201             return ret;
    202         }
    203     } else {
    204         if (_analyzer_thread->start () == false) {
    205             XCAM_LOG_WARNING ("analyzer thread start failed");
    206             stop ();
    207             return XCAM_RETURN_ERROR_THREAD;
    208         }
    209     }
    210 
    211     _started = true;
    212     XCAM_LOG_INFO ("Analyzer(%s) started in %s mode.", XCAM_STR(get_name()),
    213                    _sync ? "sync" : "async");
    214     return XCAM_RETURN_NO_ERROR;
    215 }
    216 
    217 XCamReturn
    218 XAnalyzer::stop ()
    219 {
    220     if (!_sync) {
    221         _analyzer_thread->triger_stop ();
    222         _analyzer_thread->stop ();
    223     }
    224 
    225     _started = false;
    226     XCAM_LOG_INFO ("Analyzer(%s) stopped.", XCAM_STR(get_name()));
    227     return XCAM_RETURN_NO_ERROR;
    228 }
    229 
    230 XCamReturn
    231 XAnalyzer::push_buffer (const SmartPtr<VideoBuffer> &buffer)
    232 {
    233     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    234 
    235     if (get_sync_mode ()) {
    236         ret = analyze (buffer);
    237     }
    238     else {
    239         if (!_analyzer_thread->is_running())
    240             return XCAM_RETURN_ERROR_THREAD;
    241 
    242         if (!_analyzer_thread->push_stats (buffer))
    243             return XCAM_RETURN_ERROR_THREAD;
    244     }
    245 
    246     return ret;
    247 }
    248 
    249 void
    250 XAnalyzer::set_results_timestamp (X3aResultList &results, int64_t timestamp)
    251 {
    252     if (results.empty ())
    253         return;
    254 
    255     X3aResultList::iterator i_results = results.begin ();
    256     for (; i_results != results.end ();  ++i_results)
    257     {
    258         (*i_results)->set_timestamp(timestamp);
    259     }
    260 }
    261 
    262 void
    263 XAnalyzer::notify_calculation_failed (AnalyzerHandler *handler, int64_t timestamp, const char *msg)
    264 {
    265     XCAM_UNUSED (handler);
    266 
    267     if (_callback)
    268         _callback->x3a_calculation_failed (this, timestamp, msg);
    269     XCAM_LOG_DEBUG (
    270         "calculation failed on ts:" XCAM_TIMESTAMP_FORMAT ", reason:%s",
    271         XCAM_TIMESTAMP_ARGS (timestamp), XCAM_STR (msg));
    272 }
    273 
    274 void
    275 XAnalyzer::notify_calculation_done (X3aResultList &results)
    276 {
    277     XCAM_ASSERT (!results.empty ());
    278     if (_callback)
    279         _callback->x3a_calculation_done (this, results);
    280 }
    281 
    282 };
    283