Replace Check for too many pending frames in I420_buffer_pool with returning nullptr. Added histograms for when this happens in VP8Impl.

BUG=chromium:542522
R=tommi@webrtc.org

Review URL: https://codereview.webrtc.org/2474783005 .

Cr-Commit-Position: refs/heads/master@{#14930}
This commit is contained in:
Per 2016-11-04 08:57:26 +01:00
parent f752bca4a5
commit 00983572b0
4 changed files with 34 additions and 12 deletions

View File

@ -14,10 +14,10 @@
namespace webrtc {
const size_t I420BufferPool::kMaxNumberOfFramesBeforeCrash = 300;
I420BufferPool::I420BufferPool(bool zero_initialize)
: zero_initialize_(zero_initialize) {}
I420BufferPool::I420BufferPool(bool zero_initialize,
size_t max_number_of_buffers)
: zero_initialize_(zero_initialize),
max_number_of_buffers_(max_number_of_buffers) {}
void I420BufferPool::Release() {
buffers_.clear();
@ -26,8 +26,6 @@ void I420BufferPool::Release() {
rtc::scoped_refptr<I420Buffer> I420BufferPool::CreateBuffer(int width,
int height) {
RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
RTC_CHECK_LT(buffers_.size(), kMaxNumberOfFramesBeforeCrash)
<< "I420BufferPool too big.";
// Release buffers with wrong resolution.
for (auto it = buffers_.begin(); it != buffers_.end();) {
if ((*it)->width() != width || (*it)->height() != height)
@ -44,6 +42,9 @@ rtc::scoped_refptr<I420Buffer> I420BufferPool::CreateBuffer(int width,
if (buffer->HasOneRef())
return buffer;
}
if (buffers_.size() >= max_number_of_buffers_)
return nullptr;
// Allocate new buffer.
rtc::scoped_refptr<PooledI420Buffer> buffer =
new PooledI420Buffer(width, height);

View File

@ -63,4 +63,11 @@ TEST(TestI420BufferPool, FrameValidAfterPoolDestruction) {
memset(buffer->MutableDataY(), 0xA5, 16 * buffer->StrideY());
}
TEST(TestI420BufferPool, MaxNumberOfBuffers) {
I420BufferPool pool(false, 1);
rtc::scoped_refptr<VideoFrameBuffer> buffer1 = pool.CreateBuffer(16, 16);
EXPECT_NE(nullptr, buffer1.get());
EXPECT_EQ(nullptr, pool.CreateBuffer(16, 16).get());
}
} // namespace webrtc

View File

@ -12,6 +12,7 @@
#define WEBRTC_COMMON_VIDEO_INCLUDE_I420_BUFFER_POOL_H_
#include <list>
#include <limits>
#include "webrtc/base/race_checker.h"
#include "webrtc/common_video/include/video_frame_buffer.h"
@ -27,18 +28,21 @@ namespace webrtc {
// are created. This is to prevent memory leaks where frames are not returned.
class I420BufferPool {
public:
I420BufferPool() : I420BufferPool(false) {}
explicit I420BufferPool(bool zero_initialize);
I420BufferPool()
: I420BufferPool(false, std::numeric_limits<size_t>::max()) {}
explicit I420BufferPool(bool zero_initialize)
: I420BufferPool(zero_initialize, std::numeric_limits<size_t>::max()) {}
I420BufferPool(bool zero_initialze, size_t max_number_of_buffers);
// Returns a buffer from the pool, or creates a new buffer if no suitable
// buffer exists in the pool.
// Returns a buffer from the pool. If no suitable buffer exist in the pool
// and there are less than |max_number_of_buffers| pending, a buffer is
// created. Returns null otherwise.
rtc::scoped_refptr<I420Buffer> CreateBuffer(int width, int height);
// Clears buffers_ and detaches the thread checker so that it can be reused
// later from another thread.
void Release();
private:
static const size_t kMaxNumberOfFramesBeforeCrash;
// Explicitly use a RefCountedObject to get access to HasOneRef,
// needed by the pool to check exclusive access.
using PooledI420Buffer = rtc::RefCountedObject<I420Buffer>;
@ -51,6 +55,8 @@ class I420BufferPool {
// initial allocation (as shown by FFmpeg's own buffer allocation code). It
// has to do with "Use-of-uninitialized-value" on "Linux_msan_chrome".
bool zero_initialize_;
// Max number of buffers this pool can have pending.
size_t max_number_of_buffers_;
};
} // namespace webrtc

View File

@ -31,6 +31,7 @@
#include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
#include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h"
#include "webrtc/system_wrappers/include/clock.h"
#include "webrtc/system_wrappers/include/metrics.h"
namespace webrtc {
namespace {
@ -1055,7 +1056,8 @@ int VP8EncoderImpl::RegisterEncodeCompleteCallback(
}
VP8DecoderImpl::VP8DecoderImpl()
: decode_complete_callback_(NULL),
: buffer_pool_(false, 300 /* max_number_of_buffers*/),
decode_complete_callback_(NULL),
inited_(false),
feedback_mode_(false),
decoder_(NULL),
@ -1270,6 +1272,12 @@ int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img,
// Allocate memory for decoded image.
rtc::scoped_refptr<I420Buffer> buffer =
buffer_pool_.CreateBuffer(img->d_w, img->d_h);
if (!buffer.get()) {
// Pool has too many pending frames.
RTC_HISTOGRAM_BOOLEAN("WebRTC.Video.VP8DecoderImpl.TooManyPendingFrames",
1);
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
}
libyuv::I420Copy(img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y],
img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U],