• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ENCODE_ACCELERATOR_H_
6 #define CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_ENCODE_ACCELERATOR_H_
7 
8 #include <list>
9 #include <linux/videodev2.h>
10 #include <vector>
11 
12 #include "base/memory/linked_ptr.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/threading/thread.h"
15 #include "content/common/content_export.h"
16 #include "content/common/gpu/media/v4l2_image_processor.h"
17 #include "content/common/gpu/media/v4l2_video_device.h"
18 #include "media/video/video_encode_accelerator.h"
19 #include "ui/gfx/size.h"
20 
21 namespace base {
22 
23 class MessageLoopProxy;
24 
25 }  // namespace base
26 
27 namespace media {
28 
29 class BitstreamBuffer;
30 
31 }  // namespace media
32 
33 namespace content {
34 
35 // This class handles video encode acceleration by interfacing with a V4L2
36 // device exposed by the codec hardware driver. The threading model of this
37 // class is the same as in the V4L2VideoDecodeAccelerator (from which class this
38 // was designed).
39 // This class may try to instantiate and use a V4L2ImageProcessor for input
40 // format conversion, if the input format requested via Initialize() is not
41 // accepted by the hardware codec.
42 class CONTENT_EXPORT V4L2VideoEncodeAccelerator
43     : public media::VideoEncodeAccelerator {
44  public:
45   explicit V4L2VideoEncodeAccelerator(scoped_ptr<V4L2Device> device);
46   virtual ~V4L2VideoEncodeAccelerator();
47 
48   // media::VideoEncodeAccelerator implementation.
49   virtual bool Initialize(media::VideoFrame::Format format,
50                           const gfx::Size& input_visible_size,
51                           media::VideoCodecProfile output_profile,
52                           uint32 initial_bitrate,
53                           Client* client) OVERRIDE;
54   virtual void Encode(const scoped_refptr<media::VideoFrame>& frame,
55                       bool force_keyframe) OVERRIDE;
56   virtual void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer)
57       OVERRIDE;
58   virtual void RequestEncodingParametersChange(uint32 bitrate,
59                                                uint32 framerate) OVERRIDE;
60   virtual void Destroy() OVERRIDE;
61 
62   static std::vector<media::VideoEncodeAccelerator::SupportedProfile>
63       GetSupportedProfiles();
64 
65  private:
66   // Auto-destroy reference for BitstreamBuffer, for tracking buffers passed to
67   // this instance.
68   struct BitstreamBufferRef;
69 
70   // Record for codec input buffers.
71   struct InputRecord {
72     InputRecord();
73     bool at_device;
74     scoped_refptr<media::VideoFrame> frame;
75   };
76 
77   // Record for output buffers.
78   struct OutputRecord {
79     OutputRecord();
80     bool at_device;
81     linked_ptr<BitstreamBufferRef> buffer_ref;
82     void* address;
83     size_t length;
84   };
85 
86   enum {
87     kInitialFramerate = 30,
88     // These are rather subjectively tuned.
89     kInputBufferCount = 2,
90     kOutputBufferCount = 2,
91     kOutputBufferSize = (2 * 1024 * 1024),
92   };
93 
94   // Internal state of the encoder.
95   enum State {
96     kUninitialized,  // Initialize() not yet called.
97     kInitialized,    // Initialize() returned true; ready to start encoding.
98     kEncoding,       // Encoding frames.
99     kError,          // Error in encoder state.
100   };
101 
102   //
103   // Callbacks for the image processor, if one is used.
104   //
105 
106   // Callback run by the image processor when a frame is ready for us to encode.
107   void FrameProcessed(bool force_keyframe,
108                       const scoped_refptr<media::VideoFrame>& frame);
109 
110   // Error callback for handling image processor errors.
111   void ImageProcessorError();
112 
113   //
114   // Encoding tasks, to be run on encode_thread_.
115   //
116 
117   void EncodeTask(const scoped_refptr<media::VideoFrame>& frame,
118                   bool force_keyframe);
119 
120   // Add a BitstreamBuffer to the queue of buffers ready to be used for encoder
121   // output.
122   void UseOutputBitstreamBufferTask(scoped_ptr<BitstreamBufferRef> buffer_ref);
123 
124   // Device destruction task.
125   void DestroyTask();
126 
127   // Service I/O on the V4L2 devices.  This task should only be scheduled from
128   // DevicePollTask().
129   void ServiceDeviceTask();
130 
131   // Handle the device queues.
132   void Enqueue();
133   void Dequeue();
134   // Enqueue a buffer on the corresponding queue.  Returns false on fatal error.
135   bool EnqueueInputRecord();
136   bool EnqueueOutputRecord();
137 
138   // Attempt to start/stop device_poll_thread_.
139   bool StartDevicePoll();
140   bool StopDevicePoll();
141 
142   //
143   // Device tasks, to be run on device_poll_thread_.
144   //
145 
146   // The device task.
147   void DevicePollTask(bool poll_device);
148 
149   //
150   // Safe from any thread.
151   //
152 
153   // Error notification (using PostTask() to child thread, if necessary).
154   void NotifyError(Error error);
155 
156   // Set the encoder_thread_ state (using PostTask to encoder thread, if
157   // necessary).
158   void SetEncoderState(State state);
159 
160   //
161   // Other utility functions.  Called on encoder_thread_, unless
162   // encoder_thread_ is not yet started, in which case the child thread can call
163   // these (e.g. in Initialize() or Destroy()).
164   //
165 
166   // Change encoding parameters.
167   void RequestEncodingParametersChangeTask(uint32 bitrate, uint32 framerate);
168 
169   // Set up formats and initialize the device for them.
170   bool SetFormats(media::VideoFrame::Format input_format,
171                   media::VideoCodecProfile output_profile);
172 
173   // Try to set up the device to the input format we were Initialized() with,
174   // or if the device doesn't support it, use one it can support, so that we
175   // can later instantiate a V4L2ImageProcessor to convert to it.
176   bool NegotiateInputFormat(media::VideoFrame::Format input_format);
177 
178   // Set up the device to the output format requested in Initialize().
179   bool SetOutputFormat(media::VideoCodecProfile output_profile);
180 
181   // Initialize device controls with default values.
182   bool InitControls();
183 
184   // Create the buffers we need.
185   bool CreateInputBuffers();
186   bool CreateOutputBuffers();
187 
188   // Destroy these buffers.
189   void DestroyInputBuffers();
190   void DestroyOutputBuffers();
191 
192   // Our original calling message loop for the child thread.
193   const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_;
194 
195   // WeakPtr<> pointing to |this| for use in posting tasks from the encoder or
196   // device worker threads back to the child thread.  Because the worker threads
197   // are members of this class, any task running on those threads is guaranteed
198   // that this object is still alive.  As a result, tasks posted from the child
199   // thread to the encoder or device thread should use base::Unretained(this),
200   // and tasks posted the other way should use |weak_this_|.
201   base::WeakPtrFactory<V4L2VideoEncodeAccelerator> weak_this_ptr_factory_;
202   base::WeakPtr<V4L2VideoEncodeAccelerator> weak_this_;
203 
204   // To expose client callbacks from VideoEncodeAccelerator.
205   // NOTE: all calls to these objects *MUST* be executed on
206   // child_message_loop_proxy_.
207   scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_;
208   base::WeakPtr<Client> client_;
209 
210   gfx::Size visible_size_;
211   // Input allocated size required by the device.
212   gfx::Size input_allocated_size_;
213   size_t output_buffer_byte_size_;
214 
215   // Formats for input frames and the output stream.
216   media::VideoFrame::Format device_input_format_;
217   size_t input_planes_count_;
218   uint32 output_format_fourcc_;
219 
220   //
221   // Encoder state, owned and operated by encoder_thread_.
222   // Before encoder_thread_ has started, the encoder state is managed by
223   // the child (main) thread.  After encoder_thread_ has started, the encoder
224   // thread should be the only one managing these.
225   //
226 
227   // This thread services tasks posted from the VEA API entry points by the
228   // child thread and device service callbacks posted from the device thread.
229   base::Thread encoder_thread_;
230   // Encoder state.
231   State encoder_state_;
232 
233   // We need to provide the stream header with every keyframe, to allow
234   // midstream decoding restarts.  Store it here.
235   scoped_ptr<uint8[]> stream_header_;
236   size_t stream_header_size_;
237 
238   // Video frames ready to be encoded.
239   std::list<scoped_refptr<media::VideoFrame> > encoder_input_queue_;
240 
241   // Encoder device.
242   scoped_ptr<V4L2Device> device_;
243 
244   // Input queue state.
245   bool input_streamon_;
246   // Input buffers enqueued to device.
247   int input_buffer_queued_count_;
248   // Input buffers ready to use; LIFO since we don't care about ordering.
249   std::vector<int> free_input_buffers_;
250   // Mapping of int index to input buffer record.
251   std::vector<InputRecord> input_buffer_map_;
252   enum v4l2_memory input_memory_type_;
253 
254   // Output queue state.
255   bool output_streamon_;
256   // Output buffers enqueued to device.
257   int output_buffer_queued_count_;
258   // Output buffers ready to use; LIFO since we don't care about ordering.
259   std::vector<int> free_output_buffers_;
260   // Mapping of int index to output buffer record.
261   std::vector<OutputRecord> output_buffer_map_;
262 
263   // Bitstream buffers ready to be used to return encoded output, as a LIFO
264   // since we don't care about ordering.
265   std::vector<linked_ptr<BitstreamBufferRef> > encoder_output_queue_;
266 
267   //
268   // The device polling thread handles notifications of V4L2 device changes.
269   // TODO(sheu): replace this thread with an TYPE_IO encoder_thread_.
270   //
271 
272   // The thread.
273   base::Thread device_poll_thread_;
274 
275   // Image processor, if one is in use.
276   scoped_ptr<V4L2ImageProcessor> image_processor_;
277 
278   DISALLOW_COPY_AND_ASSIGN(V4L2VideoEncodeAccelerator);
279 };
280 
281 }  // namespace content
282 
283 #endif  // CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_ENCODE_ACCELERATOR_H_
284