// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_V4L2_V4L2_QUEUE_H_
#define MEDIA_GPU_V4L2_V4L2_QUEUE_H_
#include <linux/videodev2.h>
#include <stddef.h>
#include <stdint.h>
#include <optional>
#include <queue>
#include <vector>
#include "base/containers/small_map.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "build/build_config.h"
#include "media/base/video_codecs.h"
#include "media/base/video_decoder_config.h"
#include "media/base/video_frame.h"
#include "media/gpu/chromeos/chromeos_status.h"
#include "media/gpu/chromeos/fourcc.h"
#include "media/gpu/chromeos/frame_resource.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/v4l2/v4l2_utils.h"
#include "ui/gfx/generic_shared_memory_id.h"
#include "ui/gfx/geometry/size.h"
namespace gfx {
struct NativePixmapPlane;
} // namespace gfx
namespace media {
class V4L2Queue;
class V4L2Buffer;
class V4L2BufferRefBase;
class V4L2BuffersList;
class V4L2RequestRef;
class V4L2BufferRefFactory;
typedef struct SecureBufferData SecureBufferData;
// 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;
};
// 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.
class MEDIA_GPU_EXPORT 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.
// When requests are supported, a |request_ref| can be passed along this
// the buffer to be submitted.
// 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.
[[nodiscard]] bool QueueMMap(V4L2RequestRef* request_ref = nullptr) &&;
// 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.
// When requests are supported, a |request_ref| can be passed along this
// the buffer to be submitted.
// 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.
[[nodiscard]] bool QueueUserPtr(const std::vector<void*>& ptrs,
V4L2RequestRef* request_ref = nullptr) &&;
// 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.
// When requests are supported, a |request_ref| can be passed along this
// the buffer to be submitted.
// 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.
[[nodiscard]] bool QueueDMABuf(const std::vector<base::ScopedFD>& fds,
V4L2RequestRef* request_ref = nullptr) &&;
// Queue a DMABUF buffer, assigning file descriptors of |planes| for planes.
// It is allowed the number of |planes| 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 of |planes| is only used in that case.
// When requests are supported, a |request_ref| can be passed along this
// the buffer to be submitted.
// 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.
[[nodiscard]] bool QueueDMABuf(
const std::vector<gfx::NativePixmapPlane>& planes,
V4L2RequestRef* request_ref = nullptr) &&;
// Queues |frame_resource| using its file descriptors as DMABUFs. The
// FrameResource must use DMABUF fd-based storage. When called, this method
// keeps a reference to |frame_resource| and releases it when the buffer is
// dequeued through |V4L2ReadableBufferRef::GetFrameResource()|.
// |frame_resource| is thus guaranteed to be alive until either all the
// |V4L2ReadableBufferRef| from the dequeued buffer get out of scope, or
// |V4L2Queue::Streamoff()| is called. Usage must not be mixed with
// |QueueDMABuf(scoped_refptr<VideoFrame>)|.
[[nodiscard]] bool QueueDMABuf(scoped_refptr<FrameResource> frame_resource,
V4L2RequestRef* request_ref = nullptr) &&;
// Queue a DMABUF with the corresponding |secure_handle|. This is used during
// secure playback and the corresponding FD for the |secure_handle| will be
// resolved by the V4L2Queue.
[[nodiscard]] bool QueueDMABuf(uint64_t secure_handle,
V4L2RequestRef* request_ref) &&;
// 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 FrameResource underlying this buffer. The FrameResource's layout
// will match that of the V4L2 format. This method will *always* return the
// same FrameResource instance for a given V4L2 buffer. Moreover, the
// FrameResource instance will also be the same across V4L2WritableBufferRef
// and V4L2ReadableBufferRef if both references point to the same V4L2 buffer.
// Note: at the moment, this method is valid for MMAP buffers only. It will
// return nullptr for any other buffer type.
[[nodiscard]] scoped_refptr<FrameResource> GetFrameResource();
// 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(const V4L2WritableBufferRef&) = delete;
V4L2WritableBufferRef& operator=(const V4L2WritableBufferRef&) = delete;
~V4L2WritableBufferRef();
private:
friend class V4L2BufferRefFactory;
// DoQueue does the actual queue operation once the v4l2_buffer structure is
// properly filled. When requests are supported, a |request_ref| can be
// passed along this the buffer to be submitted.
[[nodiscard]] bool DoQueue(V4L2RequestRef* request_ref,
scoped_refptr<FrameResource> frame_resource) &&;
V4L2WritableBufferRef(const struct v4l2_buffer& v4l2_buffer,
base::WeakPtr<V4L2Queue> queue);
std::unique_ptr<V4L2BufferRefBase> buffer_data_;
SEQUENCE_CHECKER(sequence_checker_);
};
// 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 frames,
// which are then passed to other threads and not necessarily destroyed before
// the V4L2Queue buffers are freed.
class MEDIA_GPU_EXPORT V4L2ReadableBuffer
: public base::RefCountedThreadSafe<V4L2ReadableBuffer> {
public:
V4L2ReadableBuffer(const V4L2ReadableBuffer&) = delete;
V4L2ReadableBuffer& operator=(const V4L2ReadableBuffer&) = delete;
// 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;
// Returns whether the V4L2_BUF_FLAG_ERROR flag is set for this buffer.
bool IsError() 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;
// Return the FrameResource underlying this buffer. The FrameResource's layout
// will match that of the V4L2 format. This method will *always* return the
// same FrameResource instance for a given V4L2 buffer. Moreover, the
// FrameResource instance will also be the same across V4L2WritableBufferRef
// and V4L2ReadableBufferRef if both references point to the same V4L2 buffer.
// Note: at the moment, this method is valid for MMAP buffers only. It will
// return nullptr for any other buffer type.
[[nodiscard]] scoped_refptr<FrameResource> GetFrameResource();
private:
friend class V4L2BufferRefFactory;
friend class base::RefCountedThreadSafe<V4L2ReadableBuffer>;
~V4L2ReadableBuffer();
V4L2ReadableBuffer(const struct v4l2_buffer& v4l2_buffer,
base::WeakPtr<V4L2Queue> queue,
scoped_refptr<FrameResource> frame);
std::unique_ptr<V4L2BufferRefBase> buffer_data_;
// If this buffer was a DMABUF buffer queued with
// QueueDMABuf(scoped_refptr<FrameResource>), then this will hold the frame
// that was passed at the time of queueing.
scoped_refptr<FrameResource> frame_;
SEQUENCE_CHECKER(sequence_checker_);
};
// Shortcut for naming consistency.
using V4L2ReadableBufferRef = scoped_refptr<V4L2ReadableBuffer>;
class V4L2Request;
// Base class for all request related classes.
//
// This class is used to manage requests and not intended to be used
// directly.
class MEDIA_GPU_EXPORT V4L2RequestRefBase {
public:
V4L2RequestRefBase(const V4L2RequestRefBase&) = delete;
V4L2RequestRefBase& operator=(const V4L2RequestRefBase&) = delete;
protected:
V4L2RequestRefBase(V4L2RequestRefBase&& req_base);
V4L2RequestRefBase(V4L2Request* request);
~V4L2RequestRefBase();
raw_ptr<V4L2Request> request_;
SEQUENCE_CHECKER(sequence_checker_);
};
class V4L2SubmittedRequestRef;
// Interface representing a request reference.
//
// The request reference allows the client to set the controls and buffer to
// the request. It also allows to submit the request to the driver.
// Once the request as been submitted, the request reference cannot be used
// any longer.
// Instead, when a request is submitted, an object denoting a submitted request
// is returned.
class MEDIA_GPU_EXPORT V4L2RequestRef : public V4L2RequestRefBase {
public:
V4L2RequestRef(V4L2RequestRef&& req_ref)
: V4L2RequestRefBase(std::move(req_ref)) {}
V4L2RequestRef(const V4L2RequestRef&) = delete;
V4L2RequestRef& operator=(const V4L2RequestRef&) = delete;
// Apply controls to the request.
bool ApplyCtrls(struct v4l2_ext_controls* ctrls) const;
// Apply buffer to the request.
[[nodiscard]] bool ApplyQueueBuffer(struct v4l2_buffer* buffer) const;
// Submits the request to the driver.
std::optional<V4L2SubmittedRequestRef> Submit() &&;
private:
friend class V4L2RequestsQueue;
V4L2RequestRef(V4L2Request* request) : V4L2RequestRefBase(request) {}
};
// Interface representing a submitted request.
//
// After a request is submitted, a request reference cannot be used anymore.
// Instead, an object representing a submitted request is returned.
// Through this object, it is possible to check whether the request
// completed or not.
class MEDIA_GPU_EXPORT V4L2SubmittedRequestRef : public V4L2RequestRefBase {
public:
V4L2SubmittedRequestRef(V4L2SubmittedRequestRef&& req_ref)
: V4L2RequestRefBase(std::move(req_ref)) {}
V4L2SubmittedRequestRef(const V4L2SubmittedRequestRef&) = delete;
V4L2SubmittedRequestRef& operator=(const V4L2SubmittedRequestRef&) = delete;
// Indicates if the request has completed.
[[nodiscard]] bool IsCompleted();
private:
friend class V4L2RequestRef;
V4L2SubmittedRequestRef(V4L2Request* request) : V4L2RequestRefBase(request) {}
};
// Interface representing a queue of requests. The requests queue manages and
// recycles requests.
//
// Requests undergo the following cycle:
// 1) Allocated requests are put into a free request pool, indicating that they
// are not used by the client and free to be used.
// 2) The client obtains a unique request reference to one of the free
// requests in order to set its controls and buffer.
// 3) The client then submit the request obtained in 2), which invalidates its
// reference and returns a reference to a submitted request.
// 4) Once client releases the submitted request reference, the request goes
// back to the free request pool described in 1).
class MEDIA_GPU_EXPORT V4L2RequestsQueue {
public:
V4L2RequestsQueue(const V4L2RequestsQueue&) = delete;
V4L2RequestsQueue& operator=(const V4L2RequestsQueue&) = delete;
// Gets a free request. If no request is available, a non-valid request
// reference will be returned.
std::optional<V4L2RequestRef> GetFreeRequest();
private:
// File descriptor of the media device (/dev/mediaX) from which requests
// are created.
base::ScopedFD media_fd_;
// Stores all available requests.
std::vector<std::unique_ptr<V4L2Request>> requests_;
std::queue<V4L2Request*> free_requests_;
// Returns a new request file descriptor.
std::optional<base::ScopedFD> CreateRequestFD();
friend class V4L2Request;
// Returns a request to the queue after being used.
void ReturnRequest(V4L2Request* request);
friend class V4L2Device;
friend std::unique_ptr<V4L2RequestsQueue>::deleter_type;
V4L2RequestsQueue(base::ScopedFD&& media_fd);
~V4L2RequestsQueue();
SEQUENCE_CHECKER(sequence_checker_);
};
// Interface representing a specific V4L2 queue. 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).
class MEDIA_GPU_EXPORT V4L2Queue
: public base::RefCountedThreadSafe<V4L2Queue> {
public:
V4L2Queue(const V4L2Queue&) = delete;
V4L2Queue& operator=(const V4L2Queue&) = delete;
// 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 gfx::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.
// 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.
[[nodiscard]] std::optional<struct v4l2_format>
SetFormat(uint32_t fourcc, const gfx::Size& size, size_t buffer_size);
// 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.
[[nodiscard]] std::optional<struct v4l2_format>
TryFormat(uint32_t fourcc, const gfx::Size& size, size_t buffer_size);
// Returns the currently set format on the queue. The result is returned as
// a std::pair where the first member is the format, or std::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 std::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.
[[nodiscard]] std::pair<std::optional<struct v4l2_format>, int> GetFormat();
// Codec-specific method to get the visible rectangle of the queue, using the
// VIDIOC_G_SELECTION ioctl if available, or VIDIOC_G_CROP as a fallback.
[[nodiscard]] std::optional<gfx::Rect> GetVisibleRect();
// 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.
//
// Setting the |incoherent| flag will allocate the buffers with the
// V4L2_MEMORY_FLAG_NON_COHERENT flag set. This allows caching, which is a
// potential performance improvement when reading from CPU, but may not be
// safe for all V4L2 hardware. In particular, the MDP won't work with
// incoherent memory.
//
// 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.
[[nodiscard]] size_t AllocateBuffers(size_t count,
enum v4l2_memory memory,
bool incoherent);
// 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.
[[nodiscard]] bool DeallocateBuffers();
// Returns the memory usage of v4l2 buffers owned by this V4L2Queue which are
// mapped in user space memory.
[[nodiscard]] size_t GetMemoryUsage() const;
// Returns |memory_|, memory type of last buffers allocated by this V4L2Queue.
[[nodiscard]] v4l2_memory GetMemoryType() const;
// This returns the secure handle for a free buffer and then tags that buffer
// as having its handle claimed. It expects another call later to
// ReleaseSecureHandle to return control of the secure handle back to the
// queue.
[[nodiscard]] CroStatus::Or<uint64_t> GetFreeSecureHandle();
void ReleaseSecureHandle(uint64_t secure_handle);
// 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.
[[nodiscard]] std::optional<V4L2WritableBufferRef> GetFreeBuffer();
// Return the buffer at index |requested_buffer_id|, if it is available at
// this time.
//
// If the buffer is currently in use or the provided index is invalid,
// return |std::nullopt|.
[[nodiscard]] std::optional<V4L2WritableBufferRef> GetFreeBuffer(
size_t requested_buffer_id);
// Return a V4L2 buffer suitable for the passed frame.
//
// This method will try as much as possible to always return the same V4L2
// buffer when the same frame is passed again, to avoid memory unmap
// operations in the kernel driver.
//
// The operating mode of the queue must be DMABUF, and the frame must be
// backed either by a GpuMemoryBuffer, or by DMABUFs. In the case of DMABUFs,
// this method will only work correctly if the same DMABUFs are passed with
// each call, i.e. no dup shall be performed.
//
// This should be the preferred way to obtain buffers when using DMABUF mode,
// since it will maximize performance in that case provided the number of
// different frames passed to this method does not exceed the number of V4L2
// buffers allocated on the queue.
[[nodiscard]] std::optional<V4L2WritableBufferRef> GetFreeBufferForFrame(
const gfx::GenericSharedMemoryId& 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.
[[nodiscard]] std::pair<bool, V4L2ReadableBufferRef> DequeueBuffer();
// Returns true if this queue is currently streaming.
[[nodiscard]] 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.
[[nodiscard]] 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.
[[nodiscard]] bool Streamoff();
// Returns the number of buffers currently allocated for this queue.
[[nodiscard]] size_t AllocatedBuffersCount() const;
// Returns the number of currently free buffers on this queue.
[[nodiscard]] size_t FreeBuffersCount() const;
// Returns the number of buffers currently queued on this queue.
[[nodiscard]] size_t QueuedBuffersCount() const;
// Returns true if requests are supported by this queue.
[[nodiscard]] bool SupportsRequests();
// TODO (b/166275274) : Remove this once V4L2 properly supports modifiers.
// Out of band method to configure V4L2 for modifier use.
[[nodiscard]] std::optional<struct v4l2_format> SetModifierFormat(
uint64_t modifier,
const gfx::Size& size);
// Sends a V4L2_DEC_CMD_STOP/V4L2_DEC_CMD_START to this queue.
[[nodiscard]] bool SendStopCommand();
[[nodiscard]] bool SendStartCommand();
// Sets the FD in a |v4L2_buffer| to be the one associated with the specified
// |secure_handle|. Returns false if no such handle exists or is not currently
// active.
bool SetBufferFdForSecureHandle(uint64_t secure_handle,
struct v4l2_buffer* v4l2_buffer);
private:
~V4L2Queue();
// Called when clients request a buffer to be queued.
[[nodiscard]] bool QueueBuffer(struct v4l2_buffer* v4l2_buffer,
scoped_refptr<FrameResource> frame);
// Sends a V4L2_DEC_CMD_* to this queue.
[[nodiscard]] bool SendCommand(__u32 command);
// Callback used from secure buffer allocation.
void SecureBufferAllocated(base::ScopedFD secure_fd, uint64_t secure_handle);
const enum v4l2_buf_type type_;
enum v4l2_memory memory_ = V4L2_MEMORY_MMAP;
bool is_streaming_ = false;
// Set to true if the queue supports requests.
bool supports_requests_ = false;
size_t planes_count_ = 0;
// Current format as set by SetFormat.
std::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, indexed
// by the v4l2_buffer queue ID. The value will be set to the FrameResource
// that has been passed when we queued the buffer, if any.
base::small_map<std::map<size_t, scoped_refptr<FrameResource>>>
queued_buffers_;
// Dictionary of queue buffers (indexed 0... |buffers_| size), indexed by the
// unique frame id (be that a GpuMemoryBuffer ID or a DmaBuf ID).
std::map<gfx::GenericSharedMemoryId, size_t> free_buffers_indexes_
GUARDED_BY_CONTEXT(sequence_checker_);
// List of the allocated secure buffers.
std::vector<SecureBufferData> secure_buffers_;
const IoctlAsCallback ioctl_cb_ GUARDED_BY_CONTEXT(sequence_checker_);
const base::RepeatingClosure schedule_poll_cb_
GUARDED_BY_CONTEXT(sequence_checker_);
const MmapAsCallback mmap_cb_ GUARDED_BY_CONTEXT(sequence_checker_);
const AllocateSecureBufferAsCallback allocate_secure_cb_
GUARDED_BY_CONTEXT(sequence_checker_);
// Callback to call in this queue's destructor.
base::OnceClosure destroy_cb_;
V4L2Queue(const IoctlAsCallback& ioctl_cb,
const base::RepeatingClosure& schedule_poll_cb,
const MmapAsCallback& mmap_cb,
const AllocateSecureBufferAsCallback& allocate_secure_cb,
enum v4l2_buf_type type,
base::OnceClosure destroy_cb);
friend class V4L2QueueFactory;
friend class V4L2BufferRefBase;
friend class base::RefCountedThreadSafe<V4L2Queue>;
friend class V4L2StatefulVideoDecoder;
SEQUENCE_CHECKER(sequence_checker_);
bool incoherent_ = false;
base::WeakPtrFactory<V4L2Queue> weak_this_factory_;
};
} // namespace media
#endif // MEDIA_GPU_V4L2_V4L2_QUEUE_H_