Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: content/renderer/media/rtc_video_decoder.cc

Issue 1817573004: Handle HW decode failures in RTCVideoDecoder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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/system_wrappers/include/ref_count.h" 23 #include "third_party/webrtc/system_wrappers/include/ref_count.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 32
32 // Maximum number of concurrent VDA::Decode() operations RVD will maintain. 33 // Maximum number of concurrent VDA::Decode() operations RVD will maintain.
33 // 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
34 // resources. 35 // resources.
35 static const size_t kMaxInFlightDecodes = 8; 36 static const size_t kMaxInFlightDecodes = 8;
36 37
37 // Number of allocated shared memory segments. 38 // Number of allocated shared memory segments.
38 static const size_t kNumSharedMemorySegments = 16; 39 static const size_t kNumSharedMemorySegments = 16;
39 40
40 // 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.
41 static const size_t kMaxNumOfPendingBuffers = 8; 42 static const size_t kMaxNumOfPendingBuffers = 8;
42 43
43 RTCVideoDecoder::BufferData::BufferData(int32_t bitstream_buffer_id, 44 RTCVideoDecoder::BufferData::BufferData(int32_t bitstream_buffer_id,
44 uint32_t timestamp, 45 uint32_t timestamp,
45 size_t size, 46 size_t size,
46 const gfx::Rect& visible_rect) 47 const gfx::Rect& visible_rect)
47 : bitstream_buffer_id(bitstream_buffer_id), 48 : bitstream_buffer_id(bitstream_buffer_id),
48 timestamp(timestamp), 49 timestamp(timestamp),
49 size(size), 50 size(size),
50 visible_rect(visible_rect) {} 51 visible_rect(visible_rect) {}
51 52
52 RTCVideoDecoder::BufferData::BufferData() {} 53 RTCVideoDecoder::BufferData::BufferData() {}
53 54
54 RTCVideoDecoder::BufferData::~BufferData() {} 55 RTCVideoDecoder::BufferData::~BufferData() {}
55 56
56 RTCVideoDecoder::RTCVideoDecoder(webrtc::VideoCodecType type, 57 RTCVideoDecoder::RTCVideoDecoder(webrtc::VideoCodecType type,
57 media::GpuVideoAcceleratorFactories* factories) 58 media::GpuVideoAcceleratorFactories* factories)
58 : video_codec_type_(type), 59 : num_vda_errors_(0),
60 video_codec_type_(type),
59 factories_(factories), 61 factories_(factories),
60 decoder_texture_target_(0), 62 decoder_texture_target_(0),
61 next_picture_buffer_id_(0), 63 next_picture_buffer_id_(0),
62 state_(UNINITIALIZED), 64 state_(UNINITIALIZED),
63 decode_complete_callback_(nullptr), 65 decode_complete_callback_(nullptr),
64 num_shm_buffers_(0), 66 num_shm_buffers_(0),
65 next_bitstream_buffer_id_(0), 67 next_bitstream_buffer_id_(0),
66 reset_bitstream_buffer_id_(ID_INVALID), 68 reset_bitstream_buffer_id_(ID_INVALID),
67 weak_factory_(this) { 69 weak_factory_(this) {
68 DCHECK(!factories_->GetTaskRunner()->BelongsToCurrentThread()); 70 DCHECK(!factories_->GetTaskRunner()->BelongsToCurrentThread());
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 155
154 base::AutoLock auto_lock(lock_); 156 base::AutoLock auto_lock(lock_);
155 157
156 if (state_ == UNINITIALIZED || !decode_complete_callback_) { 158 if (state_ == UNINITIALIZED || !decode_complete_callback_) {
157 LOG(ERROR) << "The decoder has not initialized."; 159 LOG(ERROR) << "The decoder has not initialized.";
158 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 160 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
159 } 161 }
160 162
161 if (state_ == DECODE_ERROR) { 163 if (state_ == DECODE_ERROR) {
162 LOG(ERROR) << "Decoding error occurred."; 164 LOG(ERROR) << "Decoding error occurred.";
165 // Try reseting the session |kNumVDAErrorsHandled| times.
166 if (num_vda_errors_ > kNumVDAResetsBeforeSWFallback) {
167 DLOG(ERROR) << num_vda_errors_
168 << " errors reported by VDA, falling back to software decode";
169 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
170 }
171 base::AutoUnlock auto_unlock(lock_);
172 Release();
163 return WEBRTC_VIDEO_CODEC_ERROR; 173 return WEBRTC_VIDEO_CODEC_ERROR;
164 } 174 }
165 175
166 if (missingFrames || !inputImage._completeFrame) { 176 if (missingFrames || !inputImage._completeFrame) {
167 DLOG(ERROR) << "Missing or incomplete frames."; 177 DLOG(ERROR) << "Missing or incomplete frames.";
168 // Unlike the SW decoder in libvpx, hw decoder cannot handle broken frames. 178 // Unlike the SW decoder in libvpx, hw decoder cannot handle broken frames.
169 // Return an error to request a key frame. 179 // Return an error to request a key frame.
170 return WEBRTC_VIDEO_CODEC_ERROR; 180 return WEBRTC_VIDEO_CODEC_ERROR;
171 } 181 }
172 182
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 return; 479 return;
470 480
471 LOG(ERROR) << "VDA Error:" << error; 481 LOG(ERROR) << "VDA Error:" << error;
472 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", 482 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError",
473 error, 483 error,
474 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM); 484 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM);
475 DestroyVDA(); 485 DestroyVDA();
476 486
477 base::AutoLock auto_lock(lock_); 487 base::AutoLock auto_lock(lock_);
478 state_ = DECODE_ERROR; 488 state_ = DECODE_ERROR;
489 ++num_vda_errors_;
479 } 490 }
480 491
481 void RTCVideoDecoder::RequestBufferDecode() { 492 void RTCVideoDecoder::RequestBufferDecode() {
482 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 493 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
483 if (!vda_) 494 if (!vda_)
484 return; 495 return;
485 496
486 MovePendingBuffersToDecodeBuffers(); 497 MovePendingBuffersToDecodeBuffers();
487 498
488 while (CanMoreDecodeWorkBeDone()) { 499 while (CanMoreDecodeWorkBeDone()) {
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 GetSHM_Locked(input_image._length); 609 GetSHM_Locked(input_image._length);
599 if (!shm_buffer) 610 if (!shm_buffer)
600 return; 611 return;
601 SaveToDecodeBuffers_Locked(input_image, std::move(shm_buffer), buffer_data); 612 SaveToDecodeBuffers_Locked(input_image, std::move(shm_buffer), buffer_data);
602 delete[] input_image._buffer; 613 delete[] input_image._buffer;
603 pending_buffers_.pop_front(); 614 pending_buffers_.pop_front();
604 } 615 }
605 } 616 }
606 617
607 void RTCVideoDecoder::ResetInternal() { 618 void RTCVideoDecoder::ResetInternal() {
619 DVLOG(2) << __FUNCTION__;
608 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 620 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
609 DVLOG(2) << "ResetInternal"; 621
610 if (vda_) 622 if (vda_) {
611 vda_->Reset(); 623 vda_->Reset();
624 } else {
625 CreateVDA(vda_codec_profile_, nullptr);
626 if (vda_)
627 state_ = INITIALIZED;
628 }
612 } 629 }
613 630
614 // static 631 // static
615 void RTCVideoDecoder::ReleaseMailbox( 632 void RTCVideoDecoder::ReleaseMailbox(
616 base::WeakPtr<RTCVideoDecoder> decoder, 633 base::WeakPtr<RTCVideoDecoder> decoder,
617 media::GpuVideoAcceleratorFactories* factories, 634 media::GpuVideoAcceleratorFactories* factories,
618 int64_t picture_buffer_id, 635 int64_t picture_buffer_id,
619 uint32_t texture_id, 636 uint32_t texture_id,
620 const gpu::SyncToken& release_sync_token) { 637 const gpu::SyncToken& release_sync_token) {
621 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); 638 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 690 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
674 691
675 if (!IsProfileSupported(profile)) { 692 if (!IsProfileSupported(profile)) {
676 DVLOG(1) << "Unsupported profile " << profile; 693 DVLOG(1) << "Unsupported profile " << profile;
677 } else { 694 } else {
678 vda_ = factories_->CreateVideoDecodeAccelerator(); 695 vda_ = factories_->CreateVideoDecodeAccelerator();
679 696
680 media::VideoDecodeAccelerator::Config config(profile); 697 media::VideoDecodeAccelerator::Config config(profile);
681 if (vda_ && !vda_->Initialize(config, this)) 698 if (vda_ && !vda_->Initialize(config, this))
682 vda_.release()->Destroy(); 699 vda_.release()->Destroy();
700 vda_codec_profile_ = profile;
683 } 701 }
684 702
685 waiter->Signal(); 703 if (waiter)
704 waiter->Signal();
686 } 705 }
687 706
688 void RTCVideoDecoder::DestroyTextures() { 707 void RTCVideoDecoder::DestroyTextures() {
689 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 708 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
690 709
691 // Not destroying PictureBuffers in |picture_buffers_at_display_| yet, since 710 // Not destroying PictureBuffers in |picture_buffers_at_display_| yet, since
692 // their textures may still be in use by the user of this RTCVideoDecoder. 711 // their textures may still be in use by the user of this RTCVideoDecoder.
693 for (const auto& picture_buffer_at_display : picture_buffers_at_display_) 712 for (const auto& picture_buffer_at_display : picture_buffers_at_display_)
694 assigned_picture_buffers_.erase(picture_buffer_at_display.first); 713 assigned_picture_buffers_.erase(picture_buffer_at_display.first);
695 714
696 for (const auto& assigned_picture_buffer : assigned_picture_buffers_) 715 for (const auto& assigned_picture_buffer : assigned_picture_buffers_)
697 factories_->DeleteTexture(assigned_picture_buffer.second.texture_id()); 716 factories_->DeleteTexture(assigned_picture_buffer.second.texture_id());
698 717
699 assigned_picture_buffers_.clear(); 718 assigned_picture_buffers_.clear();
700 } 719 }
701 720
702 void RTCVideoDecoder::DestroyVDA() { 721 void RTCVideoDecoder::DestroyVDA() {
703 DVLOG(2) << "DestroyVDA"; 722 DVLOG(2) << "DestroyVDA";
704 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 723 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
705 if (vda_) 724 if (vda_)
706 vda_.release()->Destroy(); 725 vda_.release()->Destroy();
707 DestroyTextures(); 726 DestroyTextures();
727
708 base::AutoLock auto_lock(lock_); 728 base::AutoLock auto_lock(lock_);
729
730 // Put the buffers back in case we restart the decoder.
731 for (const auto& buffer : bitstream_buffers_in_decoder_)
732 PutSHM_Locked(scoped_ptr<base::SharedMemory>(buffer.second));
733 bitstream_buffers_in_decoder_.clear();
734
709 state_ = UNINITIALIZED; 735 state_ = UNINITIALIZED;
710 } 736 }
711 737
712 scoped_ptr<base::SharedMemory> RTCVideoDecoder::GetSHM_Locked(size_t min_size) { 738 scoped_ptr<base::SharedMemory> RTCVideoDecoder::GetSHM_Locked(size_t min_size) {
713 // Reuse a SHM if possible. 739 // Reuse a SHM if possible.
714 if (!available_shm_segments_.empty() && 740 if (!available_shm_segments_.empty() &&
715 available_shm_segments_.back()->mapped_size() >= min_size) { 741 available_shm_segments_.back()->mapped_size() >= min_size) {
716 scoped_ptr<base::SharedMemory> buffer(available_shm_segments_.back()); 742 scoped_ptr<base::SharedMemory> buffer(available_shm_segments_.back());
717 available_shm_segments_.pop_back(); 743 available_shm_segments_.pop_back();
718 return buffer; 744 return buffer;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 } 833 }
808 834
809 void RTCVideoDecoder::ClearPendingBuffers() { 835 void RTCVideoDecoder::ClearPendingBuffers() {
810 // Delete WebRTC input buffers. 836 // Delete WebRTC input buffers.
811 for (const auto& pending_buffer : pending_buffers_) 837 for (const auto& pending_buffer : pending_buffers_)
812 delete[] pending_buffer.first._buffer; 838 delete[] pending_buffer.first._buffer;
813 pending_buffers_.clear(); 839 pending_buffers_.clear();
814 } 840 }
815 841
816 } // namespace content 842 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/rtc_video_decoder.h ('k') | content/renderer/media/rtc_video_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698