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