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> ¶m, 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> ¶m, 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> ¶m, 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> ¶m, 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> ¶m) 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