Chromium Code Reviews| Index: webkit/media/crypto/ppapi/ffmpeg_cdm_video_frame.cc | 
| diff --git a/webkit/media/crypto/ppapi/ffmpeg_cdm_video_frame.cc b/webkit/media/crypto/ppapi/ffmpeg_cdm_video_frame.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..0cb69f43a8df5f4d2fd61e8f8f53a54e425b8c3e | 
| --- /dev/null | 
| +++ b/webkit/media/crypto/ppapi/ffmpeg_cdm_video_frame.cc | 
| @@ -0,0 +1,149 @@ | 
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "webkit/media/crypto/ppapi/ffmpeg_cdm_video_frame.h" | 
| + | 
| +#include "base/logging.h" | 
| +#include "base/memory/scoped_ptr.h" | 
| +#include "media/base/limits.h" | 
| +#include "webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h" | 
| + | 
| + | 
| +namespace webkit_media { | 
| + | 
| +namespace { | 
| + | 
| +inline size_t RoundUp(size_t value, size_t alignment) { | 
| + // Check that |alignment| is a power of 2. | 
| + DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); | 
| + return ((value + (alignment - 1)) & ~(alignment-1)); | 
| +} | 
| + | 
| +int RowBytes(cdm::VideoFormat format, | 
| + cdm::VideoFrame::VideoPlane plane, | 
| + int width) { | 
| + switch (format) { | 
| + case cdm::kYv12: | 
| + case cdm::kI420: | 
| + if (plane == cdm::VideoFrame::kYPlane) | 
| + return width; | 
| + return RoundUp(width, 2) / 2; | 
| + | 
| + default: | 
| + NOTREACHED() << "Unsupported video frame format: " << format; | 
| + return 0; | 
| + } | 
| +} | 
| + | 
| +} // namespace | 
| + | 
| +// static | 
| +FFmpegCdmVideoFrame* FFmpegCdmVideoFrame::Create(cdm::Allocator* allocator, | 
| + cdm::VideoFormat format, | 
| + const cdm::Size& size) { | 
| + if (!IsValidConfig(format, size)) { | 
| + LOG(ERROR) << "VideoFrame::Create invalid config."; | 
| + return NULL; | 
| + } | 
| + | 
| + scoped_ptr<FFmpegCdmVideoFrame> frame(new FFmpegCdmVideoFrame(format, size)); | 
| + | 
| + if (!frame->AllocateYUV(allocator)) | 
| + return NULL; | 
| + | 
| + return frame.release(); | 
| +} | 
| + | 
| +FFmpegCdmVideoFrame::FFmpegCdmVideoFrame(cdm::VideoFormat format, | 
| + const cdm::Size& size) | 
| + : format_(format), | 
| + size_(size), | 
| + frame_buffer_(NULL) { | 
| + for (int32_t i = 0; i < cdm::VideoFrame::kMaxPlanes; ++i) { | 
| + plane_offsets_[i] = 0; | 
| + strides_[i] = 0; | 
| + } | 
| +} | 
| + | 
| +FFmpegCdmVideoFrame::~FFmpegCdmVideoFrame() { | 
| + if (frame_buffer_) | 
| + frame_buffer_->Destroy(); | 
| +} | 
| + | 
| +const cdm::Size& FFmpegCdmVideoFrame::size() const { | 
| + return size_; | 
| +} | 
| + | 
| +cdm::VideoFormat FFmpegCdmVideoFrame::format() const { | 
| + return format_; | 
| 
 
xhwang
2012/10/16 21:59:53
accessors can be defined in header files
 
Tom Finegan
2012/10/17 02:39:10
Done. Moved the single line ones into the header f
 
 | 
| +} | 
| + | 
| +cdm::Buffer* FFmpegCdmVideoFrame::frame_buffer() { | 
| + return frame_buffer_; | 
| +} | 
| + | 
| +int32_t FFmpegCdmVideoFrame::plane_offset(cdm::VideoFrame::VideoPlane plane) { | 
| + DCHECK(0 <= plane && plane < cdm::VideoFrame::kMaxPlanes); | 
| + return plane_offsets_[plane]; | 
| +} | 
| + | 
| +int32_t FFmpegCdmVideoFrame::stride(cdm::VideoFrame::VideoPlane plane) { | 
| + DCHECK(0 <= plane && plane < cdm::VideoFrame::kMaxPlanes); | 
| + return strides_[plane]; | 
| +} | 
| + | 
| + | 
| 
 
xhwang
2012/10/16 21:59:53
remove extra empty line
 
Tom Finegan
2012/10/17 02:39:10
Done.
 
 | 
| +cdm::Buffer* FFmpegCdmVideoFrame::ReleaseCdmBuffer() { | 
| + cdm::Buffer* buffer = frame_buffer_; | 
| + frame_buffer_ = NULL; | 
| + return buffer; | 
| +} | 
| + | 
| +bool FFmpegCdmVideoFrame::AllocateYUV(cdm::Allocator* allocator) { | 
| 
 
xhwang
2012/10/16 21:59:53
Bikeshedding: Not sure if it should be YUV or Yuv
 
Tom Finegan
2012/10/17 02:39:10
Done. I prefer Yuv anyway. :)
 
 | 
| + DCHECK(allocator); | 
| + DCHECK(format_ == cdm::kYv12 || format_ == cdm::kI420); | 
| + | 
| + // Align Y rows at least at 32 byte boundaries for safety on all platforms. | 
| + DVLOG(1) << "VideoFrame::AllocateYUV: width=" << size_.width | 
| 
 
xhwang
2012/10/16 21:59:53
s/VideoFame/FFmpegCdmVideoFrame
 
Tom Finegan
2012/10/17 02:39:10
Removed class name from the comment. File name and
 
 | 
| + << " height=" << size_.height; | 
| + size_t y_stride = RoundUp( | 
| + RowBytes(format_, cdm::VideoFrame::kYPlane, size_.width), | 
| + kBufferAlignment); | 
| + size_t uv_stride = RoundUp( | 
| + RowBytes(format_, cdm::VideoFrame::kUPlane, size_.width), | 
| + kBufferAlignment); | 
| + | 
| + size_t y_height = RoundUp(size_.height, kBufferAlignment); | 
| + size_t uv_height = format_ == cdm::kYv12 ? y_height / 2 : y_height; | 
| 
 
xhwang
2012/10/16 21:59:53
The difference b/w YV12 and I420 is that YV12 is Y
 
Tom Finegan
2012/10/17 02:39:10
Thanks for catching this-- this is based on media:
 
 | 
| + size_t y_bytes = y_height * y_stride; | 
| + size_t uv_bytes = uv_height * uv_stride; | 
| + | 
| + frame_buffer_ = allocator->Allocate(y_bytes + (uv_bytes * 2)); | 
| + if (!frame_buffer_) { | 
| + LOG(ERROR) << "cdm::Allocator::Allocate failed."; | 
| + return false; | 
| + } | 
| + | 
| + COMPILE_ASSERT(0 == cdm::VideoFrame::kYPlane, y_plane_data_must_be_index_0); | 
| + uint8_t* data = frame_buffer_->data(); | 
| + DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(data) & (kBufferAlignment - 1)); | 
| + | 
| + plane_offsets_[cdm::VideoFrame::kYPlane] = 0; | 
| + | 
| + if (format_ == cdm::kYv12) { | 
| + plane_offsets_[cdm::VideoFrame::kVPlane] = y_bytes; | 
| + plane_offsets_[cdm::VideoFrame::kUPlane] = y_bytes + uv_bytes; | 
| + } else { | 
| + plane_offsets_[cdm::VideoFrame::kUPlane] = y_bytes; | 
| + plane_offsets_[cdm::VideoFrame::kVPlane] = y_bytes + uv_bytes; | 
| + } | 
| + | 
| + strides_[cdm::VideoFrame::kYPlane] = y_stride; | 
| + strides_[cdm::VideoFrame::kUPlane] = uv_stride; | 
| + strides_[cdm::VideoFrame::kVPlane] = uv_stride; | 
| + | 
| + return true; | 
| +} | 
| + | 
| +} // namespace webkit_media |