• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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:
SyncMeta()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
signal_done(XCamReturn err)50 SyncMeta::signal_done (XCamReturn err)
51 {
52     SmartLock locker (_mutex);
53     _done = true;
54     _error = err;
55     _cond.broadcast ();
56 }
57 
58 void
wakeup()59 SyncMeta::wakeup ()
60 {
61     SmartLock locker (_mutex);
62     _error = XCAM_RETURN_ERROR_UNKNOWN;
63     _cond.broadcast ();
64 }
65 
66 XCamReturn
signal_wait_ret()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
is_error() const77 SyncMeta::is_error () const
78 {
79     SmartLock locker (_mutex);
80     return !xcam_ret_is_ok (_error);
81 }
82 
SoftHandler(const char * name)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 
~SoftHandler()91 SoftHandler::~SoftHandler ()
92 {
93 }
94 
95 bool
set_threads(const SmartPtr<ThreadPool> & pool)96 SoftHandler::set_threads (const SmartPtr<ThreadPool> &pool)
97 {
98     _threads = pool;
99     return true;
100 }
101 
102 bool
set_out_video_info(const VideoBufferInfo & info)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
enable_allocator(bool enable)111 SoftHandler::enable_allocator (bool enable)
112 {
113     _enable_allocator = enable;
114     return true;
115 }
116 
117 XCamReturn
confirm_configured()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
execute_buffer(const SmartPtr<ImageHandler::Parameters> & param,bool sync)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
finish()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
terminate()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
work_well_done(const SmartPtr<ImageHandler::Parameters> & param,XCamReturn err)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
work_broken(const SmartPtr<ImageHandler::Parameters> & param,XCamReturn err)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
param_ended(SmartPtr<ImageHandler::Parameters> param,XCamReturn err)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
check_work_continue(const SmartPtr<ImageHandler::Parameters> & param,XCamReturn err)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
is_param_error(const SmartPtr<ImageHandler::Parameters> & param)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