// Copyright 2013 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. #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/dev/buffer_dev.h" #include "ppapi/cpp/instance.h" #include "ppapi/cpp/logging.h" namespace media { class PpbBufferAllocator; // 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, PpbBufferAllocator* allocator); // cdm::Buffer implementation. virtual void Destroy() OVERRIDE; virtual uint32_t Capacity() const OVERRIDE; virtual uint8_t* Data() OVERRIDE; virtual void SetSize(uint32_t size) OVERRIDE; virtual uint32_t Size() const OVERRIDE { return size_; } // Takes the |buffer_| from this class and returns it. // Note: The caller must ensure |allocator->Release()| is called later so that // the buffer can be reused by the allocator. // Since pp::Buffer_Dev is ref-counted, the caller now holds one reference to // the buffer and this class holds no reference. Note that other references // may still exist. For example, PpbBufferAllocator always holds a reference // to all allocated buffers. pp::Buffer_Dev TakeBuffer(); uint32_t buffer_id() const { return buffer_id_; } private: PpbBuffer(pp::Buffer_Dev buffer, uint32_t buffer_id, PpbBufferAllocator* allocator); virtual ~PpbBuffer(); pp::Buffer_Dev buffer_; uint32_t buffer_id_; uint32_t size_; PpbBufferAllocator* allocator_; DISALLOW_COPY_AND_ASSIGN(PpbBuffer); }; class PpbBufferAllocator { public: explicit PpbBufferAllocator(pp::Instance* instance) : instance_(instance), next_buffer_id_(1) {} ~PpbBufferAllocator() {} cdm::Buffer* Allocate(uint32_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<uint32_t, std::pair<uint32_t, pp::Buffer_Dev> > FreeBufferMap; pp::Buffer_Dev AllocateNewBuffer(uint32_t capacity); pp::Instance* const instance_; uint32_t next_buffer_id_; AllocatedBufferMap allocated_buffers_; FreeBufferMap free_buffers_; DISALLOW_COPY_AND_ASSIGN(PpbBufferAllocator); }; 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, uint32_t offset) OVERRIDE { PP_DCHECK(plane < kMaxPlanes); plane_offsets_[plane] = offset; } virtual uint32_t PlaneOffset(VideoPlane plane) OVERRIDE { PP_DCHECK(plane < kMaxPlanes); return plane_offsets_[plane]; } virtual void SetStride(VideoPlane plane, uint32_t stride) OVERRIDE { PP_DCHECK(plane < kMaxPlanes); strides_[plane] = stride; } virtual uint32_t Stride(VideoPlane plane) OVERRIDE { PP_DCHECK(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. uint32_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. uint32_t strides_[kMaxPlanes]; // Presentation timestamp in microseconds. int64_t timestamp_; DISALLOW_COPY_AND_ASSIGN(VideoFrameImpl); }; class AudioFramesImpl : public cdm::AudioFrames_2 { public: AudioFramesImpl() : buffer_(NULL), format_(cdm::kUnknownAudioFormat) {} 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() { PpbBuffer* temp_buffer = 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_