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
18namespace 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.
23class 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