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 V4L2_V4L2_DEVICE_POLLER_H_ 7 #define V4L2_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 media { 18 19 class V4L2Device; 20 21 // Allows a client to poll() on a given V4L2Device and be signaled when 22 // a buffer is ready to be dequeued or a V4L2 event has been received. Polling 23 // is done on a dedicated thread, and notifications are delivered in the form of 24 // a callback to the listener's sequence. 25 // 26 // All the methods of this class (with the exception of the constructor) must be 27 // called from the same sequence. 28 // 29 // Note that the service callback may also be called when no particular event 30 // occurred due to the way poll() works. It is the responsibility of the caller 31 // to call SchedulePoll() again if there may still be pending events. 32 class V4L2DevicePoller { 33 public: 34 // Callback to be called when buffer ready/V4L2 event has potentially been 35 // polled. |event| is set if a V4L2 event has been detected. 36 using EventCallback = base::RepeatingCallback<void(bool event)>; 37 38 // Create a poller for |device|, using a thread named |thread_name|. 39 // Notification won't start until |StartPolling()| is called. 40 V4L2DevicePoller(V4L2Device* const device, const std::string& thread_name); 41 ~V4L2DevicePoller(); 42 43 // Starts polling. |event_callback| will be posted on the caller's sequence 44 // every time an event occurs. The client is then responsible for consuming 45 // all pending events in that callback. If new events may still happen after 46 // the callback has run, the client must call |SchedulePoll()| again in order 47 // to be notified for them. 48 // 49 // If an error occurs during polling, |error_callback| will be posted on the 50 // caller's sequence. 51 bool StartPolling(EventCallback event_callback, 52 base::RepeatingClosure error_callback); 53 // Stop polling and stop the thread. The poller won't post any new event to 54 // the caller's sequence after this method has returned. 55 bool StopPolling(); 56 // Returns true if currently polling, false otherwise. 57 bool IsPolling() const; 58 // Attempts polling the V4L2 device. This method should be called whenever 59 // doing something that may trigger an event of interest (buffer dequeue or 60 // V4L2 event), for instance queueing a buffer. In the absence of a pending 61 // event, poll() will return immediately and the service callback will be 62 // posted to the caller's sequence. The client is then responsible for calling 63 // this method again when it is interested in receiving events. 64 void SchedulePoll(); 65 66 private: 67 // Perform a poll() on |device_| and post either |service_task_| or 68 // |error_callback_| on the client's sequence when poll() returns. 69 void DevicePollTask(); 70 71 // V4L2 device we are polling. 72 V4L2Device* const device_; 73 // Thread on which polling is done. 74 base::Thread poll_thread_; 75 // Callback to post to the client's sequence when an event occurs. 76 EventCallback event_callback_; 77 // Closure to post to the client's sequence when an error occurs. 78 base::RepeatingClosure error_callback_; 79 // Client sequence's task runner, where closures are posted. 80 scoped_refptr<base::SequencedTaskRunner> client_task_runner_; 81 82 // Since poll() returns immediately if no buffers have been queued, we cannot 83 // rely on it to pause the polling thread until an event occurs. Instead, 84 // the polling thread will wait on this WaitableEvent (signaled by 85 // |SchedulePoll| before calling poll(), so we only call it when we are 86 // actually waiting for an event. 87 base::WaitableEvent trigger_poll_; 88 // Set to true when we wish to stop polling, instructing the poller thread 89 // to break its loop. 90 std::atomic_bool stop_polling_; 91 92 SEQUENCE_CHECKER(client_sequence_checker_); 93 }; 94 95 } // namespace media 96 97 #endif // V4L2_V4L2_DEVICE_POLLER_H_ 98