| 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 = 50; |
| 32 | 32 |
| 33 // Maximum number of concurrent VDA::Decode() operations RVD will maintain. | 33 // Maximum number of concurrent VDA::Decode() operations RVD will maintain. |
| 34 // Higher values allow better pipelining in the GPU, but also require more | 34 // Higher values allow better pipelining in the GPU, but also require more |
| 35 // resources. | 35 // resources. |
| 36 static const size_t kMaxInFlightDecodes = 8; | 36 static const size_t kMaxInFlightDecodes = 8; |
| 37 | 37 |
| 38 // Number of allocated shared memory segments. | 38 // Number of allocated shared memory segments. |
| 39 static const size_t kNumSharedMemorySegments = 16; | 39 static const size_t kNumSharedMemorySegments = 16; |
| 40 | 40 |
| 41 // Maximum number of pending WebRTC buffers that are waiting for shared memory. | 41 // Maximum number of pending WebRTC buffers that are waiting for shared memory. |
| 42 static const size_t kMaxNumOfPendingBuffers = 8; | 42 static const size_t kMaxNumOfPendingBuffers = 8; |
| 43 | 43 |
| 44 RTCVideoDecoder::BufferData::BufferData(int32_t bitstream_buffer_id, | 44 RTCVideoDecoder::BufferData::BufferData(int32_t bitstream_buffer_id, |
| 45 uint32_t timestamp, | 45 uint32_t timestamp, |
| 46 size_t size, | 46 size_t size, |
| 47 const gfx::Rect& visible_rect) | 47 const gfx::Rect& visible_rect) |
| 48 : bitstream_buffer_id(bitstream_buffer_id), | 48 : bitstream_buffer_id(bitstream_buffer_id), |
| 49 timestamp(timestamp), | 49 timestamp(timestamp), |
| 50 size(size), | 50 size(size), |
| 51 visible_rect(visible_rect) {} | 51 visible_rect(visible_rect) {} |
| 52 | 52 |
| 53 RTCVideoDecoder::BufferData::BufferData() {} | 53 RTCVideoDecoder::BufferData::BufferData() {} |
| 54 | 54 |
| 55 RTCVideoDecoder::BufferData::~BufferData() {} | 55 RTCVideoDecoder::BufferData::~BufferData() {} |
| 56 | 56 |
| 57 RTCVideoDecoder::RTCVideoDecoder(webrtc::VideoCodecType type, | 57 RTCVideoDecoder::RTCVideoDecoder(webrtc::VideoCodecType type, |
| 58 media::GpuVideoAcceleratorFactories* factories) | 58 media::GpuVideoAcceleratorFactories* factories) |
| 59 : num_vda_errors_(0), | 59 : vda_error_counter_(0), |
| 60 video_codec_type_(type), | 60 video_codec_type_(type), |
| 61 factories_(factories), | 61 factories_(factories), |
| 62 decoder_texture_target_(0), | 62 decoder_texture_target_(0), |
| 63 next_picture_buffer_id_(0), | 63 next_picture_buffer_id_(0), |
| 64 state_(UNINITIALIZED), | 64 state_(UNINITIALIZED), |
| 65 decode_complete_callback_(nullptr), | 65 decode_complete_callback_(nullptr), |
| 66 num_shm_buffers_(0), | 66 num_shm_buffers_(0), |
| 67 next_bitstream_buffer_id_(0), | 67 next_bitstream_buffer_id_(0), |
| 68 reset_bitstream_buffer_id_(ID_INVALID), | 68 reset_bitstream_buffer_id_(ID_INVALID), |
| 69 weak_factory_(this) { | 69 weak_factory_(this) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 | 155 |
| 156 base::AutoLock auto_lock(lock_); | 156 base::AutoLock auto_lock(lock_); |
| 157 | 157 |
| 158 if (state_ == UNINITIALIZED || !decode_complete_callback_) { | 158 if (state_ == UNINITIALIZED || !decode_complete_callback_) { |
| 159 LOG(ERROR) << "The decoder has not initialized."; | 159 LOG(ERROR) << "The decoder has not initialized."; |
| 160 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 160 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
| 161 } | 161 } |
| 162 | 162 |
| 163 if (state_ == DECODE_ERROR) { | 163 if (state_ == DECODE_ERROR) { |
| 164 LOG(ERROR) << "Decoding error occurred."; | 164 LOG(ERROR) << "Decoding error occurred."; |
| 165 // Try reseting the session |kNumVDAErrorsHandled| times. | 165 // Try reseting the session up to |kNumVDAErrorsHandled| times. |
| 166 if (num_vda_errors_ > kNumVDAResetsBeforeSWFallback) { | 166 if (vda_error_counter_ > kNumVDAErrorsBeforeSWFallback) { |
| 167 DLOG(ERROR) << num_vda_errors_ | 167 DLOG(ERROR) << vda_error_counter_ |
| 168 << " errors reported by VDA, falling back to software decode"; | 168 << " errors reported by VDA, falling back to software decode"; |
| 169 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; | 169 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; |
| 170 } | 170 } |
| 171 base::AutoUnlock auto_unlock(lock_); | 171 base::AutoUnlock auto_unlock(lock_); |
| 172 Release(); | 172 Release(); |
| 173 return WEBRTC_VIDEO_CODEC_ERROR; | 173 return WEBRTC_VIDEO_CODEC_ERROR; |
| 174 } | 174 } |
| 175 | 175 |
| 176 if (missingFrames || !inputImage._completeFrame) { | 176 if (missingFrames || !inputImage._completeFrame) { |
| 177 DLOG(ERROR) << "Missing or incomplete frames."; | 177 DLOG(ERROR) << "Missing or incomplete frames."; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 DVLOG(1) << "Exceeded maximum pending buffer count, dropping"; | 241 DVLOG(1) << "Exceeded maximum pending buffer count, dropping"; |
| 242 ClearPendingBuffers(); | 242 ClearPendingBuffers(); |
| 243 return WEBRTC_VIDEO_CODEC_ERROR; | 243 return WEBRTC_VIDEO_CODEC_ERROR; |
| 244 } | 244 } |
| 245 | 245 |
| 246 if (need_to_reset_for_midstream_resize) { | 246 if (need_to_reset_for_midstream_resize) { |
| 247 base::AutoUnlock auto_unlock(lock_); | 247 base::AutoUnlock auto_unlock(lock_); |
| 248 Release(); | 248 Release(); |
| 249 } | 249 } |
| 250 | 250 |
| 251 TryResetVDAErrorCounter_Locked(); |
| 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_Locked(); |
| 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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 if (!vda_) | 487 if (!vda_) |
| 486 return; | 488 return; |
| 487 | 489 |
| 488 LOG(ERROR) << "VDA Error:" << error; | 490 LOG(ERROR) << "VDA Error:" << error; |
| 489 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", error, | 491 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", error, |
| 490 media::VideoDecodeAccelerator::ERROR_MAX + 1); | 492 media::VideoDecodeAccelerator::ERROR_MAX + 1); |
| 491 DestroyVDA(); | 493 DestroyVDA(); |
| 492 | 494 |
| 493 base::AutoLock auto_lock(lock_); | 495 base::AutoLock auto_lock(lock_); |
| 494 state_ = DECODE_ERROR; | 496 state_ = DECODE_ERROR; |
| 495 ++num_vda_errors_; | 497 ++vda_error_counter_; |
| 496 } | 498 } |
| 497 | 499 |
| 498 void RTCVideoDecoder::RequestBufferDecode() { | 500 void RTCVideoDecoder::RequestBufferDecode() { |
| 499 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 501 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 500 if (!vda_) | 502 if (!vda_) |
| 501 return; | 503 return; |
| 502 | 504 |
| 503 MovePendingBuffersToDecodeBuffers(); | 505 MovePendingBuffersToDecodeBuffers(); |
| 504 | 506 |
| 505 while (CanMoreDecodeWorkBeDone()) { | 507 while (CanMoreDecodeWorkBeDone()) { |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); | 840 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); |
| 839 } | 841 } |
| 840 | 842 |
| 841 void RTCVideoDecoder::ClearPendingBuffers() { | 843 void RTCVideoDecoder::ClearPendingBuffers() { |
| 842 // Delete WebRTC input buffers. | 844 // Delete WebRTC input buffers. |
| 843 for (const auto& pending_buffer : pending_buffers_) | 845 for (const auto& pending_buffer : pending_buffers_) |
| 844 delete[] pending_buffer.first._buffer; | 846 delete[] pending_buffer.first._buffer; |
| 845 pending_buffers_.clear(); | 847 pending_buffers_.clear(); |
| 846 } | 848 } |
| 847 | 849 |
| 850 void RTCVideoDecoder::TryResetVDAErrorCounter_Locked() { |
| 851 lock_.AssertAcquired(); |
| 852 |
| 853 if (vda_error_counter_ == 0) |
| 854 return; |
| 855 vda_error_counter_ = 0; |
| 856 } |
| 857 |
| 848 } // namespace content | 858 } // namespace content |
| OLD | NEW |