| 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 vda_task_runner_(factories->GetTaskRunner()), | 80 vda_task_runner_(factories->GetTaskRunner()), |
| 81 decoder_texture_target_(0), | 81 decoder_texture_target_(0), |
| 82 next_picture_buffer_id_(0), | 82 next_picture_buffer_id_(0), |
| 83 state_(UNINITIALIZED), | 83 state_(UNINITIALIZED), |
| 84 decode_complete_callback_(NULL), | 84 decode_complete_callback_(NULL), |
| 85 num_shm_buffers_(0), | 85 num_shm_buffers_(0), |
| 86 next_bitstream_buffer_id_(0), | 86 next_bitstream_buffer_id_(0), |
| 87 reset_bitstream_buffer_id_(ID_INVALID), | 87 reset_bitstream_buffer_id_(ID_INVALID), |
| 88 weak_factory_(this) { | 88 weak_factory_(this) { |
| 89 DCHECK(!vda_task_runner_->BelongsToCurrentThread()); | 89 DCHECK(!vda_task_runner_->BelongsToCurrentThread()); |
| 90 weak_this_ = weak_factory_.GetWeakPtr(); | |
| 91 } | 90 } |
| 92 | 91 |
| 93 RTCVideoDecoder::~RTCVideoDecoder() { | 92 RTCVideoDecoder::~RTCVideoDecoder() { |
| 94 DVLOG(2) << "~RTCVideoDecoder"; | 93 DVLOG(2) << "~RTCVideoDecoder"; |
| 95 DCHECK(vda_task_runner_->BelongsToCurrentThread()); | 94 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
| 96 DestroyVDA(); | 95 DestroyVDA(); |
| 97 | 96 |
| 98 // Delete all shared memories. | 97 // Delete all shared memories. |
| 99 STLDeleteElements(&available_shm_segments_); | 98 STLDeleteElements(&available_shm_segments_); |
| 100 STLDeleteValues(&bitstream_buffers_in_decoder_); | 99 STLDeleteValues(&bitstream_buffers_in_decoder_); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 | 155 |
| 157 base::AutoLock auto_lock(lock_); | 156 base::AutoLock auto_lock(lock_); |
| 158 if (state_ == UNINITIALIZED || state_ == DECODE_ERROR) { | 157 if (state_ == UNINITIALIZED || state_ == DECODE_ERROR) { |
| 159 LOG(ERROR) << "VDA is not initialized. state=" << state_; | 158 LOG(ERROR) << "VDA is not initialized. state=" << state_; |
| 160 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_UNINITIALIZED); | 159 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_UNINITIALIZED); |
| 161 } | 160 } |
| 162 // Create some shared memory if the queue is empty. | 161 // Create some shared memory if the queue is empty. |
| 163 if (available_shm_segments_.size() == 0) { | 162 if (available_shm_segments_.size() == 0) { |
| 164 vda_task_runner_->PostTask(FROM_HERE, | 163 vda_task_runner_->PostTask(FROM_HERE, |
| 165 base::Bind(&RTCVideoDecoder::CreateSHM, | 164 base::Bind(&RTCVideoDecoder::CreateSHM, |
| 166 weak_this_, | 165 weak_factory_.GetWeakPtr(), |
| 167 kMaxInFlightDecodes, | 166 kMaxInFlightDecodes, |
| 168 kSharedMemorySegmentBytes)); | 167 kSharedMemorySegmentBytes)); |
| 169 } | 168 } |
| 170 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_OK); | 169 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_OK); |
| 171 } | 170 } |
| 172 | 171 |
| 173 int32_t RTCVideoDecoder::Decode( | 172 int32_t RTCVideoDecoder::Decode( |
| 174 const webrtc::EncodedImage& inputImage, | 173 const webrtc::EncodedImage& inputImage, |
| 175 bool missingFrames, | 174 bool missingFrames, |
| 176 const webrtc::RTPFragmentationHeader* /*fragmentation*/, | 175 const webrtc::RTPFragmentationHeader* /*fragmentation*/, |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 if (!SaveToPendingBuffers_Locked(inputImage, buffer_data)) | 243 if (!SaveToPendingBuffers_Locked(inputImage, buffer_data)) |
| 245 return WEBRTC_VIDEO_CODEC_ERROR; | 244 return WEBRTC_VIDEO_CODEC_ERROR; |
| 246 if (need_to_reset_for_midstream_resize) { | 245 if (need_to_reset_for_midstream_resize) { |
| 247 base::AutoUnlock auto_unlock(lock_); | 246 base::AutoUnlock auto_unlock(lock_); |
| 248 Reset(); | 247 Reset(); |
| 249 } | 248 } |
| 250 return WEBRTC_VIDEO_CODEC_OK; | 249 return WEBRTC_VIDEO_CODEC_OK; |
| 251 } | 250 } |
| 252 | 251 |
| 253 SaveToDecodeBuffers_Locked(inputImage, shm_buffer.Pass(), buffer_data); | 252 SaveToDecodeBuffers_Locked(inputImage, shm_buffer.Pass(), buffer_data); |
| 254 vda_task_runner_->PostTask( | 253 vda_task_runner_->PostTask(FROM_HERE, |
| 255 FROM_HERE, base::Bind(&RTCVideoDecoder::RequestBufferDecode, weak_this_)); | 254 base::Bind(&RTCVideoDecoder::RequestBufferDecode, |
| 255 weak_factory_.GetWeakPtr())); |
| 256 return WEBRTC_VIDEO_CODEC_OK; | 256 return WEBRTC_VIDEO_CODEC_OK; |
| 257 } | 257 } |
| 258 | 258 |
| 259 int32_t RTCVideoDecoder::RegisterDecodeCompleteCallback( | 259 int32_t RTCVideoDecoder::RegisterDecodeCompleteCallback( |
| 260 webrtc::DecodedImageCallback* callback) { | 260 webrtc::DecodedImageCallback* callback) { |
| 261 DVLOG(2) << "RegisterDecodeCompleteCallback"; | 261 DVLOG(2) << "RegisterDecodeCompleteCallback"; |
| 262 base::AutoLock auto_lock(lock_); | 262 base::AutoLock auto_lock(lock_); |
| 263 decode_complete_callback_ = callback; | 263 decode_complete_callback_ = callback; |
| 264 return WEBRTC_VIDEO_CODEC_OK; | 264 return WEBRTC_VIDEO_CODEC_OK; |
| 265 } | 265 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 278 LOG(ERROR) << "Decoder not initialized."; | 278 LOG(ERROR) << "Decoder not initialized."; |
| 279 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 279 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
| 280 } | 280 } |
| 281 if (next_bitstream_buffer_id_ != 0) | 281 if (next_bitstream_buffer_id_ != 0) |
| 282 reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1; | 282 reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1; |
| 283 else | 283 else |
| 284 reset_bitstream_buffer_id_ = ID_LAST; | 284 reset_bitstream_buffer_id_ = ID_LAST; |
| 285 // If VDA is already resetting, no need to request the reset again. | 285 // If VDA is already resetting, no need to request the reset again. |
| 286 if (state_ != RESETTING) { | 286 if (state_ != RESETTING) { |
| 287 state_ = RESETTING; | 287 state_ = RESETTING; |
| 288 vda_task_runner_->PostTask( | 288 vda_task_runner_->PostTask(FROM_HERE, |
| 289 FROM_HERE, base::Bind(&RTCVideoDecoder::ResetInternal, weak_this_)); | 289 base::Bind(&RTCVideoDecoder::ResetInternal, |
| 290 weak_factory_.GetWeakPtr())); |
| 290 } | 291 } |
| 291 return WEBRTC_VIDEO_CODEC_OK; | 292 return WEBRTC_VIDEO_CODEC_OK; |
| 292 } | 293 } |
| 293 | 294 |
| 294 void RTCVideoDecoder::NotifyInitializeDone() { | 295 void RTCVideoDecoder::NotifyInitializeDone() { |
| 295 DVLOG(2) << "NotifyInitializeDone"; | 296 DVLOG(2) << "NotifyInitializeDone"; |
| 296 NOTREACHED(); | 297 NOTREACHED(); |
| 297 } | 298 } |
| 298 | 299 |
| 299 void RTCVideoDecoder::ProvidePictureBuffers(uint32 count, | 300 void RTCVideoDecoder::ProvidePictureBuffers(uint32 count, |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 size_t size) { | 435 size_t size) { |
| 435 gfx::Rect visible_rect(width, height); | 436 gfx::Rect visible_rect(width, height); |
| 436 DCHECK(decoder_texture_target_); | 437 DCHECK(decoder_texture_target_); |
| 437 // Convert timestamp from 90KHz to ms. | 438 // Convert timestamp from 90KHz to ms. |
| 438 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( | 439 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( |
| 439 base::checked_cast<uint64_t>(timestamp) * 1000 / 90); | 440 base::checked_cast<uint64_t>(timestamp) * 1000 / 90); |
| 440 return media::VideoFrame::WrapNativeTexture( | 441 return media::VideoFrame::WrapNativeTexture( |
| 441 make_scoped_ptr(new gpu::MailboxHolder( | 442 make_scoped_ptr(new gpu::MailboxHolder( |
| 442 pb.texture_mailbox(), decoder_texture_target_, 0)), | 443 pb.texture_mailbox(), decoder_texture_target_, 0)), |
| 443 media::BindToCurrentLoop(base::Bind(&RTCVideoDecoder::ReusePictureBuffer, | 444 media::BindToCurrentLoop(base::Bind(&RTCVideoDecoder::ReusePictureBuffer, |
| 444 weak_this_, | 445 weak_factory_.GetWeakPtr(), |
| 445 picture.picture_buffer_id())), | 446 picture.picture_buffer_id())), |
| 446 pb.size(), | 447 pb.size(), |
| 447 visible_rect, | 448 visible_rect, |
| 448 visible_rect.size(), | 449 visible_rect.size(), |
| 449 timestamp_ms, | 450 timestamp_ms, |
| 450 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect)); | 451 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect)); |
| 451 } | 452 } |
| 452 | 453 |
| 453 void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { | 454 void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { |
| 454 DVLOG(3) << "NotifyEndOfBitstreamBuffer. id=" << id; | 455 DVLOG(3) << "NotifyEndOfBitstreamBuffer. id=" << id; |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 SHMBuffer* ret = NULL; | 712 SHMBuffer* ret = NULL; |
| 712 if (!available_shm_segments_.empty() && | 713 if (!available_shm_segments_.empty() && |
| 713 available_shm_segments_.back()->size >= min_size) { | 714 available_shm_segments_.back()->size >= min_size) { |
| 714 ret = available_shm_segments_.back(); | 715 ret = available_shm_segments_.back(); |
| 715 available_shm_segments_.pop_back(); | 716 available_shm_segments_.pop_back(); |
| 716 } | 717 } |
| 717 // Post to vda thread to create shared memory if SHM cannot be reused or the | 718 // Post to vda thread to create shared memory if SHM cannot be reused or the |
| 718 // queue is almost empty. | 719 // queue is almost empty. |
| 719 if (num_shm_buffers_ < kMaxNumSharedMemorySegments && | 720 if (num_shm_buffers_ < kMaxNumSharedMemorySegments && |
| 720 (ret == NULL || available_shm_segments_.size() <= 1)) { | 721 (ret == NULL || available_shm_segments_.size() <= 1)) { |
| 721 vda_task_runner_->PostTask( | 722 vda_task_runner_->PostTask(FROM_HERE, |
| 722 FROM_HERE, | 723 base::Bind(&RTCVideoDecoder::CreateSHM, |
| 723 base::Bind(&RTCVideoDecoder::CreateSHM, weak_this_, 1, min_size)); | 724 weak_factory_.GetWeakPtr(), |
| 725 1, |
| 726 min_size)); |
| 724 } | 727 } |
| 725 return scoped_ptr<SHMBuffer>(ret); | 728 return scoped_ptr<SHMBuffer>(ret); |
| 726 } | 729 } |
| 727 | 730 |
| 728 void RTCVideoDecoder::PutSHM_Locked(scoped_ptr<SHMBuffer> shm_buffer) { | 731 void RTCVideoDecoder::PutSHM_Locked(scoped_ptr<SHMBuffer> shm_buffer) { |
| 729 available_shm_segments_.push_back(shm_buffer.release()); | 732 available_shm_segments_.push_back(shm_buffer.release()); |
| 730 } | 733 } |
| 731 | 734 |
| 732 void RTCVideoDecoder::CreateSHM(int number, size_t min_size) { | 735 void RTCVideoDecoder::CreateSHM(int number, size_t min_size) { |
| 733 DCHECK(vda_task_runner_->BelongsToCurrentThread()); | 736 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 784 | 787 |
| 785 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { | 788 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { |
| 786 // Logging boolean is enough to know if HW decoding has been used. Also, | 789 // Logging boolean is enough to know if HW decoding has been used. Also, |
| 787 // InitDecode is less likely to return an error so enum is not used here. | 790 // InitDecode is less likely to return an error so enum is not used here. |
| 788 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; | 791 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; |
| 789 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample); | 792 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample); |
| 790 return status; | 793 return status; |
| 791 } | 794 } |
| 792 | 795 |
| 793 } // namespace content | 796 } // namespace content |
| OLD | NEW |