• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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