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

Unified Diff: content/renderer/media/rtc_video_decoder.cc

Issue 1236663003: RTCVideoDecoder: Fixes for high resolutions and high pressure cases. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/renderer/media/rtc_video_decoder.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/renderer/media/rtc_video_decoder.cc
diff --git a/content/renderer/media/rtc_video_decoder.cc b/content/renderer/media/rtc_video_decoder.cc
index ecb488b6e8110c1f397926fcfb90590c90acbdc6..0afdef07a1f693e8f1b9fc7fb82e24bd01af87f8 100644
--- a/content/renderer/media/rtc_video_decoder.cc
+++ b/content/renderer/media/rtc_video_decoder.cc
@@ -32,16 +32,11 @@ const int32 RTCVideoDecoder::ID_INVALID = -1;
// resources.
static const size_t kMaxInFlightDecodes = 8;
-// Size of shared-memory segments we allocate. Since we reuse them we let them
-// be on the beefy side.
-static const size_t kSharedMemorySegmentBytes = 100 << 10;
+// Number of allocated shared memory segments.
+static const size_t kNumSharedMemorySegments = 16;
-// Maximum number of allocated shared-memory segments.
-static const int kMaxNumSharedMemorySegments = 16;
-
-// Maximum number of pending WebRTC buffers that are waiting for the shared
-// memory. 10 seconds for 30 fps.
-static const size_t kMaxNumOfPendingBuffers = 300;
+// Maximum number of pending WebRTC buffers that are waiting for shared memory.
+static const size_t kMaxNumOfPendingBuffers = 8;
// A shared memory segment and its allocated size. This class has the ownership
// of |shm|.
@@ -99,14 +94,7 @@ RTCVideoDecoder::~RTCVideoDecoder() {
STLDeleteContainerPairFirstPointers(decode_buffers_.begin(),
decode_buffers_.end());
decode_buffers_.clear();
-
- // Delete WebRTC input buffers.
- for (std::deque<std::pair<webrtc::EncodedImage, BufferData> >::iterator it =
- pending_buffers_.begin();
- it != pending_buffers_.end();
- ++it) {
- delete[] it->first._buffer;
- }
+ ClearPendingBuffers();
}
// static
@@ -161,15 +149,7 @@ int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings,
LOG(ERROR) << "VDA is not initialized. state=" << state_;
return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_UNINITIALIZED);
}
- // Create some shared memory if the queue is empty.
- if (available_shm_segments_.size() == 0) {
- factories_->GetTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&RTCVideoDecoder::CreateSHM,
- weak_factory_.GetWeakPtr(),
- kMaxInFlightDecodes,
- kSharedMemorySegmentBytes));
- }
+
return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_OK);
}
@@ -249,15 +229,24 @@ int32_t RTCVideoDecoder::Decode(
// this isn't a mid-stream resolution change, then send the buffer for decode
// immediately. Otherwise, save the buffer in the queue for later decode.
scoped_ptr<SHMBuffer> shm_buffer;
- if (!need_to_reset_for_midstream_resize && pending_buffers_.size() == 0)
+ if (!need_to_reset_for_midstream_resize && pending_buffers_.empty())
shm_buffer = GetSHM_Locked(inputImage._length);
if (!shm_buffer) {
- if (!SaveToPendingBuffers_Locked(inputImage, buffer_data))
+ if (!SaveToPendingBuffers_Locked(inputImage, buffer_data)) {
+ // We have exceeded the pending buffers count, we are severely behind.
+ // Since we are returning ERROR, WebRTC will not be interested in the
+ // remaining buffers, and will provide us with a new keyframe instead.
+ // Better to drop any pending buffers and start afresh to catch up faster.
+ DVLOG(1) << "Exceeded maximum pending buffer count, dropping";
+ ClearPendingBuffers();
return WEBRTC_VIDEO_CODEC_ERROR;
+ }
+
if (need_to_reset_for_midstream_resize) {
base::AutoUnlock auto_unlock(lock_);
Reset();
}
+
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -511,7 +500,7 @@ void RTCVideoDecoder::RequestBufferDecode() {
{
base::AutoLock auto_lock(lock_);
// Do not request decode if VDA is resetting.
- if (decode_buffers_.size() == 0 || state_ == RESETTING)
+ if (decode_buffers_.empty() || state_ == RESETTING)
return;
shm_buffer = decode_buffers_.front().first;
buffer_data = decode_buffers_.front().second;
@@ -732,50 +721,58 @@ void RTCVideoDecoder::DestroyVDA() {
scoped_ptr<RTCVideoDecoder::SHMBuffer> RTCVideoDecoder::GetSHM_Locked(
size_t min_size) {
// Reuse a SHM if possible.
- SHMBuffer* ret = NULL;
if (!available_shm_segments_.empty() &&
available_shm_segments_.back()->size >= min_size) {
- ret = available_shm_segments_.back();
+ scoped_ptr<SHMBuffer> buffer(available_shm_segments_.back());
available_shm_segments_.pop_back();
+ return buffer;
}
- // Post to vda thread to create shared memory if SHM cannot be reused or the
- // queue is almost empty.
- if (num_shm_buffers_ < kMaxNumSharedMemorySegments &&
- (ret == NULL || available_shm_segments_.size() <= 1)) {
- factories_->GetTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&RTCVideoDecoder::CreateSHM,
- weak_factory_.GetWeakPtr(),
- 1,
- min_size));
+
+ if (available_shm_segments_.size() != num_shm_buffers_) {
+ // Either available_shm_segments_ is empty (and we already have some SHM
+ // buffers allocated), or the size of available segments is not large
+ // enough. In the former case we need to wait for buffers to be returned,
+ // in the latter we need to wait for all buffers to be returned to drop
+ // them and reallocate with a new size.
+ return NULL;
+ }
+
+ if (num_shm_buffers_ != 0) {
+ STLDeleteElements(&available_shm_segments_);
+ num_shm_buffers_ = 0;
}
- return scoped_ptr<SHMBuffer>(ret);
+
+ // Create twice as large buffers as required, to avoid frequent reallocation.
+ factories_->GetTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&RTCVideoDecoder::CreateSHM, weak_factory_.GetWeakPtr(),
+ kNumSharedMemorySegments, min_size * 2));
+
+ // We'll be called again after the shared memory is created.
+ return NULL;
}
void RTCVideoDecoder::PutSHM_Locked(scoped_ptr<SHMBuffer> shm_buffer) {
available_shm_segments_.push_back(shm_buffer.release());
}
-void RTCVideoDecoder::CreateSHM(int number, size_t min_size) {
+void RTCVideoDecoder::CreateSHM(size_t count, size_t size) {
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
- DVLOG(2) << "CreateSHM. size=" << min_size;
- int number_to_allocate;
- {
- base::AutoLock auto_lock(lock_);
- number_to_allocate =
- std::min(kMaxNumSharedMemorySegments - num_shm_buffers_, number);
- }
- size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes);
- for (int i = 0; i < number_to_allocate; i++) {
- scoped_ptr<base::SharedMemory> shm =
- factories_->CreateSharedMemory(size_to_allocate);
- if (shm) {
- base::AutoLock auto_lock(lock_);
- num_shm_buffers_++;
- PutSHM_Locked(
- scoped_ptr<SHMBuffer>(new SHMBuffer(shm.Pass(), size_to_allocate)));
+ DVLOG(2) << "CreateSHM. count=" << count << ", size=" << size;
+
+ for (size_t i = 0; i < count; i++) {
+ scoped_ptr<base::SharedMemory> shm = factories_->CreateSharedMemory(size);
Ville-Mikko Rautio 2015/07/17 11:26:15 Earlier it was quaranteed that each buffer would b
Pawel Osciak 2015/07/21 07:10:07 Yes, that was intentional. We may have to realloca
+ if (!shm) {
+ LOG(ERROR) << "Failed allocating shared memory of size=" << size;
+ NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
+ return;
}
+
+ base::AutoLock auto_lock(lock_);
+ PutSHM_Locked(scoped_ptr<SHMBuffer>(new SHMBuffer(shm.Pass(), size)));
+ ++num_shm_buffers_;
}
+
// Kick off the decoding.
RequestBufferDecode();
}
@@ -818,4 +815,15 @@ void RTCVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent()
DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread());
}
+void RTCVideoDecoder::ClearPendingBuffers() {
+ // Delete WebRTC input buffers.
+ for (std::deque<std::pair<webrtc::EncodedImage, BufferData>>::iterator it =
+ pending_buffers_.begin();
+ it != pending_buffers_.end(); ++it) {
+ delete[] it->first._buffer;
+ }
+
+ pending_buffers_.clear();
+}
+
} // namespace content
« no previous file with comments | « content/renderer/media/rtc_video_decoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698