Home | History | Annotate | Download | only in ppapi
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <cstring>
      6 #include <map>
      7 #include <string>
      8 #include <utility>
      9 #include <vector>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/compiler_specific.h"
     13 #include "media/cdm/ppapi/api/content_decryption_module.h"
     14 #include "media/cdm/ppapi/linked_ptr.h"
     15 #include "ppapi/c/pp_errors.h"
     16 #include "ppapi/c/pp_stdint.h"
     17 #include "ppapi/c/private/pp_content_decryptor.h"
     18 #include "ppapi/cpp/completion_callback.h"
     19 #include "ppapi/cpp/core.h"
     20 #include "ppapi/cpp/dev/buffer_dev.h"
     21 #include "ppapi/cpp/instance.h"
     22 #include "ppapi/cpp/logging.h"
     23 #include "ppapi/cpp/module.h"
     24 #include "ppapi/cpp/pass_ref.h"
     25 #include "ppapi/cpp/private/content_decryptor_private.h"
     26 #include "ppapi/cpp/resource.h"
     27 #include "ppapi/cpp/var.h"
     28 #include "ppapi/cpp/var_array_buffer.h"
     29 #include "ppapi/utility/completion_callback_factory.h"
     30 
     31 #if defined(CHECK_DOCUMENT_URL)
     32 #include "ppapi/cpp/dev/url_util_dev.h"
     33 #include "ppapi/cpp/instance_handle.h"
     34 #endif  // defined(CHECK_DOCUMENT_URL)
     35 
     36 namespace {
     37 
     38 bool IsMainThread() {
     39   return pp::Module::Get()->core()->IsMainThread();
     40 }
     41 
     42 // Posts a task to run |cb| on the main thread. The task is posted even if the
     43 // current thread is the main thread.
     44 void PostOnMain(pp::CompletionCallback cb) {
     45   pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
     46 }
     47 
     48 // Ensures |cb| is called on the main thread, either because the current thread
     49 // is the main thread or by posting it to the main thread.
     50 void CallOnMain(pp::CompletionCallback cb) {
     51   // TODO(tomfinegan): This is only necessary because PPAPI doesn't allow calls
     52   // off the main thread yet. Remove this once the change lands.
     53   if (IsMainThread())
     54     cb.Run(PP_OK);
     55   else
     56     PostOnMain(cb);
     57 }
     58 
     59 // Configures a cdm::InputBuffer. |subsamples| must exist as long as
     60 // |input_buffer| is in use.
     61 void ConfigureInputBuffer(
     62     const pp::Buffer_Dev& encrypted_buffer,
     63     const PP_EncryptedBlockInfo& encrypted_block_info,
     64     std::vector<cdm::SubsampleEntry>* subsamples,
     65     cdm::InputBuffer* input_buffer) {
     66   PP_DCHECK(subsamples);
     67   PP_DCHECK(!encrypted_buffer.is_null());
     68 
     69   input_buffer->data = static_cast<uint8_t*>(encrypted_buffer.data());
     70   input_buffer->data_size = encrypted_block_info.data_size;
     71   PP_DCHECK(encrypted_buffer.size() >=
     72             static_cast<uint32_t>(input_buffer->data_size));
     73   input_buffer->data_offset = encrypted_block_info.data_offset;
     74 
     75   PP_DCHECK(encrypted_block_info.key_id_size <=
     76             arraysize(encrypted_block_info.key_id));
     77   input_buffer->key_id_size = encrypted_block_info.key_id_size;
     78   input_buffer->key_id = input_buffer->key_id_size > 0 ?
     79       encrypted_block_info.key_id : NULL;
     80 
     81   PP_DCHECK(encrypted_block_info.iv_size <= arraysize(encrypted_block_info.iv));
     82   input_buffer->iv_size = encrypted_block_info.iv_size;
     83   input_buffer->iv = encrypted_block_info.iv_size > 0 ?
     84       encrypted_block_info.iv : NULL;
     85 
     86   input_buffer->num_subsamples = encrypted_block_info.num_subsamples;
     87   if (encrypted_block_info.num_subsamples > 0) {
     88     subsamples->reserve(encrypted_block_info.num_subsamples);
     89 
     90     for (uint32_t i = 0; i < encrypted_block_info.num_subsamples; ++i) {
     91       subsamples->push_back(cdm::SubsampleEntry(
     92           encrypted_block_info.subsamples[i].clear_bytes,
     93           encrypted_block_info.subsamples[i].cipher_bytes));
     94     }
     95 
     96     input_buffer->subsamples = &(*subsamples)[0];
     97   }
     98 
     99   input_buffer->timestamp = encrypted_block_info.tracking_info.timestamp;
    100 }
    101 
    102 PP_DecryptResult CdmStatusToPpDecryptResult(cdm::Status status) {
    103   switch (status) {
    104     case cdm::kSuccess:
    105       return PP_DECRYPTRESULT_SUCCESS;
    106     case cdm::kNoKey:
    107       return PP_DECRYPTRESULT_DECRYPT_NOKEY;
    108     case cdm::kNeedMoreData:
    109       return PP_DECRYPTRESULT_NEEDMOREDATA;
    110     case cdm::kDecryptError:
    111       return PP_DECRYPTRESULT_DECRYPT_ERROR;
    112     case cdm::kDecodeError:
    113       return PP_DECRYPTRESULT_DECODE_ERROR;
    114     default:
    115       PP_NOTREACHED();
    116       return PP_DECRYPTRESULT_DECODE_ERROR;
    117   }
    118 }
    119 
    120 PP_DecryptedFrameFormat CdmVideoFormatToPpDecryptedFrameFormat(
    121     cdm::VideoFormat format) {
    122   switch (format) {
    123     case cdm::kYv12:
    124       return PP_DECRYPTEDFRAMEFORMAT_YV12;
    125     case cdm::kI420:
    126       return PP_DECRYPTEDFRAMEFORMAT_I420;
    127     default:
    128       return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN;
    129   }
    130 }
    131 
    132 cdm::AudioDecoderConfig::AudioCodec PpAudioCodecToCdmAudioCodec(
    133     PP_AudioCodec codec) {
    134   switch (codec) {
    135     case PP_AUDIOCODEC_VORBIS:
    136       return cdm::AudioDecoderConfig::kCodecVorbis;
    137     case PP_AUDIOCODEC_AAC:
    138       return cdm::AudioDecoderConfig::kCodecAac;
    139     default:
    140       return cdm::AudioDecoderConfig::kUnknownAudioCodec;
    141   }
    142 }
    143 
    144 cdm::VideoDecoderConfig::VideoCodec PpVideoCodecToCdmVideoCodec(
    145     PP_VideoCodec codec) {
    146   switch (codec) {
    147     case PP_VIDEOCODEC_VP8:
    148       return cdm::VideoDecoderConfig::kCodecVp8;
    149     case PP_VIDEOCODEC_H264:
    150       return cdm::VideoDecoderConfig::kCodecH264;
    151     default:
    152       return cdm::VideoDecoderConfig::kUnknownVideoCodec;
    153   }
    154 }
    155 
    156 cdm::VideoDecoderConfig::VideoCodecProfile PpVCProfileToCdmVCProfile(
    157     PP_VideoCodecProfile profile) {
    158   switch (profile) {
    159     case PP_VIDEOCODECPROFILE_VP8_MAIN:
    160       return cdm::VideoDecoderConfig::kVp8ProfileMain;
    161     case PP_VIDEOCODECPROFILE_H264_BASELINE:
    162       return cdm::VideoDecoderConfig::kH264ProfileBaseline;
    163     case PP_VIDEOCODECPROFILE_H264_MAIN:
    164       return cdm::VideoDecoderConfig::kH264ProfileMain;
    165     case PP_VIDEOCODECPROFILE_H264_EXTENDED:
    166       return cdm::VideoDecoderConfig::kH264ProfileExtended;
    167     case PP_VIDEOCODECPROFILE_H264_HIGH:
    168       return cdm::VideoDecoderConfig::kH264ProfileHigh;
    169     case PP_VIDEOCODECPROFILE_H264_HIGH_10:
    170       return cdm::VideoDecoderConfig::kH264ProfileHigh10;
    171     case PP_VIDEOCODECPROFILE_H264_HIGH_422:
    172       return cdm::VideoDecoderConfig::kH264ProfileHigh422;
    173     case PP_VIDEOCODECPROFILE_H264_HIGH_444_PREDICTIVE:
    174       return cdm::VideoDecoderConfig::kH264ProfileHigh444Predictive;
    175     default:
    176       return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile;
    177   }
    178 }
    179 
    180 cdm::VideoFormat PpDecryptedFrameFormatToCdmVideoFormat(
    181     PP_DecryptedFrameFormat format) {
    182   switch (format) {
    183     case PP_DECRYPTEDFRAMEFORMAT_YV12:
    184       return cdm::kYv12;
    185     case PP_DECRYPTEDFRAMEFORMAT_I420:
    186       return cdm::kI420;
    187     default:
    188       return cdm::kUnknownVideoFormat;
    189   }
    190 }
    191 
    192 cdm::StreamType PpDecryptorStreamTypeToCdmStreamType(
    193     PP_DecryptorStreamType stream_type) {
    194   switch (stream_type) {
    195     case PP_DECRYPTORSTREAMTYPE_AUDIO:
    196       return cdm::kStreamTypeAudio;
    197     case PP_DECRYPTORSTREAMTYPE_VIDEO:
    198       return cdm::kStreamTypeVideo;
    199   }
    200 
    201   PP_NOTREACHED();
    202   return cdm::kStreamTypeVideo;
    203 }
    204 
    205 }  // namespace
    206 
    207 namespace media {
    208 
    209 // cdm::Buffer implementation that provides access to memory owned by a
    210 // pp::Buffer_Dev.
    211 // This class holds a reference to the Buffer_Dev throughout its lifetime.
    212 // TODO(xhwang): Find a better name. It's confusing to have PpbBuffer,
    213 // pp::Buffer_Dev and PPB_Buffer_Dev.
    214 class PpbBuffer : public cdm::Buffer {
    215  public:
    216   static PpbBuffer* Create(const pp::Buffer_Dev& buffer, uint32_t buffer_id) {
    217     PP_DCHECK(buffer.data());
    218     PP_DCHECK(buffer.size());
    219     PP_DCHECK(buffer_id);
    220     return new PpbBuffer(buffer, buffer_id);
    221   }
    222 
    223   // cdm::Buffer implementation.
    224   virtual void Destroy() OVERRIDE { delete this; }
    225 
    226   virtual int32_t Capacity() const OVERRIDE { return buffer_.size(); }
    227 
    228   virtual uint8_t* Data() OVERRIDE {
    229     return static_cast<uint8_t*>(buffer_.data());
    230   }
    231 
    232   virtual void SetSize(int32_t size) OVERRIDE {
    233     PP_DCHECK(size >= 0);
    234     PP_DCHECK(size < Capacity());
    235     if (size < 0 || size > Capacity()) {
    236       size_ = 0;
    237       return;
    238     }
    239 
    240     size_ = size;
    241   }
    242 
    243   virtual int32_t Size() const OVERRIDE { return size_; }
    244 
    245   pp::Buffer_Dev buffer_dev() const { return buffer_; }
    246 
    247   uint32_t buffer_id() const { return buffer_id_; }
    248 
    249  private:
    250   PpbBuffer(pp::Buffer_Dev buffer, uint32_t buffer_id)
    251       : buffer_(buffer),
    252         buffer_id_(buffer_id),
    253         size_(0) {}
    254   virtual ~PpbBuffer() {}
    255 
    256   pp::Buffer_Dev buffer_;
    257   uint32_t buffer_id_;
    258   int32_t size_;
    259 
    260   DISALLOW_COPY_AND_ASSIGN(PpbBuffer);
    261 };
    262 
    263 class PpbBufferAllocator {
    264  public:
    265   explicit PpbBufferAllocator(pp::Instance* instance)
    266       : instance_(instance),
    267         next_buffer_id_(1) {}
    268   ~PpbBufferAllocator() {}
    269 
    270   cdm::Buffer* Allocate(int32_t capacity);
    271 
    272   // Releases the buffer with |buffer_id|. A buffer can be recycled after
    273   // it is released.
    274   void Release(uint32_t buffer_id);
    275 
    276  private:
    277   typedef std::map<uint32_t, pp::Buffer_Dev> AllocatedBufferMap;
    278   typedef std::multimap<int, std::pair<uint32_t, pp::Buffer_Dev> >
    279       FreeBufferMap;
    280 
    281   // Always pad new allocated buffer so that we don't need to reallocate
    282   // buffers frequently if requested sizes fluctuate slightly.
    283   static const int kBufferPadding = 512;
    284 
    285   // Maximum number of free buffers we can keep when allocating new buffers.
    286   static const int kFreeLimit = 3;
    287 
    288   pp::Buffer_Dev AllocateNewBuffer(int capacity);
    289 
    290   pp::Instance* const instance_;
    291   uint32_t next_buffer_id_;
    292   AllocatedBufferMap allocated_buffers_;
    293   FreeBufferMap free_buffers_;
    294 
    295   DISALLOW_COPY_AND_ASSIGN(PpbBufferAllocator);
    296 };
    297 
    298 cdm::Buffer* PpbBufferAllocator::Allocate(int32_t capacity) {
    299   PP_DCHECK(IsMainThread());
    300 
    301   if (capacity <= 0)
    302     return NULL;
    303 
    304   pp::Buffer_Dev buffer;
    305   uint32_t buffer_id = 0;
    306 
    307   // Reuse a buffer in the free list if there is one that fits |capacity|.
    308   // Otherwise, create a new one.
    309   FreeBufferMap::iterator found = free_buffers_.lower_bound(capacity);
    310   if (found == free_buffers_.end()) {
    311     // TODO(xhwang): Report statistics about how many new buffers are allocated.
    312     buffer = AllocateNewBuffer(capacity);
    313     if (buffer.is_null())
    314       return NULL;
    315     buffer_id = next_buffer_id_++;
    316   } else {
    317     buffer = found->second.second;
    318     buffer_id = found->second.first;
    319     free_buffers_.erase(found);
    320   }
    321 
    322   allocated_buffers_.insert(std::make_pair(buffer_id, buffer));
    323 
    324   return PpbBuffer::Create(buffer, buffer_id);
    325 }
    326 
    327 void PpbBufferAllocator::Release(uint32_t buffer_id) {
    328   if (!buffer_id)
    329     return;
    330 
    331   AllocatedBufferMap::iterator found = allocated_buffers_.find(buffer_id);
    332   if (found == allocated_buffers_.end())
    333     return;
    334 
    335   pp::Buffer_Dev& buffer = found->second;
    336   free_buffers_.insert(
    337       std::make_pair(buffer.size(), std::make_pair(buffer_id, buffer)));
    338 
    339   allocated_buffers_.erase(found);
    340 }
    341 
    342 pp::Buffer_Dev PpbBufferAllocator::AllocateNewBuffer(int32_t capacity) {
    343   // Destroy the smallest buffer before allocating a new bigger buffer if the
    344   // number of free buffers exceeds a limit. This mechanism helps avoid ending
    345   // up with too many small buffers, which could happen if the size to be
    346   // allocated keeps increasing.
    347   if (free_buffers_.size() >= static_cast<uint32_t>(kFreeLimit))
    348     free_buffers_.erase(free_buffers_.begin());
    349 
    350   // Creation of pp::Buffer_Dev is expensive! It involves synchronous IPC calls.
    351   // That's why we try to avoid AllocateNewBuffer() as much as we can.
    352   return pp::Buffer_Dev(instance_, capacity + kBufferPadding);
    353 }
    354 
    355 class DecryptedBlockImpl : public cdm::DecryptedBlock {
    356  public:
    357   DecryptedBlockImpl() : buffer_(NULL), timestamp_(0) {}
    358   virtual ~DecryptedBlockImpl() { if (buffer_) buffer_->Destroy(); }
    359 
    360   virtual void SetDecryptedBuffer(cdm::Buffer* buffer) OVERRIDE {
    361     buffer_ = static_cast<PpbBuffer*>(buffer);
    362   }
    363   virtual cdm::Buffer* DecryptedBuffer() OVERRIDE { return buffer_; }
    364 
    365   virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
    366     timestamp_ = timestamp;
    367   }
    368   virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
    369 
    370  private:
    371   PpbBuffer* buffer_;
    372   int64_t timestamp_;
    373 
    374   DISALLOW_COPY_AND_ASSIGN(DecryptedBlockImpl);
    375 };
    376 
    377 class VideoFrameImpl : public cdm::VideoFrame {
    378  public:
    379   VideoFrameImpl();
    380   virtual ~VideoFrameImpl();
    381 
    382   virtual void SetFormat(cdm::VideoFormat format) OVERRIDE {
    383     format_ = format;
    384   }
    385   virtual cdm::VideoFormat Format() const OVERRIDE { return format_; }
    386 
    387   virtual void SetSize(cdm::Size size) OVERRIDE { size_ = size; }
    388   virtual cdm::Size Size() const OVERRIDE { return size_; }
    389 
    390   virtual void SetFrameBuffer(cdm::Buffer* frame_buffer) OVERRIDE {
    391     frame_buffer_ = static_cast<PpbBuffer*>(frame_buffer);
    392   }
    393   virtual cdm::Buffer* FrameBuffer() OVERRIDE { return frame_buffer_; }
    394 
    395   virtual void SetPlaneOffset(cdm::VideoFrame::VideoPlane plane,
    396                               int32_t offset) OVERRIDE {
    397     PP_DCHECK(0 <= plane && plane < kMaxPlanes);
    398     PP_DCHECK(offset >= 0);
    399     plane_offsets_[plane] = offset;
    400   }
    401   virtual int32_t PlaneOffset(VideoPlane plane) OVERRIDE {
    402     PP_DCHECK(0 <= plane && plane < kMaxPlanes);
    403     return plane_offsets_[plane];
    404   }
    405 
    406   virtual void SetStride(VideoPlane plane, int32_t stride) OVERRIDE {
    407     PP_DCHECK(0 <= plane && plane < kMaxPlanes);
    408     strides_[plane] = stride;
    409   }
    410   virtual int32_t Stride(VideoPlane plane) OVERRIDE {
    411     PP_DCHECK(0 <= plane && plane < kMaxPlanes);
    412     return strides_[plane];
    413   }
    414 
    415   virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
    416     timestamp_ = timestamp;
    417   }
    418   virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
    419 
    420  private:
    421   // The video buffer format.
    422   cdm::VideoFormat format_;
    423 
    424   // Width and height of the video frame.
    425   cdm::Size size_;
    426 
    427   // The video frame buffer.
    428   PpbBuffer* frame_buffer_;
    429 
    430   // Array of data pointers to each plane in the video frame buffer.
    431   int32_t plane_offsets_[kMaxPlanes];
    432 
    433   // Array of strides for each plane, typically greater or equal to the width
    434   // of the surface divided by the horizontal sampling period.  Note that
    435   // strides can be negative.
    436   int32_t strides_[kMaxPlanes];
    437 
    438   // Presentation timestamp in microseconds.
    439   int64_t timestamp_;
    440 
    441   DISALLOW_COPY_AND_ASSIGN(VideoFrameImpl);
    442 };
    443 
    444 VideoFrameImpl::VideoFrameImpl()
    445     : format_(cdm::kUnknownVideoFormat),
    446       frame_buffer_(NULL),
    447       timestamp_(0) {
    448   for (int32_t i = 0; i < kMaxPlanes; ++i) {
    449     plane_offsets_[i] = 0;
    450     strides_[i] = 0;
    451   }
    452 }
    453 
    454 VideoFrameImpl::~VideoFrameImpl() {
    455   if (frame_buffer_)
    456     frame_buffer_->Destroy();
    457 }
    458 
    459 class AudioFramesImpl : public cdm::AudioFrames {
    460  public:
    461   AudioFramesImpl() : buffer_(NULL) {}
    462   virtual ~AudioFramesImpl() {
    463     if (buffer_)
    464       buffer_->Destroy();
    465   }
    466 
    467   // AudioFrames implementation.
    468   virtual void SetFrameBuffer(cdm::Buffer* buffer) OVERRIDE {
    469     buffer_ = static_cast<PpbBuffer*>(buffer);
    470   }
    471   virtual cdm::Buffer* FrameBuffer() OVERRIDE {
    472     return buffer_;
    473   }
    474 
    475  private:
    476   PpbBuffer* buffer_;
    477 
    478   DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl);
    479 };
    480 
    481 // GetCdmHostFunc implementation.
    482 void* GetCdmHost(int host_interface_version, void* user_data);
    483 
    484 // A wrapper class for abstracting away PPAPI interaction and threading for a
    485 // Content Decryption Module (CDM).
    486 class CdmWrapper : public pp::Instance,
    487                    public pp::ContentDecryptor_Private,
    488                    public cdm::Host {
    489  public:
    490   CdmWrapper(PP_Instance instance, pp::Module* module);
    491   virtual ~CdmWrapper();
    492 
    493   // pp::Instance implementation.
    494   virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
    495     return true;
    496   }
    497 
    498   // PPP_ContentDecryptor_Private implementation.
    499   // Note: Results of calls to these methods must be reported through the
    500   // PPB_ContentDecryptor_Private interface.
    501   virtual void GenerateKeyRequest(const std::string& key_system,
    502                                   const std::string& type,
    503                                   pp::VarArrayBuffer init_data) OVERRIDE;
    504   virtual void AddKey(const std::string& session_id,
    505                       pp::VarArrayBuffer key,
    506                       pp::VarArrayBuffer init_data) OVERRIDE;
    507   virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE;
    508   virtual void Decrypt(
    509       pp::Buffer_Dev encrypted_buffer,
    510       const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
    511   virtual void InitializeAudioDecoder(
    512       const PP_AudioDecoderConfig& decoder_config,
    513       pp::Buffer_Dev extra_data_buffer) OVERRIDE;
    514   virtual void InitializeVideoDecoder(
    515       const PP_VideoDecoderConfig& decoder_config,
    516       pp::Buffer_Dev extra_data_buffer) OVERRIDE;
    517   virtual void DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
    518                                    uint32_t request_id) OVERRIDE;
    519   virtual void ResetDecoder(PP_DecryptorStreamType decoder_type,
    520                             uint32_t request_id) OVERRIDE;
    521   virtual void DecryptAndDecode(
    522       PP_DecryptorStreamType decoder_type,
    523       pp::Buffer_Dev encrypted_buffer,
    524       const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
    525 
    526   // cdm::Host implementation.
    527   virtual cdm::Buffer* Allocate(int32_t capacity) OVERRIDE;
    528   virtual void SetTimer(int64_t delay_ms, void* context) OVERRIDE;
    529   virtual double GetCurrentWallTimeInSeconds() OVERRIDE;
    530   virtual void SendKeyMessage(
    531       const char* session_id, int32_t session_id_length,
    532       const char* message, int32_t message_length,
    533       const char* default_url, int32_t default_url_length) OVERRIDE;
    534   virtual void SendKeyError(const char* session_id,
    535                             int32_t session_id_length,
    536                             cdm::MediaKeyError error_code,
    537                             uint32_t system_code) OVERRIDE;
    538   virtual void GetPrivateData(int32_t* instance,
    539                               GetPrivateInterface* get_interface) OVERRIDE;
    540 
    541  private:
    542   struct SessionInfo {
    543     SessionInfo(const std::string& key_system_in,
    544                 const std::string& session_id_in)
    545         : key_system(key_system_in),
    546           session_id(session_id_in) {}
    547     const std::string key_system;
    548     const std::string session_id;
    549   };
    550 
    551   typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock;
    552   typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame;
    553   typedef linked_ptr<AudioFramesImpl> LinkedAudioFrames;
    554 
    555   bool CreateCdmInstance(const std::string& key_system);
    556 
    557   void SendUnknownKeyError(const std::string& key_system,
    558                            const std::string& session_id);
    559 
    560   void SendKeyAdded(const std::string& key_system,
    561                     const std::string& session_id);
    562 
    563   void SendKeyErrorInternal(const std::string& key_system,
    564                             const std::string& session_id,
    565                             cdm::MediaKeyError error_code,
    566                             uint32_t system_code);
    567 
    568   // <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to
    569   // <code>callback_factory_</code> to ensure that calls into
    570   // <code>PPP_ContentDecryptor_Private</code> are asynchronous.
    571   void KeyAdded(int32_t result, const SessionInfo& session_info);
    572   void KeyMessage(int32_t result,
    573                   const SessionInfo& session_info,
    574                   const std::vector<uint8>& message,
    575                   const std::string& default_url);
    576   void KeyError(int32_t result,
    577                 const SessionInfo& session_info,
    578                 cdm::MediaKeyError error_code,
    579                 uint32_t system_code);
    580   void DeliverBlock(int32_t result,
    581                     const cdm::Status& status,
    582                     const LinkedDecryptedBlock& decrypted_block,
    583                     const PP_DecryptTrackingInfo& tracking_info);
    584   void DecoderInitializeDone(int32_t result,
    585                              PP_DecryptorStreamType decoder_type,
    586                              uint32_t request_id,
    587                              bool success);
    588   void DecoderDeinitializeDone(int32_t result,
    589                                PP_DecryptorStreamType decoder_type,
    590                                uint32_t request_id);
    591   void DecoderResetDone(int32_t result,
    592                         PP_DecryptorStreamType decoder_type,
    593                         uint32_t request_id);
    594   void DeliverFrame(int32_t result,
    595                     const cdm::Status& status,
    596                     const LinkedVideoFrame& video_frame,
    597                     const PP_DecryptTrackingInfo& tracking_info);
    598   void DeliverSamples(int32_t result,
    599                       const cdm::Status& status,
    600                       const LinkedAudioFrames& audio_frames,
    601                       const PP_DecryptTrackingInfo& tracking_info);
    602 
    603   // Helper for SetTimer().
    604   void TimerExpired(int32_t result, void* context);
    605 
    606   bool IsValidVideoFrame(const LinkedVideoFrame& video_frame);
    607 
    608   PpbBufferAllocator allocator_;
    609   pp::CompletionCallbackFactory<CdmWrapper> callback_factory_;
    610   cdm::ContentDecryptionModule* cdm_;
    611   std::string key_system_;
    612 
    613   DISALLOW_COPY_AND_ASSIGN(CdmWrapper);
    614 };
    615 
    616 CdmWrapper::CdmWrapper(PP_Instance instance, pp::Module* module)
    617     : pp::Instance(instance),
    618       pp::ContentDecryptor_Private(this),
    619       allocator_(this),
    620       cdm_(NULL) {
    621   callback_factory_.Initialize(this);
    622 }
    623 
    624 CdmWrapper::~CdmWrapper() {
    625   if (cdm_)
    626     cdm_->Destroy();
    627 }
    628 
    629 bool CdmWrapper::CreateCdmInstance(const std::string& key_system) {
    630   PP_DCHECK(!cdm_);
    631   cdm_ = static_cast<cdm::ContentDecryptionModule*>(
    632       ::CreateCdmInstance(cdm::kCdmInterfaceVersion,
    633                           key_system.data(), key_system.size(),
    634                           GetCdmHost, this));
    635 
    636   return (cdm_ != NULL);
    637 }
    638 
    639 void CdmWrapper::GenerateKeyRequest(const std::string& key_system,
    640                                     const std::string& type,
    641                                     pp::VarArrayBuffer init_data) {
    642   PP_DCHECK(!key_system.empty());
    643   PP_DCHECK(key_system_.empty() || key_system_ == key_system);
    644 
    645 #if defined(CHECK_DOCUMENT_URL)
    646   PP_URLComponents_Dev url_components = {};
    647   pp::Var href = pp::URLUtil_Dev::Get()->GetDocumentURL(
    648       pp::InstanceHandle(pp_instance()), &url_components);
    649   PP_DCHECK(href.is_string());
    650   PP_DCHECK(!href.AsString().empty());
    651   PP_DCHECK(url_components.host.begin);
    652   PP_DCHECK(0 < url_components.host.len);
    653 #endif  // defined(CHECK_DOCUMENT_URL)
    654 
    655   if (!cdm_) {
    656     if (!CreateCdmInstance(key_system)) {
    657       SendUnknownKeyError(key_system, std::string());
    658       return;
    659     }
    660   }
    661   PP_DCHECK(cdm_);
    662 
    663   // Must be set here in case the CDM synchronously calls a cdm::Host method.
    664   // Clear below on error.
    665   // TODO(ddorwin): Set/clear key_system_ & cdm_ at same time; clear both on
    666   // error below.
    667   key_system_ = key_system;
    668   cdm::Status status = cdm_->GenerateKeyRequest(
    669       type.data(), type.size(),
    670       static_cast<const uint8_t*>(init_data.Map()),
    671       init_data.ByteLength());
    672   PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
    673   if (status != cdm::kSuccess) {
    674     key_system_.clear();  // See comment above.
    675     return;
    676   }
    677 
    678   key_system_ = key_system;
    679 }
    680 
    681 void CdmWrapper::AddKey(const std::string& session_id,
    682                         pp::VarArrayBuffer key,
    683                         pp::VarArrayBuffer init_data) {
    684   PP_DCHECK(cdm_);  // GenerateKeyRequest() should have succeeded.
    685   if (!cdm_) {
    686     SendUnknownKeyError(key_system_, session_id);
    687     return;
    688   }
    689 
    690   const uint8_t* key_ptr = static_cast<const uint8_t*>(key.Map());
    691   int key_size = key.ByteLength();
    692   const uint8_t* init_data_ptr = static_cast<const uint8_t*>(init_data.Map());
    693   int init_data_size = init_data.ByteLength();
    694   PP_DCHECK(!init_data_ptr == !init_data_size);
    695 
    696   if (!key_ptr || key_size <= 0) {
    697     SendUnknownKeyError(key_system_, session_id);
    698     return;
    699   }
    700 
    701   cdm::Status status = cdm_->AddKey(session_id.data(), session_id.size(),
    702                                     key_ptr, key_size,
    703                                     init_data_ptr, init_data_size);
    704   PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
    705   if (status != cdm::kSuccess) {
    706     SendUnknownKeyError(key_system_, session_id);
    707     return;
    708   }
    709 
    710   SendKeyAdded(key_system_, session_id);
    711 }
    712 
    713 void CdmWrapper::CancelKeyRequest(const std::string& session_id) {
    714   PP_DCHECK(cdm_);  // GenerateKeyRequest() should have succeeded.
    715   if (!cdm_) {
    716     SendUnknownKeyError(key_system_, session_id);
    717     return;
    718   }
    719 
    720   cdm::Status status = cdm_->CancelKeyRequest(session_id.data(),
    721                                               session_id.size());
    722   PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
    723   if (status != cdm::kSuccess)
    724     SendUnknownKeyError(key_system_, session_id);
    725 }
    726 
    727 // Note: In the following decryption/decoding related functions, errors are NOT
    728 // reported via KeyError, but are reported via corresponding PPB calls.
    729 
    730 void CdmWrapper::Decrypt(pp::Buffer_Dev encrypted_buffer,
    731                          const PP_EncryptedBlockInfo& encrypted_block_info) {
    732   PP_DCHECK(cdm_);  // GenerateKeyRequest() should have succeeded.
    733   PP_DCHECK(!encrypted_buffer.is_null());
    734 
    735   // Release a buffer that the caller indicated it is finished with.
    736   allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
    737 
    738   cdm::Status status = cdm::kDecryptError;
    739   LinkedDecryptedBlock decrypted_block(new DecryptedBlockImpl());
    740 
    741   if (cdm_) {
    742     cdm::InputBuffer input_buffer;
    743     std::vector<cdm::SubsampleEntry> subsamples;
    744     ConfigureInputBuffer(encrypted_buffer, encrypted_block_info, &subsamples,
    745                          &input_buffer);
    746     status = cdm_->Decrypt(input_buffer, decrypted_block.get());
    747     PP_DCHECK(status != cdm::kSuccess ||
    748               (decrypted_block->DecryptedBuffer() &&
    749                decrypted_block->DecryptedBuffer()->Size()));
    750   }
    751 
    752   CallOnMain(callback_factory_.NewCallback(
    753       &CdmWrapper::DeliverBlock,
    754       status,
    755       decrypted_block,
    756       encrypted_block_info.tracking_info));
    757 }
    758 
    759 void CdmWrapper::InitializeAudioDecoder(
    760     const PP_AudioDecoderConfig& decoder_config,
    761     pp::Buffer_Dev extra_data_buffer) {
    762   PP_DCHECK(cdm_);  // GenerateKeyRequest() should have succeeded.
    763 
    764   cdm::Status status = cdm::kSessionError;
    765   if (cdm_) {
    766     cdm::AudioDecoderConfig cdm_decoder_config;
    767     cdm_decoder_config.codec =
    768         PpAudioCodecToCdmAudioCodec(decoder_config.codec);
    769     cdm_decoder_config.channel_count = decoder_config.channel_count;
    770     cdm_decoder_config.bits_per_channel = decoder_config.bits_per_channel;
    771     cdm_decoder_config.samples_per_second = decoder_config.samples_per_second;
    772     cdm_decoder_config.extra_data =
    773         static_cast<uint8_t*>(extra_data_buffer.data());
    774     cdm_decoder_config.extra_data_size =
    775         static_cast<int32_t>(extra_data_buffer.size());
    776     status = cdm_->InitializeAudioDecoder(cdm_decoder_config);
    777   }
    778 
    779   CallOnMain(callback_factory_.NewCallback(
    780       &CdmWrapper::DecoderInitializeDone,
    781       PP_DECRYPTORSTREAMTYPE_AUDIO,
    782       decoder_config.request_id,
    783       status == cdm::kSuccess));
    784 }
    785 
    786 void CdmWrapper::InitializeVideoDecoder(
    787     const PP_VideoDecoderConfig& decoder_config,
    788     pp::Buffer_Dev extra_data_buffer) {
    789   PP_DCHECK(cdm_);  // GenerateKeyRequest() should have succeeded.
    790 
    791   cdm::Status status = cdm::kSessionError;
    792   if (cdm_) {
    793     cdm::VideoDecoderConfig cdm_decoder_config;
    794     cdm_decoder_config.codec =
    795         PpVideoCodecToCdmVideoCodec(decoder_config.codec);
    796     cdm_decoder_config.profile =
    797         PpVCProfileToCdmVCProfile(decoder_config.profile);
    798     cdm_decoder_config.format =
    799         PpDecryptedFrameFormatToCdmVideoFormat(decoder_config.format);
    800     cdm_decoder_config.coded_size.width = decoder_config.width;
    801     cdm_decoder_config.coded_size.height = decoder_config.height;
    802     cdm_decoder_config.extra_data =
    803         static_cast<uint8_t*>(extra_data_buffer.data());
    804     cdm_decoder_config.extra_data_size =
    805         static_cast<int32_t>(extra_data_buffer.size());
    806     status = cdm_->InitializeVideoDecoder(cdm_decoder_config);
    807   }
    808 
    809   CallOnMain(callback_factory_.NewCallback(
    810       &CdmWrapper::DecoderInitializeDone,
    811       PP_DECRYPTORSTREAMTYPE_VIDEO,
    812       decoder_config.request_id,
    813       status == cdm::kSuccess));
    814 }
    815 
    816 void CdmWrapper::DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
    817                                      uint32_t request_id) {
    818   PP_DCHECK(cdm_);  // GenerateKeyRequest() should have succeeded.
    819   if (cdm_) {
    820     cdm_->DeinitializeDecoder(
    821         PpDecryptorStreamTypeToCdmStreamType(decoder_type));
    822   }
    823 
    824   CallOnMain(callback_factory_.NewCallback(
    825       &CdmWrapper::DecoderDeinitializeDone,
    826       decoder_type,
    827       request_id));
    828 }
    829 
    830 void CdmWrapper::ResetDecoder(PP_DecryptorStreamType decoder_type,
    831                               uint32_t request_id) {
    832   PP_DCHECK(cdm_);  // GenerateKeyRequest() should have succeeded.
    833   if (cdm_)
    834     cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type));
    835 
    836   CallOnMain(callback_factory_.NewCallback(&CdmWrapper::DecoderResetDone,
    837                                            decoder_type,
    838                                            request_id));
    839 }
    840 
    841 void CdmWrapper::DecryptAndDecode(
    842     PP_DecryptorStreamType decoder_type,
    843     pp::Buffer_Dev encrypted_buffer,
    844     const PP_EncryptedBlockInfo& encrypted_block_info) {
    845   PP_DCHECK(cdm_);  // GenerateKeyRequest() should have succeeded.
    846 
    847   // Release a buffer that the caller indicated it is finished with.
    848   allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
    849 
    850   cdm::InputBuffer input_buffer;
    851   std::vector<cdm::SubsampleEntry> subsamples;
    852   if (cdm_ && !encrypted_buffer.is_null()) {
    853     ConfigureInputBuffer(encrypted_buffer,
    854                          encrypted_block_info,
    855                          &subsamples,
    856                          &input_buffer);
    857   }
    858 
    859   cdm::Status status = cdm::kDecodeError;
    860 
    861   switch (decoder_type) {
    862     case PP_DECRYPTORSTREAMTYPE_VIDEO: {
    863       LinkedVideoFrame video_frame(new VideoFrameImpl());
    864       if (cdm_)
    865         status = cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get());
    866       CallOnMain(callback_factory_.NewCallback(
    867           &CdmWrapper::DeliverFrame,
    868           status,
    869           video_frame,
    870           encrypted_block_info.tracking_info));
    871       return;
    872     }
    873 
    874     case PP_DECRYPTORSTREAMTYPE_AUDIO: {
    875       LinkedAudioFrames audio_frames(new AudioFramesImpl());
    876       if (cdm_) {
    877         status = cdm_->DecryptAndDecodeSamples(input_buffer,
    878                                                audio_frames.get());
    879       }
    880       CallOnMain(callback_factory_.NewCallback(
    881           &CdmWrapper::DeliverSamples,
    882           status,
    883           audio_frames,
    884           encrypted_block_info.tracking_info));
    885       return;
    886     }
    887 
    888     default:
    889       PP_NOTREACHED();
    890       return;
    891   }
    892 }
    893 
    894 cdm::Buffer* CdmWrapper::Allocate(int32_t capacity) {
    895   return allocator_.Allocate(capacity);
    896 }
    897 
    898 void CdmWrapper::SetTimer(int64_t delay_ms, void* context) {
    899   // NOTE: doesn't really need to run on the main thread; could just as well run
    900   // on a helper thread if |cdm_| were thread-friendly and care was taken.  We
    901   // only use CallOnMainThread() here to get delayed-execution behavior.
    902   pp::Module::Get()->core()->CallOnMainThread(
    903       delay_ms,
    904       callback_factory_.NewCallback(&CdmWrapper::TimerExpired, context),
    905       PP_OK);
    906 }
    907 
    908 void CdmWrapper::TimerExpired(int32_t result, void* context) {
    909   PP_DCHECK(result == PP_OK);
    910   cdm_->TimerExpired(context);
    911 }
    912 
    913 double CdmWrapper::GetCurrentWallTimeInSeconds() {
    914   return pp::Module::Get()->core()->GetTime();
    915 }
    916 
    917 void CdmWrapper::SendKeyMessage(
    918     const char* session_id, int32_t session_id_length,
    919     const char* message, int32_t message_length,
    920     const char* default_url, int32_t default_url_length) {
    921   PP_DCHECK(!key_system_.empty());
    922   PostOnMain(callback_factory_.NewCallback(
    923       &CdmWrapper::KeyMessage,
    924       SessionInfo(key_system_,
    925                   std::string(session_id, session_id_length)),
    926       std::vector<uint8>(message, message + message_length),
    927       std::string(default_url, default_url_length)));
    928 }
    929 
    930 void CdmWrapper::SendKeyError(const char* session_id,
    931                               int32_t session_id_length,
    932                               cdm::MediaKeyError error_code,
    933                               uint32_t system_code) {
    934   SendKeyErrorInternal(key_system_,
    935                        std::string(session_id, session_id_length),
    936                        error_code,
    937                        system_code);
    938 }
    939 
    940 void CdmWrapper::GetPrivateData(int32_t* instance,
    941                                 cdm::Host::GetPrivateInterface* get_interface) {
    942   *instance = pp_instance();
    943   *get_interface = pp::Module::Get()->get_browser_interface();
    944 }
    945 
    946 void CdmWrapper::SendUnknownKeyError(const std::string& key_system,
    947                                      const std::string& session_id) {
    948   SendKeyErrorInternal(key_system, session_id, cdm::kUnknownError, 0);
    949 }
    950 
    951 void CdmWrapper::SendKeyAdded(const std::string& key_system,
    952                               const std::string& session_id) {
    953   PostOnMain(callback_factory_.NewCallback(
    954       &CdmWrapper::KeyAdded,
    955       SessionInfo(key_system_, session_id)));
    956 }
    957 
    958 void CdmWrapper::SendKeyErrorInternal(const std::string& key_system,
    959                                       const std::string& session_id,
    960                                       cdm::MediaKeyError error_code,
    961                                       uint32_t system_code) {
    962   PP_DCHECK(!key_system.empty());
    963   PostOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyError,
    964                                            SessionInfo(key_system_, session_id),
    965                                            error_code,
    966                                            system_code));
    967 }
    968 
    969 void CdmWrapper::KeyAdded(int32_t result, const SessionInfo& session_info) {
    970   PP_DCHECK(result == PP_OK);
    971   PP_DCHECK(!session_info.key_system.empty());
    972   pp::ContentDecryptor_Private::KeyAdded(session_info.key_system,
    973                                          session_info.session_id);
    974 }
    975 
    976 void CdmWrapper::KeyMessage(int32_t result,
    977                             const SessionInfo& session_info,
    978                             const std::vector<uint8>& message,
    979                             const std::string& default_url) {
    980   PP_DCHECK(result == PP_OK);
    981   PP_DCHECK(!session_info.key_system.empty());
    982 
    983   pp::VarArrayBuffer message_array_buffer(message.size());
    984   if (message.size() > 0) {
    985     memcpy(message_array_buffer.Map(), message.data(), message.size());
    986   }
    987 
    988   pp::ContentDecryptor_Private::KeyMessage(
    989       session_info.key_system, session_info.session_id,
    990       message_array_buffer, default_url);
    991 }
    992 
    993 void CdmWrapper::KeyError(int32_t result,
    994                           const SessionInfo& session_info,
    995                           cdm::MediaKeyError error_code,
    996                           uint32_t system_code) {
    997   PP_DCHECK(result == PP_OK);
    998   PP_DCHECK(!session_info.key_system.empty());
    999   pp::ContentDecryptor_Private::KeyError(
   1000       session_info.key_system, session_info.session_id,
   1001       error_code, system_code);
   1002 }
   1003 
   1004 void CdmWrapper::DeliverBlock(int32_t result,
   1005                               const cdm::Status& status,
   1006                               const LinkedDecryptedBlock& decrypted_block,
   1007                               const PP_DecryptTrackingInfo& tracking_info) {
   1008   PP_DCHECK(result == PP_OK);
   1009   PP_DecryptedBlockInfo decrypted_block_info;
   1010   decrypted_block_info.tracking_info = tracking_info;
   1011   decrypted_block_info.tracking_info.timestamp = decrypted_block->Timestamp();
   1012   decrypted_block_info.tracking_info.buffer_id = 0;
   1013   decrypted_block_info.data_size = 0;
   1014   decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
   1015 
   1016   pp::Buffer_Dev buffer;
   1017 
   1018   if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
   1019     PP_DCHECK(decrypted_block.get() && decrypted_block->DecryptedBuffer());
   1020     if (!decrypted_block.get() || !decrypted_block->DecryptedBuffer()) {
   1021       PP_NOTREACHED();
   1022       decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
   1023     } else {
   1024       PpbBuffer* ppb_buffer =
   1025           static_cast<PpbBuffer*>(decrypted_block->DecryptedBuffer());
   1026       buffer = ppb_buffer->buffer_dev();
   1027       decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
   1028       decrypted_block_info.data_size = ppb_buffer->Size();
   1029     }
   1030   }
   1031 
   1032   pp::ContentDecryptor_Private::DeliverBlock(buffer, decrypted_block_info);
   1033 }
   1034 
   1035 void CdmWrapper::DecoderInitializeDone(int32_t result,
   1036                                        PP_DecryptorStreamType decoder_type,
   1037                                        uint32_t request_id,
   1038                                        bool success) {
   1039   PP_DCHECK(result == PP_OK);
   1040   pp::ContentDecryptor_Private::DecoderInitializeDone(decoder_type,
   1041                                                       request_id,
   1042                                                       success);
   1043 }
   1044 
   1045 void CdmWrapper::DecoderDeinitializeDone(int32_t result,
   1046                                          PP_DecryptorStreamType decoder_type,
   1047                                          uint32_t request_id) {
   1048   pp::ContentDecryptor_Private::DecoderDeinitializeDone(decoder_type,
   1049                                                         request_id);
   1050 }
   1051 
   1052 void CdmWrapper::DecoderResetDone(int32_t result,
   1053                                   PP_DecryptorStreamType decoder_type,
   1054                                   uint32_t request_id) {
   1055   pp::ContentDecryptor_Private::DecoderResetDone(decoder_type, request_id);
   1056 }
   1057 
   1058 void CdmWrapper::DeliverFrame(
   1059     int32_t result,
   1060     const cdm::Status& status,
   1061     const LinkedVideoFrame& video_frame,
   1062     const PP_DecryptTrackingInfo& tracking_info) {
   1063   PP_DCHECK(result == PP_OK);
   1064   PP_DecryptedFrameInfo decrypted_frame_info;
   1065   decrypted_frame_info.tracking_info.request_id = tracking_info.request_id;
   1066   decrypted_frame_info.tracking_info.buffer_id = 0;
   1067   decrypted_frame_info.result = CdmStatusToPpDecryptResult(status);
   1068 
   1069   pp::Buffer_Dev buffer;
   1070 
   1071   if (decrypted_frame_info.result == PP_DECRYPTRESULT_SUCCESS) {
   1072     if (!IsValidVideoFrame(video_frame)) {
   1073       PP_NOTREACHED();
   1074       decrypted_frame_info.result = PP_DECRYPTRESULT_DECODE_ERROR;
   1075     } else {
   1076       PpbBuffer* ppb_buffer =
   1077           static_cast<PpbBuffer*>(video_frame->FrameBuffer());
   1078 
   1079       buffer = ppb_buffer->buffer_dev();
   1080 
   1081       decrypted_frame_info.tracking_info.timestamp = video_frame->Timestamp();
   1082       decrypted_frame_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
   1083       decrypted_frame_info.format =
   1084           CdmVideoFormatToPpDecryptedFrameFormat(video_frame->Format());
   1085       decrypted_frame_info.width = video_frame->Size().width;
   1086       decrypted_frame_info.height = video_frame->Size().height;
   1087       decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y] =
   1088           video_frame->PlaneOffset(cdm::VideoFrame::kYPlane);
   1089       decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_U] =
   1090           video_frame->PlaneOffset(cdm::VideoFrame::kUPlane);
   1091       decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_V] =
   1092           video_frame->PlaneOffset(cdm::VideoFrame::kVPlane);
   1093       decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_Y] =
   1094           video_frame->Stride(cdm::VideoFrame::kYPlane);
   1095       decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_U] =
   1096           video_frame->Stride(cdm::VideoFrame::kUPlane);
   1097       decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_V] =
   1098           video_frame->Stride(cdm::VideoFrame::kVPlane);
   1099     }
   1100   }
   1101   pp::ContentDecryptor_Private::DeliverFrame(buffer, decrypted_frame_info);
   1102 }
   1103 
   1104 void CdmWrapper::DeliverSamples(int32_t result,
   1105                                 const cdm::Status& status,
   1106                                 const LinkedAudioFrames& audio_frames,
   1107                                 const PP_DecryptTrackingInfo& tracking_info) {
   1108   PP_DCHECK(result == PP_OK);
   1109 
   1110   PP_DecryptedBlockInfo decrypted_block_info;
   1111   decrypted_block_info.tracking_info = tracking_info;
   1112   decrypted_block_info.tracking_info.timestamp = 0;
   1113   decrypted_block_info.tracking_info.buffer_id = 0;
   1114   decrypted_block_info.data_size = 0;
   1115   decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
   1116 
   1117   pp::Buffer_Dev buffer;
   1118 
   1119   if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
   1120     PP_DCHECK(audio_frames.get() && audio_frames->FrameBuffer());
   1121     if (!audio_frames.get() || !audio_frames->FrameBuffer()) {
   1122       PP_NOTREACHED();
   1123       decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
   1124     } else {
   1125       PpbBuffer* ppb_buffer =
   1126           static_cast<PpbBuffer*>(audio_frames->FrameBuffer());
   1127       buffer = ppb_buffer->buffer_dev();
   1128       decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
   1129       decrypted_block_info.data_size = ppb_buffer->Size();
   1130     }
   1131   }
   1132 
   1133   pp::ContentDecryptor_Private::DeliverSamples(buffer, decrypted_block_info);
   1134 }
   1135 
   1136 bool CdmWrapper::IsValidVideoFrame(const LinkedVideoFrame& video_frame) {
   1137   if (!video_frame.get() ||
   1138       !video_frame->FrameBuffer() ||
   1139       (video_frame->Format() != cdm::kI420 &&
   1140        video_frame->Format() != cdm::kYv12)) {
   1141     return false;
   1142   }
   1143 
   1144   PpbBuffer* ppb_buffer = static_cast<PpbBuffer*>(video_frame->FrameBuffer());
   1145 
   1146   for (int i = 0; i < cdm::VideoFrame::kMaxPlanes; ++i) {
   1147     int plane_height = (i == cdm::VideoFrame::kYPlane) ?
   1148         video_frame->Size().height : (video_frame->Size().height + 1) / 2;
   1149     cdm::VideoFrame::VideoPlane plane =
   1150         static_cast<cdm::VideoFrame::VideoPlane>(i);
   1151     if (ppb_buffer->Size() < video_frame->PlaneOffset(plane) +
   1152                              plane_height * video_frame->Stride(plane)) {
   1153       return false;
   1154     }
   1155   }
   1156 
   1157   return true;
   1158 }
   1159 
   1160 void* GetCdmHost(int host_interface_version, void* user_data) {
   1161   if (!host_interface_version || !user_data)
   1162     return NULL;
   1163 
   1164   if (host_interface_version != cdm::kHostInterfaceVersion)
   1165     return NULL;
   1166 
   1167   CdmWrapper* cdm_wrapper = static_cast<CdmWrapper*>(user_data);
   1168   return static_cast<cdm::Host*>(cdm_wrapper);
   1169 }
   1170 
   1171 // This object is the global object representing this plugin library as long
   1172 // as it is loaded.
   1173 class CdmWrapperModule : public pp::Module {
   1174  public:
   1175   CdmWrapperModule() : pp::Module() {
   1176     // This function blocks the renderer thread (PluginInstance::Initialize()).
   1177     // Move this call to other places if this may be a concern in the future.
   1178     INITIALIZE_CDM_MODULE();
   1179   }
   1180   virtual ~CdmWrapperModule() {
   1181     DeinitializeCdmModule();
   1182   }
   1183 
   1184   virtual pp::Instance* CreateInstance(PP_Instance instance) {
   1185     return new CdmWrapper(instance, this);
   1186   }
   1187 };
   1188 
   1189 }  // namespace media
   1190 
   1191 namespace pp {
   1192 
   1193 // Factory function for your specialization of the Module object.
   1194 Module* CreateModule() {
   1195   return new media::CdmWrapperModule();
   1196 }
   1197 
   1198 }  // namespace pp
   1199