Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Unified Diff: webkit/media/crypto/ppapi/libvpx_cdm_video_decoder.cc

Issue 11316045: Add a libvpx video decoder to ClearKeyCdm and move the fake video decoder to its own class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, fix incorrect DCHECK and fix include order. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webkit/media/crypto/ppapi/libvpx_cdm_video_decoder.h ('k') | webkit/media/webkit_media.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/media/crypto/ppapi/libvpx_cdm_video_decoder.cc
diff --git a/webkit/media/crypto/ppapi/libvpx_cdm_video_decoder.cc b/webkit/media/crypto/ppapi/libvpx_cdm_video_decoder.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d513de7cd8e9cccc06e194934f226f408078591f
--- /dev/null
+++ b/webkit/media/crypto/ppapi/libvpx_cdm_video_decoder.cc
@@ -0,0 +1,267 @@
+// 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/libvpx_cdm_video_decoder.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "media/base/buffers.h"
+#include "media/base/limits.h"
+
+// Include libvpx header files.
+// VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide
+// backwards compatibility for legacy applications using the library.
+#define VPX_CODEC_DISABLE_COMPAT 1
+extern "C" {
+#include "third_party/libvpx/libvpx.h"
+}
+
+#include "webkit/media/crypto/ppapi/content_decryption_module.h"
+
+// Enable USE_COPYPLANE_WITH_LIBVPX to use |CopyPlane()| instead of memcpy to
+// copy video frame data.
+// #define USE_COPYPLANE_WITH_LIBVPX 1
+
+namespace webkit_media {
+
+static const int kDecodeThreads = 1;
+
+static void CopyPlane(const uint8_t* source,
+ int32_t source_stride,
+ int32_t target_stride,
+ int32_t rows,
+ int32_t copy_bytes_per_row,
+ uint8_t* target) {
+ DCHECK(source);
+ DCHECK(target);
+ DCHECK_LE(copy_bytes_per_row, source_stride);
+ DCHECK_LE(copy_bytes_per_row, target_stride);
+
+ for (int i = 0; i < rows; ++i) {
+ const int source_offset = i * source_stride;
+ const int target_offset = i * target_stride;
+ memcpy(target + target_offset,
+ source + source_offset,
+ copy_bytes_per_row);
+ }
+}
+
+LibvpxCdmVideoDecoder::LibvpxCdmVideoDecoder(cdm::Allocator* allocator)
+ : is_initialized_(false),
+ allocator_(allocator),
+ vpx_codec_(NULL),
+ vpx_image_(NULL) {
+}
+
+LibvpxCdmVideoDecoder::~LibvpxCdmVideoDecoder() {
+ Deinitialize();
+}
+
+bool LibvpxCdmVideoDecoder::Initialize(const cdm::VideoDecoderConfig& config) {
+ DVLOG(1) << "Initialize()";
+
+ if (!IsValidOutputConfig(config.format, config.coded_size)) {
+ LOG(ERROR) << "Initialize(): invalid video decoder configuration.";
+ return false;
+ }
+
+ if (is_initialized_) {
+ LOG(ERROR) << "Initialize(): Already initialized.";
+ return false;
+ }
+
+ vpx_codec_ = new vpx_codec_ctx();
+ vpx_codec_dec_cfg_t vpx_config = {0};
+ vpx_config.w = config.coded_size.width;
+ vpx_config.h = config.coded_size.height;
+ vpx_config.threads = kDecodeThreads;
+
+ vpx_codec_err_t status = vpx_codec_dec_init(vpx_codec_,
+ vpx_codec_vp8_dx(),
+ &vpx_config,
+ 0);
+ if (status != VPX_CODEC_OK) {
+ LOG(ERROR) << "InitializeLibvpx(): vpx_codec_dec_init failed, ret="
+ << status;
+ delete vpx_codec_;
+ vpx_codec_ = NULL;
+ }
+
+ is_initialized_ = true;
+ return true;
+}
+
+void LibvpxCdmVideoDecoder::Deinitialize() {
+ DVLOG(1) << "Deinitialize()";
+
+ if (vpx_codec_) {
+ vpx_codec_destroy(vpx_codec_);
+ vpx_codec_ = NULL;
+ }
+
+ is_initialized_ = false;
+}
+
+void LibvpxCdmVideoDecoder::Reset() {
+ DVLOG(1) << "Reset()";
+}
+
+// static
+bool LibvpxCdmVideoDecoder::IsValidOutputConfig(cdm::VideoFormat format,
+ const cdm::Size& data_size) {
+ return ((format == cdm::kYv12 || format == cdm::kI420) &&
+ (data_size.width % 2) == 0 && (data_size.height % 2) == 0 &&
+ data_size.width > 0 && data_size.height > 0 &&
+ data_size.width <= media::limits::kMaxDimension &&
+ data_size.height <= media::limits::kMaxDimension &&
+ data_size.width * data_size.height <= media::limits::kMaxCanvas);
+}
+
+cdm::Status LibvpxCdmVideoDecoder::DecodeFrame(
+ const uint8_t* compressed_frame,
+ int32_t compressed_frame_size,
+ int64_t timestamp,
+ cdm::VideoFrame* decoded_frame) {
+ DVLOG(1) << "DecodeFrame()";
+ DCHECK(decoded_frame);
+
+ // Pass |compressed_frame| to libvpx.
+ void* user_priv = reinterpret_cast<void*>(&timestamp);
+ vpx_codec_err_t status = vpx_codec_decode(vpx_codec_,
+ compressed_frame,
+ compressed_frame_size,
+ user_priv,
+ 0);
+ if (status != VPX_CODEC_OK) {
+ LOG(ERROR) << "DecodeFrameLibvpx(): vpx_codec_decode failed, status="
+ << status;
+ return cdm::kDecodeError;
+ }
+
+ // Gets pointer to decoded data.
+ vpx_codec_iter_t iter = NULL;
+ vpx_image_ = vpx_codec_get_frame(vpx_codec_, &iter);
+ if (!vpx_image_)
+ return cdm::kNeedMoreData;
+
+ if (vpx_image_->user_priv != reinterpret_cast<void*>(&timestamp)) {
+ LOG(ERROR) << "DecodeFrameLibvpx() invalid output timestamp.";
+ return cdm::kDecodeError;
+ }
+ decoded_frame->set_timestamp(timestamp);
+
+ if (!CopyVpxImageTo(decoded_frame)) {
+ LOG(ERROR) << "DecodeFrameLibvpx() could not copy vpx image to output "
+ << "buffer.";
+ return cdm::kDecodeError;
+ }
+
+ return cdm::kSuccess;
+
+}
+
+bool LibvpxCdmVideoDecoder::CopyVpxImageTo(cdm::VideoFrame* cdm_video_frame) {
+ DCHECK(cdm_video_frame);
+ DCHECK_EQ(vpx_image_->fmt, VPX_IMG_FMT_I420);
+ DCHECK_EQ(vpx_image_->d_w % 2, 0U);
+ DCHECK_EQ(vpx_image_->d_h % 2, 0U);
+
+#if defined(USE_COPYPLANE_WITH_LIBVPX)
+ const int y_size = vpx_image_->d_w * vpx_image_->d_h;
+ const int uv_size = y_size / 2;
+ const int space_required = y_size + (uv_size * 2);
+
+ DCHECK(!cdm_video_frame->frame_buffer());
+ cdm_video_frame->set_frame_buffer(allocator_->Allocate(space_required));
+ if (!cdm_video_frame->frame_buffer()) {
+ LOG(ERROR) << "CopyVpxImageTo() cdm::Allocator::Allocate failed.";
+ return false;
+ }
+
+ CopyPlane(vpx_image_->planes[VPX_PLANE_Y],
+ vpx_image_->stride[VPX_PLANE_Y],
+ vpx_image_->d_w,
+ vpx_image_->d_h,
+ vpx_image_->d_w,
+ cdm_video_frame->frame_buffer()->data());
+
+ const int uv_stride = vpx_image_->d_w / 2;
+ const int uv_rows = vpx_image_->d_h / 2;
+ CopyPlane(vpx_image_->planes[VPX_PLANE_U],
+ vpx_image_->stride[VPX_PLANE_U],
+ uv_stride,
+ uv_rows,
+ uv_stride,
+ cdm_video_frame->frame_buffer()->data() + y_size);
+
+ CopyPlane(vpx_image_->planes[VPX_PLANE_V],
+ vpx_image_->stride[VPX_PLANE_V],
+ uv_stride,
+ uv_rows,
+ uv_stride,
+ cdm_video_frame->frame_buffer()->data() + y_size + uv_size);
+
+ cdm_video_frame->set_format(cdm::kYv12);
+
+ cdm::Size video_frame_size;
+ video_frame_size.width = vpx_image_->d_w;
+ video_frame_size.height = vpx_image_->d_h;
+ cdm_video_frame->set_size(video_frame_size);
+
+ cdm_video_frame->set_plane_offset(cdm::VideoFrame::kYPlane, 0);
+ cdm_video_frame->set_plane_offset(cdm::VideoFrame::kUPlane, y_size);
+ cdm_video_frame->set_plane_offset(cdm::VideoFrame::kVPlane,
+ y_size + uv_size);
+
+ cdm_video_frame->set_stride(cdm::VideoFrame::kYPlane, vpx_image_->d_w);
+ cdm_video_frame->set_stride(cdm::VideoFrame::kUPlane, uv_stride);
+ cdm_video_frame->set_stride(cdm::VideoFrame::kVPlane, uv_stride);
+#else
+ const int y_size = vpx_image_->stride[VPX_PLANE_Y] * vpx_image_->d_h;
+ const int uv_rows = vpx_image_->d_h / 2;
+ const int u_size = vpx_image_->stride[VPX_PLANE_U] * uv_rows;
+ const int v_size = vpx_image_->stride[VPX_PLANE_V] * uv_rows;
+ const int space_required = y_size + u_size + v_size;
+
+ DCHECK(!cdm_video_frame->frame_buffer());
+ cdm_video_frame->set_frame_buffer(allocator_->Allocate(space_required));
+ if (!cdm_video_frame->frame_buffer()) {
+ LOG(ERROR) << "CopyVpxImageTo() cdm::Allocator::Allocate failed.";
+ return false;
+ }
+
+ memcpy(cdm_video_frame->frame_buffer()->data(),
+ vpx_image_->planes[VPX_PLANE_Y],
+ y_size);
+ memcpy(cdm_video_frame->frame_buffer()->data() + y_size,
+ vpx_image_->planes[VPX_PLANE_U],
+ u_size);
+ memcpy(cdm_video_frame->frame_buffer()->data() + y_size + u_size,
+ vpx_image_->planes[VPX_PLANE_V],
+ v_size);
+
+ cdm_video_frame->set_format(cdm::kYv12);
+
+ cdm::Size video_frame_size;
+ video_frame_size.width = vpx_image_->d_w;
+ video_frame_size.height = vpx_image_->d_h;
+ cdm_video_frame->set_size(video_frame_size);
+
+ cdm_video_frame->set_plane_offset(cdm::VideoFrame::kYPlane, 0);
+ cdm_video_frame->set_plane_offset(cdm::VideoFrame::kUPlane, y_size);
+ cdm_video_frame->set_plane_offset(cdm::VideoFrame::kVPlane,
+ y_size + u_size);
+
+ cdm_video_frame->set_stride(cdm::VideoFrame::kYPlane,
+ vpx_image_->stride[VPX_PLANE_Y]);
+ cdm_video_frame->set_stride(cdm::VideoFrame::kUPlane,
+ vpx_image_->stride[VPX_PLANE_U]);
+ cdm_video_frame->set_stride(cdm::VideoFrame::kVPlane,
+ vpx_image_->stride[VPX_PLANE_V]);
+#endif // USE_COPYPLANE_WITH_LIBVPX
+
+ return true;
+}
+
+} // namespace webkit_media
« no previous file with comments | « webkit/media/crypto/ppapi/libvpx_cdm_video_decoder.h ('k') | webkit/media/webkit_media.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698