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

Unified Diff: media/cdm/ppapi/cdm_helpers.h

Issue 26155003: Add CdmWrapper to support multiple CDM versions in CdmAdapter. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add cdm_helpers.h Created 7 years, 2 months 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
Index: media/cdm/ppapi/cdm_helpers.h
diff --git a/media/cdm/ppapi/cdm_helpers.h b/media/cdm/ppapi/cdm_helpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e08510936254e22cfa8c316a9966365a13b3ffe
--- /dev/null
+++ b/media/cdm/ppapi/cdm_helpers.h
@@ -0,0 +1,314 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
xhwang 2013/10/15 20:42:33 This file is copied from cdm_wrapper.cc, with smal
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CDM_PPAPI_CDM_HELPERS_H_
+#define MEDIA_CDM_PPAPI_CDM_HELPERS_H_
+
+#include <map>
+#include <utility>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "build/build_config.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/cpp/core.h"
+#include "ppapi/cpp/dev/buffer_dev.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/logging.h"
+#include "ppapi/cpp/module.h"
xhwang 2013/10/15 20:42:33 Includes are trimmed to reflect what we use.
+
+namespace media {
+
+// cdm::Buffer implementation that provides access to memory owned by a
+// pp::Buffer_Dev.
+// This class holds a reference to the Buffer_Dev throughout its lifetime.
+// TODO(xhwang): Find a better name. It's confusing to have PpbBuffer,
+// pp::Buffer_Dev and PPB_Buffer_Dev.
+class PpbBuffer : public cdm::Buffer {
+ public:
+ static PpbBuffer* Create(const pp::Buffer_Dev& buffer, uint32_t buffer_id) {
+ PP_DCHECK(buffer.data());
+ PP_DCHECK(buffer.size());
+ PP_DCHECK(buffer_id);
+ return new PpbBuffer(buffer, buffer_id);
+ }
+
+ // cdm::Buffer implementation.
+ virtual void Destroy() OVERRIDE { delete this; }
+
+ virtual int32_t Capacity() const OVERRIDE { return buffer_.size(); }
+
+ virtual uint8_t* Data() OVERRIDE {
+ return static_cast<uint8_t*>(buffer_.data());
+ }
+
+ virtual void SetSize(int32_t size) OVERRIDE {
+ PP_DCHECK(size >= 0);
+ PP_DCHECK(size < Capacity());
+ if (size < 0 || size > Capacity()) {
+ size_ = 0;
+ return;
+ }
+
+ size_ = size;
+ }
+
+ virtual int32_t Size() const OVERRIDE { return size_; }
+
+ pp::Buffer_Dev buffer_dev() const { return buffer_; }
+
+ uint32_t buffer_id() const { return buffer_id_; }
+
+ private:
+ PpbBuffer(pp::Buffer_Dev buffer, uint32_t buffer_id)
+ : buffer_(buffer),
+ buffer_id_(buffer_id),
+ size_(0) {}
+ virtual ~PpbBuffer() {}
+
+ pp::Buffer_Dev buffer_;
+ uint32_t buffer_id_;
+ int32_t size_;
+
+ DISALLOW_COPY_AND_ASSIGN(PpbBuffer);
+};
+
+class PpbBufferAllocator {
+ public:
+ explicit PpbBufferAllocator(pp::Instance* instance)
+ : instance_(instance),
+ next_buffer_id_(1) {}
+ ~PpbBufferAllocator() {}
+
+ cdm::Buffer* Allocate(int32_t capacity);
+
+ // Releases the buffer with |buffer_id|. A buffer can be recycled after
+ // it is released.
+ void Release(uint32_t buffer_id);
+
+ private:
+ typedef std::map<uint32_t, pp::Buffer_Dev> AllocatedBufferMap;
+ typedef std::multimap<int, std::pair<uint32_t, pp::Buffer_Dev> >
+ FreeBufferMap;
+
+ // Always pad new allocated buffer so that we don't need to reallocate
+ // buffers frequently if requested sizes fluctuate slightly.
+ static const int kBufferPadding = 512;
+
+ // Maximum number of free buffers we can keep when allocating new buffers.
+ static const int kFreeLimit = 3;
+
+ pp::Buffer_Dev AllocateNewBuffer(int capacity);
+
+ pp::Instance* const instance_;
+ uint32_t next_buffer_id_;
+ AllocatedBufferMap allocated_buffers_;
+ FreeBufferMap free_buffers_;
+
+ DISALLOW_COPY_AND_ASSIGN(PpbBufferAllocator);
+};
+
+cdm::Buffer* PpbBufferAllocator::Allocate(int32_t capacity) {
+ PP_DCHECK(pp::Module::Get()->core()->IsMainThread());
xhwang 2013/10/15 20:42:33 This was IsMainThread() in cdm_wrapper.cc. I am no
+
+ if (capacity <= 0)
+ return NULL;
+
+ pp::Buffer_Dev buffer;
+ uint32_t buffer_id = 0;
+
+ // Reuse a buffer in the free list if there is one that fits |capacity|.
+ // Otherwise, create a new one.
+ FreeBufferMap::iterator found = free_buffers_.lower_bound(capacity);
+ if (found == free_buffers_.end()) {
+ // TODO(xhwang): Report statistics about how many new buffers are allocated.
+ buffer = AllocateNewBuffer(capacity);
+ if (buffer.is_null())
+ return NULL;
+ buffer_id = next_buffer_id_++;
+ } else {
+ buffer = found->second.second;
+ buffer_id = found->second.first;
+ free_buffers_.erase(found);
+ }
+
+ allocated_buffers_.insert(std::make_pair(buffer_id, buffer));
+
+ return PpbBuffer::Create(buffer, buffer_id);
+}
+
+void PpbBufferAllocator::Release(uint32_t buffer_id) {
+ if (!buffer_id)
+ return;
+
+ AllocatedBufferMap::iterator found = allocated_buffers_.find(buffer_id);
+ if (found == allocated_buffers_.end())
+ return;
+
+ pp::Buffer_Dev& buffer = found->second;
+ free_buffers_.insert(
+ std::make_pair(buffer.size(), std::make_pair(buffer_id, buffer)));
+
+ allocated_buffers_.erase(found);
+}
+
+pp::Buffer_Dev PpbBufferAllocator::AllocateNewBuffer(int32_t capacity) {
+ // Destroy the smallest buffer before allocating a new bigger buffer if the
+ // number of free buffers exceeds a limit. This mechanism helps avoid ending
+ // up with too many small buffers, which could happen if the size to be
+ // allocated keeps increasing.
+ if (free_buffers_.size() >= static_cast<uint32_t>(kFreeLimit))
+ free_buffers_.erase(free_buffers_.begin());
+
+ // Creation of pp::Buffer_Dev is expensive! It involves synchronous IPC calls.
+ // That's why we try to avoid AllocateNewBuffer() as much as we can.
+ return pp::Buffer_Dev(instance_, capacity + kBufferPadding);
+}
+
+class DecryptedBlockImpl : public cdm::DecryptedBlock {
+ public:
+ DecryptedBlockImpl() : buffer_(NULL), timestamp_(0) {}
+ virtual ~DecryptedBlockImpl() { if (buffer_) buffer_->Destroy(); }
+
+ virtual void SetDecryptedBuffer(cdm::Buffer* buffer) OVERRIDE {
+ buffer_ = static_cast<PpbBuffer*>(buffer);
+ }
+ virtual cdm::Buffer* DecryptedBuffer() OVERRIDE { return buffer_; }
+
+ virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
+ timestamp_ = timestamp;
+ }
+ virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
+
+ private:
+ PpbBuffer* buffer_;
+ int64_t timestamp_;
+
+ DISALLOW_COPY_AND_ASSIGN(DecryptedBlockImpl);
+};
+
+class VideoFrameImpl : public cdm::VideoFrame {
+ public:
+ VideoFrameImpl();
+ virtual ~VideoFrameImpl();
+
+ virtual void SetFormat(cdm::VideoFormat format) OVERRIDE {
+ format_ = format;
+ }
+ virtual cdm::VideoFormat Format() const OVERRIDE { return format_; }
+
+ virtual void SetSize(cdm::Size size) OVERRIDE { size_ = size; }
+ virtual cdm::Size Size() const OVERRIDE { return size_; }
+
+ virtual void SetFrameBuffer(cdm::Buffer* frame_buffer) OVERRIDE {
+ frame_buffer_ = static_cast<PpbBuffer*>(frame_buffer);
+ }
+ virtual cdm::Buffer* FrameBuffer() OVERRIDE { return frame_buffer_; }
+
+ virtual void SetPlaneOffset(cdm::VideoFrame::VideoPlane plane,
+ int32_t offset) OVERRIDE {
+ PP_DCHECK(0 <= plane && plane < kMaxPlanes);
+ PP_DCHECK(offset >= 0);
+ plane_offsets_[plane] = offset;
+ }
+ virtual int32_t PlaneOffset(VideoPlane plane) OVERRIDE {
+ PP_DCHECK(0 <= plane && plane < kMaxPlanes);
+ return plane_offsets_[plane];
+ }
+
+ virtual void SetStride(VideoPlane plane, int32_t stride) OVERRIDE {
+ PP_DCHECK(0 <= plane && plane < kMaxPlanes);
+ strides_[plane] = stride;
+ }
+ virtual int32_t Stride(VideoPlane plane) OVERRIDE {
+ PP_DCHECK(0 <= plane && plane < kMaxPlanes);
+ return strides_[plane];
+ }
+
+ virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
+ timestamp_ = timestamp;
+ }
+ virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
+
+ private:
+ // The video buffer format.
+ cdm::VideoFormat format_;
+
+ // Width and height of the video frame.
+ cdm::Size size_;
+
+ // The video frame buffer.
+ PpbBuffer* frame_buffer_;
+
+ // Array of data pointers to each plane in the video frame buffer.
+ int32_t plane_offsets_[kMaxPlanes];
+
+ // Array of strides for each plane, typically greater or equal to the width
+ // of the surface divided by the horizontal sampling period. Note that
+ // strides can be negative.
+ int32_t strides_[kMaxPlanes];
+
+ // Presentation timestamp in microseconds.
+ int64_t timestamp_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoFrameImpl);
+};
+
+VideoFrameImpl::VideoFrameImpl()
+ : format_(cdm::kUnknownVideoFormat),
+ frame_buffer_(NULL),
+ timestamp_(0) {
+ for (int32_t i = 0; i < kMaxPlanes; ++i) {
+ plane_offsets_[i] = 0;
+ strides_[i] = 0;
+ }
+}
+
+VideoFrameImpl::~VideoFrameImpl() {
+ if (frame_buffer_)
+ frame_buffer_->Destroy();
+}
+
+class AudioFramesImpl : public cdm::AudioFrames_1,
+ public cdm::AudioFrames_2 {
+ public:
+ AudioFramesImpl() : buffer_(NULL), format_(cdm::kAudioFormatS16) {}
+ virtual ~AudioFramesImpl() {
+ if (buffer_)
+ buffer_->Destroy();
+ }
+
+ // AudioFrames implementation.
+ virtual void SetFrameBuffer(cdm::Buffer* buffer) OVERRIDE {
+ buffer_ = static_cast<PpbBuffer*>(buffer);
+ }
+ virtual cdm::Buffer* FrameBuffer() OVERRIDE {
+ return buffer_;
+ }
+ virtual void SetFormat(cdm::AudioFormat format) OVERRIDE {
+ format_ = format;
+ }
+ virtual cdm::AudioFormat Format() const OVERRIDE {
+ return format_;
+ }
+
+ cdm::Buffer* PassFrameBuffer() {
xhwang 2013/10/15 20:42:33 Added this function so that we can transfer owners
+ PpbBuffer* temp_buffer = buffer_;
+ if (buffer_)
+ buffer_ = NULL;
+ return temp_buffer;
+ }
+
+ private:
+ PpbBuffer* buffer_;
+ cdm::AudioFormat format_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl);
+};
+
+} // namespace media
+
+#endif // MEDIA_CDM_PPAPI_CDM_HELPERS_H_

Powered by Google App Engine
This is Rietveld 408576698