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

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: mcasas@ comments. Created 4 years, 9 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/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 kNumVDAErrorsHandled = 5;
mcasas 2016/03/28 18:15:20 micro-pedantic-nit: s/kNumVDAErrorsHandled/kNumVDA
emircan 2016/03/29 01:50:50 kNumVDAResetsBeforeSWFallback?
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.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 154
154 base::AutoLock auto_lock(lock_); 155 base::AutoLock auto_lock(lock_);
155 156
156 if (state_ == UNINITIALIZED || !decode_complete_callback_) { 157 if (state_ == UNINITIALIZED || !decode_complete_callback_) {
157 LOG(ERROR) << "The decoder has not initialized."; 158 LOG(ERROR) << "The decoder has not initialized.";
158 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 159 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
159 } 160 }
160 161
161 if (state_ == DECODE_ERROR) { 162 if (state_ == DECODE_ERROR) {
162 LOG(ERROR) << "Decoding error occurred."; 163 LOG(ERROR) << "Decoding error occurred.";
164 // Try reseting the session |kNumVDAErrorsHandled| times.
165 if (num_vda_errors_ > kNumVDAErrorsHandled) {
166 DVLOG(1) << num_vda_errors_
mcasas 2016/03/28 18:15:20 nit: s/DVLOG(1)/DLOG(ERROR)/
emircan 2016/03/29 01:50:50 Done.
167 << " errors reported by VDA, falling back to software decode";
168 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
169 }
170 state_ = RESETTING;
171 factories_->GetTaskRunner()->PostTask(
172 FROM_HERE, base::Bind(&RTCVideoDecoder::ResetInternal,
173 weak_factory_.GetWeakPtr()));
163 return WEBRTC_VIDEO_CODEC_ERROR; 174 return WEBRTC_VIDEO_CODEC_ERROR;
164 } 175 }
165 176
166 if (missingFrames || !inputImage._completeFrame) { 177 if (missingFrames || !inputImage._completeFrame) {
167 DLOG(ERROR) << "Missing or incomplete frames."; 178 DLOG(ERROR) << "Missing or incomplete frames.";
168 // Unlike the SW decoder in libvpx, hw decoder cannot handle broken frames. 179 // Unlike the SW decoder in libvpx, hw decoder cannot handle broken frames.
169 // Return an error to request a key frame. 180 // Return an error to request a key frame.
170 return WEBRTC_VIDEO_CODEC_ERROR; 181 return WEBRTC_VIDEO_CODEC_ERROR;
171 } 182 }
172 183
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 return; 480 return;
470 481
471 LOG(ERROR) << "VDA Error:" << error; 482 LOG(ERROR) << "VDA Error:" << error;
472 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", 483 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError",
473 error, 484 error,
474 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM); 485 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM);
475 DestroyVDA(); 486 DestroyVDA();
476 487
477 base::AutoLock auto_lock(lock_); 488 base::AutoLock auto_lock(lock_);
478 state_ = DECODE_ERROR; 489 state_ = DECODE_ERROR;
490 num_vda_errors_++;
mcasas 2016/03/28 18:15:20 nit: prefer pre-increment. I know, I know, we coul
emircan 2016/03/29 01:50:50 Done.
479 } 491 }
480 492
481 void RTCVideoDecoder::RequestBufferDecode() { 493 void RTCVideoDecoder::RequestBufferDecode() {
482 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 494 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
483 if (!vda_) 495 if (!vda_)
484 return; 496 return;
485 497
486 MovePendingBuffersToDecodeBuffers(); 498 MovePendingBuffersToDecodeBuffers();
487 499
488 while (CanMoreDecodeWorkBeDone()) { 500 while (CanMoreDecodeWorkBeDone()) {
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 GetSHM_Locked(input_image._length); 610 GetSHM_Locked(input_image._length);
599 if (!shm_buffer) 611 if (!shm_buffer)
600 return; 612 return;
601 SaveToDecodeBuffers_Locked(input_image, std::move(shm_buffer), buffer_data); 613 SaveToDecodeBuffers_Locked(input_image, std::move(shm_buffer), buffer_data);
602 delete[] input_image._buffer; 614 delete[] input_image._buffer;
603 pending_buffers_.pop_front(); 615 pending_buffers_.pop_front();
604 } 616 }
605 } 617 }
606 618
607 void RTCVideoDecoder::ResetInternal() { 619 void RTCVideoDecoder::ResetInternal() {
620 DVLOG(2) << __FUNCTION__;
608 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 621 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
609 DVLOG(2) << "ResetInternal"; 622
610 if (vda_) 623 if (vda_) {
611 vda_->Reset(); 624 vda_->Reset();
625 } else {
626 CreateVDA(vda_codec_profile_, nullptr);
627 }
mcasas 2016/03/28 18:15:20 No {} for one-liners as I replied to pbos@ (this i
emircan 2016/03/29 01:50:50 Done.
612 } 628 }
613 629
614 // static 630 // static
615 void RTCVideoDecoder::ReleaseMailbox( 631 void RTCVideoDecoder::ReleaseMailbox(
616 base::WeakPtr<RTCVideoDecoder> decoder, 632 base::WeakPtr<RTCVideoDecoder> decoder,
617 media::GpuVideoAcceleratorFactories* factories, 633 media::GpuVideoAcceleratorFactories* factories,
618 int64_t picture_buffer_id, 634 int64_t picture_buffer_id,
619 uint32_t texture_id, 635 uint32_t texture_id,
620 const gpu::SyncToken& release_sync_token) { 636 const gpu::SyncToken& release_sync_token) {
621 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); 637 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 689 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
674 690
675 if (!IsProfileSupported(profile)) { 691 if (!IsProfileSupported(profile)) {
676 DVLOG(1) << "Unsupported profile " << profile; 692 DVLOG(1) << "Unsupported profile " << profile;
677 } else { 693 } else {
678 vda_ = factories_->CreateVideoDecodeAccelerator(); 694 vda_ = factories_->CreateVideoDecodeAccelerator();
679 695
680 media::VideoDecodeAccelerator::Config config(profile); 696 media::VideoDecodeAccelerator::Config config(profile);
681 if (vda_ && !vda_->Initialize(config, this)) 697 if (vda_ && !vda_->Initialize(config, this))
682 vda_.release()->Destroy(); 698 vda_.release()->Destroy();
699 vda_codec_profile_ = profile;
683 } 700 }
684 701
685 waiter->Signal(); 702 if (waiter)
703 waiter->Signal();
686 } 704 }
687 705
688 void RTCVideoDecoder::DestroyTextures() { 706 void RTCVideoDecoder::DestroyTextures() {
689 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 707 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
690 708
691 // Not destroying PictureBuffers in |picture_buffers_at_display_| yet, since 709 // Not destroying PictureBuffers in |picture_buffers_at_display_| yet, since
692 // their textures may still be in use by the user of this RTCVideoDecoder. 710 // 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_) 711 for (const auto& picture_buffer_at_display : picture_buffers_at_display_)
694 assigned_picture_buffers_.erase(picture_buffer_at_display.first); 712 assigned_picture_buffers_.erase(picture_buffer_at_display.first);
695 713
696 for (const auto& assigned_picture_buffer : assigned_picture_buffers_) 714 for (const auto& assigned_picture_buffer : assigned_picture_buffers_)
697 factories_->DeleteTexture(assigned_picture_buffer.second.texture_id()); 715 factories_->DeleteTexture(assigned_picture_buffer.second.texture_id());
698 716
699 assigned_picture_buffers_.clear(); 717 assigned_picture_buffers_.clear();
700 } 718 }
701 719
702 void RTCVideoDecoder::DestroyVDA() { 720 void RTCVideoDecoder::DestroyVDA() {
703 DVLOG(2) << "DestroyVDA"; 721 DVLOG(2) << "DestroyVDA";
704 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 722 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
705 if (vda_) 723 if (vda_)
706 vda_.release()->Destroy(); 724 vda_.release()->Destroy();
707 DestroyTextures(); 725 DestroyTextures();
726
708 base::AutoLock auto_lock(lock_); 727 base::AutoLock auto_lock(lock_);
728
729 // Put the buffers back in case we restart the decoder.
730 for (const auto& buffer : bitstream_buffers_in_decoder_)
731 PutSHM_Locked(scoped_ptr<base::SharedMemory>(buffer.second));
732 bitstream_buffers_in_decoder_.clear();
733
709 state_ = UNINITIALIZED; 734 state_ = UNINITIALIZED;
710 } 735 }
711 736
712 scoped_ptr<base::SharedMemory> RTCVideoDecoder::GetSHM_Locked(size_t min_size) { 737 scoped_ptr<base::SharedMemory> RTCVideoDecoder::GetSHM_Locked(size_t min_size) {
713 // Reuse a SHM if possible. 738 // Reuse a SHM if possible.
714 if (!available_shm_segments_.empty() && 739 if (!available_shm_segments_.empty() &&
715 available_shm_segments_.back()->mapped_size() >= min_size) { 740 available_shm_segments_.back()->mapped_size() >= min_size) {
716 scoped_ptr<base::SharedMemory> buffer(available_shm_segments_.back()); 741 scoped_ptr<base::SharedMemory> buffer(available_shm_segments_.back());
717 available_shm_segments_.pop_back(); 742 available_shm_segments_.pop_back();
718 return buffer; 743 return buffer;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 } 832 }
808 833
809 void RTCVideoDecoder::ClearPendingBuffers() { 834 void RTCVideoDecoder::ClearPendingBuffers() {
810 // Delete WebRTC input buffers. 835 // Delete WebRTC input buffers.
811 for (const auto& pending_buffer : pending_buffers_) 836 for (const auto& pending_buffer : pending_buffers_)
812 delete[] pending_buffer.first._buffer; 837 delete[] pending_buffer.first._buffer;
813 pending_buffers_.clear(); 838 pending_buffers_.clear();
814 } 839 }
815 840
816 } // namespace content 841 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698