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 |