| Index: webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc
|
| diff --git a/webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc b/webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc
|
| deleted file mode 100644
|
| index f175831bd3137ff38d7e10d16a3b500b4fba2ba6..0000000000000000000000000000000000000000
|
| --- a/webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc
|
| +++ /dev/null
|
| @@ -1,1198 +0,0 @@
|
| -// 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.
|
| -
|
| -#include <cstring>
|
| -#include <map>
|
| -#include <string>
|
| -#include <utility>
|
| -#include <vector>
|
| -
|
| -#include "base/basictypes.h"
|
| -#include "base/compiler_specific.h"
|
| -#include "ppapi/c/pp_errors.h"
|
| -#include "ppapi/c/pp_stdint.h"
|
| -#include "ppapi/c/private/pp_content_decryptor.h"
|
| -#include "ppapi/cpp/completion_callback.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"
|
| -#include "ppapi/cpp/pass_ref.h"
|
| -#include "ppapi/cpp/private/content_decryptor_private.h"
|
| -#include "ppapi/cpp/resource.h"
|
| -#include "ppapi/cpp/var.h"
|
| -#include "ppapi/cpp/var_array_buffer.h"
|
| -#include "ppapi/utility/completion_callback_factory.h"
|
| -#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
|
| -#include "webkit/renderer/media/crypto/ppapi/linked_ptr.h"
|
| -
|
| -#if defined(CHECK_DOCUMENT_URL)
|
| -#include "ppapi/cpp/dev/url_util_dev.h"
|
| -#include "ppapi/cpp/instance_handle.h"
|
| -#endif // defined(CHECK_DOCUMENT_URL)
|
| -
|
| -namespace {
|
| -
|
| -bool IsMainThread() {
|
| - return pp::Module::Get()->core()->IsMainThread();
|
| -}
|
| -
|
| -// Posts a task to run |cb| on the main thread. The task is posted even if the
|
| -// current thread is the main thread.
|
| -void PostOnMain(pp::CompletionCallback cb) {
|
| - pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
|
| -}
|
| -
|
| -// Ensures |cb| is called on the main thread, either because the current thread
|
| -// is the main thread or by posting it to the main thread.
|
| -void CallOnMain(pp::CompletionCallback cb) {
|
| - // TODO(tomfinegan): This is only necessary because PPAPI doesn't allow calls
|
| - // off the main thread yet. Remove this once the change lands.
|
| - if (IsMainThread())
|
| - cb.Run(PP_OK);
|
| - else
|
| - PostOnMain(cb);
|
| -}
|
| -
|
| -// Configures a cdm::InputBuffer. |subsamples| must exist as long as
|
| -// |input_buffer| is in use.
|
| -void ConfigureInputBuffer(
|
| - const pp::Buffer_Dev& encrypted_buffer,
|
| - const PP_EncryptedBlockInfo& encrypted_block_info,
|
| - std::vector<cdm::SubsampleEntry>* subsamples,
|
| - cdm::InputBuffer* input_buffer) {
|
| - PP_DCHECK(subsamples);
|
| - PP_DCHECK(!encrypted_buffer.is_null());
|
| -
|
| - input_buffer->data = static_cast<uint8_t*>(encrypted_buffer.data());
|
| - input_buffer->data_size = encrypted_block_info.data_size;
|
| - PP_DCHECK(encrypted_buffer.size() >=
|
| - static_cast<uint32_t>(input_buffer->data_size));
|
| - input_buffer->data_offset = encrypted_block_info.data_offset;
|
| -
|
| - PP_DCHECK(encrypted_block_info.key_id_size <=
|
| - arraysize(encrypted_block_info.key_id));
|
| - input_buffer->key_id_size = encrypted_block_info.key_id_size;
|
| - input_buffer->key_id = input_buffer->key_id_size > 0 ?
|
| - encrypted_block_info.key_id : NULL;
|
| -
|
| - PP_DCHECK(encrypted_block_info.iv_size <= arraysize(encrypted_block_info.iv));
|
| - input_buffer->iv_size = encrypted_block_info.iv_size;
|
| - input_buffer->iv = encrypted_block_info.iv_size > 0 ?
|
| - encrypted_block_info.iv : NULL;
|
| -
|
| - input_buffer->num_subsamples = encrypted_block_info.num_subsamples;
|
| - if (encrypted_block_info.num_subsamples > 0) {
|
| - subsamples->reserve(encrypted_block_info.num_subsamples);
|
| -
|
| - for (uint32_t i = 0; i < encrypted_block_info.num_subsamples; ++i) {
|
| - subsamples->push_back(cdm::SubsampleEntry(
|
| - encrypted_block_info.subsamples[i].clear_bytes,
|
| - encrypted_block_info.subsamples[i].cipher_bytes));
|
| - }
|
| -
|
| - input_buffer->subsamples = &(*subsamples)[0];
|
| - }
|
| -
|
| - input_buffer->timestamp = encrypted_block_info.tracking_info.timestamp;
|
| -}
|
| -
|
| -PP_DecryptResult CdmStatusToPpDecryptResult(cdm::Status status) {
|
| - switch (status) {
|
| - case cdm::kSuccess:
|
| - return PP_DECRYPTRESULT_SUCCESS;
|
| - case cdm::kNoKey:
|
| - return PP_DECRYPTRESULT_DECRYPT_NOKEY;
|
| - case cdm::kNeedMoreData:
|
| - return PP_DECRYPTRESULT_NEEDMOREDATA;
|
| - case cdm::kDecryptError:
|
| - return PP_DECRYPTRESULT_DECRYPT_ERROR;
|
| - case cdm::kDecodeError:
|
| - return PP_DECRYPTRESULT_DECODE_ERROR;
|
| - default:
|
| - PP_NOTREACHED();
|
| - return PP_DECRYPTRESULT_DECODE_ERROR;
|
| - }
|
| -}
|
| -
|
| -PP_DecryptedFrameFormat CdmVideoFormatToPpDecryptedFrameFormat(
|
| - cdm::VideoFormat format) {
|
| - switch (format) {
|
| - case cdm::kYv12:
|
| - return PP_DECRYPTEDFRAMEFORMAT_YV12;
|
| - case cdm::kI420:
|
| - return PP_DECRYPTEDFRAMEFORMAT_I420;
|
| - default:
|
| - return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN;
|
| - }
|
| -}
|
| -
|
| -cdm::AudioDecoderConfig::AudioCodec PpAudioCodecToCdmAudioCodec(
|
| - PP_AudioCodec codec) {
|
| - switch (codec) {
|
| - case PP_AUDIOCODEC_VORBIS:
|
| - return cdm::AudioDecoderConfig::kCodecVorbis;
|
| - case PP_AUDIOCODEC_AAC:
|
| - return cdm::AudioDecoderConfig::kCodecAac;
|
| - default:
|
| - return cdm::AudioDecoderConfig::kUnknownAudioCodec;
|
| - }
|
| -}
|
| -
|
| -cdm::VideoDecoderConfig::VideoCodec PpVideoCodecToCdmVideoCodec(
|
| - PP_VideoCodec codec) {
|
| - switch (codec) {
|
| - case PP_VIDEOCODEC_VP8:
|
| - return cdm::VideoDecoderConfig::kCodecVp8;
|
| - case PP_VIDEOCODEC_H264:
|
| - return cdm::VideoDecoderConfig::kCodecH264;
|
| - default:
|
| - return cdm::VideoDecoderConfig::kUnknownVideoCodec;
|
| - }
|
| -}
|
| -
|
| -cdm::VideoDecoderConfig::VideoCodecProfile PpVCProfileToCdmVCProfile(
|
| - PP_VideoCodecProfile profile) {
|
| - switch (profile) {
|
| - case PP_VIDEOCODECPROFILE_VP8_MAIN:
|
| - return cdm::VideoDecoderConfig::kVp8ProfileMain;
|
| - case PP_VIDEOCODECPROFILE_H264_BASELINE:
|
| - return cdm::VideoDecoderConfig::kH264ProfileBaseline;
|
| - case PP_VIDEOCODECPROFILE_H264_MAIN:
|
| - return cdm::VideoDecoderConfig::kH264ProfileMain;
|
| - case PP_VIDEOCODECPROFILE_H264_EXTENDED:
|
| - return cdm::VideoDecoderConfig::kH264ProfileExtended;
|
| - case PP_VIDEOCODECPROFILE_H264_HIGH:
|
| - return cdm::VideoDecoderConfig::kH264ProfileHigh;
|
| - case PP_VIDEOCODECPROFILE_H264_HIGH_10:
|
| - return cdm::VideoDecoderConfig::kH264ProfileHigh10;
|
| - case PP_VIDEOCODECPROFILE_H264_HIGH_422:
|
| - return cdm::VideoDecoderConfig::kH264ProfileHigh422;
|
| - case PP_VIDEOCODECPROFILE_H264_HIGH_444_PREDICTIVE:
|
| - return cdm::VideoDecoderConfig::kH264ProfileHigh444Predictive;
|
| - default:
|
| - return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile;
|
| - }
|
| -}
|
| -
|
| -cdm::VideoFormat PpDecryptedFrameFormatToCdmVideoFormat(
|
| - PP_DecryptedFrameFormat format) {
|
| - switch (format) {
|
| - case PP_DECRYPTEDFRAMEFORMAT_YV12:
|
| - return cdm::kYv12;
|
| - case PP_DECRYPTEDFRAMEFORMAT_I420:
|
| - return cdm::kI420;
|
| - default:
|
| - return cdm::kUnknownVideoFormat;
|
| - }
|
| -}
|
| -
|
| -cdm::StreamType PpDecryptorStreamTypeToCdmStreamType(
|
| - PP_DecryptorStreamType stream_type) {
|
| - switch (stream_type) {
|
| - case PP_DECRYPTORSTREAMTYPE_AUDIO:
|
| - return cdm::kStreamTypeAudio;
|
| - case PP_DECRYPTORSTREAMTYPE_VIDEO:
|
| - return cdm::kStreamTypeVideo;
|
| - }
|
| -
|
| - PP_NOTREACHED();
|
| - return cdm::kStreamTypeVideo;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -namespace webkit_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(IsMainThread());
|
| -
|
| - 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 {
|
| - public:
|
| - AudioFramesImpl() : buffer_(NULL) {}
|
| - 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_;
|
| - }
|
| -
|
| - private:
|
| - PpbBuffer* buffer_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl);
|
| -};
|
| -
|
| -// GetCdmHostFunc implementation.
|
| -void* GetCdmHost(int host_interface_version, void* user_data);
|
| -
|
| -// A wrapper class for abstracting away PPAPI interaction and threading for a
|
| -// Content Decryption Module (CDM).
|
| -class CdmWrapper : public pp::Instance,
|
| - public pp::ContentDecryptor_Private,
|
| - public cdm::Host {
|
| - public:
|
| - CdmWrapper(PP_Instance instance, pp::Module* module);
|
| - virtual ~CdmWrapper();
|
| -
|
| - // pp::Instance implementation.
|
| - virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
|
| - return true;
|
| - }
|
| -
|
| - // PPP_ContentDecryptor_Private implementation.
|
| - // Note: Results of calls to these methods must be reported through the
|
| - // PPB_ContentDecryptor_Private interface.
|
| - virtual void GenerateKeyRequest(const std::string& key_system,
|
| - const std::string& type,
|
| - pp::VarArrayBuffer init_data) OVERRIDE;
|
| - virtual void AddKey(const std::string& session_id,
|
| - pp::VarArrayBuffer key,
|
| - pp::VarArrayBuffer init_data) OVERRIDE;
|
| - virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE;
|
| - virtual void Decrypt(
|
| - pp::Buffer_Dev encrypted_buffer,
|
| - const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
|
| - virtual void InitializeAudioDecoder(
|
| - const PP_AudioDecoderConfig& decoder_config,
|
| - pp::Buffer_Dev extra_data_buffer) OVERRIDE;
|
| - virtual void InitializeVideoDecoder(
|
| - const PP_VideoDecoderConfig& decoder_config,
|
| - pp::Buffer_Dev extra_data_buffer) OVERRIDE;
|
| - virtual void DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
|
| - uint32_t request_id) OVERRIDE;
|
| - virtual void ResetDecoder(PP_DecryptorStreamType decoder_type,
|
| - uint32_t request_id) OVERRIDE;
|
| - virtual void DecryptAndDecode(
|
| - PP_DecryptorStreamType decoder_type,
|
| - pp::Buffer_Dev encrypted_buffer,
|
| - const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
|
| -
|
| - // cdm::Host implementation.
|
| - virtual cdm::Buffer* Allocate(int32_t capacity) OVERRIDE;
|
| - virtual void SetTimer(int64_t delay_ms, void* context) OVERRIDE;
|
| - virtual double GetCurrentWallTimeInSeconds() OVERRIDE;
|
| - virtual void SendKeyMessage(
|
| - const char* session_id, int32_t session_id_length,
|
| - const char* message, int32_t message_length,
|
| - const char* default_url, int32_t default_url_length) OVERRIDE;
|
| - virtual void SendKeyError(const char* session_id,
|
| - int32_t session_id_length,
|
| - cdm::MediaKeyError error_code,
|
| - uint32_t system_code) OVERRIDE;
|
| - virtual void GetPrivateData(int32_t* instance,
|
| - GetPrivateInterface* get_interface) OVERRIDE;
|
| -
|
| - private:
|
| - struct SessionInfo {
|
| - SessionInfo(const std::string& key_system_in,
|
| - const std::string& session_id_in)
|
| - : key_system(key_system_in),
|
| - session_id(session_id_in) {}
|
| - const std::string key_system;
|
| - const std::string session_id;
|
| - };
|
| -
|
| - typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock;
|
| - typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame;
|
| - typedef linked_ptr<AudioFramesImpl> LinkedAudioFrames;
|
| -
|
| - bool CreateCdmInstance(const std::string& key_system);
|
| -
|
| - void SendUnknownKeyError(const std::string& key_system,
|
| - const std::string& session_id);
|
| -
|
| - void SendKeyAdded(const std::string& key_system,
|
| - const std::string& session_id);
|
| -
|
| - void SendKeyErrorInternal(const std::string& key_system,
|
| - const std::string& session_id,
|
| - cdm::MediaKeyError error_code,
|
| - uint32_t system_code);
|
| -
|
| - // <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to
|
| - // <code>callback_factory_</code> to ensure that calls into
|
| - // <code>PPP_ContentDecryptor_Private</code> are asynchronous.
|
| - void KeyAdded(int32_t result, const SessionInfo& session_info);
|
| - void KeyMessage(int32_t result,
|
| - const SessionInfo& session_info,
|
| - const std::vector<uint8>& message,
|
| - const std::string& default_url);
|
| - void KeyError(int32_t result,
|
| - const SessionInfo& session_info,
|
| - cdm::MediaKeyError error_code,
|
| - uint32_t system_code);
|
| - void DeliverBlock(int32_t result,
|
| - const cdm::Status& status,
|
| - const LinkedDecryptedBlock& decrypted_block,
|
| - const PP_DecryptTrackingInfo& tracking_info);
|
| - void DecoderInitializeDone(int32_t result,
|
| - PP_DecryptorStreamType decoder_type,
|
| - uint32_t request_id,
|
| - bool success);
|
| - void DecoderDeinitializeDone(int32_t result,
|
| - PP_DecryptorStreamType decoder_type,
|
| - uint32_t request_id);
|
| - void DecoderResetDone(int32_t result,
|
| - PP_DecryptorStreamType decoder_type,
|
| - uint32_t request_id);
|
| - void DeliverFrame(int32_t result,
|
| - const cdm::Status& status,
|
| - const LinkedVideoFrame& video_frame,
|
| - const PP_DecryptTrackingInfo& tracking_info);
|
| - void DeliverSamples(int32_t result,
|
| - const cdm::Status& status,
|
| - const LinkedAudioFrames& audio_frames,
|
| - const PP_DecryptTrackingInfo& tracking_info);
|
| -
|
| - // Helper for SetTimer().
|
| - void TimerExpired(int32_t result, void* context);
|
| -
|
| - bool IsValidVideoFrame(const LinkedVideoFrame& video_frame);
|
| -
|
| - PpbBufferAllocator allocator_;
|
| - pp::CompletionCallbackFactory<CdmWrapper> callback_factory_;
|
| - cdm::ContentDecryptionModule* cdm_;
|
| - std::string key_system_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(CdmWrapper);
|
| -};
|
| -
|
| -CdmWrapper::CdmWrapper(PP_Instance instance, pp::Module* module)
|
| - : pp::Instance(instance),
|
| - pp::ContentDecryptor_Private(this),
|
| - allocator_(this),
|
| - cdm_(NULL) {
|
| - callback_factory_.Initialize(this);
|
| -}
|
| -
|
| -CdmWrapper::~CdmWrapper() {
|
| - if (cdm_)
|
| - cdm_->Destroy();
|
| -}
|
| -
|
| -bool CdmWrapper::CreateCdmInstance(const std::string& key_system) {
|
| - PP_DCHECK(!cdm_);
|
| - cdm_ = static_cast<cdm::ContentDecryptionModule*>(
|
| - ::CreateCdmInstance(cdm::kCdmInterfaceVersion,
|
| - key_system.data(), key_system.size(),
|
| - GetCdmHost, this));
|
| -
|
| - return (cdm_ != NULL);
|
| -}
|
| -
|
| -void CdmWrapper::GenerateKeyRequest(const std::string& key_system,
|
| - const std::string& type,
|
| - pp::VarArrayBuffer init_data) {
|
| - PP_DCHECK(!key_system.empty());
|
| - PP_DCHECK(key_system_.empty() || key_system_ == key_system);
|
| -
|
| -#if defined(CHECK_DOCUMENT_URL)
|
| - PP_URLComponents_Dev url_components = {};
|
| - pp::Var href = pp::URLUtil_Dev::Get()->GetDocumentURL(
|
| - pp::InstanceHandle(pp_instance()), &url_components);
|
| - PP_DCHECK(href.is_string());
|
| - PP_DCHECK(!href.AsString().empty());
|
| - PP_DCHECK(url_components.host.begin);
|
| - PP_DCHECK(0 < url_components.host.len);
|
| -#endif // defined(CHECK_DOCUMENT_URL)
|
| -
|
| - if (!cdm_) {
|
| - if (!CreateCdmInstance(key_system)) {
|
| - SendUnknownKeyError(key_system, std::string());
|
| - return;
|
| - }
|
| - }
|
| - PP_DCHECK(cdm_);
|
| -
|
| - // Must be set here in case the CDM synchronously calls a cdm::Host method.
|
| - // Clear below on error.
|
| - // TODO(ddorwin): Set/clear key_system_ & cdm_ at same time; clear both on
|
| - // error below.
|
| - key_system_ = key_system;
|
| - cdm::Status status = cdm_->GenerateKeyRequest(
|
| - type.data(), type.size(),
|
| - static_cast<const uint8_t*>(init_data.Map()),
|
| - init_data.ByteLength());
|
| - PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
|
| - if (status != cdm::kSuccess) {
|
| - key_system_.clear(); // See comment above.
|
| - return;
|
| - }
|
| -
|
| - key_system_ = key_system;
|
| -}
|
| -
|
| -void CdmWrapper::AddKey(const std::string& session_id,
|
| - pp::VarArrayBuffer key,
|
| - pp::VarArrayBuffer init_data) {
|
| - PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
|
| - if (!cdm_) {
|
| - SendUnknownKeyError(key_system_, session_id);
|
| - return;
|
| - }
|
| -
|
| - const uint8_t* key_ptr = static_cast<const uint8_t*>(key.Map());
|
| - int key_size = key.ByteLength();
|
| - const uint8_t* init_data_ptr = static_cast<const uint8_t*>(init_data.Map());
|
| - int init_data_size = init_data.ByteLength();
|
| - PP_DCHECK(!init_data_ptr == !init_data_size);
|
| -
|
| - if (!key_ptr || key_size <= 0) {
|
| - SendUnknownKeyError(key_system_, session_id);
|
| - return;
|
| - }
|
| -
|
| - cdm::Status status = cdm_->AddKey(session_id.data(), session_id.size(),
|
| - key_ptr, key_size,
|
| - init_data_ptr, init_data_size);
|
| - PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
|
| - if (status != cdm::kSuccess) {
|
| - SendUnknownKeyError(key_system_, session_id);
|
| - return;
|
| - }
|
| -
|
| - SendKeyAdded(key_system_, session_id);
|
| -}
|
| -
|
| -void CdmWrapper::CancelKeyRequest(const std::string& session_id) {
|
| - PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
|
| - if (!cdm_) {
|
| - SendUnknownKeyError(key_system_, session_id);
|
| - return;
|
| - }
|
| -
|
| - cdm::Status status = cdm_->CancelKeyRequest(session_id.data(),
|
| - session_id.size());
|
| - PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
|
| - if (status != cdm::kSuccess)
|
| - SendUnknownKeyError(key_system_, session_id);
|
| -}
|
| -
|
| -// Note: In the following decryption/decoding related functions, errors are NOT
|
| -// reported via KeyError, but are reported via corresponding PPB calls.
|
| -
|
| -void CdmWrapper::Decrypt(pp::Buffer_Dev encrypted_buffer,
|
| - const PP_EncryptedBlockInfo& encrypted_block_info) {
|
| - PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
|
| - PP_DCHECK(!encrypted_buffer.is_null());
|
| -
|
| - // Release a buffer that the caller indicated it is finished with.
|
| - allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
|
| -
|
| - cdm::Status status = cdm::kDecryptError;
|
| - LinkedDecryptedBlock decrypted_block(new DecryptedBlockImpl());
|
| -
|
| - if (cdm_) {
|
| - cdm::InputBuffer input_buffer;
|
| - std::vector<cdm::SubsampleEntry> subsamples;
|
| - ConfigureInputBuffer(encrypted_buffer, encrypted_block_info, &subsamples,
|
| - &input_buffer);
|
| - status = cdm_->Decrypt(input_buffer, decrypted_block.get());
|
| - PP_DCHECK(status != cdm::kSuccess ||
|
| - (decrypted_block->DecryptedBuffer() &&
|
| - decrypted_block->DecryptedBuffer()->Size()));
|
| - }
|
| -
|
| - CallOnMain(callback_factory_.NewCallback(
|
| - &CdmWrapper::DeliverBlock,
|
| - status,
|
| - decrypted_block,
|
| - encrypted_block_info.tracking_info));
|
| -}
|
| -
|
| -void CdmWrapper::InitializeAudioDecoder(
|
| - const PP_AudioDecoderConfig& decoder_config,
|
| - pp::Buffer_Dev extra_data_buffer) {
|
| - PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
|
| -
|
| - cdm::Status status = cdm::kSessionError;
|
| - if (cdm_) {
|
| - cdm::AudioDecoderConfig cdm_decoder_config;
|
| - cdm_decoder_config.codec =
|
| - PpAudioCodecToCdmAudioCodec(decoder_config.codec);
|
| - cdm_decoder_config.channel_count = decoder_config.channel_count;
|
| - cdm_decoder_config.bits_per_channel = decoder_config.bits_per_channel;
|
| - cdm_decoder_config.samples_per_second = decoder_config.samples_per_second;
|
| - cdm_decoder_config.extra_data =
|
| - static_cast<uint8_t*>(extra_data_buffer.data());
|
| - cdm_decoder_config.extra_data_size =
|
| - static_cast<int32_t>(extra_data_buffer.size());
|
| - status = cdm_->InitializeAudioDecoder(cdm_decoder_config);
|
| - }
|
| -
|
| - CallOnMain(callback_factory_.NewCallback(
|
| - &CdmWrapper::DecoderInitializeDone,
|
| - PP_DECRYPTORSTREAMTYPE_AUDIO,
|
| - decoder_config.request_id,
|
| - status == cdm::kSuccess));
|
| -}
|
| -
|
| -void CdmWrapper::InitializeVideoDecoder(
|
| - const PP_VideoDecoderConfig& decoder_config,
|
| - pp::Buffer_Dev extra_data_buffer) {
|
| - PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
|
| -
|
| - cdm::Status status = cdm::kSessionError;
|
| - if (cdm_) {
|
| - cdm::VideoDecoderConfig cdm_decoder_config;
|
| - cdm_decoder_config.codec =
|
| - PpVideoCodecToCdmVideoCodec(decoder_config.codec);
|
| - cdm_decoder_config.profile =
|
| - PpVCProfileToCdmVCProfile(decoder_config.profile);
|
| - cdm_decoder_config.format =
|
| - PpDecryptedFrameFormatToCdmVideoFormat(decoder_config.format);
|
| - cdm_decoder_config.coded_size.width = decoder_config.width;
|
| - cdm_decoder_config.coded_size.height = decoder_config.height;
|
| - cdm_decoder_config.extra_data =
|
| - static_cast<uint8_t*>(extra_data_buffer.data());
|
| - cdm_decoder_config.extra_data_size =
|
| - static_cast<int32_t>(extra_data_buffer.size());
|
| - status = cdm_->InitializeVideoDecoder(cdm_decoder_config);
|
| - }
|
| -
|
| - CallOnMain(callback_factory_.NewCallback(
|
| - &CdmWrapper::DecoderInitializeDone,
|
| - PP_DECRYPTORSTREAMTYPE_VIDEO,
|
| - decoder_config.request_id,
|
| - status == cdm::kSuccess));
|
| -}
|
| -
|
| -void CdmWrapper::DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
|
| - uint32_t request_id) {
|
| - PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
|
| - if (cdm_) {
|
| - cdm_->DeinitializeDecoder(
|
| - PpDecryptorStreamTypeToCdmStreamType(decoder_type));
|
| - }
|
| -
|
| - CallOnMain(callback_factory_.NewCallback(
|
| - &CdmWrapper::DecoderDeinitializeDone,
|
| - decoder_type,
|
| - request_id));
|
| -}
|
| -
|
| -void CdmWrapper::ResetDecoder(PP_DecryptorStreamType decoder_type,
|
| - uint32_t request_id) {
|
| - PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
|
| - if (cdm_)
|
| - cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type));
|
| -
|
| - CallOnMain(callback_factory_.NewCallback(&CdmWrapper::DecoderResetDone,
|
| - decoder_type,
|
| - request_id));
|
| -}
|
| -
|
| -void CdmWrapper::DecryptAndDecode(
|
| - PP_DecryptorStreamType decoder_type,
|
| - pp::Buffer_Dev encrypted_buffer,
|
| - const PP_EncryptedBlockInfo& encrypted_block_info) {
|
| - PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
|
| -
|
| - // Release a buffer that the caller indicated it is finished with.
|
| - allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
|
| -
|
| - cdm::InputBuffer input_buffer;
|
| - std::vector<cdm::SubsampleEntry> subsamples;
|
| - if (cdm_ && !encrypted_buffer.is_null()) {
|
| - ConfigureInputBuffer(encrypted_buffer,
|
| - encrypted_block_info,
|
| - &subsamples,
|
| - &input_buffer);
|
| - }
|
| -
|
| - cdm::Status status = cdm::kDecodeError;
|
| -
|
| - switch (decoder_type) {
|
| - case PP_DECRYPTORSTREAMTYPE_VIDEO: {
|
| - LinkedVideoFrame video_frame(new VideoFrameImpl());
|
| - if (cdm_)
|
| - status = cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get());
|
| - CallOnMain(callback_factory_.NewCallback(
|
| - &CdmWrapper::DeliverFrame,
|
| - status,
|
| - video_frame,
|
| - encrypted_block_info.tracking_info));
|
| - return;
|
| - }
|
| -
|
| - case PP_DECRYPTORSTREAMTYPE_AUDIO: {
|
| - LinkedAudioFrames audio_frames(new AudioFramesImpl());
|
| - if (cdm_) {
|
| - status = cdm_->DecryptAndDecodeSamples(input_buffer,
|
| - audio_frames.get());
|
| - }
|
| - CallOnMain(callback_factory_.NewCallback(
|
| - &CdmWrapper::DeliverSamples,
|
| - status,
|
| - audio_frames,
|
| - encrypted_block_info.tracking_info));
|
| - return;
|
| - }
|
| -
|
| - default:
|
| - PP_NOTREACHED();
|
| - return;
|
| - }
|
| -}
|
| -
|
| -cdm::Buffer* CdmWrapper::Allocate(int32_t capacity) {
|
| - return allocator_.Allocate(capacity);
|
| -}
|
| -
|
| -void CdmWrapper::SetTimer(int64_t delay_ms, void* context) {
|
| - // NOTE: doesn't really need to run on the main thread; could just as well run
|
| - // on a helper thread if |cdm_| were thread-friendly and care was taken. We
|
| - // only use CallOnMainThread() here to get delayed-execution behavior.
|
| - pp::Module::Get()->core()->CallOnMainThread(
|
| - delay_ms,
|
| - callback_factory_.NewCallback(&CdmWrapper::TimerExpired, context),
|
| - PP_OK);
|
| -}
|
| -
|
| -void CdmWrapper::TimerExpired(int32_t result, void* context) {
|
| - PP_DCHECK(result == PP_OK);
|
| - cdm_->TimerExpired(context);
|
| -}
|
| -
|
| -double CdmWrapper::GetCurrentWallTimeInSeconds() {
|
| - return pp::Module::Get()->core()->GetTime();
|
| -}
|
| -
|
| -void CdmWrapper::SendKeyMessage(
|
| - const char* session_id, int32_t session_id_length,
|
| - const char* message, int32_t message_length,
|
| - const char* default_url, int32_t default_url_length) {
|
| - PP_DCHECK(!key_system_.empty());
|
| - PostOnMain(callback_factory_.NewCallback(
|
| - &CdmWrapper::KeyMessage,
|
| - SessionInfo(key_system_,
|
| - std::string(session_id, session_id_length)),
|
| - std::vector<uint8>(message, message + message_length),
|
| - std::string(default_url, default_url_length)));
|
| -}
|
| -
|
| -void CdmWrapper::SendKeyError(const char* session_id,
|
| - int32_t session_id_length,
|
| - cdm::MediaKeyError error_code,
|
| - uint32_t system_code) {
|
| - SendKeyErrorInternal(key_system_,
|
| - std::string(session_id, session_id_length),
|
| - error_code,
|
| - system_code);
|
| -}
|
| -
|
| -void CdmWrapper::GetPrivateData(int32_t* instance,
|
| - cdm::Host::GetPrivateInterface* get_interface) {
|
| - *instance = pp_instance();
|
| - *get_interface = pp::Module::Get()->get_browser_interface();
|
| -}
|
| -
|
| -void CdmWrapper::SendUnknownKeyError(const std::string& key_system,
|
| - const std::string& session_id) {
|
| - SendKeyErrorInternal(key_system, session_id, cdm::kUnknownError, 0);
|
| -}
|
| -
|
| -void CdmWrapper::SendKeyAdded(const std::string& key_system,
|
| - const std::string& session_id) {
|
| - PostOnMain(callback_factory_.NewCallback(
|
| - &CdmWrapper::KeyAdded,
|
| - SessionInfo(key_system_, session_id)));
|
| -}
|
| -
|
| -void CdmWrapper::SendKeyErrorInternal(const std::string& key_system,
|
| - const std::string& session_id,
|
| - cdm::MediaKeyError error_code,
|
| - uint32_t system_code) {
|
| - PP_DCHECK(!key_system.empty());
|
| - PostOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyError,
|
| - SessionInfo(key_system_, session_id),
|
| - error_code,
|
| - system_code));
|
| -}
|
| -
|
| -void CdmWrapper::KeyAdded(int32_t result, const SessionInfo& session_info) {
|
| - PP_DCHECK(result == PP_OK);
|
| - PP_DCHECK(!session_info.key_system.empty());
|
| - pp::ContentDecryptor_Private::KeyAdded(session_info.key_system,
|
| - session_info.session_id);
|
| -}
|
| -
|
| -void CdmWrapper::KeyMessage(int32_t result,
|
| - const SessionInfo& session_info,
|
| - const std::vector<uint8>& message,
|
| - const std::string& default_url) {
|
| - PP_DCHECK(result == PP_OK);
|
| - PP_DCHECK(!session_info.key_system.empty());
|
| -
|
| - pp::VarArrayBuffer message_array_buffer(message.size());
|
| - if (message.size() > 0) {
|
| - memcpy(message_array_buffer.Map(), message.data(), message.size());
|
| - }
|
| -
|
| - pp::ContentDecryptor_Private::KeyMessage(
|
| - session_info.key_system, session_info.session_id,
|
| - message_array_buffer, default_url);
|
| -}
|
| -
|
| -void CdmWrapper::KeyError(int32_t result,
|
| - const SessionInfo& session_info,
|
| - cdm::MediaKeyError error_code,
|
| - uint32_t system_code) {
|
| - PP_DCHECK(result == PP_OK);
|
| - PP_DCHECK(!session_info.key_system.empty());
|
| - pp::ContentDecryptor_Private::KeyError(
|
| - session_info.key_system, session_info.session_id,
|
| - error_code, system_code);
|
| -}
|
| -
|
| -void CdmWrapper::DeliverBlock(int32_t result,
|
| - const cdm::Status& status,
|
| - const LinkedDecryptedBlock& decrypted_block,
|
| - const PP_DecryptTrackingInfo& tracking_info) {
|
| - PP_DCHECK(result == PP_OK);
|
| - PP_DecryptedBlockInfo decrypted_block_info;
|
| - decrypted_block_info.tracking_info = tracking_info;
|
| - decrypted_block_info.tracking_info.timestamp = decrypted_block->Timestamp();
|
| - decrypted_block_info.tracking_info.buffer_id = 0;
|
| - decrypted_block_info.data_size = 0;
|
| - decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
|
| -
|
| - pp::Buffer_Dev buffer;
|
| -
|
| - if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
|
| - PP_DCHECK(decrypted_block.get() && decrypted_block->DecryptedBuffer());
|
| - if (!decrypted_block.get() || !decrypted_block->DecryptedBuffer()) {
|
| - PP_NOTREACHED();
|
| - decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
|
| - } else {
|
| - PpbBuffer* ppb_buffer =
|
| - static_cast<PpbBuffer*>(decrypted_block->DecryptedBuffer());
|
| - buffer = ppb_buffer->buffer_dev();
|
| - decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
|
| - decrypted_block_info.data_size = ppb_buffer->Size();
|
| - }
|
| - }
|
| -
|
| - pp::ContentDecryptor_Private::DeliverBlock(buffer, decrypted_block_info);
|
| -}
|
| -
|
| -void CdmWrapper::DecoderInitializeDone(int32_t result,
|
| - PP_DecryptorStreamType decoder_type,
|
| - uint32_t request_id,
|
| - bool success) {
|
| - PP_DCHECK(result == PP_OK);
|
| - pp::ContentDecryptor_Private::DecoderInitializeDone(decoder_type,
|
| - request_id,
|
| - success);
|
| -}
|
| -
|
| -void CdmWrapper::DecoderDeinitializeDone(int32_t result,
|
| - PP_DecryptorStreamType decoder_type,
|
| - uint32_t request_id) {
|
| - pp::ContentDecryptor_Private::DecoderDeinitializeDone(decoder_type,
|
| - request_id);
|
| -}
|
| -
|
| -void CdmWrapper::DecoderResetDone(int32_t result,
|
| - PP_DecryptorStreamType decoder_type,
|
| - uint32_t request_id) {
|
| - pp::ContentDecryptor_Private::DecoderResetDone(decoder_type, request_id);
|
| -}
|
| -
|
| -void CdmWrapper::DeliverFrame(
|
| - int32_t result,
|
| - const cdm::Status& status,
|
| - const LinkedVideoFrame& video_frame,
|
| - const PP_DecryptTrackingInfo& tracking_info) {
|
| - PP_DCHECK(result == PP_OK);
|
| - PP_DecryptedFrameInfo decrypted_frame_info;
|
| - decrypted_frame_info.tracking_info.request_id = tracking_info.request_id;
|
| - decrypted_frame_info.tracking_info.buffer_id = 0;
|
| - decrypted_frame_info.result = CdmStatusToPpDecryptResult(status);
|
| -
|
| - pp::Buffer_Dev buffer;
|
| -
|
| - if (decrypted_frame_info.result == PP_DECRYPTRESULT_SUCCESS) {
|
| - if (!IsValidVideoFrame(video_frame)) {
|
| - PP_NOTREACHED();
|
| - decrypted_frame_info.result = PP_DECRYPTRESULT_DECODE_ERROR;
|
| - } else {
|
| - PpbBuffer* ppb_buffer =
|
| - static_cast<PpbBuffer*>(video_frame->FrameBuffer());
|
| -
|
| - buffer = ppb_buffer->buffer_dev();
|
| -
|
| - decrypted_frame_info.tracking_info.timestamp = video_frame->Timestamp();
|
| - decrypted_frame_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
|
| - decrypted_frame_info.format =
|
| - CdmVideoFormatToPpDecryptedFrameFormat(video_frame->Format());
|
| - decrypted_frame_info.width = video_frame->Size().width;
|
| - decrypted_frame_info.height = video_frame->Size().height;
|
| - decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y] =
|
| - video_frame->PlaneOffset(cdm::VideoFrame::kYPlane);
|
| - decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_U] =
|
| - video_frame->PlaneOffset(cdm::VideoFrame::kUPlane);
|
| - decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_V] =
|
| - video_frame->PlaneOffset(cdm::VideoFrame::kVPlane);
|
| - decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_Y] =
|
| - video_frame->Stride(cdm::VideoFrame::kYPlane);
|
| - decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_U] =
|
| - video_frame->Stride(cdm::VideoFrame::kUPlane);
|
| - decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_V] =
|
| - video_frame->Stride(cdm::VideoFrame::kVPlane);
|
| - }
|
| - }
|
| - pp::ContentDecryptor_Private::DeliverFrame(buffer, decrypted_frame_info);
|
| -}
|
| -
|
| -void CdmWrapper::DeliverSamples(int32_t result,
|
| - const cdm::Status& status,
|
| - const LinkedAudioFrames& audio_frames,
|
| - const PP_DecryptTrackingInfo& tracking_info) {
|
| - PP_DCHECK(result == PP_OK);
|
| -
|
| - PP_DecryptedBlockInfo decrypted_block_info;
|
| - decrypted_block_info.tracking_info = tracking_info;
|
| - decrypted_block_info.tracking_info.timestamp = 0;
|
| - decrypted_block_info.tracking_info.buffer_id = 0;
|
| - decrypted_block_info.data_size = 0;
|
| - decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
|
| -
|
| - pp::Buffer_Dev buffer;
|
| -
|
| - if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
|
| - PP_DCHECK(audio_frames.get() && audio_frames->FrameBuffer());
|
| - if (!audio_frames.get() || !audio_frames->FrameBuffer()) {
|
| - PP_NOTREACHED();
|
| - decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
|
| - } else {
|
| - PpbBuffer* ppb_buffer =
|
| - static_cast<PpbBuffer*>(audio_frames->FrameBuffer());
|
| - buffer = ppb_buffer->buffer_dev();
|
| - decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
|
| - decrypted_block_info.data_size = ppb_buffer->Size();
|
| - }
|
| - }
|
| -
|
| - pp::ContentDecryptor_Private::DeliverSamples(buffer, decrypted_block_info);
|
| -}
|
| -
|
| -bool CdmWrapper::IsValidVideoFrame(const LinkedVideoFrame& video_frame) {
|
| - if (!video_frame.get() ||
|
| - !video_frame->FrameBuffer() ||
|
| - (video_frame->Format() != cdm::kI420 &&
|
| - video_frame->Format() != cdm::kYv12)) {
|
| - return false;
|
| - }
|
| -
|
| - PpbBuffer* ppb_buffer = static_cast<PpbBuffer*>(video_frame->FrameBuffer());
|
| -
|
| - for (int i = 0; i < cdm::VideoFrame::kMaxPlanes; ++i) {
|
| - int plane_height = (i == cdm::VideoFrame::kYPlane) ?
|
| - video_frame->Size().height : (video_frame->Size().height + 1) / 2;
|
| - cdm::VideoFrame::VideoPlane plane =
|
| - static_cast<cdm::VideoFrame::VideoPlane>(i);
|
| - if (ppb_buffer->Size() < video_frame->PlaneOffset(plane) +
|
| - plane_height * video_frame->Stride(plane)) {
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void* GetCdmHost(int host_interface_version, void* user_data) {
|
| - if (!host_interface_version || !user_data)
|
| - return NULL;
|
| -
|
| - if (host_interface_version != cdm::kHostInterfaceVersion)
|
| - return NULL;
|
| -
|
| - CdmWrapper* cdm_wrapper = static_cast<CdmWrapper*>(user_data);
|
| - return static_cast<cdm::Host*>(cdm_wrapper);
|
| -}
|
| -
|
| -// This object is the global object representing this plugin library as long
|
| -// as it is loaded.
|
| -class CdmWrapperModule : public pp::Module {
|
| - public:
|
| - CdmWrapperModule() : pp::Module() {
|
| - // This function blocks the renderer thread (PluginInstance::Initialize()).
|
| - // Move this call to other places if this may be a concern in the future.
|
| - INITIALIZE_CDM_MODULE();
|
| - }
|
| - virtual ~CdmWrapperModule() {
|
| - DeinitializeCdmModule();
|
| - }
|
| -
|
| - virtual pp::Instance* CreateInstance(PP_Instance instance) {
|
| - return new CdmWrapper(instance, this);
|
| - }
|
| -};
|
| -
|
| -} // namespace webkit_media
|
| -
|
| -namespace pp {
|
| -
|
| -// Factory function for your specialization of the Module object.
|
| -Module* CreateModule() {
|
| - return new webkit_media::CdmWrapperModule();
|
| -}
|
| -
|
| -} // namespace pp
|
|
|