Home | History | Annotate | Download | only in soft
      1 /*
      2  * soft_handler.cpp - soft image handler implementation
      3  *
      4  *  Copyright (c) 2017 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 "soft_handler.h"
     22 #include "soft_video_buf_allocator.h"
     23 #include "thread_pool.h"
     24 #include "soft_worker.h"
     25 
     26 #define DEFAULT_SOFT_BUF_COUNT 4
     27 
     28 namespace XCam {
     29 
     30 class SyncMeta
     31     : public MetaBase
     32 {
     33 public:
     34     SyncMeta ()
     35         : _done (false)
     36         , _error (XCAM_RETURN_NO_ERROR) {}
     37     void signal_done (XCamReturn err);
     38     void wakeup ();
     39     XCamReturn signal_wait_ret ();
     40     bool is_error () const;
     41 
     42 private:
     43     mutable Mutex   _mutex;
     44     Cond            _cond;
     45     bool            _done;
     46     XCamReturn      _error;
     47 };
     48 
     49 void
     50 SyncMeta::signal_done (XCamReturn err)
     51 {
     52     SmartLock locker (_mutex);
     53     _done = true;
     54     _error = err;
     55     _cond.broadcast ();
     56 }
     57 
     58 void
     59 SyncMeta::wakeup ()
     60 {
     61     SmartLock locker (_mutex);
     62     _error = XCAM_RETURN_ERROR_UNKNOWN;
     63     _cond.broadcast ();
     64 }
     65 
     66 XCamReturn
     67 SyncMeta::signal_wait_ret ()
     68 {
     69     SmartLock locker (_mutex);
     70     if (_done)
     71         return _error;
     72     _cond.wait (_mutex);
     73     return _error;
     74 }
     75 
     76 bool
     77 SyncMeta::is_error () const
     78 {
     79     SmartLock locker (_mutex);
     80     return !xcam_ret_is_ok (_error);
     81 }
     82 
     83 SoftHandler::SoftHandler (const char* name)
     84     : ImageHandler (name)
     85     , _need_configure (true)
     86     , _enable_allocator (true)
     87     , _wip_buf_count (0)
     88 {
     89 }
     90 
     91 SoftHandler::~SoftHandler ()
     92 {
     93 }
     94 
     95 bool
     96 SoftHandler::set_threads (const SmartPtr<ThreadPool> &pool)
     97 {
     98     _threads = pool;
     99     return true;
    100 }
    101 
    102 bool
    103 SoftHandler::set_out_video_info (const VideoBufferInfo &info)
    104 {
    105     XCAM_ASSERT (info.width && info.height && info.format);
    106     _out_video_info = info;
    107     return true;
    108 }
    109 
    110 bool
    111 SoftHandler::enable_allocator (bool enable)
    112 {
    113     _enable_allocator = enable;
    114     return true;
    115 }
    116 
    117 XCamReturn
    118 SoftHandler::confirm_configured ()
    119 {
    120     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    121 
    122     XCAM_ASSERT (_need_configure);
    123     if (_enable_allocator) {
    124         XCAM_FAIL_RETURN (
    125             ERROR, _out_video_info.is_valid (), XCAM_RETURN_ERROR_PARAM,
    126             "soft_hander(%s) configure resource failed before reserver buffer since out video info was not set",
    127             XCAM_STR (get_name ()));
    128 
    129         set_allocator (new SoftVideoBufAllocator);
    130         ret = reserve_buffers (_out_video_info, DEFAULT_SOFT_BUF_COUNT);
    131         XCAM_FAIL_RETURN (
    132             ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
    133             "soft_hander(%s) configure resource failed in reserving buffers", XCAM_STR (get_name ()));
    134     }
    135 
    136     if (_threads.ptr () && !_threads->is_running ()) {
    137         ret = _threads->start ();
    138         XCAM_FAIL_RETURN (
    139             ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
    140             "soft_hander(%s) configure resource failed when starting threads", XCAM_STR (get_name ()));
    141     }
    142     _need_configure = false;
    143 
    144     return ret;
    145 }
    146 
    147 XCamReturn
    148 SoftHandler::execute_buffer (const SmartPtr<ImageHandler::Parameters> &param, bool sync)
    149 {
    150     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    151     SmartPtr<SyncMeta> sync_meta;
    152 
    153     XCAM_FAIL_RETURN (
    154         ERROR, param.ptr (), XCAM_RETURN_ERROR_PARAM,
    155         "soft_hander(%s) execute buffer failed, params is null",
    156         XCAM_STR (get_name ()));
    157 
    158     if (_need_configure) {
    159         ret = configure_resource (param);
    160         XCAM_FAIL_RETURN (
    161             WARNING, xcam_ret_is_ok (ret), ret,
    162             "soft_hander(%s) configure resource failed", XCAM_STR (get_name ()));
    163 
    164         ret = confirm_configured ();
    165         XCAM_FAIL_RETURN (
    166             WARNING, xcam_ret_is_ok (ret), ret,
    167             "soft_hander(%s) confirm configure failed", XCAM_STR (get_name ()));
    168     }
    169 
    170     if (!param->out_buf.ptr () && _enable_allocator) {
    171         param->out_buf = get_free_buf ();
    172         XCAM_FAIL_RETURN (
    173             ERROR, param->out_buf.ptr (), XCAM_RETURN_ERROR_PARAM,
    174             "soft_hander:%s execute buffer failed, output buffer failed in allocation.",
    175             XCAM_STR (get_name ()));
    176     }
    177 
    178     XCAM_ASSERT (!param->find_meta<SyncMeta> ().ptr ());
    179     sync_meta = new SyncMeta ();
    180     XCAM_ASSERT (sync_meta.ptr ());
    181     param->add_meta (sync_meta);
    182 
    183 #if 0
    184     SmartPtr<SoftWorker> worker = get_first_worker ().dynamic_cast_ptr<SoftWorker> ();
    185     XCAM_FAIL_RETURN (
    186         WARNING, worker.ptr (), XCAM_RETURN_ERROR_PARAM,
    187         "No worder set to soft_hander(%s)", XCAM_STR (get_name ()));
    188 
    189     SmartPtr<Worker::Arguments> args = get_first_worker_args (worker, params);
    190     XCAM_FAIL_RETURN (
    191         WARNING, args.ptr (), XCAM_RETURN_ERROR_PARAM,
    192         "soft_hander(%s) get first worker(%s) args failed",
    193         XCAM_STR (get_name ()), XCAM_STR (worker->get_name ()));
    194 
    195     _params.push (params);
    196     ret = worker->work (args);
    197 #else
    198     _params.push (param);
    199     ret = start_work (param);
    200 #endif
    201 
    202     if (!xcam_ret_is_ok (ret)) {
    203         _params.erase (param);
    204         XCAM_LOG_WARNING ("soft_hander(%s) execute buffer failed in starting workers", XCAM_STR (get_name ()));
    205         return ret;
    206     }
    207 
    208     ++_wip_buf_count;
    209     _cur_sync = sync_meta;
    210 
    211     if (sync) {
    212         XCAM_ASSERT (sync_meta.ptr ());
    213         ret = sync_meta->signal_wait_ret ();
    214         _cur_sync.release ();
    215     }
    216 
    217     return ret;
    218 }
    219 
    220 XCamReturn
    221 SoftHandler::finish ()
    222 {
    223     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    224     SmartPtr<SyncMeta> sync = _cur_sync;
    225     if (sync.ptr ()) {
    226         ret = sync->signal_wait_ret ();
    227     }
    228     XCAM_ASSERT (_params.is_empty ());
    229     //wait for _wip_buf_count = 0
    230     //if (ret == XCAM_RETURN_NO_ERROR)
    231     //    XCAM_ASSERT (_wip_buf_count == 0);
    232 
    233     return ret;
    234 }
    235 
    236 XCamReturn
    237 SoftHandler::terminate ()
    238 {
    239     SmartPtr<SyncMeta> sync = _cur_sync;
    240     if (sync.ptr ()) {
    241         sync->wakeup ();
    242         sync.release ();
    243     }
    244     _params.clear ();
    245     return ImageHandler::terminate ();
    246 }
    247 
    248 void
    249 SoftHandler::work_well_done (const SmartPtr<ImageHandler::Parameters> &param, XCamReturn err)
    250 {
    251     XCAM_ASSERT (param.ptr ());
    252     XCAM_ASSERT (xcam_ret_is_ok (err));
    253 
    254     if (!xcam_ret_is_ok (err)) {
    255         XCAM_LOG_WARNING ("soft_hander(%s) work_well_done but errno(%d) is not ok", XCAM_STR (get_name ()), (int)err);
    256         //continue work
    257     }
    258 
    259     if (!_params.erase (param)) {
    260         XCAM_LOG_ERROR(
    261             "soft_hander(%s) last_work_done param already removed, who removed it?", XCAM_STR (get_name ()));
    262         return;
    263     }
    264 
    265     XCAM_LOG_DEBUG ("soft_hander(%s) work well done", XCAM_STR (get_name ()));
    266 
    267     param_ended (param, err);
    268 }
    269 
    270 void
    271 SoftHandler::work_broken (const SmartPtr<ImageHandler::Parameters> &param, XCamReturn err)
    272 {
    273     XCAM_ASSERT (param.ptr ());
    274     XCAM_ASSERT (!xcam_ret_is_ok (err));
    275 
    276     if (xcam_ret_is_ok (err)) {
    277         XCAM_LOG_WARNING ("soft_hander(%s) work_broken but the errno(%d) is ok", XCAM_STR (get_name ()), (int)err);
    278         //continue work
    279     }
    280 
    281     if (!_params.erase (param)) {
    282         //already removed by other handlers
    283         return;
    284     }
    285     XCAM_LOG_WARNING ("soft_hander(%s) work broken", XCAM_STR (get_name ()));
    286 
    287     param_ended (param, err);
    288 }
    289 
    290 void
    291 SoftHandler::param_ended (SmartPtr<ImageHandler::Parameters> param, XCamReturn err)
    292 {
    293     XCAM_ASSERT (param.ptr ());
    294 
    295     SmartPtr<SyncMeta> sync_meta = param->find_meta<SyncMeta> ();
    296     XCAM_ASSERT (sync_meta.ptr ());
    297     sync_meta->signal_done (err);
    298     --_wip_buf_count;
    299     execute_status_check (param, err);
    300 }
    301 
    302 bool
    303 SoftHandler::check_work_continue (const SmartPtr<ImageHandler::Parameters> &param, XCamReturn err)
    304 {
    305     if (!xcam_ret_is_ok (err)) {
    306         work_broken (param, err);
    307         return false;
    308     }
    309 
    310     if (is_param_error (param)) {
    311         XCAM_LOG_WARNING (
    312             "soft_handler(%s) check_work_continue found param broken", XCAM_STR(get_name ()));
    313         return false;
    314     }
    315     return true;
    316 }
    317 
    318 bool
    319 SoftHandler::is_param_error (const SmartPtr<ImageHandler::Parameters> &param)
    320 {
    321     XCAM_ASSERT (param.ptr ());
    322     SmartPtr<SyncMeta> meta = param->find_meta<SyncMeta> ();
    323     if (!meta.ptr ()) { // return ok if param not set
    324         XCAM_ASSERT (meta.ptr ());
    325         return false;
    326     }
    327 
    328     return meta->is_error ();
    329 }
    330 
    331 }
    332 
    333