// 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. #ifndef CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_PROCESSOR_H_ #define CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_PROCESSOR_H_ #include #include #include "base/memory/linked_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread.h" #include "content/common/content_export.h" #include "content/common/gpu/media/v4l2_video_device.h" #include "media/base/video_frame.h" namespace content { // Handles image processing accelerators that expose a V4L2 memory-to-memory // interface. The threading model of this class is the same as for other V4L2 // hardware accelerators (see V4L2VideoDecodeAccelerator) for more details. class CONTENT_EXPORT V4L2ImageProcessor { public: explicit V4L2ImageProcessor(scoped_ptr device); virtual ~V4L2ImageProcessor(); // Initializes the processor to convert from |input_format| to |output_format| // and/or scale from |input_visible_size| to |output_visible_size|. // Request the output buffers to be of at least |output_allocated_size|. // Provided |error_cb| will be called if an error occurs. // Return true if the requested configuration is supported. bool Initialize(media::VideoFrame::Format input_format, media::VideoFrame::Format output_format, gfx::Size input_visible_size, gfx::Size output_visible_size, gfx::Size output_allocated_size, const base::Closure& error_cb); // Returns allocated size required by the processor to be fed with. gfx::Size input_allocated_size() { return input_allocated_size_; } // Callback to be used to return a processed image to the client. The client // should drop references to |frame| once it's done with it. typedef base::Callback& frame)> FrameReadyCB; // Called by client to process |frame|. The resulting processed frame will // be returned via |cb|. The processor will drop all its references to |frame| // after it finishes accessing it. void Process(const scoped_refptr& frame, const FrameReadyCB& cb); // Stop all processing and clean up. void Destroy(); private: // Record for input buffers. struct InputRecord { InputRecord(); scoped_refptr frame; bool at_device; }; // Record for output buffers. struct OutputRecord { OutputRecord(); bool at_device; bool at_client; std::vector fds; }; // Job record. Jobs are processed in a FIFO order. This is separate from // InputRecord, because an InputRecord may be returned before we dequeue // the corresponding output buffer. It can't always be associated with // an OutputRecord immediately either, because at the time of submission we // may not have one available (and don't need one to submit input to the // device). struct JobRecord { JobRecord(); scoped_refptr frame; FrameReadyCB ready_cb; }; enum { // Arbitrarily tuned. kInputBufferCount = 2, kOutputBufferCount = 2, }; void ReuseOutputBuffer(int index); void Enqueue(); void Dequeue(); bool EnqueueInputRecord(); bool EnqueueOutputRecord(); bool CreateInputBuffers(); bool CreateOutputBuffers(); void DestroyInputBuffers(); void DestroyOutputBuffers(); void NotifyError(); void DestroyTask(); void ProcessTask(scoped_ptr job_record); void ServiceDeviceTask(); // Attempt to start/stop device_poll_thread_. bool StartDevicePoll(); bool StopDevicePoll(); // Ran on device_poll_thread_ to wait for device events. void DevicePollTask(bool poll_device); // Size and format-related members remain constant after initialization. // The visible/allocated sizes of the input frame. gfx::Size input_visible_size_; gfx::Size input_allocated_size_; // The visible/allocated sizes of the destination frame. gfx::Size output_visible_size_; gfx::Size output_allocated_size_; media::VideoFrame::Format input_format_; media::VideoFrame::Format output_format_; uint32 input_format_fourcc_; uint32 output_format_fourcc_; size_t input_planes_count_; size_t output_planes_count_; // Our original calling message loop for the child thread. const scoped_refptr child_message_loop_proxy_; // V4L2 device in use. scoped_ptr device_; // Thread to communicate with the device on. base::Thread device_thread_; // Thread used to poll the V4L2 for events only. base::Thread device_poll_thread_; // All the below members are to be accessed from device_thread_ only // (if it's running). std::queue > input_queue_; std::queue > running_jobs_; // Input queue state. bool input_streamon_; // Number of input buffers enqueued to the device. int input_buffer_queued_count_; // Input buffers ready to use; LIFO since we don't care about ordering. std::vector free_input_buffers_; // Mapping of int index to an input buffer record. std::vector input_buffer_map_; // Output queue state. bool output_streamon_; // Number of output buffers enqueued to the device. int output_buffer_queued_count_; // Output buffers ready to use; LIFO since we don't care about ordering. std::vector free_output_buffers_; // Mapping of int index to an output buffer record. std::vector output_buffer_map_; // Error callback to the client. base::Closure error_cb_; // Weak factory for producing weak pointers on the device_thread_ base::WeakPtrFactory device_weak_factory_; DISALLOW_COPY_AND_ASSIGN(V4L2ImageProcessor); }; } // namespace content #endif // CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_PROCESSOR_H_