OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #ifndef CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_H_ | 5 #ifndef CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_H_ |
6 #define CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_H_ | 6 #define CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 #include "third_party/webrtc/modules/video_coding/include/video_codec_interface.
h" | 28 #include "third_party/webrtc/modules/video_coding/include/video_codec_interface.
h" |
29 #include "ui/gfx/geometry/rect.h" | 29 #include "ui/gfx/geometry/rect.h" |
30 | 30 |
31 namespace base { | 31 namespace base { |
32 class WaitableEvent; | 32 class WaitableEvent; |
33 }; | 33 }; |
34 | 34 |
35 namespace media { | 35 namespace media { |
36 class DecoderBuffer; | 36 class DecoderBuffer; |
37 class GpuVideoAcceleratorFactories; | 37 class GpuVideoAcceleratorFactories; |
| 38 class VideoDecoder; |
38 } | 39 } |
39 | 40 |
40 namespace gpu { | 41 namespace gpu { |
41 struct SyncToken; | 42 struct SyncToken; |
42 } | 43 } |
43 | 44 |
44 namespace content { | 45 namespace content { |
45 | 46 |
46 // This class uses hardware accelerated video decoder to decode video for | 47 // This class uses hardware accelerated video decoder to decode video for |
47 // WebRTC. Lives on the media thread, where VDA::Client methods run on. | 48 // WebRTC. Lives on the media thread, where VDA::Client methods run on. |
48 // webrtc::VideoDecoder methods run on WebRTC DecodingThread or | 49 // webrtc::VideoDecoder methods run on WebRTC DecodingThread or |
49 // Chrome_libJingle_WorkerThread, which are trampolined to the media thread. | 50 // Chrome_libJingle_WorkerThread, which are trampolined to the media thread. |
50 // Decode() is non-blocking and queues the buffers. Decoded frames are | 51 // Decode() is non-blocking and queues the buffers. Decoded frames are |
51 // delivered to WebRTC on the media task runner. | 52 // delivered to WebRTC on the media task runner. |
52 class CONTENT_EXPORT RTCVideoDecoder | 53 class CONTENT_EXPORT RTCVideoDecoder |
53 : NON_EXPORTED_BASE(public webrtc::VideoDecoder), | 54 : NON_EXPORTED_BASE(public webrtc::VideoDecoder) { |
54 public media::VideoDecodeAccelerator::Client { | |
55 public: | 55 public: |
56 ~RTCVideoDecoder() override; | 56 ~RTCVideoDecoder() override; |
57 | 57 |
58 // Creates a RTCVideoDecoder on the message loop of |factories|. Returns NULL | 58 using CreateVideoDecoderCB = |
59 // if failed. The video decoder will run on the message loop of |factories|. | 59 base::Callback<std::unique_ptr<media::VideoDecoder>()>; |
| 60 |
| 61 // TODO(slan): Document! |
60 static std::unique_ptr<RTCVideoDecoder> Create( | 62 static std::unique_ptr<RTCVideoDecoder> Create( |
61 webrtc::VideoCodecType type, | 63 webrtc::VideoCodecType type, |
62 media::GpuVideoAcceleratorFactories* factories); | 64 const CreateVideoDecoderCB& create_video_decoder_cb, |
63 // Destroys |decoder| on the loop of |factories| | 65 const scoped_refptr<base::SingleThreadTaskRunner>& decoder_task_runner); |
64 static void Destroy(webrtc::VideoDecoder* decoder, | 66 // Destroys |decoder| on |decoder_task_runner|. |
65 media::GpuVideoAcceleratorFactories* factories); | 67 static void Destroy( |
| 68 webrtc::VideoDecoder* decoder, |
| 69 const scoped_refptr<base::SingleThreadTaskRunner>& decoder_task_runner); |
66 | 70 |
67 // webrtc::VideoDecoder implementation. | 71 // webrtc::VideoDecoder implementation. |
68 // Called on WebRTC DecodingThread. | 72 // Called on WebRTC DecodingThread. |
69 int32_t InitDecode(const webrtc::VideoCodec* codecSettings, | 73 int32_t InitDecode(const webrtc::VideoCodec* codecSettings, |
70 int32_t numberOfCores) override; | 74 int32_t numberOfCores) override; |
71 // Called on WebRTC DecodingThread. | 75 // Called on WebRTC DecodingThread. |
72 int32_t Decode(const webrtc::EncodedImage& inputImage, | 76 int32_t Decode(const webrtc::EncodedImage& inputImage, |
73 bool missingFrames, | 77 bool missingFrames, |
74 const webrtc::RTPFragmentationHeader* fragmentation, | 78 const webrtc::RTPFragmentationHeader* fragmentation, |
75 const webrtc::CodecSpecificInfo* codecSpecificInfo = NULL, | 79 const webrtc::CodecSpecificInfo* codecSpecificInfo = NULL, |
76 int64_t renderTimeMs = -1) override; | 80 int64_t renderTimeMs = -1) override; |
77 // Called on WebRTC DecodingThread. | 81 // Called on WebRTC DecodingThread. |
78 int32_t RegisterDecodeCompleteCallback( | 82 int32_t RegisterDecodeCompleteCallback( |
79 webrtc::DecodedImageCallback* callback) override; | 83 webrtc::DecodedImageCallback* callback) override; |
80 // Called on Chrome_libJingle_WorkerThread. The child thread is blocked while | 84 // Called on Chrome_libJingle_WorkerThread. The child thread is blocked while |
81 // this runs. | 85 // this runs. |
82 int32_t Release() override; | 86 int32_t Release() override; |
83 | 87 |
84 // VideoDecodeAccelerator::Client implementation. | |
85 void ProvidePictureBuffers(uint32_t count, | |
86 media::VideoPixelFormat format, | |
87 uint32_t textures_per_buffer, | |
88 const gfx::Size& size, | |
89 uint32_t texture_target) override; | |
90 void DismissPictureBuffer(int32_t id) override; | |
91 void PictureReady(const media::Picture& picture) override; | |
92 void NotifyEndOfBitstreamBuffer(int32_t id) override; | |
93 void NotifyFlushDone() override; | |
94 void NotifyResetDone() override; | |
95 void NotifyError(media::VideoDecodeAccelerator::Error error) override; | |
96 | |
97 private: | 88 private: |
98 // Metadata of a bitstream buffer. | |
99 struct BufferData { | |
100 BufferData(int32_t bitstream_buffer_id, | |
101 uint32_t timestamp, | |
102 size_t size, | |
103 const gfx::Rect& visible_rect); | |
104 BufferData(); | |
105 ~BufferData(); | |
106 int32_t bitstream_buffer_id; | |
107 uint32_t timestamp; // in 90KHz | |
108 size_t size; // buffer size | |
109 gfx::Rect visible_rect; | |
110 }; | |
111 | |
112 FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, IsBufferAfterReset); | 89 FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, IsBufferAfterReset); |
113 FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, IsFirstBufferAfterReset); | 90 FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, IsFirstBufferAfterReset); |
114 FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, GetVDAErrorCounterForTesting); | 91 FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, GetVDAErrorCounterForTesting); |
115 | 92 |
116 RTCVideoDecoder(webrtc::VideoCodecType type, | 93 RTCVideoDecoder( |
117 media::GpuVideoAcceleratorFactories* factories); | 94 webrtc::VideoCodecType type, |
| 95 const CreateVideoDecoderCB& create_video_decoder_cb, |
| 96 const scoped_refptr<base::SingleThreadTaskRunner>& decoder_task_runner); |
118 | 97 |
119 // Requests a buffer to be decoded by VDA. | 98 // Requests a buffer to be decoded by VDA. |
120 void RequestBufferDecode(); | 99 void RequestBufferDecode(); |
121 | 100 |
122 bool CanMoreDecodeWorkBeDone(); | 101 bool CanMoreDecodeWorkBeDone(); |
123 | 102 |
124 // Returns true if bitstream buffer id |id_buffer| comes after |id_reset|. | 103 // Returns true if bitstream buffer id |id_buffer| comes after |id_reset|. |
125 // This handles the wraparound. | 104 // This handles the wraparound. |
126 bool IsBufferAfterReset(int32_t id_buffer, int32_t id_reset); | 105 bool IsBufferAfterReset(int32_t id_buffer, int32_t id_reset); |
127 | 106 |
128 // Returns true if bitstream buffer |id_buffer| is the first buffer after | 107 // Returns true if bitstream buffer |id_buffer| is the first buffer after |
129 // |id_reset|. | 108 // |id_reset|. |
130 bool IsFirstBufferAfterReset(int32_t id_buffer, int32_t id_reset); | 109 bool IsFirstBufferAfterReset(int32_t id_buffer, int32_t id_reset); |
131 | 110 |
132 int GetVDAErrorCounterForTesting() { return vda_error_counter_; } | 111 int GetVDAErrorCounterForTesting() { return decoder_error_counter_; } |
133 | 112 |
134 // Saves a WebRTC buffer in |decode_buffers_| for decode. | 113 // Saves a DecoderBuffer buffer in |pending_buffers_| waiting to be sent to |
135 void SaveToDecodeBuffers_Locked( | 114 // the decoder. Returns true on success. |
136 const webrtc::EncodedImage& input_image, | 115 bool SaveToPendingBuffers_Locked( |
137 std::unique_ptr<base::SharedMemory> shm_buffer, | 116 int32_t decoder_buffer_id, |
138 const BufferData& buffer_data); | 117 const scoped_refptr<media::DecoderBuffer>& decoder_buffer); |
139 | 118 |
140 // Saves a WebRTC buffer in |pending_buffers_| waiting for SHM available. | 119 // Calls Reset() on |decoder_|. Must be executed on the decoder thread. |
141 // Returns true on success. | 120 void ResetOnDecoderThread(); |
142 bool SaveToPendingBuffers_Locked(const webrtc::EncodedImage& input_image, | 121 void OnResetDone(); |
143 const BufferData& buffer_data); | |
144 | 122 |
145 // Gets SHM and moves pending buffers to decode buffers. | 123 void OnBufferDecoded(int32_t buffer_decode_id, |
146 void MovePendingBuffersToDecodeBuffers(); | 124 bool is_eos, |
147 | 125 media::DecodeStatus status); |
148 scoped_refptr<media::VideoFrame> CreateVideoFrame( | |
149 const media::Picture& picture, | |
150 const media::PictureBuffer& pb, | |
151 uint32_t timestamp, | |
152 const gfx::Rect& visible_rect, | |
153 media::VideoPixelFormat pixel_format); | |
154 | |
155 // Resets VDA. | |
156 void ResetInternal(); | |
157 | |
158 // Static method is to allow it to run even after RVD is deleted. | |
159 static void ReleaseMailbox(base::WeakPtr<RTCVideoDecoder> decoder, | |
160 media::GpuVideoAcceleratorFactories* factories, | |
161 int64_t picture_buffer_id, | |
162 uint32_t texture_id, | |
163 const gpu::SyncToken& release_sync_token); | |
164 // Tells VDA that a picture buffer can be recycled. | |
165 void ReusePictureBuffer(int64_t picture_buffer_id); | |
166 | |
167 // Creates |vda_| on the media thread. | |
168 void CreateVDA(media::VideoCodecProfile profile, base::WaitableEvent* waiter); | |
169 | |
170 void DestroyTextures(); | |
171 void DestroyVDA(); | |
172 | |
173 // Gets a shared-memory segment of at least |min_size| bytes from | |
174 // |available_shm_segments_|. Returns NULL if there is no buffer or the | |
175 // buffer is not big enough. | |
176 std::unique_ptr<base::SharedMemory> GetSHM_Locked(size_t min_size); | |
177 | |
178 // Returns a shared-memory segment to the available pool. | |
179 void PutSHM_Locked(std::unique_ptr<base::SharedMemory> shm_buffer); | |
180 | |
181 // Allocates |count| shared memory buffers of |size| bytes. | |
182 void CreateSHM(size_t count, size_t size); | |
183 | |
184 // Stores the buffer metadata to |input_buffer_data_|. | |
185 void RecordBufferData(const BufferData& buffer_data); | |
186 // Gets the buffer metadata from |input_buffer_data_|. | |
187 void GetBufferData(int32_t bitstream_buffer_id, | |
188 uint32_t* timestamp, | |
189 gfx::Rect* visible_rect); | |
190 | 126 |
191 // Records the result of InitDecode to UMA and returns |status|. | 127 // Records the result of InitDecode to UMA and returns |status|. |
192 int32_t RecordInitDecodeUMA(int32_t status); | 128 int32_t RecordInitDecodeUMA(int32_t status); |
193 | 129 |
194 // Asserts the contract that this class is operated on the right thread. | 130 // Asserts the contract that this class is operated on the right thread. |
195 void DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() const; | 131 void DCheckDecoderTaskRunnerIsCurrent() const; |
196 | 132 |
197 // Queries factories_ whether |profile| is supported and return true is so, | 133 // Queries factories_ whether |profile| is supported and return true is so, |
198 // false otherwise. If true, also set resolution limits for |profile| | 134 // false otherwise. If true, also set resolution limits for |profile| |
199 // in min/max_resolution_. | 135 // in min/max_resolution_. |
200 bool IsProfileSupported(media::VideoCodecProfile profile); | 136 bool IsProfileSupported(media::VideoCodecProfile profile); |
201 | 137 |
202 // Clears the pending_buffers_ queue, freeing memory. | 138 // Clears the pending_buffers_ queue, freeing memory. Guarded by |lock_|. |
203 void ClearPendingBuffers(); | 139 void ClearPendingBuffers_Locked(); |
204 | 140 |
205 enum State { | 141 enum State { |
206 UNINITIALIZED, // The decoder has not initialized. | 142 UNINITIALIZED, // The decoder has not initialized. |
207 INITIALIZED, // The decoder has initialized. | 143 INITIALIZED, // The decoder has initialized. |
208 RESETTING, // The decoder is being reset. | 144 RESETTING, // The decoder is being reset. |
209 DECODE_ERROR, // Decoding error happened. | 145 DECODE_ERROR, // Decoding error happened. |
210 }; | 146 }; |
211 | 147 |
212 static const int32_t ID_LAST; // maximum bitstream buffer id | 148 static const int32_t ID_LAST; // maximum bitstream buffer id |
213 static const int32_t ID_HALF; // half of the maximum bitstream buffer id | 149 static const int32_t ID_HALF; // half of the maximum bitstream buffer id |
214 static const int32_t ID_INVALID; // indicates Reset or Release never occurred | 150 static const int32_t ID_INVALID; // indicates Reset or Release never occurred |
215 | 151 |
216 // The hardware video decoder. | 152 // The hardware video decoder. |
217 std::unique_ptr<media::VideoDecodeAccelerator> vda_; | 153 std::unique_ptr<::media::VideoDecoder> decoder_; |
| 154 void InitializeDecoder(media::VideoCodecProfile profile, |
| 155 media::VideoCodec codec, |
| 156 base::WaitableEvent* waiter); |
| 157 void OnDecoderInitialized(base::WaitableEvent* waiter, bool success); |
| 158 void OnFrameReady(const scoped_refptr<media::VideoFrame>& frame); |
218 | 159 |
219 media::VideoCodecProfile vda_codec_profile_; | 160 media::VideoCodecProfile vda_codec_profile_; |
220 | 161 |
221 // Number of times that |vda_| notified of an error. | 162 // Number of times that |vda_| notified of an error. |
222 uint32_t vda_error_counter_; | 163 uint32_t decoder_error_counter_; |
223 | 164 |
224 // The video codec type, as reported by WebRTC. | 165 // The video codec type, as reported by WebRTC. |
225 const webrtc::VideoCodecType video_codec_type_; | 166 const webrtc::VideoCodecType video_codec_type_; |
226 | 167 |
227 // The size of the incoming video frames. | 168 // The size of the incoming video frames. |
228 gfx::Size frame_size_; | 169 gfx::Size frame_size_; |
229 | 170 |
230 media::GpuVideoAcceleratorFactories* const factories_; | 171 const CreateVideoDecoderCB create_video_decoder_cb_; |
231 | 172 scoped_refptr<base::SingleThreadTaskRunner> decoder_task_runner_; |
232 // The texture target used for decoded pictures. | |
233 uint32_t decoder_texture_target_; | |
234 | 173 |
235 // The format of the decoded pictures. | 174 // The format of the decoded pictures. |
236 media::VideoPixelFormat pixel_format_; | 175 media::VideoPixelFormat pixel_format_; |
237 | 176 |
238 // Metadata of the buffers that have been sent for decode. | |
239 std::list<BufferData> input_buffer_data_; | |
240 | |
241 // A map from bitstream buffer IDs to bitstream buffers that are being | |
242 // processed by VDA. | |
243 std::map<int32_t, std::unique_ptr<base::SharedMemory>> | |
244 bitstream_buffers_in_decoder_; | |
245 | |
246 // A map from picture buffer IDs to texture-backed picture buffers. | |
247 std::map<int32_t, media::PictureBuffer> assigned_picture_buffers_; | |
248 | |
249 // PictureBuffers given to us by VDA via PictureReady, which we sent forward | |
250 // as VideoFrames to be rendered via read_cb_, and which will be returned | |
251 // to us via ReusePictureBuffer. | |
252 typedef std::map<int32_t /* picture_buffer_id */, uint32_t /* texture_id */> | |
253 PictureBufferTextureMap; | |
254 PictureBufferTextureMap picture_buffers_at_display_; | |
255 | |
256 // The id that will be given to the next picture buffer. | |
257 int32_t next_picture_buffer_id_; | |
258 | |
259 // Protects |state_|, |decode_complete_callback_| , |num_shm_buffers_|, | 177 // Protects |state_|, |decode_complete_callback_| , |num_shm_buffers_|, |
260 // |available_shm_segments_|, |pending_buffers_|, |decode_buffers_|, | 178 // |available_shm_segments_|, |pending_buffers_|, |decode_buffers_|, |
261 // |next_bitstream_buffer_id_|, |reset_bitstream_buffer_id_| and | 179 // |next_decoder_buffer_id_|, |reset_bitstream_buffer_id_| and |
262 // |vda_error_counter_|. | 180 // |decoder_error_counter_|. |
263 base::Lock lock_; | 181 base::Lock lock_; |
264 | 182 |
265 // The state of RTCVideoDecoder. Guarded by |lock_|. | 183 // The state of RTCVideoDecoder. Guarded by |lock_|. |
266 State state_; | 184 State state_; |
267 | 185 |
268 // Guarded by |lock_|. | 186 // Guarded by |lock_|. |
269 webrtc::DecodedImageCallback* decode_complete_callback_; | 187 webrtc::DecodedImageCallback* decode_complete_callback_; |
270 | 188 |
271 // Total number of allocated SHM buffers. Guarded by |lock_|. | |
272 size_t num_shm_buffers_; | |
273 | |
274 // Shared-memory buffer pool. Since allocating SHM segments requires a | |
275 // round-trip to the browser process, we keep allocation out of the | |
276 // steady-state of the decoder. Guarded by |lock_|. | |
277 std::vector<std::unique_ptr<base::SharedMemory>> available_shm_segments_; | |
278 | |
279 // A queue storing WebRTC encoding images (and their metadata) that are | 189 // A queue storing WebRTC encoding images (and their metadata) that are |
280 // waiting for the shared memory. Guarded by |lock_|. | 190 // waiting for the shared memory. Guarded by |lock_|. |
281 std::deque<std::pair<webrtc::EncodedImage, BufferData>> pending_buffers_; | 191 std::deque<std::pair<int32_t, scoped_refptr<media::DecoderBuffer>>> |
| 192 pending_buffers_; |
282 | 193 |
283 // A queue storing buffers (and their metadata) that will be sent to VDA for | 194 std::unordered_map<int32_t /* decoder_buffer_id */, |
284 // decode. Guarded by |lock_|. | 195 scoped_refptr<media::DecoderBuffer>> |
285 std::deque<std::pair<std::unique_ptr<base::SharedMemory>, BufferData>> | 196 buffers_in_decoder_; |
286 decode_buffers_; | |
287 | 197 |
288 // The id that will be given to the next bitstream buffer. Guarded by |lock_|. | 198 // The id that will be given to the next bitstream buffer. Guarded by |lock_|. |
289 int32_t next_bitstream_buffer_id_; | 199 int32_t next_decoder_buffer_id_; |
290 | 200 |
291 // A buffer that has an id less than this should be dropped because Reset or | 201 // A buffer that has an id less than this should be dropped because Reset or |
292 // Release has been called. Guarded by |lock_|. | 202 // Release has been called. Guarded by |lock_|. |
293 int32_t reset_bitstream_buffer_id_; | 203 int32_t reset_decoder_buffer_id_; |
294 | 204 |
295 // Minimum and maximum supported resolutions for the current profile/VDA. | 205 // Minimum and maximum supported resolutions for the current profile/VDA. |
296 gfx::Size min_resolution_; | 206 gfx::Size min_resolution_; |
297 gfx::Size max_resolution_; | 207 gfx::Size max_resolution_; |
298 | 208 |
299 // Must be destroyed, or invalidated, on the media thread. | 209 // Must be destroyed, or invalidated, on the media thread. |
300 // NOTE: Weak pointers must be invalidated before all other member variables. | 210 // NOTE: Weak pointers must be invalidated before all other member variables. |
301 base::WeakPtrFactory<RTCVideoDecoder> weak_factory_; | 211 base::WeakPtrFactory<RTCVideoDecoder> weak_factory_; |
302 | 212 |
303 DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoder); | 213 DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoder); |
304 }; | 214 }; |
305 | 215 |
306 } // namespace content | 216 } // namespace content |
307 | 217 |
308 #endif // CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_H_ | 218 #endif // CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_H_ |
OLD | NEW |