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