1 /*
2 * poll_thread.cpp - poll thread for event and buffer
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@intel.com>
19 */
20
21 #include "poll_thread.h"
22 #include "xcam_thread.h"
23 //#include <linux/rkisp.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26
27 namespace XCam {
28
29 class PollThread;
30
31 const char*
32 PollThread::isp_poll_type_to_str[ISP_POLL_POST_MAX] =
33 {
34 "luma_poll",
35 "ispp_poll",
36 "stats_poll",
37 "params_poll",
38 "pparams_poll",
39 };
40
41 class IspPollThread
42 : public Thread
43 {
44 public:
IspPollThread(PollThread * poll,int type)45 IspPollThread (PollThread *poll, int type)
46 : Thread (PollThread::isp_poll_type_to_str[type])
47 , _poll (poll)
48 , _type (type)
49 {}
50
51 protected:
loop()52 virtual bool loop () {
53 XCamReturn ret = _poll->poll_buffer_loop (_type);
54
55 if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_ERROR_TIMEOUT ||
56 XCAM_RETURN_BYPASS)
57 return true;
58 return false;
59 }
60
61 private:
62 PollThread *_poll;
63 int _type;
64 };
65
66 class EventPollThread
67 : public Thread
68 {
69 public:
EventPollThread(PollThread * poll)70 EventPollThread (PollThread *poll)
71 : Thread ("event_poll")
72 , _poll (poll)
73 {}
74
75 protected:
loop()76 virtual bool loop () {
77 XCamReturn ret = _poll->poll_subdev_event_loop ();
78
79 if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_ERROR_TIMEOUT)
80 return true;
81 return false;
82 }
83
84 private:
85 PollThread *_poll;
86 };
87
88 const int PollThread::default_poll_timeout = 300; // ms
89
PollThread()90 PollThread::PollThread ()
91 : _poll_callback (NULL)
92 , frameid (0)
93 {
94 #if 0
95 SmartPtr<EventPollThread> event_loop = new EventPollThread(this);
96 XCAM_ASSERT (event_loop.ptr ());
97 _event_loop = event_loop;
98
99 SmartPtr<IspPollThread> isp_stats_loop = new IspPollThread(this, ISP_POLL_3A_STATS);
100 XCAM_ASSERT (isp_stats_loop.ptr ());
101 _isp_stats_loop = isp_stats_loop;
102
103 SmartPtr<IspPollThread> isp_luma_loop = new IspPollThread(this, ISP_POLL_LUMA);
104 XCAM_ASSERT (isp_luma_loop.ptr ());
105 _isp_luma_loop = isp_luma_loop;
106
107 SmartPtr<IspPollThread> isp_params_loop = new IspPollThread(this, ISP_POLL_PARAMS);
108 XCAM_ASSERT (isp_params_loop.ptr ());
109 _isp_params_loop = isp_params_loop;
110
111 SmartPtr<IspPollThread> isp_pparams_loop = new IspPollThread(this, ISP_POLL_POST_PARAMS);
112 XCAM_ASSERT (isp_pparams_loop.ptr ());
113 _isp_pparams_loop = isp_pparams_loop;
114
115 SmartPtr<IspPollThread> ispp_stats_loop = new IspPollThread(this, ISPP_POLL_STATS);
116 XCAM_ASSERT (ispp_stats_loop.ptr ());
117 _ispp_stats_loop = ispp_stats_loop;
118
119 _ispp_poll_stop_fd[0] = -1;
120 _ispp_poll_stop_fd[1] = -1;
121 _luma_poll_stop_fd[0] = -1;
122 _luma_poll_stop_fd[1] = -1;
123 _3a_stats_poll_stop_fd[0] = -1;
124 _3a_stats_poll_stop_fd[1] = -1;
125 _event_poll_stop_fd[0] = -1;
126 _event_poll_stop_fd[1] = -1;
127 _isp_params_poll_stop_fd[0] = -1;
128 _isp_params_poll_stop_fd[1] = -1;
129 _isp_pparams_poll_stop_fd[0] = -1;
130 _isp_pparams_poll_stop_fd[1] = -1;
131 #endif
132 XCAM_LOG_DEBUG ("PollThread constructed");
133 }
134
~PollThread()135 PollThread::~PollThread ()
136 {
137 stop();
138
139 XCAM_LOG_DEBUG ("~PollThread destructed");
140 }
141
142 bool
set_event_device(SmartPtr<V4l2SubDevice> & dev)143 PollThread::set_event_device (SmartPtr<V4l2SubDevice> &dev)
144 {
145 XCAM_ASSERT (!_event_dev.ptr());
146 _event_dev = dev;
147 return true;
148 }
149
150 bool
set_isp_stats_device(SmartPtr<V4l2Device> & dev)151 PollThread::set_isp_stats_device (SmartPtr<V4l2Device> &dev)
152 {
153 XCAM_ASSERT (!_isp_stats_dev.ptr());
154 _isp_stats_dev = dev;
155 return true;
156 }
157
158 bool
set_isp_luma_device(SmartPtr<V4l2Device> & dev)159 PollThread::set_isp_luma_device (SmartPtr<V4l2Device> &dev)
160 {
161 XCAM_ASSERT (!_isp_luma_dev.ptr());
162 _isp_luma_dev = dev;
163 return true;
164 }
165
166 bool
set_ispp_stats_device(SmartPtr<V4l2Device> & dev)167 PollThread::set_ispp_stats_device (SmartPtr<V4l2Device> &dev)
168 {
169 XCAM_ASSERT (!_ispp_stats_dev.ptr());
170 _ispp_stats_dev = dev;
171 return true;
172 }
173
174 bool
set_isp_params_devices(SmartPtr<V4l2Device> & params_dev,SmartPtr<V4l2Device> & post_params_dev)175 PollThread::set_isp_params_devices (SmartPtr<V4l2Device> ¶ms_dev,
176 SmartPtr<V4l2Device> &post_params_dev)
177 {
178 XCAM_ASSERT (!_isp_params_dev.ptr());
179 XCAM_ASSERT (!_isp_pparams_dev.ptr());
180 _isp_params_dev = params_dev;
181 _isp_pparams_dev = post_params_dev;
182 return true;
183 }
184
185 bool
set_poll_callback(PollCallback * callback)186 PollThread::set_poll_callback (PollCallback *callback)
187 {
188 XCAM_ASSERT (!_poll_callback);
189 _poll_callback = callback;
190 return true;
191 }
192
destroy_stop_fds()193 void PollThread::destroy_stop_fds () {
194 if (_ispp_poll_stop_fd[1] != -1 || _ispp_poll_stop_fd[0] != -1) {
195 close(_ispp_poll_stop_fd[0]);
196 close(_ispp_poll_stop_fd[1]);
197 _ispp_poll_stop_fd[0] = -1;
198 _ispp_poll_stop_fd[1] = -1;
199 }
200
201 if (_luma_poll_stop_fd[1] != -1 || _luma_poll_stop_fd[0] != -1) {
202 close(_luma_poll_stop_fd[0]);
203 close(_luma_poll_stop_fd[1]);
204 _luma_poll_stop_fd[0] = -1;
205 _luma_poll_stop_fd[1] = -1;
206 }
207
208 if (_3a_stats_poll_stop_fd[1] != -1 || _3a_stats_poll_stop_fd[0] != -1) {
209 close(_3a_stats_poll_stop_fd[0]);
210 close(_3a_stats_poll_stop_fd[1]);
211 _3a_stats_poll_stop_fd[0] = -1;
212 _3a_stats_poll_stop_fd[1] = -1;
213 }
214
215 if (_event_poll_stop_fd[1] != -1 || _event_poll_stop_fd[0] != -1) {
216 close(_event_poll_stop_fd[0]);
217 close(_event_poll_stop_fd[1]);
218 _event_poll_stop_fd[0] = -1;
219 _event_poll_stop_fd[1] = -1;
220 }
221
222 if (_isp_params_poll_stop_fd[1] != -1 || _isp_params_poll_stop_fd[0] != -1) {
223 close(_isp_params_poll_stop_fd[0]);
224 close(_isp_params_poll_stop_fd[1]);
225 _isp_params_poll_stop_fd[0] = -1;
226 _isp_params_poll_stop_fd[1] = -1;
227 }
228
229 if (_isp_pparams_poll_stop_fd[1] != -1 || _isp_pparams_poll_stop_fd[0] != -1) {
230 close(_isp_pparams_poll_stop_fd[0]);
231 close(_isp_pparams_poll_stop_fd[1]);
232 _isp_pparams_poll_stop_fd[0] = -1;
233 _isp_pparams_poll_stop_fd[1] = -1;
234 }
235 }
236
create_stop_fds()237 XCamReturn PollThread::create_stop_fds () {
238 int status = 0;
239 XCamReturn ret = XCAM_RETURN_NO_ERROR;
240
241 destroy_stop_fds ();
242
243 status = pipe(_ispp_poll_stop_fd);
244 if (status < 0) {
245 XCAM_LOG_ERROR ("Failed to create ispp poll stop pipe: %s", strerror(errno));
246 ret = XCAM_RETURN_ERROR_UNKNOWN;
247 goto exit_error;
248 }
249
250 /**
251 * make the reading end of the pipe non blocking.
252 * This helps during flush to read any information left there without
253 * blocking
254 */
255 status = fcntl(_ispp_poll_stop_fd[0], F_SETFL, O_NONBLOCK);
256 if (status < 0) {
257 XCAM_LOG_ERROR ("Fail to set event ispp stop pipe flag: %s", strerror(errno));
258 ret = XCAM_RETURN_ERROR_UNKNOWN;
259 goto exit_error;
260 }
261
262 status = pipe(_luma_poll_stop_fd);
263 if (status < 0) {
264 XCAM_LOG_ERROR ("Failed to create luma poll stop pipe: %s", strerror(errno));
265 ret = XCAM_RETURN_ERROR_UNKNOWN;
266 goto exit_error;
267 }
268
269 /**
270 * make the reading end of the pipe non blocking.
271 * This helps during flush to read any information left there without
272 * blocking
273 */
274 status = fcntl(_luma_poll_stop_fd[0], F_SETFL, O_NONBLOCK);
275 if (status < 0) {
276 XCAM_LOG_ERROR ("Fail to set event luma stop pipe flag: %s", strerror(errno));
277 ret = XCAM_RETURN_ERROR_UNKNOWN;
278 goto exit_error;
279 }
280
281 status = pipe(_3a_stats_poll_stop_fd);
282 if (status < 0) {
283 XCAM_LOG_ERROR ("Failed to create stats poll stop pipe: %s", strerror(errno));
284 ret = XCAM_RETURN_ERROR_UNKNOWN;
285 goto exit_error;
286 }
287
288 /**
289 * make the reading end of the pipe non blocking.
290 * This helps during flush to read any information left there without
291 * blocking
292 */
293 status = fcntl(_3a_stats_poll_stop_fd[0], F_SETFL, O_NONBLOCK);
294 if (status < 0) {
295 XCAM_LOG_ERROR ("Fail to set stats poll stop pipe flag: %s", strerror(errno));
296 ret = XCAM_RETURN_ERROR_UNKNOWN;
297 goto exit_error;
298 }
299
300 status = pipe(_event_poll_stop_fd);
301 if (status < 0) {
302 XCAM_LOG_ERROR ("Failed to create event poll stop pipe: %s", strerror(errno));
303 ret = XCAM_RETURN_ERROR_UNKNOWN;
304 goto exit_error;
305 }
306
307 /**
308 * make the reading end of the pipe non blocking.
309 * This helps during flush to read any information left there without
310 * blocking
311 */
312 status = fcntl(_event_poll_stop_fd[0], F_SETFL, O_NONBLOCK);
313 if (status < 0) {
314 XCAM_LOG_ERROR ("Fail to set stats poll stop pipe flag: %s", strerror(errno));
315 ret = XCAM_RETURN_ERROR_UNKNOWN;
316 goto exit_error;
317 }
318
319 status = pipe(_isp_params_poll_stop_fd);
320 if (status < 0) {
321 XCAM_LOG_ERROR ("Failed to create params poll stop pipe: %s", strerror(errno));
322 ret = XCAM_RETURN_ERROR_UNKNOWN;
323 goto exit_error;
324 }
325
326 /**
327 * make the reading end of the pipe non blocking.
328 * This helps during flush to read any information left there without
329 * blocking
330 */
331 status = fcntl(_isp_params_poll_stop_fd[0], F_SETFL, O_NONBLOCK);
332 if (status < 0) {
333 XCAM_LOG_ERROR ("Fail to set params poll stop pipe flag: %s", strerror(errno));
334 ret = XCAM_RETURN_ERROR_UNKNOWN;
335 goto exit_error;
336 }
337
338 status = pipe(_isp_pparams_poll_stop_fd);
339 if (status < 0) {
340 XCAM_LOG_ERROR ("Failed to create pparams poll stop pipe: %s", strerror(errno));
341 ret = XCAM_RETURN_ERROR_UNKNOWN;
342 goto exit_error;
343 }
344
345 /**
346 * make the reading end of the pipe non blocking.
347 * This helps during flush to read any information left there without
348 * blocking
349 */
350 status = fcntl(_isp_pparams_poll_stop_fd[0], F_SETFL, O_NONBLOCK);
351 if (status < 0) {
352 XCAM_LOG_ERROR ("Fail to set pparams poll stop pipe flag: %s", strerror(errno));
353 ret = XCAM_RETURN_ERROR_UNKNOWN;
354 goto exit_error;
355 }
356 return XCAM_RETURN_NO_ERROR;
357 exit_error:
358 destroy_stop_fds ();
359 return ret;
360 }
361
start()362 XCamReturn PollThread::start ()
363 {
364 if (create_stop_fds ()) {
365 XCAM_LOG_ERROR("create stop fds failed !");
366 return XCAM_RETURN_ERROR_UNKNOWN;
367 }
368
369 if (_event_dev.ptr () && !_event_loop->start ()) {
370 return XCAM_RETURN_ERROR_THREAD;
371 }
372
373 if (_isp_stats_dev.ptr () && !_isp_stats_loop->start ()) {
374 return XCAM_RETURN_ERROR_THREAD;
375 }
376
377 if (_isp_luma_dev.ptr () && !_isp_luma_loop->start ()) {
378 return XCAM_RETURN_ERROR_THREAD;
379 }
380
381 if (_isp_params_dev.ptr () && !_isp_params_loop->start ()) {
382 return XCAM_RETURN_ERROR_THREAD;
383 }
384
385 if (_ispp_stats_dev.ptr () && !_ispp_stats_loop->start ()) {
386 return XCAM_RETURN_ERROR_THREAD;
387 }
388
389 if (_isp_pparams_dev.ptr () && !_isp_pparams_loop->start ()) {
390 return XCAM_RETURN_ERROR_THREAD;
391 }
392
393 return XCAM_RETURN_NO_ERROR;
394 }
395
stop()396 XCamReturn PollThread::stop ()
397 {
398 XCAM_LOG_DEBUG ("PollThread stop");
399
400 if (_event_dev.ptr ()) {
401 if (_event_poll_stop_fd[1] != -1) {
402 char buf = 0xf; // random value to write to flush fd.
403 unsigned int size = write(_event_poll_stop_fd[1], &buf, sizeof(char));
404 if (size != sizeof(char)) {
405 XCAM_LOG_WARNING("Flush write not completed");
406 }
407 }
408 _event_loop->stop ();
409 }
410
411 if (_ispp_stats_dev.ptr ()) {
412 if (_ispp_poll_stop_fd[1] != -1) {
413 char buf = 0xf; // random value to write to flush fd.
414 unsigned int size = write(_ispp_poll_stop_fd[1], &buf, sizeof(char));
415 if (size != sizeof(char)) {
416 XCAM_LOG_WARNING("Flush write not completed");
417 }
418 }
419 _ispp_stats_loop->stop ();
420 }
421
422 if (_isp_stats_dev.ptr ()) {
423 if (_3a_stats_poll_stop_fd[1] != -1) {
424 char buf = 0xf; // random value to write to flush fd.
425 unsigned int size = write(_3a_stats_poll_stop_fd[1], &buf, sizeof(char));
426 if (size != sizeof(char)) {
427 XCAM_LOG_WARNING("Flush write not completed");
428 }
429 }
430 _isp_stats_loop->stop ();
431 }
432
433 if (_isp_luma_dev.ptr ()) {
434 if (_luma_poll_stop_fd[1] != -1) {
435 char buf = 0xf; // random value to write to flush fd.
436 unsigned int size = write(_luma_poll_stop_fd[1], &buf, sizeof(char));
437 if (size != sizeof(char)) {
438 XCAM_LOG_WARNING("Flush write not completed");
439 }
440 }
441 _isp_luma_loop->stop ();
442 }
443
444 if (_isp_params_dev.ptr ()) {
445 if (_isp_params_poll_stop_fd[1] != -1) {
446 char buf = 0xf; // random value to write to flush fd.
447 unsigned int size = write(_isp_params_poll_stop_fd[1], &buf, sizeof(char));
448 if (size != sizeof(char)) {
449 XCAM_LOG_WARNING("Flush write not completed");
450 }
451 }
452 _isp_params_loop->stop ();
453 }
454
455 if (_isp_pparams_dev.ptr ()) {
456 if (_isp_pparams_poll_stop_fd[1] != -1) {
457 char buf = 0xf; // random value to write to flush fd.
458 unsigned int size = write(_isp_pparams_poll_stop_fd[1], &buf, sizeof(char));
459 if (size != sizeof(char)) {
460 XCAM_LOG_WARNING("Flush write not completed");
461 }
462 }
463 _isp_pparams_loop->stop ();
464 }
465
466 destroy_stop_fds ();
467
468 return XCAM_RETURN_NO_ERROR;
469 }
470
471 XCamReturn
notify_sof(uint64_t time,uint32_t frameid)472 PollThread::notify_sof (uint64_t time, uint32_t frameid)
473 {
474 XCAM_UNUSED (time);
475 XCAM_UNUSED (frameid);
476
477 return XCAM_RETURN_NO_ERROR;
478 }
479
480 XCamReturn
handle_events(struct v4l2_event & event)481 PollThread::handle_events (struct v4l2_event &event)
482 {
483 XCamReturn ret = XCAM_RETURN_NO_ERROR;
484 switch (event.type) {
485 case V4L2_EVENT_FRAME_SYNC:
486 ret = handle_frame_sync_event (event);
487 break;
488 default:
489 ret = XCAM_RETURN_ERROR_UNKNOWN;
490 break;
491 }
492
493 return ret;
494 }
495
496 XCamReturn
handle_frame_sync_event(struct v4l2_event & event)497 PollThread::handle_frame_sync_event (struct v4l2_event &event)
498 {
499 int64_t tv_sec = event.timestamp.tv_sec;
500 int64_t tv_nsec = event.timestamp.tv_nsec;
501 int exp_id = event.u.frame_sync.frame_sequence;
502
503 notify_sof(tv_sec * 1000 * 1000 * 1000 + tv_nsec, exp_id);
504
505 return XCAM_RETURN_NO_ERROR;
506 }
507
508 XCamReturn
poll_subdev_event_loop()509 PollThread::poll_subdev_event_loop ()
510 {
511 XCamReturn ret = XCAM_RETURN_NO_ERROR;
512 struct v4l2_event event;
513 int poll_ret = 0;
514
515 poll_ret = _event_dev->poll_event (PollThread::default_poll_timeout,
516 _event_poll_stop_fd[0]);
517
518 if (poll_ret == POLL_STOP_RET) {
519 XCAM_LOG_DEBUG ("poll event stop success !");
520 // stop success, return error to stop the poll thread
521 return XCAM_RETURN_ERROR_UNKNOWN;
522 }
523
524 if (poll_ret < 0) {
525 XCAM_LOG_WARNING ("poll event failed but continue");
526 ::usleep (1000); // 1ms
527 return XCAM_RETURN_ERROR_TIMEOUT;
528 }
529
530 /* timeout */
531 if (poll_ret == 0) {
532 XCAM_LOG_WARNING ("poll event timeout and continue");
533 return XCAM_RETURN_ERROR_TIMEOUT;
534 }
535
536 xcam_mem_clear (event);
537 ret = _event_dev->dequeue_event (event);
538 if (ret != XCAM_RETURN_NO_ERROR) {
539 XCAM_LOG_WARNING ("dequeue event failed on dev:%s", XCAM_STR(_event_dev->get_device_name()));
540 return XCAM_RETURN_ERROR_IOCTL;
541 }
542
543 ret = handle_events (event);
544
545 XCAM_ASSERT (_poll_callback);
546
547 if (_poll_callback && event.type == V4L2_EVENT_FRAME_SYNC)
548 return _poll_callback->poll_event_ready (event.u.frame_sync.frame_sequence,
549 event.type);
550
551 return ret;
552 }
553
554 SmartPtr<VideoBuffer>
new_video_buffer(SmartPtr<V4l2Buffer> buf,SmartPtr<V4l2Device> dev,int type)555 PollThread::new_video_buffer(SmartPtr<V4l2Buffer> buf,
556 SmartPtr<V4l2Device> dev,
557 int type)
558 {
559 SmartPtr<VideoBuffer> video_buf = new V4l2BufferProxy (buf, dev);
560
561 return video_buf;
562 }
563
564 XCamReturn
poll_buffer_loop(int type)565 PollThread::poll_buffer_loop (int type)
566 {
567 XCamReturn ret = XCAM_RETURN_NO_ERROR;
568 int poll_ret = 0;
569 SmartPtr<V4l2Buffer> buf;
570 SmartPtr<V4l2Device> dev;
571 int stop_fd = -1;
572 #if 0
573 if (type == ISP_POLL_LUMA) {
574 dev = _isp_luma_dev;
575 stop_fd = _luma_poll_stop_fd[0];
576 } else if (type == ISPP_POLL_STATS) {
577 dev = _ispp_stats_dev;
578 stop_fd = _ispp_poll_stop_fd[0];
579 } else if (type == ISP_POLL_3A_STATS) {
580 dev = _isp_stats_dev;
581 stop_fd = _3a_stats_poll_stop_fd[0];
582 } else if (type == ISP_POLL_PARAMS) {
583 dev = _isp_params_dev;
584 stop_fd = _isp_params_poll_stop_fd[0];
585 } else if (type == ISP_POLL_POST_PARAMS) {
586 dev = _isp_pparams_dev;
587 stop_fd = _isp_pparams_poll_stop_fd[0];
588 } else
589 return XCAM_RETURN_ERROR_UNKNOWN;
590
591 poll_ret = dev->poll_event (PollThread::default_poll_timeout,
592 stop_fd);
593
594 if (poll_ret == POLL_STOP_RET) {
595 XCAM_LOG_DEBUG ("poll %s buffer stop success !", isp_poll_type_to_str[type]);
596 // stop success, return error to stop the poll thread
597 return XCAM_RETURN_ERROR_UNKNOWN;
598 }
599
600 if (poll_ret <= 0) {
601 XCAM_LOG_DEBUG ("poll %s buffer event got error(0x%x) but continue\n", isp_poll_type_to_str[type], poll_ret);
602 ::usleep (100000); // 100ms
603 return XCAM_RETURN_ERROR_TIMEOUT;
604 }
605
606 ret = dev->dequeue_buffer (buf);
607 if (ret != XCAM_RETURN_NO_ERROR) {
608 XCAM_LOG_WARNING ("dequeue %s buffer failed", isp_poll_type_to_str[type]);
609 return ret;
610 }
611
612 XCAM_ASSERT (buf.ptr());
613 XCAM_ASSERT (_poll_callback);
614
615 if (_poll_callback &&
616 (type == ISP_POLL_3A_STATS || type == ISP_POLL_LUMA || type == ISPP_POLL_STATS)) {
617 SmartPtr<VideoBuffer> video_buf = new_video_buffer(buf, dev, type);
618
619 return _poll_callback->poll_buffer_ready (video_buf, type);
620 }
621 #endif
622 return ret;
623 }
624
625 }
626