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 #include "content/renderer/media/rtc_video_decoder.h" | 5 #include "content/renderer/media/rtc_video_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
10 #include "base/message_loop/message_loop_proxy.h" | 10 #include "base/message_loop/message_loop_proxy.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 height(height), | 67 height(height), |
68 size(size) {} | 68 size(size) {} |
69 | 69 |
70 RTCVideoDecoder::BufferData::BufferData() {} | 70 RTCVideoDecoder::BufferData::BufferData() {} |
71 | 71 |
72 RTCVideoDecoder::BufferData::~BufferData() {} | 72 RTCVideoDecoder::BufferData::~BufferData() {} |
73 | 73 |
74 RTCVideoDecoder::RTCVideoDecoder( | 74 RTCVideoDecoder::RTCVideoDecoder( |
75 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories) | 75 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories) |
76 : factories_(factories), | 76 : factories_(factories), |
77 vda_loop_proxy_(factories->GetMessageLoop()), | 77 vda_task_runner_(factories->GetTaskRunner()), |
78 decoder_texture_target_(0), | 78 decoder_texture_target_(0), |
79 next_picture_buffer_id_(0), | 79 next_picture_buffer_id_(0), |
80 state_(UNINITIALIZED), | 80 state_(UNINITIALIZED), |
81 decode_complete_callback_(NULL), | 81 decode_complete_callback_(NULL), |
82 num_shm_buffers_(0), | 82 num_shm_buffers_(0), |
83 next_bitstream_buffer_id_(0), | 83 next_bitstream_buffer_id_(0), |
84 reset_bitstream_buffer_id_(ID_INVALID), | 84 reset_bitstream_buffer_id_(ID_INVALID), |
85 weak_factory_(this) { | 85 weak_factory_(this) { |
86 DCHECK(!vda_loop_proxy_->BelongsToCurrentThread()); | 86 DCHECK(!vda_task_runner_->BelongsToCurrentThread()); |
87 | |
88 weak_this_ = weak_factory_.GetWeakPtr(); | 87 weak_this_ = weak_factory_.GetWeakPtr(); |
89 | 88 |
90 base::WaitableEvent message_loop_async_waiter(false, false); | 89 base::WaitableEvent message_loop_async_waiter(false, false); |
91 // Waiting here is safe. The media thread is stopped in the child thread and | 90 // Waiting here is safe. The media thread is stopped in the child thread and |
92 // the child thread is blocked when VideoDecoderFactory::CreateVideoDecoder | 91 // the child thread is blocked when VideoDecoderFactory::CreateVideoDecoder |
93 // runs. | 92 // runs. |
94 vda_loop_proxy_->PostTask(FROM_HERE, | 93 vda_task_runner_->PostTask(FROM_HERE, |
95 base::Bind(&RTCVideoDecoder::Initialize, | 94 base::Bind(&RTCVideoDecoder::Initialize, |
96 base::Unretained(this), | 95 base::Unretained(this), |
97 &message_loop_async_waiter)); | 96 &message_loop_async_waiter)); |
98 message_loop_async_waiter.Wait(); | 97 message_loop_async_waiter.Wait(); |
99 } | 98 } |
100 | 99 |
101 RTCVideoDecoder::~RTCVideoDecoder() { | 100 RTCVideoDecoder::~RTCVideoDecoder() { |
102 DVLOG(2) << "~RTCVideoDecoder"; | 101 DVLOG(2) << "~RTCVideoDecoder"; |
103 // Destroy VDA and remove |this| from the observer if this is vda thread. | 102 // Destroy VDA and remove |this| from the observer if this is vda thread. |
104 if (vda_loop_proxy_->BelongsToCurrentThread()) { | 103 if (vda_task_runner_->BelongsToCurrentThread()) { |
105 base::MessageLoop::current()->RemoveDestructionObserver(this); | 104 base::MessageLoop::current()->RemoveDestructionObserver(this); |
106 DestroyVDA(); | 105 DestroyVDA(); |
107 } else { | 106 } else { |
108 // VDA should have been destroyed in WillDestroyCurrentMessageLoop. | 107 // VDA should have been destroyed in WillDestroyCurrentMessageLoop. |
109 DCHECK(!vda_); | 108 DCHECK(!vda_); |
110 } | 109 } |
111 | 110 |
112 // Delete all shared memories. | 111 // Delete all shared memories. |
113 STLDeleteElements(&available_shm_segments_); | 112 STLDeleteElements(&available_shm_segments_); |
114 STLDeleteValues(&bitstream_buffers_in_decoder_); | 113 STLDeleteValues(&bitstream_buffers_in_decoder_); |
(...skipping 25 matching lines...) Expand all Loading... |
140 return decoder.Pass(); | 139 return decoder.Pass(); |
141 } | 140 } |
142 | 141 |
143 decoder.reset(new RTCVideoDecoder(factories)); | 142 decoder.reset(new RTCVideoDecoder(factories)); |
144 decoder->vda_ = | 143 decoder->vda_ = |
145 factories->CreateVideoDecodeAccelerator(profile, decoder.get()).Pass(); | 144 factories->CreateVideoDecodeAccelerator(profile, decoder.get()).Pass(); |
146 // vda can be NULL if VP8 is not supported. | 145 // vda can be NULL if VP8 is not supported. |
147 if (decoder->vda_ != NULL) { | 146 if (decoder->vda_ != NULL) { |
148 decoder->state_ = INITIALIZED; | 147 decoder->state_ = INITIALIZED; |
149 } else { | 148 } else { |
150 factories->GetMessageLoop()->DeleteSoon(FROM_HERE, decoder.release()); | 149 factories->GetTaskRunner()->DeleteSoon(FROM_HERE, decoder.release()); |
151 } | 150 } |
152 return decoder.Pass(); | 151 return decoder.Pass(); |
153 } | 152 } |
154 | 153 |
155 int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings, | 154 int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings, |
156 int32_t /*numberOfCores*/) { | 155 int32_t /*numberOfCores*/) { |
157 DVLOG(2) << "InitDecode"; | 156 DVLOG(2) << "InitDecode"; |
158 DCHECK_EQ(codecSettings->codecType, webrtc::kVideoCodecVP8); | 157 DCHECK_EQ(codecSettings->codecType, webrtc::kVideoCodecVP8); |
159 if (codecSettings->codecSpecific.VP8.feedbackModeOn) { | 158 if (codecSettings->codecSpecific.VP8.feedbackModeOn) { |
160 LOG(ERROR) << "Feedback mode not supported"; | 159 LOG(ERROR) << "Feedback mode not supported"; |
161 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_ERROR); | 160 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_ERROR); |
162 } | 161 } |
163 | 162 |
164 base::AutoLock auto_lock(lock_); | 163 base::AutoLock auto_lock(lock_); |
165 if (state_ == UNINITIALIZED || state_ == DECODE_ERROR) { | 164 if (state_ == UNINITIALIZED || state_ == DECODE_ERROR) { |
166 LOG(ERROR) << "VDA is not initialized. state=" << state_; | 165 LOG(ERROR) << "VDA is not initialized. state=" << state_; |
167 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_UNINITIALIZED); | 166 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_UNINITIALIZED); |
168 } | 167 } |
169 // Create some shared memory if the queue is empty. | 168 // Create some shared memory if the queue is empty. |
170 if (available_shm_segments_.size() == 0) { | 169 if (available_shm_segments_.size() == 0) { |
171 vda_loop_proxy_->PostTask(FROM_HERE, | 170 vda_task_runner_->PostTask(FROM_HERE, |
172 base::Bind(&RTCVideoDecoder::CreateSHM, | 171 base::Bind(&RTCVideoDecoder::CreateSHM, |
173 weak_this_, | 172 weak_this_, |
174 kMaxInFlightDecodes, | 173 kMaxInFlightDecodes, |
175 kSharedMemorySegmentBytes)); | 174 kSharedMemorySegmentBytes)); |
176 } | 175 } |
177 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_OK); | 176 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_OK); |
178 } | 177 } |
179 | 178 |
180 int32_t RTCVideoDecoder::Decode( | 179 int32_t RTCVideoDecoder::Decode( |
181 const webrtc::EncodedImage& inputImage, | 180 const webrtc::EncodedImage& inputImage, |
182 bool missingFrames, | 181 bool missingFrames, |
183 const webrtc::RTPFragmentationHeader* /*fragmentation*/, | 182 const webrtc::RTPFragmentationHeader* /*fragmentation*/, |
184 const webrtc::CodecSpecificInfo* /*codecSpecificInfo*/, | 183 const webrtc::CodecSpecificInfo* /*codecSpecificInfo*/, |
185 int64_t /*renderTimeMs*/) { | 184 int64_t /*renderTimeMs*/) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 if (!SaveToPendingBuffers_Locked(inputImage, buffer_data)) | 250 if (!SaveToPendingBuffers_Locked(inputImage, buffer_data)) |
252 return WEBRTC_VIDEO_CODEC_ERROR; | 251 return WEBRTC_VIDEO_CODEC_ERROR; |
253 if (need_to_reset_for_midstream_resize) { | 252 if (need_to_reset_for_midstream_resize) { |
254 base::AutoUnlock auto_unlock(lock_); | 253 base::AutoUnlock auto_unlock(lock_); |
255 Reset(); | 254 Reset(); |
256 } | 255 } |
257 return WEBRTC_VIDEO_CODEC_OK; | 256 return WEBRTC_VIDEO_CODEC_OK; |
258 } | 257 } |
259 | 258 |
260 SaveToDecodeBuffers_Locked(inputImage, shm_buffer.Pass(), buffer_data); | 259 SaveToDecodeBuffers_Locked(inputImage, shm_buffer.Pass(), buffer_data); |
261 vda_loop_proxy_->PostTask( | 260 vda_task_runner_->PostTask( |
262 FROM_HERE, base::Bind(&RTCVideoDecoder::RequestBufferDecode, weak_this_)); | 261 FROM_HERE, base::Bind(&RTCVideoDecoder::RequestBufferDecode, weak_this_)); |
263 return WEBRTC_VIDEO_CODEC_OK; | 262 return WEBRTC_VIDEO_CODEC_OK; |
264 } | 263 } |
265 | 264 |
266 int32_t RTCVideoDecoder::RegisterDecodeCompleteCallback( | 265 int32_t RTCVideoDecoder::RegisterDecodeCompleteCallback( |
267 webrtc::DecodedImageCallback* callback) { | 266 webrtc::DecodedImageCallback* callback) { |
268 DVLOG(2) << "RegisterDecodeCompleteCallback"; | 267 DVLOG(2) << "RegisterDecodeCompleteCallback"; |
269 base::AutoLock auto_lock(lock_); | 268 base::AutoLock auto_lock(lock_); |
270 decode_complete_callback_ = callback; | 269 decode_complete_callback_ = callback; |
271 return WEBRTC_VIDEO_CODEC_OK; | 270 return WEBRTC_VIDEO_CODEC_OK; |
(...skipping 13 matching lines...) Expand all Loading... |
285 LOG(ERROR) << "Decoder not initialized."; | 284 LOG(ERROR) << "Decoder not initialized."; |
286 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 285 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
287 } | 286 } |
288 if (next_bitstream_buffer_id_ != 0) | 287 if (next_bitstream_buffer_id_ != 0) |
289 reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1; | 288 reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1; |
290 else | 289 else |
291 reset_bitstream_buffer_id_ = ID_LAST; | 290 reset_bitstream_buffer_id_ = ID_LAST; |
292 // If VDA is already resetting, no need to request the reset again. | 291 // If VDA is already resetting, no need to request the reset again. |
293 if (state_ != RESETTING) { | 292 if (state_ != RESETTING) { |
294 state_ = RESETTING; | 293 state_ = RESETTING; |
295 vda_loop_proxy_->PostTask( | 294 vda_task_runner_->PostTask( |
296 FROM_HERE, base::Bind(&RTCVideoDecoder::ResetInternal, weak_this_)); | 295 FROM_HERE, base::Bind(&RTCVideoDecoder::ResetInternal, weak_this_)); |
297 } | 296 } |
298 return WEBRTC_VIDEO_CODEC_OK; | 297 return WEBRTC_VIDEO_CODEC_OK; |
299 } | 298 } |
300 | 299 |
301 void RTCVideoDecoder::NotifyInitializeDone() { | 300 void RTCVideoDecoder::NotifyInitializeDone() { |
302 DVLOG(2) << "NotifyInitializeDone"; | 301 DVLOG(2) << "NotifyInitializeDone"; |
303 NOTREACHED(); | 302 NOTREACHED(); |
304 } | 303 } |
305 | 304 |
306 void RTCVideoDecoder::ProvidePictureBuffers(uint32 count, | 305 void RTCVideoDecoder::ProvidePictureBuffers(uint32 count, |
307 const gfx::Size& size, | 306 const gfx::Size& size, |
308 uint32 texture_target) { | 307 uint32 texture_target) { |
309 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 308 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
310 DVLOG(3) << "ProvidePictureBuffers. texture_target=" << texture_target; | 309 DVLOG(3) << "ProvidePictureBuffers. texture_target=" << texture_target; |
311 | 310 |
312 if (!vda_) | 311 if (!vda_) |
313 return; | 312 return; |
314 | 313 |
315 std::vector<uint32> texture_ids; | 314 std::vector<uint32> texture_ids; |
316 std::vector<gpu::Mailbox> texture_mailboxes; | 315 std::vector<gpu::Mailbox> texture_mailboxes; |
317 decoder_texture_target_ = texture_target; | 316 decoder_texture_target_ = texture_target; |
318 // Discards the sync point returned here since PictureReady will imply that | 317 // Discards the sync point returned here since PictureReady will imply that |
319 // the produce has already happened, and the texture is ready for use. | 318 // the produce has already happened, and the texture is ready for use. |
(...skipping 14 matching lines...) Expand all Loading... |
334 next_picture_buffer_id_++, size, texture_ids[i], texture_mailboxes[i])); | 333 next_picture_buffer_id_++, size, texture_ids[i], texture_mailboxes[i])); |
335 bool inserted = assigned_picture_buffers_.insert(std::make_pair( | 334 bool inserted = assigned_picture_buffers_.insert(std::make_pair( |
336 picture_buffers.back().id(), picture_buffers.back())).second; | 335 picture_buffers.back().id(), picture_buffers.back())).second; |
337 DCHECK(inserted); | 336 DCHECK(inserted); |
338 } | 337 } |
339 vda_->AssignPictureBuffers(picture_buffers); | 338 vda_->AssignPictureBuffers(picture_buffers); |
340 } | 339 } |
341 | 340 |
342 void RTCVideoDecoder::DismissPictureBuffer(int32 id) { | 341 void RTCVideoDecoder::DismissPictureBuffer(int32 id) { |
343 DVLOG(3) << "DismissPictureBuffer. id=" << id; | 342 DVLOG(3) << "DismissPictureBuffer. id=" << id; |
344 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 343 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
345 | 344 |
346 std::map<int32, media::PictureBuffer>::iterator it = | 345 std::map<int32, media::PictureBuffer>::iterator it = |
347 assigned_picture_buffers_.find(id); | 346 assigned_picture_buffers_.find(id); |
348 if (it == assigned_picture_buffers_.end()) { | 347 if (it == assigned_picture_buffers_.end()) { |
349 NOTREACHED() << "Missing picture buffer: " << id; | 348 NOTREACHED() << "Missing picture buffer: " << id; |
350 return; | 349 return; |
351 } | 350 } |
352 | 351 |
353 media::PictureBuffer buffer_to_dismiss = it->second; | 352 media::PictureBuffer buffer_to_dismiss = it->second; |
354 assigned_picture_buffers_.erase(it); | 353 assigned_picture_buffers_.erase(it); |
355 | 354 |
356 std::set<int32>::iterator at_display_it = | 355 std::set<int32>::iterator at_display_it = |
357 picture_buffers_at_display_.find(id); | 356 picture_buffers_at_display_.find(id); |
358 | 357 |
359 if (at_display_it == picture_buffers_at_display_.end()) { | 358 if (at_display_it == picture_buffers_at_display_.end()) { |
360 // We can delete the texture immediately as it's not being displayed. | 359 // We can delete the texture immediately as it's not being displayed. |
361 factories_->DeleteTexture(buffer_to_dismiss.texture_id()); | 360 factories_->DeleteTexture(buffer_to_dismiss.texture_id()); |
362 } else { | 361 } else { |
363 // Texture in display. Postpone deletion until after it's returned to us. | 362 // Texture in display. Postpone deletion until after it's returned to us. |
364 bool inserted = dismissed_picture_buffers_ | 363 bool inserted = dismissed_picture_buffers_ |
365 .insert(std::make_pair(id, buffer_to_dismiss)).second; | 364 .insert(std::make_pair(id, buffer_to_dismiss)).second; |
366 DCHECK(inserted); | 365 DCHECK(inserted); |
367 } | 366 } |
368 } | 367 } |
369 | 368 |
370 void RTCVideoDecoder::PictureReady(const media::Picture& picture) { | 369 void RTCVideoDecoder::PictureReady(const media::Picture& picture) { |
371 DVLOG(3) << "PictureReady"; | 370 DVLOG(3) << "PictureReady"; |
372 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 371 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
373 | 372 |
374 std::map<int32, media::PictureBuffer>::iterator it = | 373 std::map<int32, media::PictureBuffer>::iterator it = |
375 assigned_picture_buffers_.find(picture.picture_buffer_id()); | 374 assigned_picture_buffers_.find(picture.picture_buffer_id()); |
376 if (it == assigned_picture_buffers_.end()) { | 375 if (it == assigned_picture_buffers_.end()) { |
377 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); | 376 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); |
378 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 377 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); |
379 return; | 378 return; |
380 } | 379 } |
381 const media::PictureBuffer& pb = it->second; | 380 const media::PictureBuffer& pb = it->second; |
382 | 381 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 timestamp_ms, | 434 timestamp_ms, |
436 base::Bind(&media::GpuVideoAcceleratorFactories::ReadPixels, | 435 base::Bind(&media::GpuVideoAcceleratorFactories::ReadPixels, |
437 factories_, | 436 factories_, |
438 pb.texture_id(), | 437 pb.texture_id(), |
439 natural_size), | 438 natural_size), |
440 base::Closure()); | 439 base::Closure()); |
441 } | 440 } |
442 | 441 |
443 void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { | 442 void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { |
444 DVLOG(3) << "NotifyEndOfBitstreamBuffer. id=" << id; | 443 DVLOG(3) << "NotifyEndOfBitstreamBuffer. id=" << id; |
445 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 444 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
446 | 445 |
447 std::map<int32, SHMBuffer*>::iterator it = | 446 std::map<int32, SHMBuffer*>::iterator it = |
448 bitstream_buffers_in_decoder_.find(id); | 447 bitstream_buffers_in_decoder_.find(id); |
449 if (it == bitstream_buffers_in_decoder_.end()) { | 448 if (it == bitstream_buffers_in_decoder_.end()) { |
450 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 449 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); |
451 NOTREACHED() << "Missing bitstream buffer: " << id; | 450 NOTREACHED() << "Missing bitstream buffer: " << id; |
452 return; | 451 return; |
453 } | 452 } |
454 | 453 |
455 { | 454 { |
456 base::AutoLock auto_lock(lock_); | 455 base::AutoLock auto_lock(lock_); |
457 PutSHM_Locked(scoped_ptr<SHMBuffer>(it->second)); | 456 PutSHM_Locked(scoped_ptr<SHMBuffer>(it->second)); |
458 } | 457 } |
459 bitstream_buffers_in_decoder_.erase(it); | 458 bitstream_buffers_in_decoder_.erase(it); |
460 | 459 |
461 RequestBufferDecode(); | 460 RequestBufferDecode(); |
462 } | 461 } |
463 | 462 |
464 void RTCVideoDecoder::NotifyFlushDone() { | 463 void RTCVideoDecoder::NotifyFlushDone() { |
465 DVLOG(3) << "NotifyFlushDone"; | 464 DVLOG(3) << "NotifyFlushDone"; |
466 NOTREACHED() << "Unexpected flush done notification."; | 465 NOTREACHED() << "Unexpected flush done notification."; |
467 } | 466 } |
468 | 467 |
469 void RTCVideoDecoder::NotifyResetDone() { | 468 void RTCVideoDecoder::NotifyResetDone() { |
470 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 469 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
471 DVLOG(3) << "NotifyResetDone"; | 470 DVLOG(3) << "NotifyResetDone"; |
472 | 471 |
473 if (!vda_) | 472 if (!vda_) |
474 return; | 473 return; |
475 | 474 |
476 input_buffer_data_.clear(); | 475 input_buffer_data_.clear(); |
477 { | 476 { |
478 base::AutoLock auto_lock(lock_); | 477 base::AutoLock auto_lock(lock_); |
479 state_ = INITIALIZED; | 478 state_ = INITIALIZED; |
480 } | 479 } |
481 // Send the pending buffers for decoding. | 480 // Send the pending buffers for decoding. |
482 RequestBufferDecode(); | 481 RequestBufferDecode(); |
483 } | 482 } |
484 | 483 |
485 void RTCVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 484 void RTCVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
486 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 485 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
487 if (!vda_) | 486 if (!vda_) |
488 return; | 487 return; |
489 | 488 |
490 LOG(ERROR) << "VDA Error:" << error; | 489 LOG(ERROR) << "VDA Error:" << error; |
491 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", | 490 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", |
492 error, | 491 error, |
493 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM); | 492 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM); |
494 DestroyVDA(); | 493 DestroyVDA(); |
495 | 494 |
496 base::AutoLock auto_lock(lock_); | 495 base::AutoLock auto_lock(lock_); |
497 state_ = DECODE_ERROR; | 496 state_ = DECODE_ERROR; |
498 } | 497 } |
499 | 498 |
500 void RTCVideoDecoder::WillDestroyCurrentMessageLoop() { | 499 void RTCVideoDecoder::WillDestroyCurrentMessageLoop() { |
501 DVLOG(2) << "WillDestroyCurrentMessageLoop"; | 500 DVLOG(2) << "WillDestroyCurrentMessageLoop"; |
502 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 501 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
503 factories_->Abort(); | 502 factories_->Abort(); |
504 weak_factory_.InvalidateWeakPtrs(); | 503 weak_factory_.InvalidateWeakPtrs(); |
505 DestroyVDA(); | 504 DestroyVDA(); |
506 } | 505 } |
507 | 506 |
508 void RTCVideoDecoder::Initialize(base::WaitableEvent* waiter) { | 507 void RTCVideoDecoder::Initialize(base::WaitableEvent* waiter) { |
509 DVLOG(2) << "Initialize"; | 508 DVLOG(2) << "Initialize"; |
510 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 509 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
511 base::MessageLoop::current()->AddDestructionObserver(this); | 510 base::MessageLoop::current()->AddDestructionObserver(this); |
512 waiter->Signal(); | 511 waiter->Signal(); |
513 } | 512 } |
514 | 513 |
515 void RTCVideoDecoder::RequestBufferDecode() { | 514 void RTCVideoDecoder::RequestBufferDecode() { |
516 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 515 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
517 if (!vda_) | 516 if (!vda_) |
518 return; | 517 return; |
519 | 518 |
520 MovePendingBuffersToDecodeBuffers(); | 519 MovePendingBuffersToDecodeBuffers(); |
521 | 520 |
522 while (CanMoreDecodeWorkBeDone()) { | 521 while (CanMoreDecodeWorkBeDone()) { |
523 // Get a buffer and data from the queue. | 522 // Get a buffer and data from the queue. |
524 SHMBuffer* shm_buffer = NULL; | 523 SHMBuffer* shm_buffer = NULL; |
525 BufferData buffer_data; | 524 BufferData buffer_data; |
526 { | 525 { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 scoped_ptr<SHMBuffer> shm_buffer = GetSHM_Locked(input_image._length); | 627 scoped_ptr<SHMBuffer> shm_buffer = GetSHM_Locked(input_image._length); |
629 if (!shm_buffer) | 628 if (!shm_buffer) |
630 return; | 629 return; |
631 SaveToDecodeBuffers_Locked(input_image, shm_buffer.Pass(), buffer_data); | 630 SaveToDecodeBuffers_Locked(input_image, shm_buffer.Pass(), buffer_data); |
632 delete[] input_image._buffer; | 631 delete[] input_image._buffer; |
633 pending_buffers_.pop_front(); | 632 pending_buffers_.pop_front(); |
634 } | 633 } |
635 } | 634 } |
636 | 635 |
637 void RTCVideoDecoder::ResetInternal() { | 636 void RTCVideoDecoder::ResetInternal() { |
638 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 637 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
639 DVLOG(2) << "ResetInternal"; | 638 DVLOG(2) << "ResetInternal"; |
640 if (vda_) | 639 if (vda_) |
641 vda_->Reset(); | 640 vda_->Reset(); |
642 } | 641 } |
643 | 642 |
644 void RTCVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id, | 643 void RTCVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id, |
645 uint32 sync_point) { | 644 uint32 sync_point) { |
646 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 645 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
647 DVLOG(3) << "ReusePictureBuffer. id=" << picture_buffer_id; | 646 DVLOG(3) << "ReusePictureBuffer. id=" << picture_buffer_id; |
648 | 647 |
649 if (!vda_) | 648 if (!vda_) |
650 return; | 649 return; |
651 | 650 |
652 CHECK(!picture_buffers_at_display_.empty()); | 651 CHECK(!picture_buffers_at_display_.empty()); |
653 | 652 |
654 size_t num_erased = picture_buffers_at_display_.erase(picture_buffer_id); | 653 size_t num_erased = picture_buffers_at_display_.erase(picture_buffer_id); |
655 DCHECK(num_erased); | 654 DCHECK(num_erased); |
656 | 655 |
657 std::map<int32, media::PictureBuffer>::iterator it = | 656 std::map<int32, media::PictureBuffer>::iterator it = |
658 assigned_picture_buffers_.find(picture_buffer_id); | 657 assigned_picture_buffers_.find(picture_buffer_id); |
659 | 658 |
660 if (it == assigned_picture_buffers_.end()) { | 659 if (it == assigned_picture_buffers_.end()) { |
661 // This picture was dismissed while in display, so we postponed deletion. | 660 // This picture was dismissed while in display, so we postponed deletion. |
662 it = dismissed_picture_buffers_.find(picture_buffer_id); | 661 it = dismissed_picture_buffers_.find(picture_buffer_id); |
663 DCHECK(it != dismissed_picture_buffers_.end()); | 662 DCHECK(it != dismissed_picture_buffers_.end()); |
664 factories_->DeleteTexture(it->second.texture_id()); | 663 factories_->DeleteTexture(it->second.texture_id()); |
665 dismissed_picture_buffers_.erase(it); | 664 dismissed_picture_buffers_.erase(it); |
666 return; | 665 return; |
667 } | 666 } |
668 | 667 |
669 factories_->WaitSyncPoint(sync_point); | 668 factories_->WaitSyncPoint(sync_point); |
670 | 669 |
671 vda_->ReusePictureBuffer(picture_buffer_id); | 670 vda_->ReusePictureBuffer(picture_buffer_id); |
672 } | 671 } |
673 | 672 |
674 void RTCVideoDecoder::DestroyTextures() { | 673 void RTCVideoDecoder::DestroyTextures() { |
675 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 674 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
676 std::map<int32, media::PictureBuffer>::iterator it; | 675 std::map<int32, media::PictureBuffer>::iterator it; |
677 | 676 |
678 for (it = assigned_picture_buffers_.begin(); | 677 for (it = assigned_picture_buffers_.begin(); |
679 it != assigned_picture_buffers_.end(); | 678 it != assigned_picture_buffers_.end(); |
680 ++it) { | 679 ++it) { |
681 factories_->DeleteTexture(it->second.texture_id()); | 680 factories_->DeleteTexture(it->second.texture_id()); |
682 } | 681 } |
683 assigned_picture_buffers_.clear(); | 682 assigned_picture_buffers_.clear(); |
684 | 683 |
685 for (it = dismissed_picture_buffers_.begin(); | 684 for (it = dismissed_picture_buffers_.begin(); |
686 it != dismissed_picture_buffers_.end(); | 685 it != dismissed_picture_buffers_.end(); |
687 ++it) { | 686 ++it) { |
688 factories_->DeleteTexture(it->second.texture_id()); | 687 factories_->DeleteTexture(it->second.texture_id()); |
689 } | 688 } |
690 dismissed_picture_buffers_.clear(); | 689 dismissed_picture_buffers_.clear(); |
691 } | 690 } |
692 | 691 |
693 void RTCVideoDecoder::DestroyVDA() { | 692 void RTCVideoDecoder::DestroyVDA() { |
694 DVLOG(2) << "DestroyVDA"; | 693 DVLOG(2) << "DestroyVDA"; |
695 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 694 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
696 if (vda_) | 695 if (vda_) |
697 vda_.release()->Destroy(); | 696 vda_.release()->Destroy(); |
698 DestroyTextures(); | 697 DestroyTextures(); |
699 base::AutoLock auto_lock(lock_); | 698 base::AutoLock auto_lock(lock_); |
700 state_ = UNINITIALIZED; | 699 state_ = UNINITIALIZED; |
701 } | 700 } |
702 | 701 |
703 scoped_ptr<RTCVideoDecoder::SHMBuffer> RTCVideoDecoder::GetSHM_Locked( | 702 scoped_ptr<RTCVideoDecoder::SHMBuffer> RTCVideoDecoder::GetSHM_Locked( |
704 size_t min_size) { | 703 size_t min_size) { |
705 // Reuse a SHM if possible. | 704 // Reuse a SHM if possible. |
706 SHMBuffer* ret = NULL; | 705 SHMBuffer* ret = NULL; |
707 if (!available_shm_segments_.empty() && | 706 if (!available_shm_segments_.empty() && |
708 available_shm_segments_.back()->size >= min_size) { | 707 available_shm_segments_.back()->size >= min_size) { |
709 ret = available_shm_segments_.back(); | 708 ret = available_shm_segments_.back(); |
710 available_shm_segments_.pop_back(); | 709 available_shm_segments_.pop_back(); |
711 } | 710 } |
712 // Post to vda thread to create shared memory if SHM cannot be reused or the | 711 // Post to vda thread to create shared memory if SHM cannot be reused or the |
713 // queue is almost empty. | 712 // queue is almost empty. |
714 if (num_shm_buffers_ < kMaxNumSharedMemorySegments && | 713 if (num_shm_buffers_ < kMaxNumSharedMemorySegments && |
715 (ret == NULL || available_shm_segments_.size() <= 1)) { | 714 (ret == NULL || available_shm_segments_.size() <= 1)) { |
716 vda_loop_proxy_->PostTask( | 715 vda_task_runner_->PostTask( |
717 FROM_HERE, | 716 FROM_HERE, |
718 base::Bind(&RTCVideoDecoder::CreateSHM, weak_this_, 1, min_size)); | 717 base::Bind(&RTCVideoDecoder::CreateSHM, weak_this_, 1, min_size)); |
719 } | 718 } |
720 return scoped_ptr<SHMBuffer>(ret); | 719 return scoped_ptr<SHMBuffer>(ret); |
721 } | 720 } |
722 | 721 |
723 void RTCVideoDecoder::PutSHM_Locked(scoped_ptr<SHMBuffer> shm_buffer) { | 722 void RTCVideoDecoder::PutSHM_Locked(scoped_ptr<SHMBuffer> shm_buffer) { |
724 available_shm_segments_.push_back(shm_buffer.release()); | 723 available_shm_segments_.push_back(shm_buffer.release()); |
725 } | 724 } |
726 | 725 |
727 void RTCVideoDecoder::CreateSHM(int number, size_t min_size) { | 726 void RTCVideoDecoder::CreateSHM(int number, size_t min_size) { |
728 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 727 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
729 DVLOG(2) << "CreateSHM. size=" << min_size; | 728 DVLOG(2) << "CreateSHM. size=" << min_size; |
730 int number_to_allocate; | 729 int number_to_allocate; |
731 { | 730 { |
732 base::AutoLock auto_lock(lock_); | 731 base::AutoLock auto_lock(lock_); |
733 number_to_allocate = | 732 number_to_allocate = |
734 std::min(kMaxNumSharedMemorySegments - num_shm_buffers_, number); | 733 std::min(kMaxNumSharedMemorySegments - num_shm_buffers_, number); |
735 } | 734 } |
736 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); | 735 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); |
737 for (int i = 0; i < number_to_allocate; i++) { | 736 for (int i = 0; i < number_to_allocate; i++) { |
738 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); | 737 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 | 778 |
780 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { | 779 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { |
781 // Logging boolean is enough to know if HW decoding has been used. Also, | 780 // Logging boolean is enough to know if HW decoding has been used. Also, |
782 // InitDecode is less likely to return an error so enum is not used here. | 781 // InitDecode is less likely to return an error so enum is not used here. |
783 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; | 782 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; |
784 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample); | 783 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample); |
785 return status; | 784 return status; |
786 } | 785 } |
787 | 786 |
788 } // namespace content | 787 } // namespace content |
OLD | NEW |