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 |