Home | History | Annotate | Download | only in xcore
      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 (at) intel.com>
     19  */
     20 
     21 #include "poll_thread.h"
     22 #include "xcam_thread.h"
     23 #include <unistd.h>
     24 
     25 namespace XCam {
     26 
     27 class PollThread;
     28 
     29 class EventPollThread
     30     : public Thread
     31 {
     32 public:
     33     EventPollThread (PollThread *poll)
     34         : Thread ("event_poll")
     35         , _poll (poll)
     36     {}
     37 
     38 protected:
     39     virtual bool started () {
     40         XCamReturn ret = _poll->init_3a_stats_pool ();
     41         if (ret != XCAM_RETURN_NO_ERROR)
     42             return false;
     43         return true;
     44     }
     45     virtual bool loop () {
     46         XCamReturn ret = _poll->poll_subdev_event_loop ();
     47 
     48         if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_ERROR_TIMEOUT)
     49             return true;
     50         return false;
     51     }
     52 
     53 private:
     54     PollThread   *_poll;
     55 };
     56 
     57 class CapturePollThread
     58     : public Thread
     59 {
     60 public:
     61     CapturePollThread (PollThread *poll)
     62         : Thread ("capture_poll")
     63         , _poll (poll)
     64     {}
     65 
     66 protected:
     67     virtual bool loop () {
     68         XCamReturn ret = _poll->poll_buffer_loop ();
     69 
     70         if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_ERROR_TIMEOUT)
     71             return true;
     72         return false;
     73     }
     74 
     75 private:
     76     PollThread   *_poll;
     77 };
     78 
     79 const int PollThread::default_subdev_event_timeout = 100; // ms
     80 const int PollThread::default_capture_event_timeout = 100; // ms
     81 
     82 PollThread::PollThread ()
     83     : _poll_callback (NULL)
     84     , _stats_callback (NULL)
     85 {
     86     _event_loop = new EventPollThread(this);
     87     _capture_loop = new CapturePollThread (this);
     88 
     89     XCAM_LOG_DEBUG ("PollThread constructed");
     90 }
     91 
     92 PollThread::~PollThread ()
     93 {
     94     stop();
     95 
     96     XCAM_LOG_DEBUG ("~PollThread destructed");
     97 }
     98 
     99 bool
    100 PollThread::set_capture_device (SmartPtr<V4l2Device> &dev)
    101 {
    102     XCAM_ASSERT (!_capture_dev.ptr());
    103     _capture_dev = dev;
    104     return true;
    105 }
    106 
    107 bool
    108 PollThread::set_event_device (SmartPtr<V4l2SubDevice> &dev)
    109 {
    110     XCAM_ASSERT (!_event_dev.ptr());
    111     _event_dev = dev;
    112     return true;
    113 }
    114 
    115 bool
    116 PollThread::set_poll_callback (PollCallback *callback)
    117 {
    118     XCAM_ASSERT (!_poll_callback);
    119     _poll_callback = callback;
    120     return true;
    121 }
    122 
    123 bool
    124 PollThread::set_stats_callback (StatsCallback *callback)
    125 {
    126     XCAM_ASSERT (!_stats_callback);
    127     _stats_callback = callback;
    128     return true;
    129 }
    130 
    131 XCamReturn PollThread::start ()
    132 {
    133     if (_event_dev.ptr () && !_event_loop->start ()) {
    134         return XCAM_RETURN_ERROR_THREAD;
    135     }
    136     if (!_capture_loop->start ()) {
    137         return XCAM_RETURN_ERROR_THREAD;
    138     }
    139 
    140     return XCAM_RETURN_NO_ERROR;
    141 }
    142 
    143 XCamReturn PollThread::stop ()
    144 {
    145     _event_loop->stop ();
    146     _capture_loop->stop ();
    147 
    148     return XCAM_RETURN_NO_ERROR;
    149 }
    150 
    151 XCamReturn
    152 PollThread::init_3a_stats_pool ()
    153 {
    154     return XCAM_RETURN_NO_ERROR;
    155 }
    156 
    157 XCamReturn
    158 PollThread::capture_3a_stats (SmartPtr<X3aStats> &stats)
    159 {
    160     XCAM_UNUSED (stats);
    161 
    162     return XCAM_RETURN_NO_ERROR;
    163 }
    164 
    165 XCamReturn
    166 PollThread::handle_events (struct v4l2_event &event)
    167 {
    168     XCAM_UNUSED (event);
    169 
    170     return XCAM_RETURN_NO_ERROR;
    171 }
    172 
    173 XCamReturn
    174 PollThread::handle_3a_stats_event (struct v4l2_event &event)
    175 {
    176     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    177     SmartPtr<X3aStats> stats;
    178 
    179     ret = capture_3a_stats (stats);
    180     if (ret != XCAM_RETURN_NO_ERROR || !stats.ptr()) {
    181         XCAM_LOG_WARNING ("capture 3a stats failed");
    182         return ret;
    183     }
    184     stats->set_timestamp (XCAM_TIMESPEC_2_USEC (event.timestamp));
    185 
    186     if (_stats_callback)
    187         return _stats_callback->x3a_stats_ready (stats);
    188 
    189     return ret;
    190 }
    191 
    192 XCamReturn
    193 PollThread::poll_subdev_event_loop ()
    194 {
    195     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    196     struct v4l2_event event;
    197     int poll_ret = 0;
    198 
    199     poll_ret = _event_dev->poll_event (PollThread::default_subdev_event_timeout);
    200 
    201     if (poll_ret < 0) {
    202         XCAM_LOG_WARNING ("poll event failed but continue");
    203         ::usleep (100000); // 100ms
    204         return XCAM_RETURN_ERROR_TIMEOUT;
    205     }
    206 
    207     /* timeout */
    208     if (poll_ret == 0) {
    209         XCAM_LOG_DEBUG ("poll event timeout and continue");
    210         return XCAM_RETURN_ERROR_TIMEOUT;
    211     }
    212 
    213     xcam_mem_clear (event);
    214     ret = _event_dev->dequeue_event (event);
    215     if (ret != XCAM_RETURN_NO_ERROR) {
    216         XCAM_LOG_WARNING ("dequeue event failed on dev:%s", XCAM_STR(_event_dev->get_device_name()));
    217         return XCAM_RETURN_ERROR_IOCTL;
    218     }
    219 
    220     ret = handle_events (event);
    221     return ret;
    222 }
    223 
    224 XCamReturn
    225 PollThread::poll_buffer_loop ()
    226 {
    227     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    228     int poll_ret = 0;
    229     SmartPtr<V4l2Buffer> buf;
    230 
    231     poll_ret = _capture_dev->poll_event (PollThread::default_capture_event_timeout);
    232 
    233     if (poll_ret < 0) {
    234         XCAM_LOG_DEBUG ("poll buffer event got error but continue");
    235         ::usleep (100000); // 100ms
    236         return XCAM_RETURN_ERROR_TIMEOUT;
    237     }
    238 
    239     /* timeout */
    240     if (poll_ret == 0) {
    241         XCAM_LOG_DEBUG ("poll buffer timeout and continue");
    242         return XCAM_RETURN_ERROR_TIMEOUT;
    243     }
    244 
    245     ret = _capture_dev->dequeue_buffer (buf);
    246     if (ret != XCAM_RETURN_NO_ERROR) {
    247         XCAM_LOG_WARNING ("capture buffer failed");
    248         return ret;
    249     }
    250     XCAM_ASSERT (buf.ptr());
    251     XCAM_ASSERT (_poll_callback);
    252 
    253     SmartPtr<VideoBuffer> video_buf = new V4l2BufferProxy (buf, _capture_dev);
    254 
    255     if (_poll_callback)
    256         return _poll_callback->poll_buffer_ready (video_buf);
    257 
    258     return ret;
    259 }
    260 
    261 };
    262