Home | History | Annotate | Download | only in media
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_PROCESSOR_H_
      6 #define CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_PROCESSOR_H_
      7 
      8 #include <queue>
      9 #include <vector>
     10 
     11 #include "base/memory/linked_ptr.h"
     12 #include "base/memory/weak_ptr.h"
     13 #include "base/threading/thread.h"
     14 #include "content/common/content_export.h"
     15 #include "content/common/gpu/media/v4l2_video_device.h"
     16 #include "media/base/video_frame.h"
     17 
     18 namespace content {
     19 
     20 // Handles image processing accelerators that expose a V4L2 memory-to-memory
     21 // interface. The threading model of this class is the same as for other V4L2
     22 // hardware accelerators (see V4L2VideoDecodeAccelerator) for more details.
     23 class CONTENT_EXPORT V4L2ImageProcessor {
     24  public:
     25   explicit V4L2ImageProcessor(scoped_ptr<V4L2Device> device);
     26   virtual ~V4L2ImageProcessor();
     27 
     28   // Initializes the processor to convert from |input_format| to |output_format|
     29   // and/or scale from |input_visible_size| to |output_visible_size|.
     30   // Request the output buffers to be of at least |output_allocated_size|.
     31   // Provided |error_cb| will be called if an error occurs.
     32   // Return true if the requested configuration is supported.
     33   bool Initialize(media::VideoFrame::Format input_format,
     34                   media::VideoFrame::Format output_format,
     35                   gfx::Size input_visible_size,
     36                   gfx::Size output_visible_size,
     37                   gfx::Size output_allocated_size,
     38                   const base::Closure& error_cb);
     39 
     40   // Returns allocated size required by the processor to be fed with.
     41   gfx::Size input_allocated_size() { return input_allocated_size_; }
     42 
     43   // Callback to be used to return a processed image to the client. The client
     44   // should drop references to |frame| once it's done with it.
     45   typedef base::Callback<void(const scoped_refptr<media::VideoFrame>& frame)>
     46       FrameReadyCB;
     47 
     48   // Called by client to process |frame|. The resulting processed frame will
     49   // be returned via |cb|. The processor will drop all its references to |frame|
     50   // after it finishes accessing it.
     51   void Process(const scoped_refptr<media::VideoFrame>& frame,
     52                const FrameReadyCB& cb);
     53 
     54   // Stop all processing and clean up.
     55   void Destroy();
     56 
     57  private:
     58   // Record for input buffers.
     59   struct InputRecord {
     60     InputRecord();
     61     scoped_refptr<media::VideoFrame> frame;
     62     bool at_device;
     63   };
     64 
     65   // Record for output buffers.
     66   struct OutputRecord {
     67     OutputRecord();
     68     bool at_device;
     69     bool at_client;
     70     std::vector<int> fds;
     71   };
     72 
     73   // Job record. Jobs are processed in a FIFO order. This is separate from
     74   // InputRecord, because an InputRecord may be returned before we dequeue
     75   // the corresponding output buffer. It can't always be associated with
     76   // an OutputRecord immediately either, because at the time of submission we
     77   // may not have one available (and don't need one to submit input to the
     78   // device).
     79   struct JobRecord {
     80     JobRecord();
     81     scoped_refptr<media::VideoFrame> frame;
     82     FrameReadyCB ready_cb;
     83   };
     84 
     85   enum {
     86     // Arbitrarily tuned.
     87     kInputBufferCount = 2,
     88     kOutputBufferCount = 2,
     89   };
     90 
     91   void ReuseOutputBuffer(int index);
     92 
     93   void Enqueue();
     94   void Dequeue();
     95   bool EnqueueInputRecord();
     96   bool EnqueueOutputRecord();
     97   bool CreateInputBuffers();
     98   bool CreateOutputBuffers();
     99   void DestroyInputBuffers();
    100   void DestroyOutputBuffers();
    101 
    102   void NotifyError();
    103   void DestroyTask();
    104 
    105   void ProcessTask(scoped_ptr<JobRecord> job_record);
    106   void ServiceDeviceTask();
    107 
    108   // Attempt to start/stop device_poll_thread_.
    109   bool StartDevicePoll();
    110   bool StopDevicePoll();
    111 
    112   // Ran on device_poll_thread_ to wait for device events.
    113   void DevicePollTask(bool poll_device);
    114 
    115   // Size and format-related members remain constant after initialization.
    116   // The visible/allocated sizes of the input frame.
    117   gfx::Size input_visible_size_;
    118   gfx::Size input_allocated_size_;
    119 
    120   // The visible/allocated sizes of the destination frame.
    121   gfx::Size output_visible_size_;
    122   gfx::Size output_allocated_size_;
    123 
    124   media::VideoFrame::Format input_format_;
    125   media::VideoFrame::Format output_format_;
    126   uint32 input_format_fourcc_;
    127   uint32 output_format_fourcc_;
    128 
    129   size_t input_planes_count_;
    130   size_t output_planes_count_;
    131 
    132   // Our original calling message loop for the child thread.
    133   const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_;
    134 
    135   // V4L2 device in use.
    136   scoped_ptr<V4L2Device> device_;
    137 
    138   // Thread to communicate with the device on.
    139   base::Thread device_thread_;
    140   // Thread used to poll the V4L2 for events only.
    141   base::Thread device_poll_thread_;
    142 
    143   // All the below members are to be accessed from device_thread_ only
    144   // (if it's running).
    145   std::queue<linked_ptr<JobRecord> > input_queue_;
    146   std::queue<linked_ptr<JobRecord> > running_jobs_;
    147 
    148   // Input queue state.
    149   bool input_streamon_;
    150   // Number of input buffers enqueued to the device.
    151   int input_buffer_queued_count_;
    152   // Input buffers ready to use; LIFO since we don't care about ordering.
    153   std::vector<int> free_input_buffers_;
    154   // Mapping of int index to an input buffer record.
    155   std::vector<InputRecord> input_buffer_map_;
    156 
    157   // Output queue state.
    158   bool output_streamon_;
    159   // Number of output buffers enqueued to the device.
    160   int output_buffer_queued_count_;
    161   // Output buffers ready to use; LIFO since we don't care about ordering.
    162   std::vector<int> free_output_buffers_;
    163   // Mapping of int index to an output buffer record.
    164   std::vector<OutputRecord> output_buffer_map_;
    165 
    166   // Error callback to the client.
    167   base::Closure error_cb_;
    168 
    169   // Weak factory for producing weak pointers on the device_thread_
    170   base::WeakPtrFactory<V4L2ImageProcessor> device_weak_factory_;
    171 
    172   DISALLOW_COPY_AND_ASSIGN(V4L2ImageProcessor);
    173 };
    174 
    175 }  // namespace content
    176 
    177 #endif  // CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_PROCESSOR_H_
    178