// Copyright 2014 The Chromium Authors. All rights reserved. // 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. #ifndef MEDIA_GPU_V4L2_V4L2_DEVICE_H_ #define MEDIA_GPU_V4L2_V4L2_DEVICE_H_ #include #include #include #include #include #include "base/containers/flat_map.h" #include "base/files/scoped_file.h" #include "base/memory/ref_counted.h" #include "base/optional.h" #include "base/sequence_checker.h" #include "media/base/video_codecs.h" #include "media/base/video_decoder_config.h" #include "media/base/video_frame.h" #include "media/base/video_frame_layout.h" #include "media/gpu/chromeos/fourcc.h" #include "media/gpu/media_gpu_export.h" #include "media/gpu/v4l2/v4l2_device_poller.h" #include "media/video/video_decode_accelerator.h" #include "media/video/video_encode_accelerator.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_pixmap_handle.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_image.h" // TODO(mojahsu): remove this once V4L2 headers are updated. #ifndef V4L2_PIX_FMT_JPEG_RAW #define V4L2_PIX_FMT_JPEG_RAW v4l2_fourcc('J', 'P', 'G', 'R') #endif #ifndef V4L2_CID_JPEG_LUMA_QUANTIZATION #define V4L2_CID_JPEG_LUMA_QUANTIZATION (V4L2_CID_JPEG_CLASS_BASE + 5) #endif #ifndef V4L2_CID_JPEG_CHROMA_QUANTIZATION #define V4L2_CID_JPEG_CHROMA_QUANTIZATION (V4L2_CID_JPEG_CLASS_BASE + 6) #endif // TODO(b/132589320): remove this once V4L2 header is updated. #ifndef V4L2_PIX_FMT_MM21 // MTK 8-bit block mode, two non-contiguous planes. #define V4L2_PIX_FMT_MM21 v4l2_fourcc('M', 'M', '2', '1') #endif namespace gfx { struct NativePixmapPlane; } // namespace gfx namespace media { class V4L2Queue; class V4L2BufferRefBase; class V4L2BuffersList; class V4L2DecodeSurface; class V4L2RequestRef; // 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. 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. bool QueueUserPtr(const std::vector& 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. bool QueueDMABuf(const std::vector& 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. bool QueueDMABuf(const std::vector& planes, V4L2RequestRef* request_ref = nullptr) &&; // Queue a |video_frame| using its file descriptors as DMABUFs. The VideoFrame // must have been constructed from its file descriptors. // The particularity of this method is that a reference to |video_frame| is // kept and made available again when the buffer is dequeued through // |V4L2ReadableBufferRef::GetVideoFrame()|. |video_frame| is thus guaranteed // to be alive until either all the |V4L2ReadableBufferRef| from the dequeued // buffer get out of scope, or |V4L2Queue::Streamoff()| is called. bool QueueDMABuf(scoped_refptr video_frame, V4L2RequestRef* request_ref = nullptr) &&; // 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 VideoFrame underlying this buffer. The VideoFrame's layout // will match that of the V4L2 format. This method will *always* return the // same VideoFrame instance for a given V4L2 buffer. Moreover, the VideoFrame // 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. scoped_refptr GetVideoFrame() WARN_UNUSED_RESULT; // 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; // Set the passed config store to this buffer. // This method is only used for backward compatibility until the config // store is deprecated and should not be called by new code. void SetConfigStore(uint32_t config_store); ~V4L2WritableBufferRef(); private: // Do 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. bool DoQueue(V4L2RequestRef* request_ref, scoped_refptr video_frame) &&; V4L2WritableBufferRef(const struct v4l2_buffer& v4l2_buffer, base::WeakPtr queue); friend class V4L2BufferRefFactory; std::unique_ptr buffer_data_; SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(V4L2WritableBufferRef); }; // 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 MEDIA_GPU_EXPORT V4L2ReadableBuffer : public base::RefCountedThreadSafe { 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; // Return the VideoFrame underlying this buffer. The VideoFrame's layout // will match that of the V4L2 format. This method will *always* return the // same VideoFrame instance for a given V4L2 buffer. Moreover, the VideoFrame // 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. scoped_refptr GetVideoFrame() WARN_UNUSED_RESULT; private: friend class V4L2BufferRefFactory; friend class base::RefCountedThreadSafe; ~V4L2ReadableBuffer(); V4L2ReadableBuffer(const struct v4l2_buffer& v4l2_buffer, base::WeakPtr queue, scoped_refptr video_frame); std::unique_ptr buffer_data_; // If this buffer was a DMABUF buffer queued with // QueueDMABuf(scoped_refptr), then this will hold the VideoFrame // that has been passed at the time of queueing. scoped_refptr video_frame_; SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(V4L2ReadableBuffer); }; // Shortcut for naming consistency. using V4L2ReadableBufferRef = scoped_refptr; 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. // // 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 { 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 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. base::Optional SetFormat(uint32_t fourcc, const gfx::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, 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. base::Optional 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. // // 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 GetFreeBuffer(); // 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 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; // Returns true if requests are supported by this queue. bool SupportsRequests(); private: ~V4L2Queue(); // Called when clients request a buffer to be queued. bool QueueBuffer(struct v4l2_buffer* v4l2_buffer, scoped_refptr video_frame); 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. base::Optional current_format_; std::vector> 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 free_buffers_; // Buffers that have been queued by the client, and not dequeued yet. The // value will be set to the VideoFrame that has been passed when we queued // the buffer, if any. std::map> queued_buffers_; scoped_refptr device_; // Callback to call in this queue's destructor. base::OnceClosure destroy_cb_; V4L2Queue(scoped_refptr dev, enum v4l2_buf_type type, base::OnceClosure destroy_cb); friend class V4L2QueueFactory; friend class V4L2BufferRefBase; friend class base::RefCountedThreadSafe; SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory weak_this_factory_; DISALLOW_COPY_AND_ASSIGN(V4L2Queue); }; 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 { protected: V4L2RequestRefBase(V4L2RequestRefBase&& req_base); V4L2RequestRefBase(V4L2Request* request); ~V4L2RequestRefBase(); V4L2Request* request_; SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(V4L2RequestRefBase); }; 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)) {} // Apply controls to the request. bool ApplyCtrls(struct v4l2_ext_controls* ctrls) const; // Apply buffer to the request. bool ApplyQueueBuffer(struct v4l2_buffer* buffer) const; // Submits the request to the driver. base::Optional Submit() &&; private: friend class V4L2RequestsQueue; V4L2RequestRef(V4L2Request* request) : V4L2RequestRefBase(request) {} DISALLOW_COPY_AND_ASSIGN(V4L2RequestRef); }; // 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)) {} // Indicates if the request has completed. bool IsCompleted(); private: friend class V4L2RequestRef; V4L2SubmittedRequestRef(V4L2Request* request) : V4L2RequestRefBase(request) {} DISALLOW_COPY_AND_ASSIGN(V4L2SubmittedRequestRef); }; // 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: // Gets a free request. If no request is available, a non-valid request // reference will be returned. base::Optional 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> requests_; std::queue free_requests_; // Returns a new request file descriptor. base::Optional CreateRequestFD(); friend class V4L2Request; // Returns a request to the queue after being used. void ReturnRequest(V4L2Request* request); friend class V4L2Device; friend std::unique_ptr::deleter_type; V4L2RequestsQueue(base::ScopedFD&& media_fd); ~V4L2RequestsQueue(); SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(V4L2RequestsQueue); }; class MEDIA_GPU_EXPORT V4L2Device : public base::RefCountedThreadSafe { 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 V4L2PixFmtToVideoCodecProfiles( uint32_t pix_fmt, bool is_encoder); static uint32_t V4L2PixFmtToDrmFormat(uint32_t format); // Calculates the largest plane's allocation size requested by a V4L2 device. static gfx::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 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, kImageProcessor, kJpegDecoder, kJpegEncoder, }; // Create and initialize an appropriate V4L2Device instance for the current // platform, or return nullptr if not available. static scoped_refptr Create(); // Open a V4L2 device of |type| for use with |v4l2_pixfmt|. // Return true on success. // The device will be closed in the destructor. virtual bool Open(Type type, uint32_t v4l2_pixfmt) = 0; // Returns the V4L2Queue corresponding to the requested |type|, or nullptr // if the requested queue type is not supported. scoped_refptr GetQueue(enum v4l2_buf_type type); // Parameters and return value are the same as for the standard ioctl() system // call. virtual int Ioctl(int request, void* arg) = 0; // 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. virtual bool Poll(bool poll_device, bool* event_pending) = 0; // 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. virtual bool SetDevicePollInterrupt() = 0; virtual bool ClearDevicePollInterrupt() = 0; // Wrappers for standard mmap/munmap system calls. virtual void* Mmap(void* addr, unsigned int len, int prot, int flags, unsigned int offset) = 0; virtual void Munmap(void* addr, unsigned int len) = 0; // 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. virtual std::vector GetDmabufsForV4L2Buffer( int index, size_t num_planes, enum v4l2_buf_type type) = 0; // Return true if the given V4L2 pixfmt can be used in CreateEGLImage() // for the current platform. virtual bool CanCreateEGLImageFrom(const Fourcc fourcc) const = 0; // Create an EGLImage from provided |handle|, taking full ownership of it. // Some implementations may also require the V4L2 |buffer_index| of the buffer // for which |handle| has been exported. // Return EGL_NO_IMAGE_KHR on failure. virtual EGLImageKHR CreateEGLImage(EGLDisplay egl_display, EGLContext egl_context, GLuint texture_id, const gfx::Size& size, unsigned int buffer_index, const Fourcc fourcc, gfx::NativePixmapHandle handle) const = 0; // Create a GLImage from provided |handle|, taking full ownership of it. virtual scoped_refptr CreateGLImage( const gfx::Size& size, const Fourcc fourcc, gfx::NativePixmapHandle handle) const = 0; // Destroys the EGLImageKHR. virtual EGLBoolean DestroyEGLImage(EGLDisplay egl_display, EGLImageKHR egl_image) const = 0; // Returns the supported texture target for the V4L2Device. virtual GLenum GetTextureTarget() const = 0; // Returns the preferred V4L2 input formats for |type| or empty if none. virtual std::vector PreferredInputFormat(Type type) const = 0; // Get minimum and maximum resolution for fourcc |pixelformat| and store to // |min_resolution| and |max_resolution|. void GetSupportedResolution(uint32_t pixelformat, gfx::Size* min_resolution, gfx::Size* max_resolution); std::vector EnumerateSupportedPixelformats(v4l2_buf_type buf_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(b/150431552): fix this. // Return V4L2 pixelformats supported by the available image processor // devices for |buf_type|. virtual std::vector GetSupportedImageProcessorPixelformats( v4l2_buf_type buf_type) = 0; // Return supported profiles for decoder, including only profiles for given // fourcc |pixelformats|. virtual VideoDecodeAccelerator::SupportedProfiles GetSupportedDecodeProfiles( const size_t num_formats, const uint32_t pixelformats[]) = 0; // Return supported profiles for encoder. virtual VideoEncodeAccelerator::SupportedProfiles GetSupportedEncodeProfiles() = 0; // Return true if image processing is supported, false otherwise. virtual bool IsImageProcessingSupported() = 0; // Return true if JPEG codec is supported, false otherwise. virtual bool IsJpegDecodingSupported() = 0; virtual bool IsJpegEncodingSupported() = 0; // 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(); // Attempt to dequeue a V4L2 event and return it. base::Optional DequeueEvent(); // Returns requests queue to get free requests. A null pointer is returned if // the queue creation failed or if requests are not supported. V4L2RequestsQueue* GetRequestsQueue(); // 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 ctrls); // Get the value of a single control, or base::nullopt of the control is not // exposed by the device. base::Optional GetCtrl(uint32_t ctrl_id); protected: friend class base::RefCountedThreadSafe; V4L2Device(); virtual ~V4L2Device(); VideoDecodeAccelerator::SupportedProfiles EnumerateSupportedDecodeProfiles( const size_t num_formats, const uint32_t pixelformats[]); VideoEncodeAccelerator::SupportedProfiles EnumerateSupportedEncodeProfiles(); private: // Perform platform-specific initialization of the device instance. // Return true on success, false on error or if the particular implementation // is not available. virtual bool Initialize() = 0; // Associates a v4l2_buf_type to its queue. base::flat_map queues_; // Callback that is called upon a queue's destruction, to cleanup its pointer // in queues_. void OnQueueDestroyed(v4l2_buf_type buf_type); // Used if EnablePolling() is called to signal the user that an event // happened or a buffer is ready to be dequeued. std::unique_ptr device_poller_; // Indicates whether the request queue creation has been tried once. bool requests_queue_creation_called_ = false; // The request queue stores all requests allocated to be used. std::unique_ptr requests_queue_; SEQUENCE_CHECKER(client_sequence_checker_); }; } // namespace media #endif // MEDIA_GPU_V4L2_V4L2_DEVICE_H_