Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: content/common/gpu/media/v4l2_slice_video_decode_accelerator.h

Issue 1882373004: Migrate content/common/gpu/media code to media/gpu (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Squash and rebase Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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_SLICE_VIDEO_DECODE_ACCELERATOR_H_
6 #define CONTENT_COMMON_GPU_MEDIA_V4L2_SLICE_VIDEO_DECODE_ACCELERATOR_H_
7
8 #include <linux/videodev2.h>
9 #include <stddef.h>
10 #include <stdint.h>
11
12 #include <memory>
13 #include <queue>
14 #include <utility>
15 #include <vector>
16
17 #include "base/macros.h"
18 #include "base/memory/linked_ptr.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/memory/weak_ptr.h"
21 #include "base/synchronization/waitable_event.h"
22 #include "base/threading/thread.h"
23 #include "content/common/content_export.h"
24 #include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h"
25 #include "content/common/gpu/media/h264_decoder.h"
26 #include "content/common/gpu/media/v4l2_device.h"
27 #include "content/common/gpu/media/vp8_decoder.h"
28 #include "media/video/video_decode_accelerator.h"
29
30 namespace content {
31
32 // An implementation of VideoDecodeAccelerator that utilizes the V4L2 slice
33 // level codec API for decoding. The slice level API provides only a low-level
34 // decoding functionality and requires userspace to provide support for parsing
35 // the input stream and managing decoder state across frames.
36 class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
37 : public media::VideoDecodeAccelerator {
38 public:
39 class V4L2DecodeSurface;
40
41 V4L2SliceVideoDecodeAccelerator(
42 const scoped_refptr<V4L2Device>& device,
43 EGLDisplay egl_display,
44 const GetGLContextCallback& get_gl_context_cb,
45 const MakeGLContextCurrentCallback& make_context_current_cb);
46 ~V4L2SliceVideoDecodeAccelerator() override;
47
48 // media::VideoDecodeAccelerator implementation.
49 bool Initialize(const Config& config, Client* client) override;
50 void Decode(const media::BitstreamBuffer& bitstream_buffer) override;
51 void AssignPictureBuffers(
52 const std::vector<media::PictureBuffer>& buffers) override;
53 void ImportBufferForPicture(int32_t picture_buffer_id,
54 const std::vector<gfx::GpuMemoryBufferHandle>&
55 gpu_memory_buffer_handles) override;
56 void ReusePictureBuffer(int32_t picture_buffer_id) override;
57 void Flush() override;
58 void Reset() override;
59 void Destroy() override;
60 bool TryToSetupDecodeOnSeparateThread(
61 const base::WeakPtr<Client>& decode_client,
62 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
63 override;
64 media::VideoPixelFormat GetOutputFormat() const override;
65
66 static media::VideoDecodeAccelerator::SupportedProfiles
67 GetSupportedProfiles();
68
69 private:
70 class V4L2H264Accelerator;
71 class V4L2VP8Accelerator;
72
73 // Record for input buffers.
74 struct InputRecord {
75 InputRecord();
76 int32_t input_id;
77 void* address;
78 size_t length;
79 size_t bytes_used;
80 bool at_device;
81 };
82
83 // Record for output buffers.
84 struct OutputRecord {
85 OutputRecord();
86 bool at_device;
87 bool at_client;
88 int32_t picture_id;
89 GLuint texture_id;
90 EGLImageKHR egl_image;
91 EGLSyncKHR egl_sync;
92 std::vector<base::ScopedFD> dmabuf_fds;
93 bool cleared;
94 };
95
96 // See http://crbug.com/255116.
97 // Input bitstream buffer size for up to 1080p streams.
98 const size_t kInputBufferMaxSizeFor1080p = 1024 * 1024;
99 // Input bitstream buffer size for up to 4k streams.
100 const size_t kInputBufferMaxSizeFor4k = 4 * kInputBufferMaxSizeFor1080p;
101 const size_t kNumInputBuffers = 16;
102
103 // Input format V4L2 fourccs this class supports.
104 static const uint32_t supported_input_fourccs_[];
105
106 //
107 // Below methods are used by accelerator implementations.
108 //
109 // Append slice data in |data| of size |size| to pending hardware
110 // input buffer with |index|. This buffer will be submitted for decode
111 // on the next DecodeSurface(). Return true on success.
112 bool SubmitSlice(int index, const uint8_t* data, size_t size);
113
114 // Submit controls in |ext_ctrls| to hardware. Return true on success.
115 bool SubmitExtControls(struct v4l2_ext_controls* ext_ctrls);
116
117 // Decode of |dec_surface| is ready to be submitted and all codec-specific
118 // settings are set in hardware.
119 void DecodeSurface(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
120
121 // |dec_surface| is ready to be outputted once decode is finished.
122 // This can be called before decode is actually done in hardware, and this
123 // method is responsible for maintaining the ordering, i.e. the surfaces will
124 // be outputted in the same order as SurfaceReady calls. To do so, the
125 // surfaces are put on decoder_display_queue_ and sent to output in that
126 // order once all preceding surfaces are sent.
127 void SurfaceReady(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
128
129 //
130 // Internal methods of this class.
131 //
132 // Recycle a V4L2 input buffer with |index| after dequeuing from device.
133 void ReuseInputBuffer(int index);
134
135 // Recycle V4L2 output buffer with |index|. Used as surface release callback.
136 void ReuseOutputBuffer(int index);
137
138 // Queue a |dec_surface| to device for decoding.
139 void Enqueue(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
140
141 // Dequeue any V4L2 buffers available and process.
142 void Dequeue();
143
144 // V4L2 QBUF helpers.
145 bool EnqueueInputRecord(int index, uint32_t config_store);
146 bool EnqueueOutputRecord(int index);
147
148 // Set input and output formats in hardware.
149 bool SetupFormats();
150
151 // Create input and output buffers.
152 bool CreateInputBuffers();
153 bool CreateOutputBuffers();
154
155 // Destroy input buffers.
156 void DestroyInputBuffers();
157
158 // Destroy output buffers and release associated resources (textures,
159 // EGLImages). If |dismiss| is true, also dismissing the associated
160 // PictureBuffers.
161 bool DestroyOutputs(bool dismiss);
162
163 // Used by DestroyOutputs.
164 bool DestroyOutputBuffers();
165
166 // Dismiss all |picture_buffer_ids| via Client::DismissPictureBuffer()
167 // and signal |done| after finishing.
168 void DismissPictures(const std::vector<int32_t>& picture_buffer_ids,
169 base::WaitableEvent* done);
170
171 // Task to finish initialization on decoder_thread_.
172 void InitializeTask();
173
174 void NotifyError(Error error);
175 void DestroyTask();
176
177 // Sets the state to kError and notifies client if needed.
178 void SetErrorState(Error error);
179
180 // Event handling. Events include flush, reset and resolution change and are
181 // processed while in kIdle state.
182
183 // Surface set change (resolution change) flow.
184 // If we have no surfaces allocated, start it immediately, otherwise mark
185 // ourselves as pending for surface set change.
186 void InitiateSurfaceSetChange();
187 // If a surface set change is pending and we are ready, stop the device,
188 // destroy outputs, releasing resources and dismissing pictures as required,
189 // followed by starting the flow to allocate a new set for the current
190 // resolution/DPB size, as provided by decoder.
191 bool FinishSurfaceSetChange();
192
193 // Flush flow when requested by client.
194 // When Flush() is called, it posts a FlushTask, which checks the input queue.
195 // If nothing is pending for decode on decoder_input_queue_, we call
196 // InitiateFlush() directly. Otherwise, we push a dummy BitstreamBufferRef
197 // onto the decoder_input_queue_ to schedule a flush. When we reach it later
198 // on, we call InitiateFlush() to perform it at the correct time.
199 void FlushTask();
200 // Tell the decoder to flush all frames, reset it and mark us as scheduled
201 // for flush, so that we can finish it once all pending decodes are finished.
202 void InitiateFlush();
203 // To be called if decoder_flushing_ is true. If not all pending frames are
204 // decoded, return false, requesting the caller to try again later.
205 // Otherwise perform flush by sending all pending pictures to the client,
206 // notify it that flush is finished and return true, informing the caller
207 // that further progress can be made.
208 bool FinishFlush();
209
210 // Reset flow when requested by client.
211 // Drop all inputs, reset the decoder and mark us as pending for reset.
212 void ResetTask();
213 // To be called if decoder_resetting_ is true. If not all pending frames are
214 // decoded, return false, requesting the caller to try again later.
215 // Otherwise perform reset by dropping all pending outputs (client is not
216 // interested anymore), notifying it that reset is finished, and return true,
217 // informing the caller that further progress can be made.
218 bool FinishReset();
219
220 // Called when a new event is pended. Transitions us into kIdle state (if not
221 // already in it), if possible. Also starts processing events.
222 void NewEventPending();
223
224 // Called after all events are processed successfully (i.e. all Finish*()
225 // methods return true) to return to decoding state.
226 bool FinishEventProcessing();
227
228 // Process pending events, if any.
229 void ProcessPendingEventsIfNeeded();
230
231
232 // Allocate V4L2 buffers and assign them to |buffers| provided by the client
233 // via AssignPictureBuffers() on decoder thread.
234 void AssignPictureBuffersTask(
235 const std::vector<media::PictureBuffer>& buffers);
236
237 // Use buffer backed by dmabuf file descriptors in |passed_dmabuf_fds| for the
238 // OutputRecord associated with |picture_buffer_id|, taking ownership of the
239 // file descriptors.
240 void ImportBufferForPictureTask(
241 int32_t picture_buffer_id,
242 // TODO(posciak): (crbug.com/561749) we should normally be able to pass
243 // the vector by itself via std::move, but it's not possible to do this
244 // if this method is used as a callback.
245 std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds);
246
247 // Create an EGLImage for the buffer associated with V4L2 |buffer_index| and
248 // for |picture_buffer_id|, backed by dmabuf file descriptors in
249 // |passed_dmabuf_fds|, taking ownership of them.
250 // The buffer should be bound to |texture_id| and is of |size| and format
251 // described by |fourcc|.
252 void CreateEGLImageFor(
253 size_t buffer_index,
254 int32_t picture_buffer_id,
255 // TODO(posciak): (crbug.com/561749) we should normally be able to pass
256 // the vector by itself via std::move, but it's not possible to do this
257 // if this method is used as a callback.
258 std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds,
259 GLuint texture_id,
260 const gfx::Size& size,
261 uint32_t fourcc);
262
263 // Take the EGLImage |egl_image|, created for |picture_buffer_id|, and use it
264 // for OutputRecord at |buffer_index|. The buffer is backed by
265 // |passed_dmabuf_fds|, and the OutputRecord takes ownership of them.
266 void AssignEGLImage(
267 size_t buffer_index,
268 int32_t picture_buffer_id,
269 EGLImageKHR egl_image,
270 // TODO(posciak): (crbug.com/561749) we should normally be able to pass
271 // the vector by itself via std::move, but it's not possible to do this
272 // if this method is used as a callback.
273 std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds);
274
275 // Performed on decoder_thread_ as a consequence of poll() on decoder_thread_
276 // returning an event.
277 void ServiceDeviceTask();
278
279 // Schedule poll if we have any buffers queued and the poll thread
280 // is not stopped (on surface set change).
281 void SchedulePollIfNeeded();
282
283 // Attempt to start/stop device_poll_thread_.
284 bool StartDevicePoll();
285 bool StopDevicePoll(bool keep_input_state);
286
287 // Ran on device_poll_thread_ to wait for device events.
288 void DevicePollTask(bool poll_device);
289
290 enum State {
291 // We are in this state until Initialize() returns successfully.
292 // We can't post errors to the client in this state yet.
293 kUninitialized,
294 // Initialize() returned successfully.
295 kInitialized,
296 // This state allows making progress decoding more input stream.
297 kDecoding,
298 // Transitional state when we are not decoding any more stream, but are
299 // performing flush, reset, resolution change or are destroying ourselves.
300 kIdle,
301 // Requested new PictureBuffers via ProvidePictureBuffers(), awaiting
302 // AssignPictureBuffers().
303 kAwaitingPictureBuffers,
304 // Error state, set when sending NotifyError to client.
305 kError,
306 };
307
308 // Buffer id for flush buffer, queued by FlushTask().
309 const int kFlushBufferId = -2;
310
311 // Handler for Decode() on decoder_thread_.
312 void DecodeTask(const media::BitstreamBuffer& bitstream_buffer);
313
314 // Schedule a new DecodeBufferTask if we are decoding.
315 void ScheduleDecodeBufferTaskIfNeeded();
316
317 // Main decoder loop. Keep decoding the current buffer in decoder_, asking
318 // for more stream via TrySetNewBistreamBuffer() if decoder_ requests so,
319 // and handle other returns from it appropriately.
320 void DecodeBufferTask();
321
322 // Check decoder_input_queue_ for any available buffers to decode and
323 // set the decoder_current_bitstream_buffer_ to the next buffer if one is
324 // available, taking it off the queue. Also set the current stream pointer
325 // in decoder_, and return true.
326 // Return false if no buffers are pending on decoder_input_queue_.
327 bool TrySetNewBistreamBuffer();
328
329 // Auto-destruction reference for EGLSync (for message-passing).
330 struct EGLSyncKHRRef;
331 void ReusePictureBufferTask(int32_t picture_buffer_id,
332 std::unique_ptr<EGLSyncKHRRef> egl_sync_ref);
333
334 // Called to actually send |dec_surface| to the client, after it is decoded
335 // preserving the order in which it was scheduled via SurfaceReady().
336 void OutputSurface(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
337
338 // Goes over the |decoder_display_queue_| and sends all buffers from the
339 // front of the queue that are already decoded to the client, in order.
340 void TryOutputSurfaces();
341
342 // Creates a new decode surface or returns nullptr if one is not available.
343 scoped_refptr<V4L2DecodeSurface> CreateSurface();
344
345 // Send decoded pictures to PictureReady.
346 void SendPictureReady();
347
348 // Callback that indicates a picture has been cleared.
349 void PictureCleared();
350
351 size_t input_planes_count_;
352 size_t output_planes_count_;
353
354 // GPU Child thread task runner.
355 const scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_;
356
357 // Task runner Decode() and PictureReady() run on.
358 scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner_;
359
360 // WeakPtr<> pointing to |this| for use in posting tasks from the decoder or
361 // device worker threads back to the child thread.
362 base::WeakPtr<V4L2SliceVideoDecodeAccelerator> weak_this_;
363
364 // To expose client callbacks from VideoDecodeAccelerator.
365 // NOTE: all calls to these objects *MUST* be executed on
366 // child_task_runner_.
367 std::unique_ptr<base::WeakPtrFactory<VideoDecodeAccelerator::Client>>
368 client_ptr_factory_;
369 base::WeakPtr<VideoDecodeAccelerator::Client> client_;
370 // Callbacks to |decode_client_| must be executed on |decode_task_runner_|.
371 base::WeakPtr<Client> decode_client_;
372
373 // V4L2 device in use.
374 scoped_refptr<V4L2Device> device_;
375
376 // Thread to communicate with the device on.
377 base::Thread decoder_thread_;
378 scoped_refptr<base::SingleThreadTaskRunner> decoder_thread_task_runner_;
379
380 // Thread used to poll the device for events.
381 base::Thread device_poll_thread_;
382
383 // Input queue state.
384 bool input_streamon_;
385 // Number of input buffers enqueued to the device.
386 int input_buffer_queued_count_;
387 // Input buffers ready to use; LIFO since we don't care about ordering.
388 std::list<int> free_input_buffers_;
389 // Mapping of int index to an input buffer record.
390 std::vector<InputRecord> input_buffer_map_;
391
392 // Output queue state.
393 bool output_streamon_;
394 // Number of output buffers enqueued to the device.
395 int output_buffer_queued_count_;
396 // Output buffers ready to use.
397 std::list<int> free_output_buffers_;
398 // Mapping of int index to an output buffer record.
399 std::vector<OutputRecord> output_buffer_map_;
400
401 media::VideoCodecProfile video_profile_;
402 uint32_t output_format_fourcc_;
403 gfx::Size visible_size_;
404 gfx::Size coded_size_;
405
406 struct BitstreamBufferRef;
407 // Input queue of stream buffers coming from the client.
408 std::queue<linked_ptr<BitstreamBufferRef>> decoder_input_queue_;
409 // BitstreamBuffer currently being processed.
410 std::unique_ptr<BitstreamBufferRef> decoder_current_bitstream_buffer_;
411
412 // Queue storing decode surfaces ready to be output as soon as they are
413 // decoded. The surfaces must be output in order they are queued.
414 std::queue<scoped_refptr<V4L2DecodeSurface>> decoder_display_queue_;
415
416 // Decoder state.
417 State state_;
418
419 Config::OutputMode output_mode_;
420
421 // If any of these are true, we are waiting for the device to finish decoding
422 // all previously-queued frames, so we can finish the flush/reset/surface
423 // change flows. These can stack.
424 bool decoder_flushing_;
425 bool decoder_resetting_;
426 bool surface_set_change_pending_;
427
428 // Hardware accelerators.
429 // TODO(posciak): Try to have a superclass here if possible.
430 std::unique_ptr<V4L2H264Accelerator> h264_accelerator_;
431 std::unique_ptr<V4L2VP8Accelerator> vp8_accelerator_;
432
433 // Codec-specific software decoder in use.
434 std::unique_ptr<AcceleratedVideoDecoder> decoder_;
435
436 // Surfaces queued to device to keep references to them while decoded.
437 using V4L2DecodeSurfaceByOutputId =
438 std::map<int, scoped_refptr<V4L2DecodeSurface>>;
439 V4L2DecodeSurfaceByOutputId surfaces_at_device_;
440
441 // Surfaces sent to client to keep references to them while displayed.
442 using V4L2DecodeSurfaceByPictureBufferId =
443 std::map<int32_t, scoped_refptr<V4L2DecodeSurface>>;
444 V4L2DecodeSurfaceByPictureBufferId surfaces_at_display_;
445
446 // Record for decoded pictures that can be sent to PictureReady.
447 struct PictureRecord;
448 // Pictures that are ready but not sent to PictureReady yet.
449 std::queue<PictureRecord> pending_picture_ready_;
450
451 // The number of pictures that are sent to PictureReady and will be cleared.
452 int picture_clearing_count_;
453
454 // EGL state
455 EGLDisplay egl_display_;
456
457 // Callback to get current GLContext.
458 GetGLContextCallback get_gl_context_cb_;
459 // Callback to set the correct gl context.
460 MakeGLContextCurrentCallback make_context_current_cb_;
461
462 // The WeakPtrFactory for |weak_this_|.
463 base::WeakPtrFactory<V4L2SliceVideoDecodeAccelerator> weak_this_factory_;
464
465 DISALLOW_COPY_AND_ASSIGN(V4L2SliceVideoDecodeAccelerator);
466 };
467
468 class V4L2H264Picture;
469 class V4L2VP8Picture;
470
471 } // namespace content
472
473 #endif // CONTENT_COMMON_GPU_MEDIA_V4L2_SLICE_VIDEO_DECODE_ACCELERATOR_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698