summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-12 22:16:45 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-12 22:16:45 +0000
commitb6d544ebb4e1087a1ba5661776afad930bd81ad4 (patch)
treed0847fe6d20fb5707aa19c976e7c1b86da0db75f /remoting
parent53ab4800b3fe2d847c6ac09eaaf746166fea3803 (diff)
downloadchromium_src-b6d544ebb4e1087a1ba5661776afad930bd81ad4.zip
chromium_src-b6d544ebb4e1087a1ba5661776afad930bd81ad4.tar.gz
chromium_src-b6d544ebb4e1087a1ba5661776afad930bd81ad4.tar.bz2
Add padding at the end of encoder buffer to workaround crbug.com/119633.
Beside that fixed a bug in the encoder that would cause it to allocated too small buffer for images with odd size. BUG=119636 Review URL: https://chromiumcodereview.appspot.com/10020062 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132071 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/base/encoder_vp8.cc56
1 files changed, 31 insertions, 25 deletions
diff --git a/remoting/base/encoder_vp8.cc b/remoting/base/encoder_vp8.cc
index ed126d1..fae1c27 100644
--- a/remoting/base/encoder_vp8.cc
+++ b/remoting/base/encoder_vp8.cc
@@ -64,12 +64,32 @@ bool EncoderVp8::Init(const SkISize& size) {
image_->d_h = size.height();
image_->h = size.height();
+ // Initialize active map.
+ active_map_width_ = (size.width() + kMacroBlockSize - 1) / kMacroBlockSize;
+ active_map_height_ = (size.height() + kMacroBlockSize - 1) / kMacroBlockSize;
+ active_map_.reset(new uint8[active_map_width_ * active_map_height_]);
+
// YUV image size is 1.5 times of a plane. Multiplication is performed first
// to avoid rounding error.
- const int plane_size = size.width() * size.height();
- const int yuv_image_size = plane_size * 3 / 2;
-
- yuv_image_.reset(new uint8[yuv_image_size]);
+ const int y_plane_size = size.width() * size.height();
+ const int uv_width = (size.width() + 1) / 2;
+ const int uv_height = (size.height() + 1) / 2;
+ const int uv_plane_size = uv_width * uv_height;
+ const int yuv_image_size = y_plane_size + uv_plane_size * 2;
+
+ // libvpx may try to access memory after the buffer (it still
+ // doesn't use it) - it copies the data in 16x16 blocks:
+ // crbug.com/119633 . Here we workaround that problem by adding
+ // padding at the end of the buffer. Overreading to U and V buffers
+ // is safe so the padding is necessary only at the end.
+ //
+ // TODO(sergeyu): Remove this padding when the bug is fixed in libvpx.
+ const int active_map_area = active_map_width_ * kMacroBlockSize *
+ active_map_height_ * kMacroBlockSize;
+ const int padding_size = active_map_area - y_plane_size;
+ const int buffer_size = yuv_image_size + padding_size;
+
+ yuv_image_.reset(new uint8[buffer_size]);
// Reset image value to 128 so we just need to fill in the y plane.
memset(yuv_image_.get(), 128, yuv_image_size);
@@ -77,10 +97,8 @@ bool EncoderVp8::Init(const SkISize& size) {
// Fill in the information for |image_|.
unsigned char* image = reinterpret_cast<unsigned char*>(yuv_image_.get());
image_->planes[0] = image;
- image_->planes[1] = image + plane_size;
-
- // The V plane starts from 1.25 of the plane size.
- image_->planes[2] = image + plane_size + plane_size / 4;
+ image_->planes[1] = image + y_plane_size;
+ image_->planes[2] = image + y_plane_size + uv_plane_size;
// In YV12 Y plane has full width, UV plane has half width because of
// subsampling.
@@ -95,11 +113,6 @@ bool EncoderVp8::Init(const SkISize& size) {
if (ret != VPX_CODEC_OK)
return false;
- // Initialize active map.
- active_map_width_ = (size.width() + kMacroBlockSize - 1) / kMacroBlockSize;
- active_map_height_ = (size.height() + kMacroBlockSize - 1) / kMacroBlockSize;
- active_map_.reset(new uint8[active_map_width_ * active_map_height_]);
-
config.rc_target_bitrate = size.width() * size.height() *
config.rc_target_bitrate / config.g_w / config.g_h;
config.g_w = size.width();
@@ -174,17 +187,10 @@ bool EncoderVp8::PrepareImage(scoped_refptr<CaptureData> capture_data,
if (!rect.isEmpty())
updated_rects->push_back(rect);
- ConvertRGB32ToYUVWithRect(in,
- y_out,
- u_out,
- v_out,
- rect.fLeft,
- rect.fTop,
- rect.width(),
- rect.height(),
- in_stride,
- y_stride,
- uv_stride);
+ ConvertRGB32ToYUVWithRect(
+ in, y_out, u_out, v_out,
+ rect.fLeft, rect.fTop, rect.width(), rect.height(),
+ in_stride, y_stride, uv_stride);
}
return true;
}
@@ -220,7 +226,7 @@ void EncoderVp8::Encode(scoped_refptr<CaptureData> capture_data,
if (!initialized_ || (capture_data->size() != size_)) {
bool ret = Init(capture_data->size());
// TODO(hclam): Handle error better.
- DCHECK(ret) << "Initialization of encoder failed";
+ CHECK(ret) << "Initialization of encoder failed";
initialized_ = ret;
}