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