Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "remoting/codec/video_encoder_vpx.h" | 5 #include "remoting/codec/video_encoder_vpx.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/sys_info.h" | 9 #include "base/sys_info.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 // libvpx should derive this from|fmt| but currently has a bug: | 258 // libvpx should derive this from|fmt| but currently has a bug: |
| 259 // https://code.google.com/p/webm/issues/detail?id=627 | 259 // https://code.google.com/p/webm/issues/detail?id=627 |
| 260 image_->x_chroma_shift = 1; | 260 image_->x_chroma_shift = 1; |
| 261 image_->y_chroma_shift = 1; | 261 image_->y_chroma_shift = 1; |
| 262 | 262 |
| 263 // Initialize active map. | 263 // Initialize active map. |
| 264 active_map_width_ = (image_->w + kMacroBlockSize - 1) / kMacroBlockSize; | 264 active_map_width_ = (image_->w + kMacroBlockSize - 1) / kMacroBlockSize; |
| 265 active_map_height_ = (image_->h + kMacroBlockSize - 1) / kMacroBlockSize; | 265 active_map_height_ = (image_->h + kMacroBlockSize - 1) / kMacroBlockSize; |
| 266 active_map_.reset(new uint8[active_map_width_ * active_map_height_]); | 266 active_map_.reset(new uint8[active_map_width_ * active_map_height_]); |
| 267 | 267 |
| 268 // YUV image size is 1.5 times of a plane. Multiplication is performed first | 268 // libyuv's fast-path requires 16-byte aligned pointers and strides, so pad |
| 269 // to avoid rounding error. | 269 // the Y, U and V planes' strides to multiples of 16 bytes. |
| 270 const int y_plane_size = image_->w * image_->h; | 270 const int y_stride = ((image_->w - 1) & ~15) + 16; |
| 271 const int uv_width = (image_->w + 1) / 2; | 271 const int uv_unaligned_stride = y_stride / 2; |
| 272 const int uv_height = (image_->h + 1) / 2; | 272 const int uv_stride = ((uv_unaligned_stride - 1) & ~15) + 16; |
| 273 const int uv_plane_size = uv_width * uv_height; | |
| 274 const int yuv_image_size = y_plane_size + uv_plane_size * 2; | |
| 275 | 273 |
| 276 // libvpx may try to access memory after the buffer (it still | 274 // libvpx accesses the source image in macro blocks, and will over-read |
| 277 // doesn't use it) - it copies the data in 16x16 blocks: | 275 // if the image is not padded out to the next macroblock: crbug.com/119633. |
| 278 // crbug.com/119633 . Here we workaround that problem by adding | 276 // Pad the Y, U and V planes' height out to compensate. |
| 279 // padding at the end of the buffer. Overreading to U and V buffers | 277 // Assuming macroblocks are 16x16, aligning the planes' strides above also |
| 280 // is safe so the padding is necessary only at the end. | 278 // macroblock aligned them. |
| 281 // | 279 DCHECK_EQ(16, kMacroBlockSize); |
| 282 // TODO(sergeyu): Remove this padding when the bug is fixed in libvpx. | 280 const int y_rows = active_map_height_ * kMacroBlockSize; |
| 283 const int active_map_area = active_map_width_ * kMacroBlockSize * | 281 const int uv_rows = y_rows / 2; |
|
Sergey Ulanov
2014/05/03 00:57:26
should this be (y_rows + 1) / 2?
You need one extr
Wez
2014/05/03 01:19:12
y_rows is already a multiple of 16 at this point.
| |
| 284 active_map_height_ * kMacroBlockSize; | |
| 285 const int padding_size = active_map_area - y_plane_size; | |
| 286 const int buffer_size = yuv_image_size + padding_size; | |
| 287 | 282 |
| 283 // Allocate a YUV buffer large enough for the aligned data & padding. | |
| 284 const int buffer_size = y_stride * y_rows + 2*uv_stride * uv_rows; | |
|
Sergey Ulanov
2014/05/03 00:57:26
nit: s/2*/2 * /
| |
| 288 yuv_image_.reset(new uint8[buffer_size]); | 285 yuv_image_.reset(new uint8[buffer_size]); |
| 289 | 286 |
| 290 // Reset image value to 128 so we just need to fill in the y plane. | 287 // Reset image value to 128 so we just need to fill in the y plane. |
| 291 memset(yuv_image_.get(), 128, yuv_image_size); | 288 memset(yuv_image_.get(), 128, buffer_size); |
| 292 | 289 |
| 293 // Fill in the information for |image_|. | 290 // Fill in the information for |image_|. |
| 294 unsigned char* image = reinterpret_cast<unsigned char*>(yuv_image_.get()); | 291 unsigned char* image = reinterpret_cast<unsigned char*>(yuv_image_.get()); |
| 295 image_->planes[0] = image; | 292 image_->planes[0] = image; |
| 296 image_->planes[1] = image + y_plane_size; | 293 image_->planes[1] = image_->planes[0] + y_stride * y_rows; |
| 297 image_->planes[2] = image + y_plane_size + uv_plane_size; | 294 image_->planes[2] = image_->planes[1] + uv_stride * uv_rows; |
| 298 image_->stride[0] = image_->w; | 295 image_->stride[0] = y_stride; |
| 299 image_->stride[1] = uv_width; | 296 image_->stride[1] = uv_stride; |
| 300 image_->stride[2] = uv_width; | 297 image_->stride[2] = uv_stride; |
| 301 | 298 |
| 302 // Initialize the codec. | 299 // Initialize the codec. |
| 303 codec_ = init_codec_.Run(size); | 300 codec_ = init_codec_.Run(size); |
| 304 | 301 |
| 305 return codec_; | 302 return codec_; |
| 306 } | 303 } |
| 307 | 304 |
| 308 void VideoEncoderVpx::PrepareImage(const webrtc::DesktopFrame& frame, | 305 void VideoEncoderVpx::PrepareImage(const webrtc::DesktopFrame& frame, |
| 309 webrtc::DesktopRegion* updated_region) { | 306 webrtc::DesktopRegion* updated_region) { |
| 310 if (frame.updated_region().is_empty()) { | 307 if (frame.updated_region().is_empty()) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 uint8* map = active_map_.get() + top * active_map_width_; | 367 uint8* map = active_map_.get() + top * active_map_width_; |
| 371 for (int y = top; y <= bottom; ++y) { | 368 for (int y = top; y <= bottom; ++y) { |
| 372 for (int x = left; x <= right; ++x) | 369 for (int x = left; x <= right; ++x) |
| 373 map[x] = 1; | 370 map[x] = 1; |
| 374 map += active_map_width_; | 371 map += active_map_width_; |
| 375 } | 372 } |
| 376 } | 373 } |
| 377 } | 374 } |
| 378 | 375 |
| 379 } // namespace remoting | 376 } // namespace remoting |
| OLD | NEW |