Chromium Code Reviews| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 #include "third_party/skia/include/core/SkBitmap.h" | 21 #include "third_party/skia/include/core/SkBitmap.h" |
| 22 #include "third_party/webrtc/base/bind.h" | 22 #include "third_party/webrtc/base/bind.h" |
| 23 #include "third_party/webrtc/base/refcount.h" | 23 #include "third_party/webrtc/base/refcount.h" |
| 24 #include "third_party/webrtc/video_frame.h" | 24 #include "third_party/webrtc/video_frame.h" |
| 25 | 25 |
| 26 namespace content { | 26 namespace content { |
| 27 | 27 |
| 28 const int32_t RTCVideoDecoder::ID_LAST = 0x3FFFFFFF; | 28 const int32_t RTCVideoDecoder::ID_LAST = 0x3FFFFFFF; |
| 29 const int32_t RTCVideoDecoder::ID_HALF = 0x20000000; | 29 const int32_t RTCVideoDecoder::ID_HALF = 0x20000000; |
| 30 const int32_t RTCVideoDecoder::ID_INVALID = -1; | 30 const int32_t RTCVideoDecoder::ID_INVALID = -1; |
| 31 const uint32_t kNumVDAResetsBeforeSWFallback = 5; | 31 const uint32_t kNumVDAErrorsBeforeSWFallback = 5; |
| 32 const uint32_t kNumDecodeBeforeResettingVDAErrorCounter = 300; | |
| 32 | 33 |
| 33 // Maximum number of concurrent VDA::Decode() operations RVD will maintain. | 34 // Maximum number of concurrent VDA::Decode() operations RVD will maintain. |
| 34 // Higher values allow better pipelining in the GPU, but also require more | 35 // Higher values allow better pipelining in the GPU, but also require more |
| 35 // resources. | 36 // resources. |
| 36 static const size_t kMaxInFlightDecodes = 8; | 37 static const size_t kMaxInFlightDecodes = 8; |
| 37 | 38 |
| 38 // Number of allocated shared memory segments. | 39 // Number of allocated shared memory segments. |
| 39 static const size_t kNumSharedMemorySegments = 16; | 40 static const size_t kNumSharedMemorySegments = 16; |
| 40 | 41 |
| 41 // Maximum number of pending WebRTC buffers that are waiting for shared memory. | 42 // Maximum number of pending WebRTC buffers that are waiting for shared memory. |
| 42 static const size_t kMaxNumOfPendingBuffers = 8; | 43 static const size_t kMaxNumOfPendingBuffers = 8; |
| 43 | 44 |
| 44 RTCVideoDecoder::BufferData::BufferData(int32_t bitstream_buffer_id, | 45 RTCVideoDecoder::BufferData::BufferData(int32_t bitstream_buffer_id, |
| 45 uint32_t timestamp, | 46 uint32_t timestamp, |
| 46 size_t size, | 47 size_t size, |
| 47 const gfx::Rect& visible_rect) | 48 const gfx::Rect& visible_rect) |
| 48 : bitstream_buffer_id(bitstream_buffer_id), | 49 : bitstream_buffer_id(bitstream_buffer_id), |
| 49 timestamp(timestamp), | 50 timestamp(timestamp), |
| 50 size(size), | 51 size(size), |
| 51 visible_rect(visible_rect) {} | 52 visible_rect(visible_rect) {} |
| 52 | 53 |
| 53 RTCVideoDecoder::BufferData::BufferData() {} | 54 RTCVideoDecoder::BufferData::BufferData() {} |
| 54 | 55 |
| 55 RTCVideoDecoder::BufferData::~BufferData() {} | 56 RTCVideoDecoder::BufferData::~BufferData() {} |
| 56 | 57 |
| 57 RTCVideoDecoder::RTCVideoDecoder(webrtc::VideoCodecType type, | 58 RTCVideoDecoder::RTCVideoDecoder(webrtc::VideoCodecType type, |
| 58 media::GpuVideoAcceleratorFactories* factories) | 59 media::GpuVideoAcceleratorFactories* factories) |
| 59 : num_vda_errors_(0), | 60 : vda_error_counter_(0), |
| 60 video_codec_type_(type), | 61 video_codec_type_(type), |
| 61 factories_(factories), | 62 factories_(factories), |
| 62 decoder_texture_target_(0), | 63 decoder_texture_target_(0), |
| 63 next_picture_buffer_id_(0), | 64 next_picture_buffer_id_(0), |
| 64 state_(UNINITIALIZED), | 65 state_(UNINITIALIZED), |
| 65 decode_complete_callback_(nullptr), | 66 decode_complete_callback_(nullptr), |
| 66 num_shm_buffers_(0), | 67 num_shm_buffers_(0), |
| 67 next_bitstream_buffer_id_(0), | 68 next_bitstream_buffer_id_(0), |
| 68 reset_bitstream_buffer_id_(ID_INVALID), | 69 reset_bitstream_buffer_id_(ID_INVALID), |
| 69 weak_factory_(this) { | 70 weak_factory_(this) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 | 156 |
| 156 base::AutoLock auto_lock(lock_); | 157 base::AutoLock auto_lock(lock_); |
| 157 | 158 |
| 158 if (state_ == UNINITIALIZED || !decode_complete_callback_) { | 159 if (state_ == UNINITIALIZED || !decode_complete_callback_) { |
| 159 LOG(ERROR) << "The decoder has not initialized."; | 160 LOG(ERROR) << "The decoder has not initialized."; |
| 160 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 161 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
| 161 } | 162 } |
| 162 | 163 |
| 163 if (state_ == DECODE_ERROR) { | 164 if (state_ == DECODE_ERROR) { |
| 164 LOG(ERROR) << "Decoding error occurred."; | 165 LOG(ERROR) << "Decoding error occurred."; |
| 165 // Try reseting the session |kNumVDAErrorsHandled| times. | 166 // Try reseting the session |kNumVDAErrorsHandled| times. |
|
mcasas
2016/04/01 16:39:09
nit: s/the session/ the session up to/
emircan
2016/04/05 18:02:18
Done.
| |
| 166 if (num_vda_errors_ > kNumVDAResetsBeforeSWFallback) { | 167 if (vda_error_counter_ > kNumVDAErrorsBeforeSWFallback) { |
| 167 DLOG(ERROR) << num_vda_errors_ | 168 DLOG(ERROR) << vda_error_counter_ |
| 168 << " errors reported by VDA, falling back to software decode"; | 169 << " errors reported by VDA, falling back to software decode"; |
| 169 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; | 170 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; |
| 170 } | 171 } |
| 171 base::AutoUnlock auto_unlock(lock_); | 172 base::AutoUnlock auto_unlock(lock_); |
| 172 Release(); | 173 Release(); |
| 173 return WEBRTC_VIDEO_CODEC_ERROR; | 174 return WEBRTC_VIDEO_CODEC_ERROR; |
| 174 } | 175 } |
| 175 | 176 |
| 176 if (missingFrames || !inputImage._completeFrame) { | 177 if (missingFrames || !inputImage._completeFrame) { |
| 177 DLOG(ERROR) << "Missing or incomplete frames."; | 178 DLOG(ERROR) << "Missing or incomplete frames."; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 249 } | 250 } |
| 250 | 251 |
| 251 return WEBRTC_VIDEO_CODEC_OK; | 252 return WEBRTC_VIDEO_CODEC_OK; |
| 252 } | 253 } |
| 253 | 254 |
| 254 SaveToDecodeBuffers_Locked(inputImage, std::move(shm_buffer), buffer_data); | 255 SaveToDecodeBuffers_Locked(inputImage, std::move(shm_buffer), buffer_data); |
| 255 factories_->GetTaskRunner()->PostTask( | 256 factories_->GetTaskRunner()->PostTask( |
| 256 FROM_HERE, | 257 FROM_HERE, |
| 257 base::Bind(&RTCVideoDecoder::RequestBufferDecode, | 258 base::Bind(&RTCVideoDecoder::RequestBufferDecode, |
| 258 weak_factory_.GetWeakPtr())); | 259 weak_factory_.GetWeakPtr())); |
| 260 TryResetVDAErrorCounter(); | |
| 259 return WEBRTC_VIDEO_CODEC_OK; | 261 return WEBRTC_VIDEO_CODEC_OK; |
| 260 } | 262 } |
| 261 | 263 |
| 262 int32_t RTCVideoDecoder::RegisterDecodeCompleteCallback( | 264 int32_t RTCVideoDecoder::RegisterDecodeCompleteCallback( |
| 263 webrtc::DecodedImageCallback* callback) { | 265 webrtc::DecodedImageCallback* callback) { |
| 264 DVLOG(2) << "RegisterDecodeCompleteCallback"; | 266 DVLOG(2) << "RegisterDecodeCompleteCallback"; |
| 265 DCHECK(callback); | 267 DCHECK(callback); |
| 266 base::AutoLock auto_lock(lock_); | 268 base::AutoLock auto_lock(lock_); |
| 267 decode_complete_callback_ = callback; | 269 decode_complete_callback_ = callback; |
| 268 return WEBRTC_VIDEO_CODEC_OK; | 270 return WEBRTC_VIDEO_CODEC_OK; |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 if (!vda_) | 480 if (!vda_) |
| 479 return; | 481 return; |
| 480 | 482 |
| 481 LOG(ERROR) << "VDA Error:" << error; | 483 LOG(ERROR) << "VDA Error:" << error; |
| 482 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", error, | 484 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", error, |
| 483 media::VideoDecodeAccelerator::ERROR_MAX + 1); | 485 media::VideoDecodeAccelerator::ERROR_MAX + 1); |
| 484 DestroyVDA(); | 486 DestroyVDA(); |
| 485 | 487 |
| 486 base::AutoLock auto_lock(lock_); | 488 base::AutoLock auto_lock(lock_); |
| 487 state_ = DECODE_ERROR; | 489 state_ = DECODE_ERROR; |
| 488 ++num_vda_errors_; | 490 IncrementVDAErrorCounter(); |
| 489 } | 491 } |
| 490 | 492 |
| 491 void RTCVideoDecoder::RequestBufferDecode() { | 493 void RTCVideoDecoder::RequestBufferDecode() { |
| 492 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 494 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 493 if (!vda_) | 495 if (!vda_) |
| 494 return; | 496 return; |
| 495 | 497 |
| 496 MovePendingBuffersToDecodeBuffers(); | 498 MovePendingBuffersToDecodeBuffers(); |
| 497 | 499 |
| 498 while (CanMoreDecodeWorkBeDone()) { | 500 while (CanMoreDecodeWorkBeDone()) { |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 831 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); | 833 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); |
| 832 } | 834 } |
| 833 | 835 |
| 834 void RTCVideoDecoder::ClearPendingBuffers() { | 836 void RTCVideoDecoder::ClearPendingBuffers() { |
| 835 // Delete WebRTC input buffers. | 837 // Delete WebRTC input buffers. |
| 836 for (const auto& pending_buffer : pending_buffers_) | 838 for (const auto& pending_buffer : pending_buffers_) |
| 837 delete[] pending_buffer.first._buffer; | 839 delete[] pending_buffer.first._buffer; |
| 838 pending_buffers_.clear(); | 840 pending_buffers_.clear(); |
| 839 } | 841 } |
| 840 | 842 |
| 843 void RTCVideoDecoder::IncrementVDAErrorCounter() { | |
|
mcasas
2016/04/01 16:39:09
This file adds a suffix "_Lock" to the
methods tha
emircan
2016/04/05 18:02:18
Done.
| |
| 844 DVLOG(3) << __FUNCTION__; | |
| 845 lock_.AssertAcquired(); | |
| 846 | |
| 847 ++vda_error_counter_; | |
| 848 num_consecutive_vda_success_since_error_ = 0; | |
| 849 } | |
| 850 | |
| 851 void RTCVideoDecoder::TryResetVDAErrorCounter() { | |
| 852 lock_.AssertAcquired(); | |
| 853 | |
| 854 if (vda_error_counter_ > 0) { | |
|
mcasas
2016/04/01 16:39:09
if (vda_error_counter_ == 0)
return;
//...
emircan
2016/04/05 18:02:18
Done.
| |
| 855 if (++num_consecutive_vda_success_since_error_ == | |
| 856 kNumDecodeBeforeResettingVDAErrorCounter) { | |
| 857 vda_error_counter_ = 0; | |
| 858 } | |
| 859 } | |
| 860 } | |
| 861 | |
| 841 } // namespace content | 862 } // namespace content |
| OLD | NEW |