diff options
Diffstat (limited to 'common/include/v4l2_codec2')
-rw-r--r-- | common/include/v4l2_codec2/common/V4L2Device.h | 1009 | ||||
-rw-r--r-- | common/include/v4l2_codec2/common/V4L2DevicePoller.h | 139 |
2 files changed, 524 insertions, 624 deletions
diff --git a/common/include/v4l2_codec2/common/V4L2Device.h b/common/include/v4l2_codec2/common/V4L2Device.h index fcd34b8..70a72b7 100644 --- a/common/include/v4l2_codec2/common/V4L2Device.h +++ b/common/include/v4l2_codec2/common/V4L2Device.h @@ -2,49 +2,35 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// This file defines the V4L2Device interface which is used by the -// V4L2DecodeAccelerator class to delegate/pass the device specific -// handling of any of the functionalities. -// Note: ported from Chromium commit head: 2f13d62f0c0d -// Note: the complete v4l2 device code is ported from Chromium, but some parts -// have been removed: -// - All V4L2 request functionality has been removed, as it required a newer -// kernel version. -// - void SetConfigStore() has been removed as it depends on a newer kernel -// version. -// - QueueDMABuf() from native pixmap planes has been removed, as -// NativePixmapPlane have not been ported. -// - GetVideoFrame() is removed as it depends on some helper functions that have -// not been ported. -// - GL-related functionality has been removed: canCreateEGLImageFrom(), -// CreateEGLImage(), CreateGLImage() and GetTextureTarget() -// - V4L2PixFmtToDrmFormat() has been removed, as DRM is not supported yet. - -#ifndef V4L2_DEVICE_H_ -#define V4L2_DEVICE_H_ +// This file defines the V4L2Device which is used by the V4L2Decoder and V4L2Encoder classes to +// delegate/pass the device specific handling of any of the functionalities. +// Note: ported from Chromium commit head: 2f13d62f0c0d, but some parts have been removed. + +#ifndef ANDROID_V4L2_CODEC2_COMMON_V4L2_DEVICE_H +#define ANDROID_V4L2_CODEC2_COMMON_V4L2_DEVICE_H #include <linux/videodev2.h> #include <stddef.h> #include <stdint.h> -#include <queue> +#include <optional> #include <vector> -#include "base/containers/flat_map.h" -#include "base/files/scoped_file.h" -#include "base/memory/ref_counted.h" +#include <base/containers/flat_map.h> +#include <base/files/scoped_file.h> +#include <base/memory/ref_counted.h> -#include "fourcc.h" -#include "size.h" -#include "video_codecs.h" -#include "video_decode_accelerator.h" -#include "video_encode_accelerator.h" -#include "video_frame.h" -#include "video_frame_layout.h" -#include "video_pixel_format.h" -#include "v4l2_codec2/common/V4L2DevicePoller.h" +#include <fourcc.h> +#include <size.h> +#include <v4l2_codec2/common/V4L2DevicePoller.h> +#include <video_codecs.h> +#include <video_decode_accelerator.h> +#include <video_encode_accelerator.h> +#include <video_frame.h> +#include <video_frame_layout.h> +#include <video_pixel_format.h> -namespace media { +namespace android { class V4L2Queue; class V4L2BufferRefBase; @@ -53,154 +39,131 @@ class V4L2DecodeSurface; // Wrapper for the 'v4l2_ext_control' structure. struct V4L2ExtCtrl { - V4L2ExtCtrl(uint32_t id); - V4L2ExtCtrl(uint32_t id, int32_t val); - struct v4l2_ext_control ctrl; + V4L2ExtCtrl(uint32_t id); + V4L2ExtCtrl(uint32_t id, int32_t val); + struct v4l2_ext_control ctrl; }; // A unique reference to a buffer for clients to prepare and submit. // -// Clients can prepare a buffer for queuing using the methods of this class, and -// then either queue it using the Queue() method corresponding to the memory -// type of the buffer, or drop the reference to make the buffer available again. +// Clients can prepare a buffer for queuing using the methods of this class, and then either queue +// it using the Queue() method corresponding to the memory type of the buffer, or drop the reference +// to make the buffer available again. class V4L2WritableBufferRef { - public: - V4L2WritableBufferRef(V4L2WritableBufferRef&& other); - V4L2WritableBufferRef() = delete; - V4L2WritableBufferRef& operator=(V4L2WritableBufferRef&& other); - - // Return the memory type of the buffer. Useful to e.g. decide which Queue() - // method to use. - enum v4l2_memory Memory() const; - - // Queue a MMAP buffer. - // If successful, true is returned and the reference to the buffer is dropped - // so this reference becomes invalid. - // In case of error, false is returned and the buffer is returned to the free - // list. - bool QueueMMap() &&; - // Queue a USERPTR buffer, assigning |ptrs| as pointer for each plane. - // The size of |ptrs| must be equal to the number of planes of this buffer. - // If successful, true is returned and the reference to the buffer is dropped - // so this reference becomes invalid. - // In case of error, false is returned and the buffer is returned to the free - // list. - bool QueueUserPtr(const std::vector<void*>& ptrs) &&; - // Queue a DMABUF buffer, assigning |fds| as file descriptors for each plane. - // It is allowed the number of |fds| might be greater than the number of - // planes of this buffer. It happens when the v4l2 pixel format is single - // planar. The fd of the first plane is only used in that case. - // If successful, true is returned and the reference to the buffer is dropped - // so this reference becomes invalid. - // In case of error, false is returned and the buffer is returned to the free - // list. - bool QueueDMABuf(const std::vector<base::ScopedFD>& scoped_fds) &&; - // Queue a DMABUF buffer, assigning |fds| as file descriptors for each plane. - // It is allowed the number of |fds| might be greater than the number of - // planes of this buffer. It happens when the v4l2 pixel format is single - // planar. The fd of the first plane is only used in that case. - // If successful, true is returned and the reference to the buffer is dropped - // so this reference becomes invalid. - // In case of error, false is returned and the buffer is returned to the free - // list. - bool QueueDMABuf(const std::vector<int>& fds) &&; - - // Returns the number of planes in this buffer. - size_t PlanesCount() const; - // Returns the size of the requested |plane|, in bytes. - size_t GetPlaneSize(const size_t plane) const; - // Set the size of the requested |plane|, in bytes. It is only valid for - // USERPTR and DMABUF buffers. When using MMAP buffer, this method triggers a - // DCHECK and is a no-op for release builds. - void SetPlaneSize(const size_t plane, const size_t size); - // This method can only be used with MMAP buffers. - // It will return a pointer to the data of the |plane|th plane. - // In case of error (invalid plane index or mapping failed), a nullptr is - // returned. - void* GetPlaneMapping(const size_t plane); - // Set the timestamp field for this buffer. - void SetTimeStamp(const struct timeval& timestamp); - // Return the previously-set timestamp field for this buffer. - const struct timeval& GetTimeStamp() const; - // Set the number of bytes used for |plane|. - void SetPlaneBytesUsed(const size_t plane, const size_t bytes_used); - // Returns the previously-set number of bytes used for |plane|. - size_t GetPlaneBytesUsed(const size_t plane) const; - // Set the data offset for |plane|, in bytes. - void SetPlaneDataOffset(const size_t plane, const size_t data_offset); - - // Return the V4L2 buffer ID of the underlying buffer. - // TODO(acourbot) This is used for legacy clients but should be ultimately - // removed. See crbug/879971 - size_t BufferId() const; - - ~V4L2WritableBufferRef(); - - private: - // Do the actual queue operation once the v4l2_buffer structure is properly - // filled. - bool DoQueue() &&; - - V4L2WritableBufferRef(const struct v4l2_buffer& v4l2_buffer, - base::WeakPtr<V4L2Queue> queue); - friend class V4L2BufferRefFactory; - - std::unique_ptr<V4L2BufferRefBase> buffer_data_; - - SEQUENCE_CHECKER(sequence_checker_); - DISALLOW_COPY_AND_ASSIGN(V4L2WritableBufferRef); +public: + V4L2WritableBufferRef(V4L2WritableBufferRef&& other); + V4L2WritableBufferRef() = delete; + V4L2WritableBufferRef& operator=(V4L2WritableBufferRef&& other); + + // Return the memory type of the buffer. Useful to e.g. decide which Queue() method to use. + enum v4l2_memory memory() const; + + // Queue a MMAP buffer. If successful, true is returned and the reference to the buffer is + // dropped so this reference becomes invalid. In case of error, false is returned and the buffer + // is returned to the free list. + bool queueMMap() &&; + // Queue a USERPTR buffer, assigning |ptrs| as pointer for each plane. The size of |ptrs| must + // be equal to the number of planes of this buffer. If successful, true is returned and the + // reference to the buffer is dropped so this reference becomes invalid. In case of error, false + // is returned and the buffer is returned to the free list. + bool queueUserPtr(const std::vector<void*>& ptrs) &&; + // Queue a DMABUF buffer, assigning |fds| as file descriptors for each plane. It is allowed the + // number of |fds| might be greater than the number of planes of this buffer. It happens when + // the v4l2 pixel format is single planar. The fd of the first plane is only used in that case. + // If successful, true is returned and the reference to the buffer is dropped so this reference + // becomes invalid. In case of error, false is returned and the buffer is returned to the free + // list. + bool queueDMABuf(const std::vector<int>& fds) &&; + + // Returns the number of planes in this buffer. + size_t planesCount() const; + // Returns the size of the requested |plane|, in bytes. + size_t getPlaneSize(const size_t plane) const; + // Set the size of the requested |plane|, in bytes. It is only valid for USERPTR and DMABUF + // buffers. When using an MMAP buffer, this method triggers an assert and is a no-op for release + // builds. + void setPlaneSize(const size_t plane, const size_t size); + // This method can only be used with MMAP buffers. It will return a pointer to the data of the + // |plane|th plane. In case of error (invalid plane index or mapping failed), a nullptr is + // returned. + void* getPlaneMapping(const size_t plane); + // Set the timestamp field for this buffer. + void setTimeStamp(const struct timeval& timestamp); + // Return the previously-set timestamp field for this buffer. + const struct timeval& getTimeStamp() const; + // Set the number of bytes used for |plane|. + void setPlaneBytesUsed(const size_t plane, const size_t bytesUsed); + // Returns the previously-set number of bytes used for |plane|. + size_t getPlaneBytesUsed(const size_t plane) const; + // Set the data offset for |plane|, in bytes. + void setPlaneDataOffset(const size_t plane, const size_t dataOffset); + + // Return the V4L2 buffer ID of the underlying buffer. + size_t bufferId() const; + + ~V4L2WritableBufferRef(); + +private: + friend class V4L2BufferRefFactory; + + // Do the actual queue operation once the v4l2_buffer structure is properly filled. + bool doQueue() &&; + + V4L2WritableBufferRef(const struct v4l2_buffer& v4l2Buffer, base::WeakPtr<V4L2Queue> queue); + + V4L2WritableBufferRef(const V4L2WritableBufferRef&) = delete; + V4L2WritableBufferRef& operator=(const V4L2WritableBufferRef&) = delete; + + std::unique_ptr<V4L2BufferRefBase> mBufferData; + + SEQUENCE_CHECKER(mSequenceChecker); }; // A reference to a read-only, dequeued buffer. // -// Clients use this class to query the buffer state and content, and are -// guaranteed that the buffer will not be reused until all references are -// destroyed. -// All methods of this class must be called from the same sequence, but -// instances of V4L2ReadableBuffer objects can be destroyed from any sequence. -// They can even outlive the V4L2 buffers they originate from. This flexibility -// is required because V4L2ReadableBufferRefs can be embedded into VideoFrames, -// which are then passed to other threads and not necessarily destroyed before -// the V4L2Queue buffers are freed. -class V4L2ReadableBuffer - : public base::RefCountedThreadSafe<V4L2ReadableBuffer> { - public: - // Returns whether the V4L2_BUF_FLAG_LAST flag is set for this buffer. - bool IsLast() const; - // Returns whether the V4L2_BUF_FLAG_KEYFRAME flag is set for this buffer. - bool IsKeyframe() const; - // Return the timestamp set by the driver on this buffer. - struct timeval GetTimeStamp() const; - // Returns the number of planes in this buffer. - size_t PlanesCount() const; - // Returns the number of bytes used for |plane|. - size_t GetPlaneBytesUsed(size_t plane) const; - // Returns the data offset for |plane|. - size_t GetPlaneDataOffset(size_t plane) const; - // This method can only be used with MMAP buffers. - // It will return a pointer to the data of the |plane|th plane. - // In case of error (invalid plane index or mapping failed), a nullptr is - // returned. - const void* GetPlaneMapping(const size_t plane) const; - - // Return the V4L2 buffer ID of the underlying buffer. - // TODO(acourbot) This is used for legacy clients but should be ultimately - // removed. See crbug/879971 - size_t BufferId() const; - - private: - friend class V4L2BufferRefFactory; - friend class base::RefCountedThreadSafe<V4L2ReadableBuffer>; - - ~V4L2ReadableBuffer(); - - V4L2ReadableBuffer(const struct v4l2_buffer& v4l2_buffer, - base::WeakPtr<V4L2Queue> queue); - - std::unique_ptr<V4L2BufferRefBase> buffer_data_; - - SEQUENCE_CHECKER(sequence_checker_); - DISALLOW_COPY_AND_ASSIGN(V4L2ReadableBuffer); +// Clients use this class to query the buffer state and content, and are guaranteed that the buffer +// will not be reused until all references are destroyed. +// All methods of this class must be called from the same sequence, but instances of +// V4L2ReadableBuffer objects can be destroyed from any sequence. They can even outlive the V4L2 +// buffers they originate from. This flexibility is required because V4L2ReadableBufferRefs can be +// embedded into VideoFrames, which are then passed to other threads and not necessarily destroyed +// before the V4L2Queue buffers are freed. +class V4L2ReadableBuffer : public base::RefCountedThreadSafe<V4L2ReadableBuffer> { +public: + // Returns whether the V4L2_BUF_FLAG_LAST flag is set for this buffer. + bool isLast() const; + // Returns whether the V4L2_BUF_FLAG_KEYFRAME flag is set for this buffer. + bool isKeyframe() const; + // Return the timestamp set by the driver on this buffer. + struct timeval getTimeStamp() const; + // Returns the number of planes in this buffer. + size_t planesCount() const; + // Returns the number of bytes used for |plane|. + size_t getPlaneBytesUsed(size_t plane) const; + // Returns the data offset for |plane|. + size_t getPlaneDataOffset(size_t plane) const; + // This method can only be used with MMAP buffers. It will return a pointer to the data of the + // |plane|th plane. In case of error (invalid plane index or mapping failed), a nullptr is + // returned. + const void* getPlaneMapping(const size_t plane) const; + + // Return the V4L2 buffer ID of the underlying buffer. + size_t bufferId() const; + +private: + friend class V4L2BufferRefFactory; + friend class base::RefCountedThreadSafe<V4L2ReadableBuffer>; + + ~V4L2ReadableBuffer(); + + V4L2ReadableBuffer(const struct v4l2_buffer& v4l2Buffer, base::WeakPtr<V4L2Queue> queue); + + V4L2ReadableBuffer(const V4L2ReadableBuffer&) = delete; + V4L2ReadableBuffer& operator=(const V4L2ReadableBuffer&) = delete; + + std::unique_ptr<V4L2BufferRefBase> mBufferData; + + SEQUENCE_CHECKER(mSequenceChecker); }; // Shortcut for naming consistency. @@ -209,389 +172,335 @@ using V4L2ReadableBufferRef = scoped_refptr<V4L2ReadableBuffer>; class V4L2Device; class V4L2Buffer; -// Interface representing a specific queue of a |V4L2Device|. It provides free -// and queued buffer management that is commonly required by clients. +// Interface representing a specific queue of a |V4L2Device|. It provides free and queued buffer +// management that is commonly required by clients. // // Buffers managed by this class undergo the following cycle: -// 1) Allocated buffers are put into a free buffers pool, indicating that they -// are used neither by the client nor the hardware. -// 2) The client obtains a unique, writable reference to one of the free -// buffers in order to set its content and other parameters. -// 3) The client then queues the buffer obtained in 2), which invalidates its -// reference. The buffer is now prepared to be processed by the hardware. -// 4) Once the hardware is done with the buffer, it is ready to be dequeued by -// the client. The client obtains a read-only, counted reference to the -// buffer and can read its content and metadata, as well as making other -// references to it. The buffer will not be reused until all the references -// are dropped. Once this happens, the buffer goes back to the free list -// described in 1). +// 1) Allocated buffers are put into a free buffers pool, indicating that they are used neither by +// the client nor the hardware. +// 2) The client obtains a unique, writable reference to one of the free buffers in order to set +// its content and other parameters. +// 3) The client then queues the buffer obtained in 2), which invalidates its reference. The buffer +// is now prepared to be processed by the hardware. +// 4) Once the hardware is done with the buffer, it is ready to be dequeued by the client. The +// client obtains a read-only, counted reference to the buffer and can read its content and +// metadata, as well as making other references to it. The buffer will not be reused until all +// the references are dropped. Once this happens, the buffer goes back to the free list described +// in 1). class V4L2Queue : public base::RefCountedThreadSafe<V4L2Queue> { - public: - // Set |fourcc| as the current format on this queue. |size| corresponds to the - // desired buffer's dimensions (i.e. width and height members of - // v4l2_pix_format_mplane (if not applicable, pass Size()). - // |buffer_size| is the desired size in bytes of the buffer for single-planar - // formats (i.e. sizeimage of the first plane). It can be set to 0 if not - // relevant for the desired format. - // |stride| is the desired stride in bytes of the buffer (i.e. bytesperline). - // It can be set to 0 if not relevant or to let the driver decide. - // If the format could be set, then the |v4l2_format| reflecting the actual - // format is returned. It is guaranteed to feature the specified |fourcc|, - // but any other parameter (including |size| and |buffer_size| may have been - // adjusted by the driver, so the caller must check their values. - base::Optional<struct v4l2_format> SetFormat(uint32_t fourcc, - const Size& size, - size_t buffer_size, - uint32_t stride = 0) - WARN_UNUSED_RESULT; - - // Identical to |SetFormat|, but does not actually apply the format, and can - // be called anytime. - // Returns an adjusted V4L2 format if |fourcc| is supported by the queue, or - // |nullopt| if |fourcc| is not supported or an ioctl error happened. - base::Optional<struct v4l2_format> TryFormat(uint32_t fourcc, - const Size& size, - size_t buffer_size) - WARN_UNUSED_RESULT; - - // Returns the currently set format on the queue. The result is returned as - // a std::pair where the first member is the format, or base::nullopt if the - // format could not be obtained due to an ioctl error. The second member is - // only used in case of an error and contains the |errno| set by the failing - // ioctl. If the first member is not base::nullopt, the second member will - // always be zero. - // - // If the second member is 0, then the first member is guaranteed to have - // a valid value. So clients that are not interested in the precise error - // message can just check that the first member is valid and go on. - // - // This pair is used because not all failures to get the format are - // necessarily errors, so we need to way to let the use decide whether it - // is one or not. - std::pair<base::Optional<struct v4l2_format>, int> GetFormat(); - - // Allocate |count| buffers for the current format of this queue, with a - // specific |memory| allocation, and returns the number of buffers allocated - // or zero if an error occurred, or if references to any previously allocated - // buffers are still held by any clients. - // - // The number of allocated buffers may be larger than the number requested, so - // callers must always check the return value. - // - // Calling this method while buffers are still allocated results in an error. - size_t AllocateBuffers(size_t count, - enum v4l2_memory memory) WARN_UNUSED_RESULT; - - // Deallocate all buffers previously allocated by |AllocateBuffers|. Any - // references to buffers previously allocated held by the client must be - // released, or this call will fail. - bool DeallocateBuffers(); - - // Returns the memory usage of v4l2 buffers owned by this V4L2Queue which are - // mapped in user space memory. - size_t GetMemoryUsage() const; - - // Returns |memory_|, memory type of last buffers allocated by this V4L2Queue. - v4l2_memory GetMemoryType() const; - - // Return a reference to a free buffer for the caller to prepare and submit, - // or nullopt if no buffer is currently free. - // - // If the caller discards the returned reference, the underlying buffer is - // made available to clients again. - base::Optional<V4L2WritableBufferRef> GetFreeBuffer(); - base::Optional<V4L2WritableBufferRef> GetFreeBuffer( - size_t requested_buffer_id); - - // Attempt to dequeue a buffer, and return a reference to it if one was - // available. - // - // The first element of the returned pair will be false if an error occurred, - // in which case the second element will be nullptr. If no error occurred, - // then the first element will be true and the second element will contain a - // reference to the dequeued buffer if one was available, or nullptr - // otherwise. - // Dequeued buffers will not be reused by the driver until all references to - // them are dropped. - std::pair<bool, V4L2ReadableBufferRef> DequeueBuffer(); - - // Returns true if this queue is currently streaming. - bool IsStreaming() const; - // If not currently streaming, starts streaming. Returns true if we started - // streaming, or were already streaming, or false if we were not streaming - // and an error occurred when attempting to start the stream. On failure, any - // previously-queued buffers will be dequeued without processing and made - // available to the client, while any buffers held by the client will remain - // unchanged and their ownership will remain with the client. - bool Streamon(); - // If currently streaming, stops streaming. Also make all queued buffers - // available to the client again regardless of the streaming state. - // If an error occurred while attempting to stop streaming, then false is - // returned and queued buffers are left untouched since the V4L2 queue may - // still be using them. - bool Streamoff(); - - // Returns the number of buffers currently allocated for this queue. - size_t AllocatedBuffersCount() const; - // Returns the number of currently free buffers on this queue. - size_t FreeBuffersCount() const; - // Returns the number of buffers currently queued on this queue. - size_t QueuedBuffersCount() const; - - private: - ~V4L2Queue(); - - // Called when clients request a buffer to be queued. - bool QueueBuffer(struct v4l2_buffer* v4l2_buffer); - - const enum v4l2_buf_type type_; - enum v4l2_memory memory_ = V4L2_MEMORY_MMAP; - bool is_streaming_ = false; - size_t planes_count_ = 0; - // Current format as set by SetFormat. - base::Optional<struct v4l2_format> current_format_; - - std::vector<std::unique_ptr<V4L2Buffer>> buffers_; - - // Buffers that are available for client to get and submit. - // Buffers in this list are not referenced by anyone else than ourselves. - scoped_refptr<V4L2BuffersList> free_buffers_; - // Buffers that have been queued by the client, and not dequeued yet. - std::set<size_t> queued_buffers_; - - scoped_refptr<V4L2Device> device_; - // Callback to call in this queue's destructor. - base::OnceClosure destroy_cb_; - - V4L2Queue(scoped_refptr<V4L2Device> dev, - enum v4l2_buf_type type, - base::OnceClosure destroy_cb); - friend class V4L2QueueFactory; - friend class V4L2BufferRefBase; - friend class base::RefCountedThreadSafe<V4L2Queue>; - - SEQUENCE_CHECKER(sequence_checker_); - - base::WeakPtrFactory<V4L2Queue> weak_this_factory_; - - DISALLOW_COPY_AND_ASSIGN(V4L2Queue); +public: + // Set |fourcc| as the current format on this queue. |size| corresponds to the desired buffer's + // dimensions (i.e. width and height members of v4l2_pix_format_mplane (if not applicable, pass + // Size()). + // |bufferSize| is the desired size in bytes of the buffer for single-planar formats (i.e. + // sizeimage of the first plane). It can be set to 0 if not relevant for the desired format. + // |stride| is the desired stride in bytes of the buffer (i.e. bytesperline). It can be set to 0 + // if not relevant or to let the driver decide. If the format could be set, then the + // |v4l2_format| reflecting the actual format is returned. It is guaranteed to feature the + // specified |fourcc|, but any other parameter (including |size| and |bufferSize| may have been + // adjusted by the driver, so the caller must check their values. + std::optional<struct v4l2_format> setFormat(uint32_t fourcc, const media::Size& size, + size_t bufferSize, + uint32_t stride = 0) WARN_UNUSED_RESULT; + + // Identical to |setFormat|, but does not actually apply the format, and can be called anytime. + // Returns an adjusted V4L2 format if |fourcc| is supported by the queue, or |nullopt| if + // |fourcc| is not supported or an ioctl error happened. + std::optional<struct v4l2_format> tryFormat(uint32_t fourcc, const media::Size& size, + size_t bufferSize) WARN_UNUSED_RESULT; + + // Returns the currently set format on the queue. The result is returned as a std::pair where + // the first member is the format, or base::nullopt if the format could not be obtained due to + // an ioctl error. The second member is only used in case of an error and contains the |errno| + // set by the failing ioctl. If the first member is not base::nullopt, the second member will + // always be zero. + // + // If the second member is 0, then the first member is guaranteed to have a valid value. So + // clients that are not interested in the precise error message can just check that the first + // member is valid and go on. + // + // This pair is used because not all failures to get the format are necessarily errors, so we + // need to way to let the use decide whether it is one or not. + std::pair<std::optional<struct v4l2_format>, int> getFormat(); + + // Allocate |count| buffers for the current format of this queue, with a specific |memory| + // allocation, and returns the number of buffers allocated or zero if an error occurred, or if + // references to any previously allocated buffers are still held by any clients. + // + // The number of allocated buffers may be larger than the number requested, so callers must + // always check the return value. + // + // Calling this method while buffers are still allocated results in an error. + size_t allocateBuffers(size_t count, enum v4l2_memory memory) WARN_UNUSED_RESULT; + + // Deallocate all buffers previously allocated by |allocateBuffers|. Any references to buffers + // previously allocated held by the client must be released, or this call will fail. + bool deallocateBuffers(); + + // Returns the memory usage of v4l2 buffers owned by this V4L2Queue which are mapped in user + // space memory. + size_t getMemoryUsage() const; + + // Returns |mMemory|, memory type of last buffers allocated by this V4L2Queue. + v4l2_memory getMemoryType() const; + + // Return a reference to a free buffer for the caller to prepare and submit, or nullopt if no + // buffer is currently free. + // + // If the caller discards the returned reference, the underlying buffer is made available to + // clients again. + std::optional<V4L2WritableBufferRef> getFreeBuffer(); + std::optional<V4L2WritableBufferRef> getFreeBuffer(size_t requestedBufferId); + + // Attempt to dequeue a buffer, and return a reference to it if one was available. + // + // The first element of the returned pair will be false if an error occurred, in which case the + // second element will be nullptr. If no error occurred, then the first element will be true and + // the second element will contain a reference to the dequeued buffer if one was available, or + // nullptr otherwise. Dequeued buffers will not be reused by the driver until all references to + // them are dropped. + std::pair<bool, V4L2ReadableBufferRef> dequeueBuffer(); + + // Returns true if this queue is currently streaming. + bool isStreaming() const; + // If not currently streaming, starts streaming. Returns true if we started streaming, or were + // already streaming, or false if we were not streaming and an error occurred when attempting to + // start the stream. On failure, any previously-queued buffers will be dequeued without + // processing and made available to the client, while any buffers held by the client will remain + // unchanged and their ownership will remain with the client. + bool streamon(); + // If currently streaming, stops streaming. Also make all queued buffers available to the client + // again regardless of the streaming state. If an error occurred while attempting to stop + // streaming, then false is returned and queued buffers are left untouched since the V4L2 queue + // may still be using them. + bool streamoff(); + + // Returns the number of buffers currently allocated for this queue. + size_t allocatedBuffersCount() const; + // Returns the number of currently free buffers on this queue. + size_t freeBuffersCount() const; + // Returns the number of buffers currently queued on this queue. + size_t queuedBuffersCount() const; + +private: + ~V4L2Queue(); + + V4L2Queue(const V4L2Queue&) = delete; + V4L2Queue& operator=(const V4L2Queue&) = delete; + + // Called when clients request a buffer to be queued. + bool queueBuffer(struct v4l2_buffer* v4l2Buffer); + + const enum v4l2_buf_type mType; + enum v4l2_memory mMemory = V4L2_MEMORY_MMAP; + bool mIsStreaming = false; + size_t mPlanesCount = 0; + // Current format as set by SetFormat. + std::optional<struct v4l2_format> mCurrentFormat; + + std::vector<std::unique_ptr<V4L2Buffer>> mBuffers; + + // Buffers that are available for client to get and submit. Buffers in this list are not + // referenced by anyone else than ourselves. + scoped_refptr<V4L2BuffersList> mFreeBuffers; + // Buffers that have been queued by the client, and not dequeued yet. + std::set<size_t> mQueuedBuffers; + + scoped_refptr<V4L2Device> mDevice; + // Callback to call in this queue's destructor. + base::OnceClosure mDestroyCb; + + V4L2Queue(scoped_refptr<V4L2Device> dev, enum v4l2_buf_type type, base::OnceClosure destroyCb); + friend class V4L2QueueFactory; + friend class V4L2BufferRefBase; + friend class base::RefCountedThreadSafe<V4L2Queue>; + + SEQUENCE_CHECKER(mSequenceChecker); + + base::WeakPtrFactory<V4L2Queue> mWeakThisFactory{this}; }; class V4L2Device : public base::RefCountedThreadSafe<V4L2Device> { - public: - // Utility format conversion functions - // If there is no corresponding single- or multi-planar format, returns 0. - static uint32_t VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile, - bool slice_based); - static VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec, - uint32_t profile); - std::vector<VideoCodecProfile> V4L2PixFmtToVideoCodecProfiles( - uint32_t pix_fmt, - bool is_encoder); - // Calculates the largest plane's allocation size requested by a V4L2 device. - static Size AllocatedSizeFromV4L2Format(const struct v4l2_format& format); - - // Convert required H264 profile and level to V4L2 enums. - static int32_t VideoCodecProfileToV4L2H264Profile(VideoCodecProfile profile); - static int32_t H264LevelIdcToV4L2H264Level(uint8_t level_idc); - - // Converts v4l2_memory to a string. - static const char* V4L2MemoryToString(const v4l2_memory memory); - - // Returns the printable name of a v4l2_buf_type. - static const char* V4L2BufferTypeToString(const enum v4l2_buf_type buf_type); - - // Composes human readable string of v4l2_format. - static std::string V4L2FormatToString(const struct v4l2_format& format); - - // Composes human readable string of v4l2_buffer. - static std::string V4L2BufferToString(const struct v4l2_buffer& buffer); - - // Composes VideoFrameLayout based on v4l2_format. - // If error occurs, it returns base::nullopt. - static base::Optional<VideoFrameLayout> V4L2FormatToVideoFrameLayout( - const struct v4l2_format& format); - - // Returns number of planes of |pix_fmt|. - static size_t GetNumPlanesOfV4L2PixFmt(uint32_t pix_fmt); - - enum class Type { - kDecoder, - kEncoder, - }; - - // Create and initialize an appropriate V4L2Device instance for the current - // platform, or return nullptr if not available. - static scoped_refptr<V4L2Device> Create(); - - // Open a V4L2 device of |type| for use with |v4l2_pixfmt|. - // Return true on success. - // The device will be closed in the destructor. - bool Open(Type type, uint32_t v4l2_pixfmt); - - // Returns the V4L2Queue corresponding to the requested |type|, or nullptr - // if the requested queue type is not supported. - scoped_refptr<V4L2Queue> GetQueue(enum v4l2_buf_type type); - - // Parameters and return value are the same as for the standard ioctl() system - // call. - int Ioctl(int request, void* arg); - - // This method sleeps until either: - // - SetDevicePollInterrupt() is called (on another thread), - // - |poll_device| is true, and there is new data to be read from the device, - // or an event from the device has arrived; in the latter case - // |*event_pending| will be set to true. - // Returns false on error, true otherwise. - // This method should be called from a separate thread. - bool Poll(bool poll_device, bool* event_pending); - - // These methods are used to interrupt the thread sleeping on Poll() and force - // it to return regardless of device state, which is usually when the client - // is no longer interested in what happens with the device (on cleanup, - // client state change, etc.). When SetDevicePollInterrupt() is called, Poll() - // will return immediately, and any subsequent calls to it will also do so - // until ClearDevicePollInterrupt() is called. - bool SetDevicePollInterrupt(); - bool ClearDevicePollInterrupt(); - - // Wrappers for standard mmap/munmap system calls. - void* Mmap(void* addr, - unsigned int len, - int prot, - int flags, - unsigned int offset); - void Munmap(void* addr, unsigned int len); - - // Return a vector of dmabuf file descriptors, exported for V4L2 buffer with - // |index|, assuming the buffer contains |num_planes| V4L2 planes and is of - // |type|. Return an empty vector on failure. - // The caller is responsible for closing the file descriptors after use. - std::vector<base::ScopedFD> GetDmabufsForV4L2Buffer( - int index, - size_t num_planes, - enum v4l2_buf_type type); - - // Returns the preferred V4L2 input formats for |type| or empty if none. - std::vector<uint32_t> PreferredInputFormat(Type type); - - // NOTE: The below methods to query capabilities have a side effect of - // closing the previously-open device, if any, and should not be called after - // Open(). - // TODO(posciak): fix this. - - // Get minimum and maximum resolution for fourcc |pixelformat| and store to - // |min_resolution| and |max_resolution|. - void GetSupportedResolution(uint32_t pixelformat, - Size* min_resolution, - Size* max_resolution); - - std::vector<uint32_t> EnumerateSupportedPixelformats(v4l2_buf_type buf_type); - - // Return supported profiles for decoder, including only profiles for given - // fourcc |pixelformats|. - VideoDecodeAccelerator::SupportedProfiles GetSupportedDecodeProfiles( - const size_t num_formats, - const uint32_t pixelformats[]); - - // Return supported profiles for encoder. - VideoEncodeAccelerator::SupportedProfiles - GetSupportedEncodeProfiles(); - - // Start polling on this V4L2Device. |event_callback| will be posted to - // the caller's sequence if a buffer is ready to be dequeued and/or a V4L2 - // event has been posted. |error_callback| will be posted to the client's - // sequence if a polling error has occurred. - bool StartPolling(V4L2DevicePoller::EventCallback event_callback, - base::RepeatingClosure error_callback); - // Stop polling this V4L2Device if polling was active. No new events will - // be posted after this method has returned. - bool StopPolling(); - // Schedule a polling event if polling is enabled. This method is intended - // to be called from V4L2Queue, clients should not need to call it directly. - void SchedulePoll(); - - // Check whether the V4L2 control with specified |ctrl_id| is supported. - bool IsCtrlExposed(uint32_t ctrl_id); - // Set the specified list of |ctrls| for the specified |ctrl_class|, returns - // whether the operation succeeded. - bool SetExtCtrls(uint32_t ctrl_class, std::vector<V4L2ExtCtrl> ctrls); - - // Check whether the V4L2 command with specified |command_id| is supported. - bool IsCommandSupported(uint32_t command_id); - // Check whether the V4L2 device has the specified |capabilities|. - bool HasCapabilities(uint32_t capabilities); - - private: - // Vector of video device node paths and corresponding pixelformats supported - // by each device node. - using Devices = std::vector<std::pair<std::string, std::vector<uint32_t>>>; - - friend class base::RefCountedThreadSafe<V4L2Device>; - V4L2Device(); - ~V4L2Device(); - - VideoDecodeAccelerator::SupportedProfiles EnumerateSupportedDecodeProfiles( - const size_t num_formats, - const uint32_t pixelformats[]); - - VideoEncodeAccelerator::SupportedProfiles EnumerateSupportedEncodeProfiles(); - - // Perform platform-specific initialization of the device instance. - // Return true on success, false on error or if the particular implementation - // is not available. - bool Initialize(); - - // Open device node for |path| as a device of |type|. - bool OpenDevicePath(const std::string& path, Type type); - - // Close the currently open device. - void CloseDevice(); - - // Enumerate all V4L2 devices on the system for |type| and store the results - // under devices_by_type_[type]. - void EnumerateDevicesForType(V4L2Device::Type type); - - // Return device information for all devices of |type| available in the - // system. Enumerates and queries devices on first run and caches the results - // for subsequent calls. - const Devices& GetDevicesForType(V4L2Device::Type type); - - // Return device node path for device of |type| supporting |pixfmt|, or - // an empty string if the given combination is not supported by the system. - std::string GetDevicePathFor(V4L2Device::Type type, uint32_t pixfmt); - - // Callback that is called upon a queue's destruction, to cleanup its pointer - // in queues_. - void OnQueueDestroyed(v4l2_buf_type buf_type); - - // Lazily initialize static data after sandbox is enabled. Return false on - // init failure. - static bool PostSandboxInitialization(); - - // Stores information for all devices available on the system - // for each device Type. - std::map<V4L2Device::Type, Devices> devices_by_type_; - - // The actual device fd. - base::ScopedFD device_fd_; - - // eventfd fd to signal device poll thread when its poll() should be - // interrupted. - base::ScopedFD device_poll_interrupt_fd_; - - // Associates a v4l2_buf_type to its queue. - base::flat_map<enum v4l2_buf_type, V4L2Queue*> queues_; - - // Used if EnablePolling() is called to signal the user that an event - // happened or a buffer is ready to be dequeued. - std::unique_ptr<V4L2DevicePoller> device_poller_; - - DISALLOW_COPY_AND_ASSIGN(V4L2Device); - - SEQUENCE_CHECKER(client_sequence_checker_); +public: + // Utility format conversion functions + // If there is no corresponding single- or multi-planar format, returns 0. + static uint32_t videoCodecProfileToV4L2PixFmt(media::VideoCodecProfile profile, + bool sliceBased); + static media::VideoCodecProfile v4L2ProfileToVideoCodecProfile(media::VideoCodec codec, + uint32_t profile); + std::vector<media::VideoCodecProfile> v4L2PixFmtToVideoCodecProfiles(uint32_t pixFmt, + bool isEncoder); + // Calculates the largest plane's allocation size requested by a V4L2 device. + static media::Size allocatedSizeFromV4L2Format(const struct v4l2_format& format); + + // Convert required H264 profile and level to V4L2 enums. + static int32_t videoCodecProfileToV4L2H264Profile(media::VideoCodecProfile profile); + static int32_t h264LevelIdcToV4L2H264Level(uint8_t levelIdc); + + // Converts v4l2_memory to a string. + static const char* v4L2MemoryToString(const v4l2_memory memory); + + // Returns the printable name of a v4l2_buf_type. + static const char* v4L2BufferTypeToString(const enum v4l2_buf_type bufType); + + // Composes human readable string of v4l2_format. + static std::string v4L2FormatToString(const struct v4l2_format& format); + + // Composes human readable string of v4l2_buffer. + static std::string v4L2BufferToString(const struct v4l2_buffer& buffer); + + // Composes VideoFrameLayout based on v4l2_format. + // If error occurs, it returns base::nullopt. + static std::optional<media::VideoFrameLayout> v4L2FormatToVideoFrameLayout( + const struct v4l2_format& format); + + // Returns number of planes of |pixFmt|. + static size_t getNumPlanesOfV4L2PixFmt(uint32_t pixFmt); + + enum class Type { kDecoder, kEncoder }; + + // Create and initialize an appropriate V4L2Device instance for the current platform, or return + // nullptr if not available. + static scoped_refptr<V4L2Device> create(); + + // Open a V4L2 device of |type| for use with |v4l2PixFmt|. Return true on success. The device + // will be closed in the destructor. + bool open(Type type, uint32_t v4l2PixFmt); + + // Returns the V4L2Queue corresponding to the requested |type|, or nullptr if the requested + // queue type is not supported. + scoped_refptr<V4L2Queue> getQueue(enum v4l2_buf_type type); + + // Parameters and return value are the same as for the standard ioctl() system call. + int ioctl(int request, void* arg); + + // This method sleeps until either: + // - SetDevicePollInterrupt() is called (on another thread), + // - |pollDevice| is true, and there is new data to be read from the device, + // or an event from the device has arrived; in the latter case + // |*eventPending| will be set to true. + // Returns false on error, true otherwise. This method should be called from a separate thread. + bool poll(bool pollDevice, bool* eventPending); + + // These methods are used to interrupt the thread sleeping on poll() and force it to return + // regardless of device state, which is usually when the client is no longer interested in what + // happens with the device (on cleanup, client state change, etc.). When + // setDevicePollInterrupt() is called, poll() will return immediately, and any subsequent calls + // to it will also do so until clearDevicePollInterrupt() is called. + bool setDevicePollInterrupt(); + bool clearDevicePollInterrupt(); + + // Wrappers for standard mmap/munmap system calls. + void* mmap(void* addr, unsigned int len, int prot, int flags, unsigned int offset); + void munmap(void* addr, unsigned int len); + + // Return a vector of dmabuf file descriptors, exported for V4L2 buffer with |index|, assuming + // the buffer contains |numPlanes| V4L2 planes and is of |bufType|. Return an empty vector on + // failure. The caller is responsible for closing the file descriptors after use. + std::vector<base::ScopedFD> getDmabufsForV4L2Buffer(int index, size_t numPlanes, + enum v4l2_buf_type bufType); + + // Returns the preferred V4L2 input formats for |type| or empty if none. + std::vector<uint32_t> preferredInputFormat(Type type); + + // NOTE: The below methods to query capabilities have a side effect of closing the + // previously-open device, if any, and should not be called after Open(). + + // Get minimum and maximum resolution for fourcc |pixelFormat| and store to |minResolution| and + // |maxResolution|. + void getSupportedResolution(uint32_t pixelFormat, media::Size* minResolution, + media::Size* maxResolution); + + std::vector<uint32_t> enumerateSupportedPixelformats(v4l2_buf_type bufType); + + // Return supported profiles for decoder, including only profiles for given fourcc + // |pixelFormats|. + media::VideoDecodeAccelerator::SupportedProfiles getSupportedDecodeProfiles( + const size_t numFormats, const uint32_t pixelFormats[]); + + // Return supported profiles for encoder. + media::VideoEncodeAccelerator::SupportedProfiles getSupportedEncodeProfiles(); + + // Start polling on this V4L2Device. |eventCallback| will be posted to the caller's sequence if + // a buffer is ready to be dequeued and/or a V4L2 event has been posted. |errorCallback| will + // be posted to the client's + // sequence if a polling error has occurred. + bool startPolling(android::V4L2DevicePoller::EventCallback eventCallback, + base::RepeatingClosure errorCallback); + // Stop polling this V4L2Device if polling was active. No new events will be posted after this + // method has returned. + bool stopPolling(); + // Schedule a polling event if polling is enabled. This method is intended to be called from + // V4L2Queue, clients should not need to call it directly. + void schedulePoll(); + + // Check whether the V4L2 control with specified |ctrlId| is supported. + bool isCtrlExposed(uint32_t ctrlId); + // Set the specified list of |ctrls| for the specified |ctrlClass|, returns whether the + // operation succeeded. + bool setExtCtrls(uint32_t ctrlClass, std::vector<V4L2ExtCtrl> ctrls); + + // Check whether the V4L2 command with specified |commandId| is supported. + bool isCommandSupported(uint32_t commandId); + // Check whether the V4L2 device has the specified |capabilities|. + bool hasCapabilities(uint32_t capabilities); + +private: + // Vector of video device node paths and corresponding pixelformats supported by each device node. + using Devices = std::vector<std::pair<std::string, std::vector<uint32_t>>>; + + friend class base::RefCountedThreadSafe<V4L2Device>; + V4L2Device(); + ~V4L2Device(); + + V4L2Device(const V4L2Device&) = delete; + V4L2Device& operator=(const V4L2Device&) = delete; + + media::VideoDecodeAccelerator::SupportedProfiles enumerateSupportedDecodeProfiles( + const size_t numFormats, const uint32_t pixelFormats[]); + + media::VideoEncodeAccelerator::SupportedProfiles enumerateSupportedEncodeProfiles(); + + // Open device node for |path| as a device of |type|. + bool openDevicePath(const std::string& path, Type type); + + // Close the currently open device. + void closeDevice(); + + // Enumerate all V4L2 devices on the system for |type| and store the results under + // mDevicesByType[type]. + void enumerateDevicesForType(V4L2Device::Type type); + + // Return device information for all devices of |type| available in the system. Enumerates and + // queries devices on first run and caches the results for subsequent calls. + const Devices& getDevicesForType(V4L2Device::Type type); + + // Return device node path for device of |type| supporting |pixFmt|, or an empty string if the + // given combination is not supported by the system. + std::string getDevicePathFor(V4L2Device::Type type, uint32_t pixFmt); + + // Callback that is called upon a queue's destruction, to cleanup its pointer in mQueues. + void onQueueDestroyed(v4l2_buf_type buf_type); + + // Stores information for all devices available on the system for each device Type. + std::map<V4L2Device::Type, Devices> mDevicesByType; + + // The actual device fd. + base::ScopedFD mDeviceFd; + + // eventfd fd to signal device poll thread when its poll() should be interrupted. + base::ScopedFD mDevicePollInterruptFd; + + // Associates a v4l2_buf_type to its queue. + base::flat_map<enum v4l2_buf_type, V4L2Queue*> mQueues; + + // Used if EnablePolling() is called to signal the user that an event happened or a buffer is + // ready to be dequeued. + std::unique_ptr<android::V4L2DevicePoller> mDevicePoller; + + SEQUENCE_CHECKER(mClientSequenceChecker); }; -} // namespace media +} // namespace android -#endif // V4L2_DEVICE_H_ +#endif // ANDROID_V4L2_CODEC2_COMMON_V4L2_DEVICE_H diff --git a/common/include/v4l2_codec2/common/V4L2DevicePoller.h b/common/include/v4l2_codec2/common/V4L2DevicePoller.h index aac3d8c..ad256be 100644 --- a/common/include/v4l2_codec2/common/V4L2DevicePoller.h +++ b/common/include/v4l2_codec2/common/V4L2DevicePoller.h @@ -3,95 +3,86 @@ // found in the LICENSE file. // Note: ported from Chromium commit head: f65c38dcdac2 -#ifndef V4L2_V4L2_DEVICE_POLLER_H_ -#define V4L2_V4L2_DEVICE_POLLER_H_ +#ifndef ANDROID_V4L2_CODEC2_COMMON_V4L2_DEVICE_POLLER_H +#define ANDROID_V4L2_CODEC2_COMMON_V4L2_DEVICE_POLLER_H #include <atomic> -#include "base/callback_forward.h" -#include "base/sequence_checker.h" -#include "base/sequenced_task_runner.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" +#include <base/callback_forward.h> +#include <base/sequence_checker.h> +#include <base/sequenced_task_runner.h> +#include <base/synchronization/waitable_event.h> +#include <base/threading/thread.h> -namespace media { +namespace android { class V4L2Device; -// Allows a client to poll() on a given V4L2Device and be signaled when -// a buffer is ready to be dequeued or a V4L2 event has been received. Polling -// is done on a dedicated thread, and notifications are delivered in the form of -// a callback to the listener's sequence. +// Allows a client to poll() on a given V4L2Device and be signaled when a buffer is ready to be +// dequeued or a V4L2 event has been received. Polling is done on a dedicated thread, and +// notifications are delivered in the form of a callback to the listener's sequence. // -// All the methods of this class (with the exception of the constructor) must be -// called from the same sequence. +// All the methods of this class (with the exception of the constructor) must be called from the +// same sequence. // -// Note that the service callback may also be called when no particular event -// occurred due to the way poll() works. It is the responsibility of the caller -// to call SchedulePoll() again if there may still be pending events. +// Note that the service callback may also be called when no particular event occurred due to the +// way poll() works. It is the responsibility of the caller to call SchedulePoll() again if there +// may still be pending events. class V4L2DevicePoller { - public: - // Callback to be called when buffer ready/V4L2 event has potentially been - // polled. |event| is set if a V4L2 event has been detected. - using EventCallback = base::RepeatingCallback<void(bool event)>; +public: + // Callback to be called when buffer ready/V4L2 event has potentially been polled. |event| is + // set if a V4L2 event has been detected. + using EventCallback = base::RepeatingCallback<void(bool event)>; - // Create a poller for |device|, using a thread named |thread_name|. - // Notification won't start until |StartPolling()| is called. - V4L2DevicePoller(V4L2Device* const device, const std::string& thread_name); - ~V4L2DevicePoller(); + // Create a poller for |device|, using a thread named |threadName|. Notification won't start + // until |startPolling()| is called. + V4L2DevicePoller(V4L2Device* const device, const std::string& threadName); + ~V4L2DevicePoller(); - // Starts polling. |event_callback| will be posted on the caller's sequence - // every time an event occurs. The client is then responsible for consuming - // all pending events in that callback. If new events may still happen after - // the callback has run, the client must call |SchedulePoll()| again in order - // to be notified for them. - // - // If an error occurs during polling, |error_callback| will be posted on the - // caller's sequence. - bool StartPolling(EventCallback event_callback, - base::RepeatingClosure error_callback); - // Stop polling and stop the thread. The poller won't post any new event to - // the caller's sequence after this method has returned. - bool StopPolling(); - // Returns true if currently polling, false otherwise. - bool IsPolling() const; - // Attempts polling the V4L2 device. This method should be called whenever - // doing something that may trigger an event of interest (buffer dequeue or - // V4L2 event), for instance queueing a buffer. In the absence of a pending - // event, poll() will return immediately and the service callback will be - // posted to the caller's sequence. The client is then responsible for calling - // this method again when it is interested in receiving events. - void SchedulePoll(); + // Starts polling. |mEventCallback| will be posted on the caller's sequence every time an event + // occurs. The client is then responsible for consuming all pending events in that callback. If + // new events may still happen after the callback has run, the client must call |schedulePoll()| + // again in order to be notified for them. + // + // If an error occurs during polling, |mErrorCallback| will be posted on the caller's sequence. + bool startPolling(EventCallback eventCallback, base::RepeatingClosure errorCallback); + // Stop polling and stop the thread. The poller won't post any new event to the caller's + // sequence after this method has returned. + bool stopPolling(); + // Returns true if currently polling, false otherwise. + bool isPolling() const; + // Attempts polling the V4L2 device. This method should be called whenever doing something that + // may trigger an event of interest (buffer dequeue or V4L2 event), for instance queueing a + // buffer. In the absence of a pending event, poll() will return immediately and the service + // callback will be posted to the caller's sequence. The client is then responsible for calling + // this method again when it is interested in receiving events. + void schedulePoll(); - private: - // Perform a poll() on |device_| and post either |service_task_| or - // |error_callback_| on the client's sequence when poll() returns. - void DevicePollTask(); +private: + // Perform a poll() on |mDevice| and post either |mEventCallback| or |mErrorCallback| on the + // client's sequence when poll() returns. + void devicePollTask(); - // V4L2 device we are polling. - V4L2Device* const device_; - // Thread on which polling is done. - base::Thread poll_thread_; - // Callback to post to the client's sequence when an event occurs. - EventCallback event_callback_; - // Closure to post to the client's sequence when an error occurs. - base::RepeatingClosure error_callback_; - // Client sequence's task runner, where closures are posted. - scoped_refptr<base::SequencedTaskRunner> client_task_runner_; + // V4L2 device we are polling. + V4L2Device* const mDevice; + // Thread on which polling is done. + base::Thread mPollThread; + // Callback to post to the client's sequence when an event occurs. + EventCallback mEventCallback; + // Closure to post to the client's sequence when an error occurs. + base::RepeatingClosure mErrorCallback; + // Client sequence's task runner, where closures are posted. + scoped_refptr<base::SequencedTaskRunner> mClientTaskTunner; - // Since poll() returns immediately if no buffers have been queued, we cannot - // rely on it to pause the polling thread until an event occurs. Instead, - // the polling thread will wait on this WaitableEvent (signaled by - // |SchedulePoll| before calling poll(), so we only call it when we are - // actually waiting for an event. - base::WaitableEvent trigger_poll_; - // Set to true when we wish to stop polling, instructing the poller thread - // to break its loop. - std::atomic_bool stop_polling_; - - SEQUENCE_CHECKER(client_sequence_checker_); + // Since poll() returns immediately if no buffers have been queued, we cannot rely on it to + // pause the polling thread until an event occurs. Instead, + // the polling thread will wait on this WaitableEvent (signaled by |schedulePoll| before calling + // poll(), so we only call it when we are actually waiting for an event. + base::WaitableEvent mTriggerPoll; + // Set to true when we wish to stop polling, instructing the poller thread to break its loop. + std::atomic_bool mStopPolling; }; -} // namespace media +} // namespace android -#endif // V4L2_V4L2_DEVICE_POLLER_H_ +#endif // ANDROID_V4L2_CODEC2_COMMON_V4L2_DEVICE_POLLER_H |