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> ¶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
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> ¶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
work_broken(const SmartPtr<ImageHandler::Parameters> & param,XCamReturn err)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
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> ¶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
is_param_error(const SmartPtr<ImageHandler::Parameters> & param)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