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