1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // Note: ported from Chromium commit head: f65c38dcdac2 5 6 #ifndef ANDROID_V4L2_CODEC2_COMMON_V4L2_DEVICE_POLLER_H 7 #define ANDROID_V4L2_CODEC2_COMMON_V4L2_DEVICE_POLLER_H 8 9 #include <atomic> 10 11 #include <base/callback_forward.h> 12 #include <base/sequence_checker.h> 13 #include <base/sequenced_task_runner.h> 14 #include <base/synchronization/waitable_event.h> 15 #include <base/threading/thread.h> 16 17 namespace android { 18 19 class V4L2Device; 20 21 // Allows a client to poll() on a given V4L2Device and be signaled when a buffer is ready to be 22 // dequeued or a V4L2 event has been received. Polling is done on a dedicated thread, and 23 // notifications are delivered in the form of a callback to the listener's sequence. 24 // 25 // All the methods of this class (with the exception of the constructor) must be called from the 26 // same sequence. 27 // 28 // Note that the service callback may also be called when no particular event occurred due to the 29 // way poll() works. It is the responsibility of the caller to call SchedulePoll() again if there 30 // may still be pending events. 31 class V4L2DevicePoller { 32 public: 33 // Callback to be called when buffer ready/V4L2 event has potentially been polled. |event| is 34 // set if a V4L2 event has been detected. 35 using EventCallback = base::RepeatingCallback<void(bool event)>; 36 37 // Create a poller for |device|, using a thread named |threadName|. Notification won't start 38 // until |startPolling()| is called. 39 V4L2DevicePoller(V4L2Device* const device, const std::string& threadName); 40 ~V4L2DevicePoller(); 41 42 // Starts polling. |mEventCallback| will be posted on the caller's sequence every time an event 43 // occurs. The client is then responsible for consuming all pending events in that callback. If 44 // new events may still happen after the callback has run, the client must call |schedulePoll()| 45 // again in order to be notified for them. 46 // 47 // If an error occurs during polling, |mErrorCallback| will be posted on the caller's sequence. 48 bool startPolling(EventCallback eventCallback, base::RepeatingClosure errorCallback); 49 // Stop polling and stop the thread. The poller won't post any new event to the caller's 50 // sequence after this method has returned. 51 bool stopPolling(); 52 // Returns true if currently polling, false otherwise. 53 bool isPolling() const; 54 // Attempts polling the V4L2 device. This method should be called whenever doing something that 55 // may trigger an event of interest (buffer dequeue or V4L2 event), for instance queueing a 56 // buffer. In the absence of a pending event, poll() will return immediately and the service 57 // callback will be posted to the caller's sequence. The client is then responsible for calling 58 // this method again when it is interested in receiving events. 59 void schedulePoll(); 60 61 private: 62 // Perform a poll() on |mDevice| and post either |mEventCallback| or |mErrorCallback| on the 63 // client's sequence when poll() returns. 64 void devicePollTask(); 65 66 // V4L2 device we are polling. 67 V4L2Device* const mDevice; 68 // Thread on which polling is done. 69 base::Thread mPollThread; 70 // Callback to post to the client's sequence when an event occurs. 71 EventCallback mEventCallback; 72 // Closure to post to the client's sequence when an error occurs. 73 base::RepeatingClosure mErrorCallback; 74 // Client sequence's task runner, where closures are posted. 75 scoped_refptr<base::SequencedTaskRunner> mClientTaskTunner; 76 77 // Since poll() returns immediately if no buffers have been queued, we cannot rely on it to 78 // pause the polling thread until an event occurs. Instead, 79 // the polling thread will wait on this WaitableEvent (signaled by |schedulePoll| before calling 80 // poll(), so we only call it when we are actually waiting for an event. 81 base::WaitableEvent mTriggerPoll; 82 // Set to true when we wish to stop polling, instructing the poller thread to break its loop. 83 std::atomic_bool mStopPolling; 84 }; 85 86 } // namespace android 87 88 #endif // ANDROID_V4L2_CODEC2_COMMON_V4L2_DEVICE_POLLER_H 89