OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // | 4 // |
5 // This file contains an implementation of VideoDecodeAccelerator | 5 // This file contains an implementation of VideoDecodeAccelerator |
6 // that utilizes hardware video decoders, which expose Video4Linux 2 API | 6 // that utilizes hardware video decoders, which expose Video4Linux 2 API |
7 // (http://linuxtv.org/downloads/v4l-dvb-apis/). | 7 // (http://linuxtv.org/downloads/v4l-dvb-apis/). |
8 | 8 |
9 #ifndef CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_DECODE_ACCELERATOR_H_ | 9 #ifndef MEDIA_GPU_V4L2_VIDEO_DECODE_ACCELERATOR_H_ |
10 #define CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_DECODE_ACCELERATOR_H_ | 10 #define MEDIA_GPU_V4L2_VIDEO_DECODE_ACCELERATOR_H_ |
11 | 11 |
12 #include <stddef.h> | 12 #include <stddef.h> |
13 #include <stdint.h> | 13 #include <stdint.h> |
14 | 14 |
15 #include <memory> | 15 #include <memory> |
16 #include <queue> | 16 #include <queue> |
17 #include <vector> | 17 #include <vector> |
18 | 18 |
19 #include "base/callback_forward.h" | 19 #include "base/callback_forward.h" |
20 #include "base/macros.h" | 20 #include "base/macros.h" |
21 #include "base/memory/linked_ptr.h" | 21 #include "base/memory/linked_ptr.h" |
22 #include "base/memory/ref_counted.h" | 22 #include "base/memory/ref_counted.h" |
23 #include "base/synchronization/waitable_event.h" | 23 #include "base/synchronization/waitable_event.h" |
24 #include "base/threading/thread.h" | 24 #include "base/threading/thread.h" |
25 #include "content/common/content_export.h" | |
26 #include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h" | |
27 #include "content/common/gpu/media/v4l2_device.h" | |
28 #include "media/base/limits.h" | 25 #include "media/base/limits.h" |
29 #include "media/base/video_decoder_config.h" | 26 #include "media/base/video_decoder_config.h" |
| 27 #include "media/gpu/gpu_video_decode_accelerator_helpers.h" |
| 28 #include "media/gpu/media_gpu_export.h" |
| 29 #include "media/gpu/v4l2_device.h" |
30 #include "media/video/picture.h" | 30 #include "media/video/picture.h" |
31 #include "media/video/video_decode_accelerator.h" | 31 #include "media/video/video_decode_accelerator.h" |
32 #include "ui/gfx/geometry/size.h" | 32 #include "ui/gfx/geometry/size.h" |
33 #include "ui/gl/gl_bindings.h" | 33 #include "ui/gl/gl_bindings.h" |
34 | 34 |
35 namespace media { | 35 namespace media { |
36 class H264Parser; | 36 class H264Parser; |
37 } // namespace media | 37 } // namespace media |
38 | 38 |
39 namespace content { | 39 namespace media { |
40 // This class handles video accelerators directly through a V4L2 device exported | 40 // This class handles video accelerators directly through a V4L2 device exported |
41 // by the hardware blocks. | 41 // by the hardware blocks. |
42 // | 42 // |
43 // The threading model of this class is driven by the fact that it needs to | 43 // The threading model of this class is driven by the fact that it needs to |
44 // interface two fundamentally different event queues -- the one Chromium | 44 // interface two fundamentally different event queues -- the one Chromium |
45 // provides through MessageLoop, and the one driven by the V4L2 devices which | 45 // provides through MessageLoop, and the one driven by the V4L2 devices which |
46 // is waited on with epoll(). There are three threads involved in this class: | 46 // is waited on with epoll(). There are three threads involved in this class: |
47 // | 47 // |
48 // * The child thread, which is the main GPU process thread which calls the | 48 // * The child thread, which is the main GPU process thread which calls the |
49 // media::VideoDecodeAccelerator entry points. Calls from this thread | 49 // media::VideoDecodeAccelerator entry points. Calls from this thread |
(...skipping 17 matching lines...) Expand all Loading... |
67 // right order, not fiddling with locks. | 67 // right order, not fiddling with locks. |
68 // Buffer creation is a two-step process that is serviced partially on the | 68 // Buffer creation is a two-step process that is serviced partially on the |
69 // Child thread, because we need to wait for the client to provide textures | 69 // Child thread, because we need to wait for the client to provide textures |
70 // for the buffers we allocate. We cannot keep the decoder thread running while | 70 // for the buffers we allocate. We cannot keep the decoder thread running while |
71 // the client allocates Pictures for us, because we need to REQBUFS first to get | 71 // the client allocates Pictures for us, because we need to REQBUFS first to get |
72 // the required number of output buffers from the device and that cannot be done | 72 // the required number of output buffers from the device and that cannot be done |
73 // unless we free the previous set of buffers, leaving the decoding in a | 73 // unless we free the previous set of buffers, leaving the decoding in a |
74 // inoperable state for the duration of the wait for Pictures. So to prevent | 74 // inoperable state for the duration of the wait for Pictures. So to prevent |
75 // subtle races (esp. if we get Reset() in the meantime), we block the decoder | 75 // subtle races (esp. if we get Reset() in the meantime), we block the decoder |
76 // thread while we wait for AssignPictureBuffers from the client. | 76 // thread while we wait for AssignPictureBuffers from the client. |
77 class CONTENT_EXPORT V4L2VideoDecodeAccelerator | 77 class MEDIA_GPU_EXPORT V4L2VideoDecodeAccelerator |
78 : public media::VideoDecodeAccelerator { | 78 : public media::VideoDecodeAccelerator { |
79 public: | 79 public: |
80 V4L2VideoDecodeAccelerator( | 80 V4L2VideoDecodeAccelerator( |
81 EGLDisplay egl_display, | 81 EGLDisplay egl_display, |
82 const GetGLContextCallback& get_gl_context_cb, | 82 const GetGLContextCallback& get_gl_context_cb, |
83 const MakeGLContextCurrentCallback& make_context_current_cb, | 83 const MakeGLContextCurrentCallback& make_context_current_cb, |
84 const scoped_refptr<V4L2Device>& device); | 84 const scoped_refptr<V4L2Device>& device); |
85 ~V4L2VideoDecodeAccelerator() override; | 85 ~V4L2VideoDecodeAccelerator() override; |
86 | 86 |
87 // media::VideoDecodeAccelerator implementation. | 87 // media::VideoDecodeAccelerator implementation. |
88 // Note: Initialize() and Destroy() are synchronous. | 88 // Note: Initialize() and Destroy() are synchronous. |
89 bool Initialize(const Config& config, Client* client) override; | 89 bool Initialize(const Config& config, Client* client) override; |
90 void Decode(const media::BitstreamBuffer& bitstream_buffer) override; | 90 void Decode(const media::BitstreamBuffer& bitstream_buffer) override; |
91 void AssignPictureBuffers( | 91 void AssignPictureBuffers( |
92 const std::vector<media::PictureBuffer>& buffers) override; | 92 const std::vector<media::PictureBuffer>& buffers) override; |
93 void ReusePictureBuffer(int32_t picture_buffer_id) override; | 93 void ReusePictureBuffer(int32_t picture_buffer_id) override; |
94 void Flush() override; | 94 void Flush() override; |
95 void Reset() override; | 95 void Reset() override; |
96 void Destroy() override; | 96 void Destroy() override; |
97 bool TryToSetupDecodeOnSeparateThread( | 97 bool TryToSetupDecodeOnSeparateThread( |
98 const base::WeakPtr<Client>& decode_client, | 98 const base::WeakPtr<Client>& decode_client, |
99 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) | 99 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) |
100 override; | 100 override; |
101 | 101 |
102 static media::VideoDecodeAccelerator::SupportedProfiles | 102 static media::VideoDecodeAccelerator::SupportedProfiles |
103 GetSupportedProfiles(); | 103 GetSupportedProfiles(); |
104 | 104 |
105 private: | 105 private: |
106 // These are rather subjectively tuned. | 106 // These are rather subjectively tuned. |
107 enum { | 107 enum { |
108 kInputBufferCount = 8, | 108 kInputBufferCount = 8, |
109 // TODO(posciak): determine input buffer size based on level limits. | 109 // TODO(posciak): determine input buffer size based on level limits. |
110 // See http://crbug.com/255116. | 110 // See http://crbug.com/255116. |
111 // Input bitstream buffer size for up to 1080p streams. | 111 // Input bitstream buffer size for up to 1080p streams. |
112 kInputBufferMaxSizeFor1080p = 1024 * 1024, | 112 kInputBufferMaxSizeFor1080p = 1024 * 1024, |
113 // Input bitstream buffer size for up to 4k streams. | 113 // Input bitstream buffer size for up to 4k streams. |
114 kInputBufferMaxSizeFor4k = 4 * kInputBufferMaxSizeFor1080p, | 114 kInputBufferMaxSizeFor4k = 4 * kInputBufferMaxSizeFor1080p, |
115 // Number of output buffers to use for each VDA stage above what's required | 115 // Number of output buffers to use for each VDA stage above what's required |
116 // by the decoder (e.g. DPB size, in H264). We need | 116 // by the decoder (e.g. DPB size, in H264). We need |
117 // media::limits::kMaxVideoFrames to fill up the GpuVideoDecode pipeline, | 117 // media::limits::kMaxVideoFrames to fill up the GpuVideoDecode pipeline, |
118 // and +1 for a frame in transit. | 118 // and +1 for a frame in transit. |
119 kDpbOutputBufferExtraCount = media::limits::kMaxVideoFrames + 1, | 119 kDpbOutputBufferExtraCount = media::limits::kMaxVideoFrames + 1, |
120 }; | 120 }; |
121 | 121 |
122 // Internal state of the decoder. | 122 // Internal state of the decoder. |
123 enum State { | 123 enum State { |
124 kUninitialized, // Initialize() not yet called. | 124 kUninitialized, // Initialize() not yet called. |
125 kInitialized, // Initialize() returned true; ready to start decoding. | 125 kInitialized, // Initialize() returned true; ready to start decoding. |
126 kDecoding, // DecodeBufferInitial() successful; decoding frames. | 126 kDecoding, // DecodeBufferInitial() successful; decoding frames. |
127 kResetting, // Presently resetting. | 127 kResetting, // Presently resetting. |
128 kAfterReset, // After Reset(), ready to start decoding again. | 128 kAfterReset, // After Reset(), ready to start decoding again. |
129 kChangingResolution, // Performing resolution change, all remaining | 129 kChangingResolution, // Performing resolution change, all remaining |
130 // pre-change frames decoded and processed. | 130 // pre-change frames decoded and processed. |
131 kError, // Error in kDecoding state. | 131 kError, // Error in kDecoding state. |
132 }; | 132 }; |
133 | 133 |
134 enum BufferId { | 134 enum BufferId { |
135 kFlushBufferId = -2 // Buffer id for flush buffer, queued by FlushTask(). | 135 kFlushBufferId = -2 // Buffer id for flush buffer, queued by FlushTask(). |
136 }; | 136 }; |
137 | 137 |
138 // Auto-destruction reference for BitstreamBuffer, for message-passing from | 138 // Auto-destruction reference for BitstreamBuffer, for message-passing from |
139 // Decode() to DecodeTask(). | 139 // Decode() to DecodeTask(). |
140 struct BitstreamBufferRef; | 140 struct BitstreamBufferRef; |
141 | 141 |
142 // Auto-destruction reference for EGLSync (for message-passing). | 142 // Auto-destruction reference for EGLSync (for message-passing). |
143 struct EGLSyncKHRRef; | 143 struct EGLSyncKHRRef; |
144 | 144 |
145 // Record for decoded pictures that can be sent to PictureReady. | 145 // Record for decoded pictures that can be sent to PictureReady. |
146 struct PictureRecord; | 146 struct PictureRecord; |
147 | 147 |
148 // Record for input buffers. | 148 // Record for input buffers. |
149 struct InputRecord { | 149 struct InputRecord { |
150 InputRecord(); | 150 InputRecord(); |
151 ~InputRecord(); | 151 ~InputRecord(); |
152 bool at_device; // held by device. | 152 bool at_device; // held by device. |
153 void* address; // mmap() address. | 153 void* address; // mmap() address. |
154 size_t length; // mmap() length. | 154 size_t length; // mmap() length. |
155 off_t bytes_used; // bytes filled in the mmap() segment. | 155 off_t bytes_used; // bytes filled in the mmap() segment. |
156 int32_t input_id; // triggering input_id as given to Decode(). | 156 int32_t input_id; // triggering input_id as given to Decode(). |
157 }; | 157 }; |
158 | 158 |
159 // Record for output buffers. | 159 // Record for output buffers. |
160 struct OutputRecord { | 160 struct OutputRecord { |
161 OutputRecord(); | 161 OutputRecord(); |
162 ~OutputRecord(); | 162 ~OutputRecord(); |
163 bool at_device; // held by device. | 163 bool at_device; // held by device. |
164 bool at_client; // held by client. | 164 bool at_client; // held by client. |
165 EGLImageKHR egl_image; // EGLImageKHR for the output buffer. | 165 EGLImageKHR egl_image; // EGLImageKHR for the output buffer. |
166 EGLSyncKHR egl_sync; // sync the compositor's use of the EGLImage. | 166 EGLSyncKHR egl_sync; // sync the compositor's use of the EGLImage. |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 // task execution should complete one buffer. If we fall behind (due to | 363 // task execution should complete one buffer. If we fall behind (due to |
364 // resource backpressure, etc.), we'll have to schedule more to catch up. | 364 // resource backpressure, etc.), we'll have to schedule more to catch up. |
365 int decoder_decode_buffer_tasks_scheduled_; | 365 int decoder_decode_buffer_tasks_scheduled_; |
366 // Picture buffers held by the client. | 366 // Picture buffers held by the client. |
367 int decoder_frames_at_client_; | 367 int decoder_frames_at_client_; |
368 // Are we flushing? | 368 // Are we flushing? |
369 bool decoder_flushing_; | 369 bool decoder_flushing_; |
370 // Got a reset request while we were performing resolution change. | 370 // Got a reset request while we were performing resolution change. |
371 bool resolution_change_reset_pending_; | 371 bool resolution_change_reset_pending_; |
372 // Input queue for decoder_thread_: BitstreamBuffers in. | 372 // Input queue for decoder_thread_: BitstreamBuffers in. |
373 std::queue<linked_ptr<BitstreamBufferRef> > decoder_input_queue_; | 373 std::queue<linked_ptr<BitstreamBufferRef>> decoder_input_queue_; |
374 // For H264 decode, hardware requires that we send it frame-sized chunks. | 374 // For H264 decode, hardware requires that we send it frame-sized chunks. |
375 // We'll need to parse the stream. | 375 // We'll need to parse the stream. |
376 std::unique_ptr<media::H264Parser> decoder_h264_parser_; | 376 std::unique_ptr<media::H264Parser> decoder_h264_parser_; |
377 // Set if the decoder has a pending incomplete frame in an input buffer. | 377 // Set if the decoder has a pending incomplete frame in an input buffer. |
378 bool decoder_partial_frame_pending_; | 378 bool decoder_partial_frame_pending_; |
379 | 379 |
380 // | 380 // |
381 // Hardware state and associated queues. Since decoder_thread_ services | 381 // Hardware state and associated queues. Since decoder_thread_ services |
382 // the hardware, decoder_thread_ owns these too. | 382 // the hardware, decoder_thread_ owns these too. |
383 // output_buffer_map_, free_output_buffers_ and output_planes_count_ are an | 383 // output_buffer_map_, free_output_buffers_ and output_planes_count_ are an |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 | 455 |
456 // Input format V4L2 fourccs this class supports. | 456 // Input format V4L2 fourccs this class supports. |
457 static const uint32_t supported_input_fourccs_[]; | 457 static const uint32_t supported_input_fourccs_[]; |
458 | 458 |
459 // The WeakPtrFactory for |weak_this_|. | 459 // The WeakPtrFactory for |weak_this_|. |
460 base::WeakPtrFactory<V4L2VideoDecodeAccelerator> weak_this_factory_; | 460 base::WeakPtrFactory<V4L2VideoDecodeAccelerator> weak_this_factory_; |
461 | 461 |
462 DISALLOW_COPY_AND_ASSIGN(V4L2VideoDecodeAccelerator); | 462 DISALLOW_COPY_AND_ASSIGN(V4L2VideoDecodeAccelerator); |
463 }; | 463 }; |
464 | 464 |
465 } // namespace content | 465 } // namespace media |
466 | 466 |
467 #endif // CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_DECODE_ACCELERATOR_H_ | 467 #endif // MEDIA_GPU_V4L2_VIDEO_DECODE_ACCELERATOR_H_ |
OLD | NEW |