| 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 |