Home | History | Annotate | Download | only in pepper
      1 // Copyright (c) 2012 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 "content/renderer/pepper/content_decryptor_delegate.h"
      6 
      7 #include "base/callback_helpers.h"
      8 #include "base/debug/trace_event.h"
      9 #include "base/message_loop/message_loop_proxy.h"
     10 #include "base/numerics/safe_conversions.h"
     11 #include "content/renderer/pepper/ppb_buffer_impl.h"
     12 #include "media/base/audio_buffer.h"
     13 #include "media/base/audio_decoder_config.h"
     14 #include "media/base/bind_to_current_loop.h"
     15 #include "media/base/cdm_promise.h"
     16 #include "media/base/channel_layout.h"
     17 #include "media/base/data_buffer.h"
     18 #include "media/base/decoder_buffer.h"
     19 #include "media/base/decrypt_config.h"
     20 #include "media/base/video_decoder_config.h"
     21 #include "media/base/video_frame.h"
     22 #include "media/base/video_util.h"
     23 #include "ppapi/shared_impl/scoped_pp_resource.h"
     24 #include "ppapi/shared_impl/var.h"
     25 #include "ppapi/shared_impl/var_tracker.h"
     26 #include "ppapi/thunk/enter.h"
     27 #include "ppapi/thunk/ppb_buffer_api.h"
     28 #include "ui/gfx/rect.h"
     29 
     30 using media::CdmPromise;
     31 using media::Decryptor;
     32 using media::MediaKeys;
     33 using media::NewSessionCdmPromise;
     34 using media::SimpleCdmPromise;
     35 using ppapi::ArrayBufferVar;
     36 using ppapi::PpapiGlobals;
     37 using ppapi::ScopedPPResource;
     38 using ppapi::StringVar;
     39 using ppapi::thunk::EnterResourceNoLock;
     40 using ppapi::thunk::PPB_Buffer_API;
     41 
     42 namespace content {
     43 
     44 namespace {
     45 
     46 // Fills |resource| with a PPB_Buffer_Impl and copies |data| into the buffer
     47 // resource. The |*resource|, if valid, will be in the ResourceTracker with a
     48 // reference-count of 0. If |data| is NULL, sets |*resource| to NULL. Returns
     49 // true upon success and false if any error happened.
     50 bool MakeBufferResource(PP_Instance instance,
     51                         const uint8* data,
     52                         uint32_t size,
     53                         scoped_refptr<PPB_Buffer_Impl>* resource) {
     54   TRACE_EVENT0("media", "ContentDecryptorDelegate - MakeBufferResource");
     55   DCHECK(resource);
     56 
     57   if (!data || !size) {
     58     DCHECK(!data && !size);
     59     resource = NULL;
     60     return true;
     61   }
     62 
     63   scoped_refptr<PPB_Buffer_Impl> buffer(
     64       PPB_Buffer_Impl::CreateResource(instance, size));
     65   if (!buffer.get())
     66     return false;
     67 
     68   BufferAutoMapper mapper(buffer.get());
     69   if (!mapper.data() || mapper.size() < size)
     70     return false;
     71   memcpy(mapper.data(), data, size);
     72 
     73   *resource = buffer;
     74   return true;
     75 }
     76 
     77 // Copies the content of |str| into |array|.
     78 // Returns true if copy succeeded. Returns false if copy failed, e.g. if the
     79 // |array_size| is smaller than the |str| length.
     80 template <uint32_t array_size>
     81 bool CopyStringToArray(const std::string& str, uint8 (&array)[array_size]) {
     82   if (array_size < str.size())
     83     return false;
     84 
     85   memcpy(array, str.data(), str.size());
     86   return true;
     87 }
     88 
     89 // Fills the |block_info| with information from |encrypted_buffer|.
     90 //
     91 // Returns true if |block_info| is successfully filled. Returns false
     92 // otherwise.
     93 static bool MakeEncryptedBlockInfo(
     94     const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
     95     uint32_t request_id,
     96     PP_EncryptedBlockInfo* block_info) {
     97   // TODO(xhwang): Fix initialization of PP_EncryptedBlockInfo here and
     98   // anywhere else.
     99   memset(block_info, 0, sizeof(*block_info));
    100   block_info->tracking_info.request_id = request_id;
    101 
    102   // EOS buffers need a request ID and nothing more.
    103   if (encrypted_buffer->end_of_stream())
    104     return true;
    105 
    106   DCHECK(encrypted_buffer->data_size())
    107       << "DecryptConfig is set on an empty buffer";
    108 
    109   block_info->tracking_info.timestamp =
    110       encrypted_buffer->timestamp().InMicroseconds();
    111   block_info->data_size = encrypted_buffer->data_size();
    112 
    113   const media::DecryptConfig* decrypt_config =
    114       encrypted_buffer->decrypt_config();
    115 
    116   if (!CopyStringToArray(decrypt_config->key_id(), block_info->key_id) ||
    117       !CopyStringToArray(decrypt_config->iv(), block_info->iv))
    118     return false;
    119 
    120   block_info->key_id_size = decrypt_config->key_id().size();
    121   block_info->iv_size = decrypt_config->iv().size();
    122 
    123   if (decrypt_config->subsamples().size() > arraysize(block_info->subsamples))
    124     return false;
    125 
    126   block_info->num_subsamples = decrypt_config->subsamples().size();
    127   for (uint32_t i = 0; i < block_info->num_subsamples; ++i) {
    128     block_info->subsamples[i].clear_bytes =
    129         decrypt_config->subsamples()[i].clear_bytes;
    130     block_info->subsamples[i].cipher_bytes =
    131         decrypt_config->subsamples()[i].cypher_bytes;
    132   }
    133 
    134   return true;
    135 }
    136 
    137 PP_AudioCodec MediaAudioCodecToPpAudioCodec(media::AudioCodec codec) {
    138   switch (codec) {
    139     case media::kCodecVorbis:
    140       return PP_AUDIOCODEC_VORBIS;
    141     case media::kCodecAAC:
    142       return PP_AUDIOCODEC_AAC;
    143     default:
    144       return PP_AUDIOCODEC_UNKNOWN;
    145   }
    146 }
    147 
    148 PP_VideoCodec MediaVideoCodecToPpVideoCodec(media::VideoCodec codec) {
    149   switch (codec) {
    150     case media::kCodecVP8:
    151       return PP_VIDEOCODEC_VP8;
    152     case media::kCodecH264:
    153       return PP_VIDEOCODEC_H264;
    154     case media::kCodecVP9:
    155       return PP_VIDEOCODEC_VP9;
    156     default:
    157       return PP_VIDEOCODEC_UNKNOWN;
    158   }
    159 }
    160 
    161 PP_VideoCodecProfile MediaVideoCodecProfileToPpVideoCodecProfile(
    162     media::VideoCodecProfile profile) {
    163   switch (profile) {
    164     // TODO(xhwang): VP8 and VP9 do not have profiles. Clean up
    165     // media::VideoCodecProfile and remove these two cases.
    166     case media::VP8PROFILE_MAIN:
    167     case media::VP9PROFILE_MAIN:
    168       return PP_VIDEOCODECPROFILE_NOT_NEEDED;
    169     case media::H264PROFILE_BASELINE:
    170       return PP_VIDEOCODECPROFILE_H264_BASELINE;
    171     case media::H264PROFILE_MAIN:
    172       return PP_VIDEOCODECPROFILE_H264_MAIN;
    173     case media::H264PROFILE_EXTENDED:
    174       return PP_VIDEOCODECPROFILE_H264_EXTENDED;
    175     case media::H264PROFILE_HIGH:
    176       return PP_VIDEOCODECPROFILE_H264_HIGH;
    177     case media::H264PROFILE_HIGH10PROFILE:
    178       return PP_VIDEOCODECPROFILE_H264_HIGH_10;
    179     case media::H264PROFILE_HIGH422PROFILE:
    180       return PP_VIDEOCODECPROFILE_H264_HIGH_422;
    181     case media::H264PROFILE_HIGH444PREDICTIVEPROFILE:
    182       return PP_VIDEOCODECPROFILE_H264_HIGH_444_PREDICTIVE;
    183     default:
    184       return PP_VIDEOCODECPROFILE_UNKNOWN;
    185   }
    186 }
    187 
    188 PP_DecryptedFrameFormat MediaVideoFormatToPpDecryptedFrameFormat(
    189     media::VideoFrame::Format format) {
    190   switch (format) {
    191     case media::VideoFrame::YV12:
    192       return PP_DECRYPTEDFRAMEFORMAT_YV12;
    193     case media::VideoFrame::I420:
    194       return PP_DECRYPTEDFRAMEFORMAT_I420;
    195     default:
    196       return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN;
    197   }
    198 }
    199 
    200 Decryptor::Status PpDecryptResultToMediaDecryptorStatus(
    201     PP_DecryptResult result) {
    202   switch (result) {
    203     case PP_DECRYPTRESULT_SUCCESS:
    204       return Decryptor::kSuccess;
    205     case PP_DECRYPTRESULT_DECRYPT_NOKEY:
    206       return Decryptor::kNoKey;
    207     case PP_DECRYPTRESULT_NEEDMOREDATA:
    208       return Decryptor::kNeedMoreData;
    209     case PP_DECRYPTRESULT_DECRYPT_ERROR:
    210       return Decryptor::kError;
    211     case PP_DECRYPTRESULT_DECODE_ERROR:
    212       return Decryptor::kError;
    213     default:
    214       NOTREACHED();
    215       return Decryptor::kError;
    216   }
    217 }
    218 
    219 PP_DecryptorStreamType MediaDecryptorStreamTypeToPpStreamType(
    220     Decryptor::StreamType stream_type) {
    221   switch (stream_type) {
    222     case Decryptor::kAudio:
    223       return PP_DECRYPTORSTREAMTYPE_AUDIO;
    224     case Decryptor::kVideo:
    225       return PP_DECRYPTORSTREAMTYPE_VIDEO;
    226     default:
    227       NOTREACHED();
    228       return PP_DECRYPTORSTREAMTYPE_VIDEO;
    229   }
    230 }
    231 
    232 media::SampleFormat PpDecryptedSampleFormatToMediaSampleFormat(
    233     PP_DecryptedSampleFormat result) {
    234   switch (result) {
    235     case PP_DECRYPTEDSAMPLEFORMAT_U8:
    236       return media::kSampleFormatU8;
    237     case PP_DECRYPTEDSAMPLEFORMAT_S16:
    238       return media::kSampleFormatS16;
    239     case PP_DECRYPTEDSAMPLEFORMAT_S32:
    240       return media::kSampleFormatS32;
    241     case PP_DECRYPTEDSAMPLEFORMAT_F32:
    242       return media::kSampleFormatF32;
    243     case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_S16:
    244       return media::kSampleFormatPlanarS16;
    245     case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_F32:
    246       return media::kSampleFormatPlanarF32;
    247     default:
    248       NOTREACHED();
    249       return media::kUnknownSampleFormat;
    250   }
    251 }
    252 
    253 PP_SessionType MediaSessionTypeToPpSessionType(
    254     MediaKeys::SessionType session_type) {
    255   switch (session_type) {
    256     case MediaKeys::TEMPORARY_SESSION:
    257       return PP_SESSIONTYPE_TEMPORARY;
    258     case MediaKeys::PERSISTENT_SESSION:
    259       return PP_SESSIONTYPE_PERSISTENT;
    260     default:
    261       NOTREACHED();
    262       return PP_SESSIONTYPE_TEMPORARY;
    263   }
    264 }
    265 
    266 MediaKeys::Exception PpExceptionTypeToMediaException(
    267     PP_CdmExceptionCode exception_code) {
    268   switch (exception_code) {
    269     case PP_CDMEXCEPTIONCODE_NOTSUPPORTEDERROR:
    270       return MediaKeys::NOT_SUPPORTED_ERROR;
    271     case PP_CDMEXCEPTIONCODE_INVALIDSTATEERROR:
    272       return MediaKeys::INVALID_STATE_ERROR;
    273     case PP_CDMEXCEPTIONCODE_INVALIDACCESSERROR:
    274       return MediaKeys::INVALID_ACCESS_ERROR;
    275     case PP_CDMEXCEPTIONCODE_QUOTAEXCEEDEDERROR:
    276       return MediaKeys::QUOTA_EXCEEDED_ERROR;
    277     case PP_CDMEXCEPTIONCODE_UNKNOWNERROR:
    278       return MediaKeys::UNKNOWN_ERROR;
    279     case PP_CDMEXCEPTIONCODE_CLIENTERROR:
    280       return MediaKeys::CLIENT_ERROR;
    281     case PP_CDMEXCEPTIONCODE_OUTPUTERROR:
    282       return MediaKeys::OUTPUT_ERROR;
    283     default:
    284       NOTREACHED();
    285       return MediaKeys::UNKNOWN_ERROR;
    286   }
    287 }
    288 
    289 }  // namespace
    290 
    291 ContentDecryptorDelegate::ContentDecryptorDelegate(
    292     PP_Instance pp_instance,
    293     const PPP_ContentDecryptor_Private* plugin_decryption_interface)
    294     : pp_instance_(pp_instance),
    295       plugin_decryption_interface_(plugin_decryption_interface),
    296       next_decryption_request_id_(1),
    297       audio_samples_per_second_(0),
    298       audio_channel_count_(0),
    299       audio_channel_layout_(media::CHANNEL_LAYOUT_NONE),
    300       next_promise_id_(1),
    301       weak_ptr_factory_(this) {
    302   weak_this_ = weak_ptr_factory_.GetWeakPtr();
    303 }
    304 
    305 ContentDecryptorDelegate::~ContentDecryptorDelegate() {
    306   SatisfyAllPendingCallbacksOnError();
    307 }
    308 
    309 void ContentDecryptorDelegate::Initialize(
    310     const std::string& key_system,
    311     const media::SessionMessageCB& session_message_cb,
    312     const media::SessionReadyCB& session_ready_cb,
    313     const media::SessionClosedCB& session_closed_cb,
    314     const media::SessionErrorCB& session_error_cb,
    315     const base::Closure& fatal_plugin_error_cb) {
    316   DCHECK(!key_system.empty());
    317   DCHECK(key_system_.empty());
    318   key_system_ = key_system;
    319 
    320   session_message_cb_ = session_message_cb;
    321   session_ready_cb_ = session_ready_cb;
    322   session_closed_cb_ = session_closed_cb;
    323   session_error_cb_ = session_error_cb;
    324   fatal_plugin_error_cb_ = fatal_plugin_error_cb;
    325 
    326   plugin_decryption_interface_->Initialize(
    327       pp_instance_, StringVar::StringToPPVar(key_system_));
    328 }
    329 
    330 void ContentDecryptorDelegate::InstanceCrashed() {
    331   fatal_plugin_error_cb_.Run();
    332   SatisfyAllPendingCallbacksOnError();
    333 }
    334 
    335 void ContentDecryptorDelegate::CreateSession(
    336     const std::string& init_data_type,
    337     const uint8* init_data,
    338     int init_data_length,
    339     MediaKeys::SessionType session_type,
    340     scoped_ptr<NewSessionCdmPromise> promise) {
    341   uint32_t promise_id = SavePromise(promise.PassAs<CdmPromise>());
    342   PP_Var init_data_array =
    343       PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
    344           init_data_length, init_data);
    345   plugin_decryption_interface_->CreateSession(
    346       pp_instance_,
    347       promise_id,
    348       StringVar::StringToPPVar(init_data_type),
    349       init_data_array,
    350       MediaSessionTypeToPpSessionType(session_type));
    351 }
    352 
    353 void ContentDecryptorDelegate::LoadSession(
    354     const std::string& web_session_id,
    355     scoped_ptr<NewSessionCdmPromise> promise) {
    356   uint32_t promise_id = SavePromise(promise.PassAs<CdmPromise>());
    357   plugin_decryption_interface_->LoadSession(
    358       pp_instance_, promise_id, StringVar::StringToPPVar(web_session_id));
    359 }
    360 
    361 void ContentDecryptorDelegate::UpdateSession(
    362     const std::string& web_session_id,
    363     const uint8* response,
    364     int response_length,
    365     scoped_ptr<SimpleCdmPromise> promise) {
    366   uint32_t promise_id = SavePromise(promise.PassAs<CdmPromise>());
    367   PP_Var response_array =
    368       PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
    369           response_length, response);
    370   plugin_decryption_interface_->UpdateSession(
    371       pp_instance_,
    372       promise_id,
    373       StringVar::StringToPPVar(web_session_id),
    374       response_array);
    375 }
    376 
    377 void ContentDecryptorDelegate::ReleaseSession(
    378     const std::string& web_session_id,
    379     scoped_ptr<SimpleCdmPromise> promise) {
    380   uint32_t promise_id = SavePromise(promise.PassAs<CdmPromise>());
    381   plugin_decryption_interface_->ReleaseSession(
    382       pp_instance_, promise_id, StringVar::StringToPPVar(web_session_id));
    383 }
    384 
    385 // TODO(xhwang): Remove duplication of code in Decrypt(),
    386 // DecryptAndDecodeAudio() and DecryptAndDecodeVideo().
    387 bool ContentDecryptorDelegate::Decrypt(
    388     Decryptor::StreamType stream_type,
    389     const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
    390     const Decryptor::DecryptCB& decrypt_cb) {
    391   DVLOG(3) << "Decrypt() - stream_type: " << stream_type;
    392 
    393   // |{audio|video}_input_resource_| is not being used by the plugin
    394   // now because there is only one pending audio/video decrypt request at any
    395   // time. This is enforced by the media pipeline.
    396   scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
    397   if (!MakeMediaBufferResource(
    398           stream_type, encrypted_buffer, &encrypted_resource) ||
    399       !encrypted_resource.get()) {
    400     return false;
    401   }
    402   ScopedPPResource pp_resource(encrypted_resource.get());
    403 
    404   const uint32_t request_id = next_decryption_request_id_++;
    405   DVLOG(2) << "Decrypt() - request_id " << request_id;
    406 
    407   PP_EncryptedBlockInfo block_info = {};
    408   DCHECK(encrypted_buffer->decrypt_config());
    409   if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
    410     return false;
    411   }
    412 
    413   // There is only one pending decrypt request at any time per stream. This is
    414   // enforced by the media pipeline.
    415   switch (stream_type) {
    416     case Decryptor::kAudio:
    417       audio_decrypt_cb_.Set(request_id, decrypt_cb);
    418       break;
    419     case Decryptor::kVideo:
    420       video_decrypt_cb_.Set(request_id, decrypt_cb);
    421       break;
    422     default:
    423       NOTREACHED();
    424       return false;
    425   }
    426 
    427   SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
    428 
    429   plugin_decryption_interface_->Decrypt(pp_instance_, pp_resource, &block_info);
    430   return true;
    431 }
    432 
    433 bool ContentDecryptorDelegate::CancelDecrypt(
    434     Decryptor::StreamType stream_type) {
    435   DVLOG(3) << "CancelDecrypt() - stream_type: " << stream_type;
    436 
    437   Decryptor::DecryptCB decrypt_cb;
    438   switch (stream_type) {
    439     case Decryptor::kAudio:
    440       // Release the shared memory as it can still be in use by the plugin.
    441       // The next Decrypt() call will need to allocate a new shared memory
    442       // buffer.
    443       audio_input_resource_ = NULL;
    444       decrypt_cb = audio_decrypt_cb_.ResetAndReturn();
    445       break;
    446     case Decryptor::kVideo:
    447       // Release the shared memory as it can still be in use by the plugin.
    448       // The next Decrypt() call will need to allocate a new shared memory
    449       // buffer.
    450       video_input_resource_ = NULL;
    451       decrypt_cb = video_decrypt_cb_.ResetAndReturn();
    452       break;
    453     default:
    454       NOTREACHED();
    455       return false;
    456   }
    457 
    458   if (!decrypt_cb.is_null())
    459     decrypt_cb.Run(Decryptor::kSuccess, NULL);
    460 
    461   return true;
    462 }
    463 
    464 bool ContentDecryptorDelegate::InitializeAudioDecoder(
    465     const media::AudioDecoderConfig& decoder_config,
    466     const Decryptor::DecoderInitCB& init_cb) {
    467   PP_AudioDecoderConfig pp_decoder_config;
    468   pp_decoder_config.codec =
    469       MediaAudioCodecToPpAudioCodec(decoder_config.codec());
    470   pp_decoder_config.channel_count =
    471       media::ChannelLayoutToChannelCount(decoder_config.channel_layout());
    472   pp_decoder_config.bits_per_channel = decoder_config.bits_per_channel();
    473   pp_decoder_config.samples_per_second = decoder_config.samples_per_second();
    474   pp_decoder_config.request_id = next_decryption_request_id_++;
    475 
    476   audio_samples_per_second_ = pp_decoder_config.samples_per_second;
    477   audio_channel_count_ = pp_decoder_config.channel_count;
    478   audio_channel_layout_ = decoder_config.channel_layout();
    479 
    480   scoped_refptr<PPB_Buffer_Impl> extra_data_resource;
    481   if (!MakeBufferResource(pp_instance_,
    482                           decoder_config.extra_data(),
    483                           decoder_config.extra_data_size(),
    484                           &extra_data_resource)) {
    485     return false;
    486   }
    487   ScopedPPResource pp_resource(extra_data_resource.get());
    488 
    489   audio_decoder_init_cb_.Set(pp_decoder_config.request_id, init_cb);
    490   plugin_decryption_interface_->InitializeAudioDecoder(
    491       pp_instance_, &pp_decoder_config, pp_resource);
    492   return true;
    493 }
    494 
    495 bool ContentDecryptorDelegate::InitializeVideoDecoder(
    496     const media::VideoDecoderConfig& decoder_config,
    497     const Decryptor::DecoderInitCB& init_cb) {
    498   PP_VideoDecoderConfig pp_decoder_config;
    499   pp_decoder_config.codec =
    500       MediaVideoCodecToPpVideoCodec(decoder_config.codec());
    501   pp_decoder_config.profile =
    502       MediaVideoCodecProfileToPpVideoCodecProfile(decoder_config.profile());
    503   pp_decoder_config.format =
    504       MediaVideoFormatToPpDecryptedFrameFormat(decoder_config.format());
    505   pp_decoder_config.width = decoder_config.coded_size().width();
    506   pp_decoder_config.height = decoder_config.coded_size().height();
    507   pp_decoder_config.request_id = next_decryption_request_id_++;
    508 
    509   scoped_refptr<PPB_Buffer_Impl> extra_data_resource;
    510   if (!MakeBufferResource(pp_instance_,
    511                           decoder_config.extra_data(),
    512                           decoder_config.extra_data_size(),
    513                           &extra_data_resource)) {
    514     return false;
    515   }
    516   ScopedPPResource pp_resource(extra_data_resource.get());
    517 
    518   video_decoder_init_cb_.Set(pp_decoder_config.request_id, init_cb);
    519   natural_size_ = decoder_config.natural_size();
    520 
    521   plugin_decryption_interface_->InitializeVideoDecoder(
    522       pp_instance_, &pp_decoder_config, pp_resource);
    523   return true;
    524 }
    525 
    526 bool ContentDecryptorDelegate::DeinitializeDecoder(
    527     Decryptor::StreamType stream_type) {
    528   CancelDecode(stream_type);
    529 
    530   if (stream_type == Decryptor::kVideo)
    531     natural_size_ = gfx::Size();
    532 
    533   // TODO(tomfinegan): Add decoder deinitialize request tracking, and get
    534   // stream type from media stack.
    535   plugin_decryption_interface_->DeinitializeDecoder(
    536       pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0);
    537   return true;
    538 }
    539 
    540 bool ContentDecryptorDelegate::ResetDecoder(Decryptor::StreamType stream_type) {
    541   CancelDecode(stream_type);
    542 
    543   // TODO(tomfinegan): Add decoder reset request tracking.
    544   plugin_decryption_interface_->ResetDecoder(
    545       pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0);
    546   return true;
    547 }
    548 
    549 bool ContentDecryptorDelegate::DecryptAndDecodeAudio(
    550     const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
    551     const Decryptor::AudioDecodeCB& audio_decode_cb) {
    552   // |audio_input_resource_| is not being used by the plugin now
    553   // because there is only one pending audio decode request at any time.
    554   // This is enforced by the media pipeline.
    555   scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
    556   if (!MakeMediaBufferResource(
    557           Decryptor::kAudio, encrypted_buffer, &encrypted_resource)) {
    558     return false;
    559   }
    560 
    561   // The resource should not be NULL for non-EOS buffer.
    562   if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get())
    563     return false;
    564 
    565   const uint32_t request_id = next_decryption_request_id_++;
    566   DVLOG(2) << "DecryptAndDecodeAudio() - request_id " << request_id;
    567 
    568   PP_EncryptedBlockInfo block_info = {};
    569   if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
    570     return false;
    571   }
    572 
    573   SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
    574 
    575   // There is only one pending audio decode request at any time. This is
    576   // enforced by the media pipeline. If this DCHECK is violated, our buffer
    577   // reuse policy is not valid, and we may have race problems for the shared
    578   // buffer.
    579   audio_decode_cb_.Set(request_id, audio_decode_cb);
    580 
    581   ScopedPPResource pp_resource(encrypted_resource.get());
    582   plugin_decryption_interface_->DecryptAndDecode(
    583       pp_instance_, PP_DECRYPTORSTREAMTYPE_AUDIO, pp_resource, &block_info);
    584   return true;
    585 }
    586 
    587 bool ContentDecryptorDelegate::DecryptAndDecodeVideo(
    588     const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
    589     const Decryptor::VideoDecodeCB& video_decode_cb) {
    590   // |video_input_resource_| is not being used by the plugin now
    591   // because there is only one pending video decode request at any time.
    592   // This is enforced by the media pipeline.
    593   scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
    594   if (!MakeMediaBufferResource(
    595           Decryptor::kVideo, encrypted_buffer, &encrypted_resource)) {
    596     return false;
    597   }
    598 
    599   // The resource should not be 0 for non-EOS buffer.
    600   if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get())
    601     return false;
    602 
    603   const uint32_t request_id = next_decryption_request_id_++;
    604   DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id;
    605   TRACE_EVENT_ASYNC_BEGIN0(
    606       "media", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
    607 
    608   PP_EncryptedBlockInfo block_info = {};
    609   if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
    610     return false;
    611   }
    612 
    613   SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
    614 
    615   // Only one pending video decode request at any time. This is enforced by the
    616   // media pipeline. If this DCHECK is violated, our buffer
    617   // reuse policy is not valid, and we may have race problems for the shared
    618   // buffer.
    619   video_decode_cb_.Set(request_id, video_decode_cb);
    620 
    621   // TODO(tomfinegan): Need to get stream type from media stack.
    622   ScopedPPResource pp_resource(encrypted_resource.get());
    623   plugin_decryption_interface_->DecryptAndDecode(
    624       pp_instance_, PP_DECRYPTORSTREAMTYPE_VIDEO, pp_resource, &block_info);
    625   return true;
    626 }
    627 
    628 void ContentDecryptorDelegate::OnPromiseResolved(uint32 promise_id) {
    629   scoped_ptr<CdmPromise> promise = TakePromise(promise_id);
    630   if (promise) {
    631     SimpleCdmPromise* simple_promise(
    632         static_cast<SimpleCdmPromise*>(promise.get()));
    633     simple_promise->resolve();
    634   }
    635 }
    636 
    637 void ContentDecryptorDelegate::OnPromiseResolvedWithSession(
    638     uint32 promise_id,
    639     PP_Var web_session_id) {
    640   scoped_ptr<CdmPromise> promise = TakePromise(promise_id);
    641 
    642   StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id);
    643   DCHECK(web_session_id_string);
    644 
    645   if (promise) {
    646     NewSessionCdmPromise* session_promise(
    647         static_cast<NewSessionCdmPromise*>(promise.get()));
    648     session_promise->resolve(web_session_id_string->value());
    649   }
    650 }
    651 
    652 void ContentDecryptorDelegate::OnPromiseRejected(
    653     uint32 promise_id,
    654     PP_CdmExceptionCode exception_code,
    655     uint32 system_code,
    656     PP_Var error_description) {
    657   StringVar* error_description_string = StringVar::FromPPVar(error_description);
    658   DCHECK(error_description_string);
    659 
    660   scoped_ptr<CdmPromise> promise = TakePromise(promise_id);
    661   if (promise) {
    662     promise->reject(PpExceptionTypeToMediaException(exception_code),
    663                     system_code,
    664                     error_description_string->value());
    665   }
    666 }
    667 
    668 void ContentDecryptorDelegate::OnSessionMessage(PP_Var web_session_id,
    669                                                 PP_Var message,
    670                                                 PP_Var destination_url) {
    671   if (session_message_cb_.is_null())
    672     return;
    673 
    674   StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id);
    675   DCHECK(web_session_id_string);
    676 
    677   ArrayBufferVar* message_array_buffer = ArrayBufferVar::FromPPVar(message);
    678   std::vector<uint8> message_vector;
    679   if (message_array_buffer) {
    680     const uint8* data = static_cast<const uint8*>(message_array_buffer->Map());
    681     message_vector.assign(data, data + message_array_buffer->ByteLength());
    682   }
    683 
    684   StringVar* destination_url_string = StringVar::FromPPVar(destination_url);
    685   DCHECK(destination_url_string);
    686 
    687   GURL verified_gurl = GURL(destination_url_string->value());
    688   if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) {
    689     DLOG(WARNING) << "SessionMessage default_url is invalid : "
    690                   << verified_gurl.possibly_invalid_spec();
    691     verified_gurl = GURL::EmptyGURL();  // Replace invalid destination_url.
    692   }
    693 
    694   session_message_cb_.Run(
    695       web_session_id_string->value(), message_vector, verified_gurl);
    696 }
    697 
    698 void ContentDecryptorDelegate::OnSessionReady(PP_Var web_session_id) {
    699   if (session_ready_cb_.is_null())
    700     return;
    701 
    702   StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id);
    703   DCHECK(web_session_id_string);
    704 
    705   session_ready_cb_.Run(web_session_id_string->value());
    706 }
    707 
    708 void ContentDecryptorDelegate::OnSessionClosed(PP_Var web_session_id) {
    709   if (session_closed_cb_.is_null())
    710     return;
    711 
    712   StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id);
    713   DCHECK(web_session_id_string);
    714 
    715   session_closed_cb_.Run(web_session_id_string->value());
    716 }
    717 
    718 void ContentDecryptorDelegate::OnSessionError(
    719     PP_Var web_session_id,
    720     PP_CdmExceptionCode exception_code,
    721     uint32 system_code,
    722     PP_Var error_description) {
    723   if (session_error_cb_.is_null())
    724     return;
    725 
    726   StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id);
    727   DCHECK(web_session_id_string);
    728 
    729   StringVar* error_description_string = StringVar::FromPPVar(error_description);
    730   DCHECK(error_description_string);
    731 
    732   session_error_cb_.Run(web_session_id_string->value(),
    733                         PpExceptionTypeToMediaException(exception_code),
    734                         system_code,
    735                         error_description_string->value());
    736 }
    737 
    738 void ContentDecryptorDelegate::DecoderInitializeDone(
    739     PP_DecryptorStreamType decoder_type,
    740     uint32_t request_id,
    741     PP_Bool success) {
    742   if (decoder_type == PP_DECRYPTORSTREAMTYPE_AUDIO) {
    743     // If the request ID is not valid or does not match what's saved, do
    744     // nothing.
    745     if (request_id == 0 || !audio_decoder_init_cb_.Matches(request_id))
    746       return;
    747 
    748     audio_decoder_init_cb_.ResetAndReturn().Run(PP_ToBool(success));
    749   } else {
    750     if (request_id == 0 || !video_decoder_init_cb_.Matches(request_id))
    751       return;
    752 
    753     if (!success)
    754       natural_size_ = gfx::Size();
    755 
    756     video_decoder_init_cb_.ResetAndReturn().Run(PP_ToBool(success));
    757   }
    758 }
    759 
    760 void ContentDecryptorDelegate::DecoderDeinitializeDone(
    761     PP_DecryptorStreamType decoder_type,
    762     uint32_t request_id) {
    763   // TODO(tomfinegan): Add decoder stop completion handling.
    764 }
    765 
    766 void ContentDecryptorDelegate::DecoderResetDone(
    767     PP_DecryptorStreamType decoder_type,
    768     uint32_t request_id) {
    769   // TODO(tomfinegan): Add decoder reset completion handling.
    770 }
    771 
    772 void ContentDecryptorDelegate::DeliverBlock(
    773     PP_Resource decrypted_block,
    774     const PP_DecryptedBlockInfo* block_info) {
    775   DCHECK(block_info);
    776 
    777   FreeBuffer(block_info->tracking_info.buffer_id);
    778 
    779   const uint32_t request_id = block_info->tracking_info.request_id;
    780   DVLOG(2) << "DeliverBlock() - request_id: " << request_id;
    781 
    782   // If the request ID is not valid or does not match what's saved, do nothing.
    783   if (request_id == 0) {
    784     DVLOG(1) << "DeliverBlock() - invalid request_id " << request_id;
    785     return;
    786   }
    787 
    788   Decryptor::DecryptCB decrypt_cb;
    789   if (audio_decrypt_cb_.Matches(request_id)) {
    790     decrypt_cb = audio_decrypt_cb_.ResetAndReturn();
    791   } else if (video_decrypt_cb_.Matches(request_id)) {
    792     decrypt_cb = video_decrypt_cb_.ResetAndReturn();
    793   } else {
    794     DVLOG(1) << "DeliverBlock() - request_id " << request_id << " not found";
    795     return;
    796   }
    797 
    798   Decryptor::Status status =
    799       PpDecryptResultToMediaDecryptorStatus(block_info->result);
    800   if (status != Decryptor::kSuccess) {
    801     decrypt_cb.Run(status, NULL);
    802     return;
    803   }
    804 
    805   EnterResourceNoLock<PPB_Buffer_API> enter(decrypted_block, true);
    806   if (!enter.succeeded()) {
    807     decrypt_cb.Run(Decryptor::kError, NULL);
    808     return;
    809   }
    810   BufferAutoMapper mapper(enter.object());
    811   if (!mapper.data() || !mapper.size() ||
    812       mapper.size() < block_info->data_size) {
    813     decrypt_cb.Run(Decryptor::kError, NULL);
    814     return;
    815   }
    816 
    817   // TODO(tomfinegan): Find a way to take ownership of the shared memory
    818   // managed by the PPB_Buffer_Dev, and avoid the extra copy.
    819   scoped_refptr<media::DecoderBuffer> decrypted_buffer(
    820       media::DecoderBuffer::CopyFrom(static_cast<uint8*>(mapper.data()),
    821                                      block_info->data_size));
    822   decrypted_buffer->set_timestamp(
    823       base::TimeDelta::FromMicroseconds(block_info->tracking_info.timestamp));
    824   decrypt_cb.Run(Decryptor::kSuccess, decrypted_buffer);
    825 }
    826 
    827 // Use a non-class-member function here so that if for some reason
    828 // ContentDecryptorDelegate is destroyed before VideoFrame calls this callback,
    829 // we can still get the shared memory unmapped.
    830 static void BufferNoLongerNeeded(
    831     const scoped_refptr<PPB_Buffer_Impl>& ppb_buffer,
    832     base::Closure buffer_no_longer_needed_cb) {
    833   ppb_buffer->Unmap();
    834   buffer_no_longer_needed_cb.Run();
    835 }
    836 
    837 // Enters |resource|, maps shared memory and returns pointer of mapped data.
    838 // Returns NULL if any error occurs.
    839 static uint8* GetMappedBuffer(PP_Resource resource,
    840                               scoped_refptr<PPB_Buffer_Impl>* ppb_buffer) {
    841   EnterResourceNoLock<PPB_Buffer_API> enter(resource, true);
    842   if (!enter.succeeded())
    843     return NULL;
    844 
    845   uint8* mapped_data = static_cast<uint8*>(enter.object()->Map());
    846   if (!enter.object()->IsMapped() || !mapped_data)
    847     return NULL;
    848 
    849   uint32_t mapped_size = 0;
    850   if (!enter.object()->Describe(&mapped_size) || !mapped_size) {
    851     enter.object()->Unmap();
    852     return NULL;
    853   }
    854 
    855   *ppb_buffer = static_cast<PPB_Buffer_Impl*>(enter.object());
    856 
    857   return mapped_data;
    858 }
    859 
    860 void ContentDecryptorDelegate::DeliverFrame(
    861     PP_Resource decrypted_frame,
    862     const PP_DecryptedFrameInfo* frame_info) {
    863   DCHECK(frame_info);
    864 
    865   const uint32_t request_id = frame_info->tracking_info.request_id;
    866   DVLOG(2) << "DeliverFrame() - request_id: " << request_id;
    867 
    868   // If the request ID is not valid or does not match what's saved, do nothing.
    869   if (request_id == 0 || !video_decode_cb_.Matches(request_id)) {
    870     DVLOG(1) << "DeliverFrame() - request_id " << request_id << " not found";
    871     FreeBuffer(frame_info->tracking_info.buffer_id);
    872     return;
    873   }
    874 
    875   TRACE_EVENT_ASYNC_END0(
    876       "media", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
    877 
    878   Decryptor::VideoDecodeCB video_decode_cb = video_decode_cb_.ResetAndReturn();
    879 
    880   Decryptor::Status status =
    881       PpDecryptResultToMediaDecryptorStatus(frame_info->result);
    882   if (status != Decryptor::kSuccess) {
    883     DCHECK(!frame_info->tracking_info.buffer_id);
    884     video_decode_cb.Run(status, NULL);
    885     return;
    886   }
    887 
    888   scoped_refptr<PPB_Buffer_Impl> ppb_buffer;
    889   uint8* frame_data = GetMappedBuffer(decrypted_frame, &ppb_buffer);
    890   if (!frame_data) {
    891     FreeBuffer(frame_info->tracking_info.buffer_id);
    892     video_decode_cb.Run(Decryptor::kError, NULL);
    893     return;
    894   }
    895 
    896   gfx::Size frame_size(frame_info->width, frame_info->height);
    897   DCHECK_EQ(frame_info->format, PP_DECRYPTEDFRAMEFORMAT_YV12);
    898 
    899   scoped_refptr<media::VideoFrame> decoded_frame =
    900       media::VideoFrame::WrapExternalYuvData(
    901           media::VideoFrame::YV12,
    902           frame_size,
    903           gfx::Rect(frame_size),
    904           natural_size_,
    905           frame_info->strides[PP_DECRYPTEDFRAMEPLANES_Y],
    906           frame_info->strides[PP_DECRYPTEDFRAMEPLANES_U],
    907           frame_info->strides[PP_DECRYPTEDFRAMEPLANES_V],
    908           frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y],
    909           frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_U],
    910           frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_V],
    911           base::TimeDelta::FromMicroseconds(
    912               frame_info->tracking_info.timestamp),
    913           media::BindToCurrentLoop(
    914               base::Bind(&BufferNoLongerNeeded,
    915                          ppb_buffer,
    916                          base::Bind(&ContentDecryptorDelegate::FreeBuffer,
    917                                     weak_this_,
    918                                     frame_info->tracking_info.buffer_id))));
    919 
    920   video_decode_cb.Run(Decryptor::kSuccess, decoded_frame);
    921 }
    922 
    923 void ContentDecryptorDelegate::DeliverSamples(
    924     PP_Resource audio_frames,
    925     const PP_DecryptedSampleInfo* sample_info) {
    926   DCHECK(sample_info);
    927 
    928   FreeBuffer(sample_info->tracking_info.buffer_id);
    929 
    930   const uint32_t request_id = sample_info->tracking_info.request_id;
    931   DVLOG(2) << "DeliverSamples() - request_id: " << request_id;
    932 
    933   // If the request ID is not valid or does not match what's saved, do nothing.
    934   if (request_id == 0 || !audio_decode_cb_.Matches(request_id)) {
    935     DVLOG(1) << "DeliverSamples() - request_id " << request_id << " not found";
    936     return;
    937   }
    938 
    939   Decryptor::AudioDecodeCB audio_decode_cb = audio_decode_cb_.ResetAndReturn();
    940 
    941   const Decryptor::AudioBuffers empty_frames;
    942 
    943   Decryptor::Status status =
    944       PpDecryptResultToMediaDecryptorStatus(sample_info->result);
    945   if (status != Decryptor::kSuccess) {
    946     audio_decode_cb.Run(status, empty_frames);
    947     return;
    948   }
    949 
    950   media::SampleFormat sample_format =
    951       PpDecryptedSampleFormatToMediaSampleFormat(sample_info->format);
    952 
    953   Decryptor::AudioBuffers audio_frame_list;
    954   if (!DeserializeAudioFrames(audio_frames,
    955                               sample_info->data_size,
    956                               sample_format,
    957                               &audio_frame_list)) {
    958     NOTREACHED() << "CDM did not serialize the buffer correctly.";
    959     audio_decode_cb.Run(Decryptor::kError, empty_frames);
    960     return;
    961   }
    962 
    963   audio_decode_cb.Run(Decryptor::kSuccess, audio_frame_list);
    964 }
    965 
    966 // TODO(xhwang): Try to remove duplicate logic here and in CancelDecrypt().
    967 void ContentDecryptorDelegate::CancelDecode(Decryptor::StreamType stream_type) {
    968   switch (stream_type) {
    969     case Decryptor::kAudio:
    970       // Release the shared memory as it can still be in use by the plugin.
    971       // The next DecryptAndDecode() call will need to allocate a new shared
    972       // memory buffer.
    973       audio_input_resource_ = NULL;
    974       if (!audio_decode_cb_.is_null())
    975         audio_decode_cb_.ResetAndReturn().Run(Decryptor::kSuccess,
    976                                               Decryptor::AudioBuffers());
    977       break;
    978     case Decryptor::kVideo:
    979       // Release the shared memory as it can still be in use by the plugin.
    980       // The next DecryptAndDecode() call will need to allocate a new shared
    981       // memory buffer.
    982       video_input_resource_ = NULL;
    983       if (!video_decode_cb_.is_null())
    984         video_decode_cb_.ResetAndReturn().Run(Decryptor::kSuccess, NULL);
    985       break;
    986     default:
    987       NOTREACHED();
    988   }
    989 }
    990 
    991 bool ContentDecryptorDelegate::MakeMediaBufferResource(
    992     Decryptor::StreamType stream_type,
    993     const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
    994     scoped_refptr<PPB_Buffer_Impl>* resource) {
    995   TRACE_EVENT0("media", "ContentDecryptorDelegate::MakeMediaBufferResource");
    996 
    997   // End of stream buffers are represented as null resources.
    998   if (encrypted_buffer->end_of_stream()) {
    999     *resource = NULL;
   1000     return true;
   1001   }
   1002 
   1003   DCHECK(stream_type == Decryptor::kAudio || stream_type == Decryptor::kVideo);
   1004   scoped_refptr<PPB_Buffer_Impl>& media_resource =
   1005       (stream_type == Decryptor::kAudio) ? audio_input_resource_
   1006                                          : video_input_resource_;
   1007 
   1008   const size_t data_size = static_cast<size_t>(encrypted_buffer->data_size());
   1009   if (!media_resource.get() || media_resource->size() < data_size) {
   1010     // Either the buffer hasn't been created yet, or we have one that isn't big
   1011     // enough to fit |size| bytes.
   1012 
   1013     // Media resource size starts from |kMinimumMediaBufferSize| and grows
   1014     // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl,
   1015     // which is usually expensive. Since input media buffers are compressed,
   1016     // they are usually small (compared to outputs). The over-allocated memory
   1017     // should be negligible.
   1018     const uint32_t kMinimumMediaBufferSize = 1024;
   1019     uint32_t media_resource_size =
   1020         media_resource.get() ? media_resource->size() : kMinimumMediaBufferSize;
   1021     while (media_resource_size < data_size)
   1022       media_resource_size *= 2;
   1023 
   1024     DVLOG(2) << "Size of media buffer for "
   1025              << ((stream_type == Decryptor::kAudio) ? "audio" : "video")
   1026              << " stream bumped to " << media_resource_size
   1027              << " bytes to fit input.";
   1028     media_resource =
   1029         PPB_Buffer_Impl::CreateResource(pp_instance_, media_resource_size);
   1030     if (!media_resource.get())
   1031       return false;
   1032   }
   1033 
   1034   BufferAutoMapper mapper(media_resource.get());
   1035   if (!mapper.data() || mapper.size() < data_size) {
   1036     media_resource = NULL;
   1037     return false;
   1038   }
   1039   memcpy(mapper.data(), encrypted_buffer->data(), data_size);
   1040 
   1041   *resource = media_resource;
   1042   return true;
   1043 }
   1044 
   1045 void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) {
   1046   if (buffer_id)
   1047     free_buffers_.push(buffer_id);
   1048 }
   1049 
   1050 void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo(
   1051     PP_DecryptTrackingInfo* tracking_info) {
   1052   DCHECK_EQ(tracking_info->buffer_id, 0u);
   1053 
   1054   if (free_buffers_.empty())
   1055     return;
   1056 
   1057   tracking_info->buffer_id = free_buffers_.front();
   1058   free_buffers_.pop();
   1059 }
   1060 
   1061 bool ContentDecryptorDelegate::DeserializeAudioFrames(
   1062     PP_Resource audio_frames,
   1063     size_t data_size,
   1064     media::SampleFormat sample_format,
   1065     Decryptor::AudioBuffers* frames) {
   1066   DCHECK(frames);
   1067   EnterResourceNoLock<PPB_Buffer_API> enter(audio_frames, true);
   1068   if (!enter.succeeded())
   1069     return false;
   1070 
   1071   BufferAutoMapper mapper(enter.object());
   1072   if (!mapper.data() || !mapper.size() ||
   1073       mapper.size() < static_cast<uint32_t>(data_size))
   1074     return false;
   1075 
   1076   // TODO(jrummell): Pass ownership of data() directly to AudioBuffer to avoid
   1077   // the copy. Since it is possible to get multiple buffers, it would need to be
   1078   // sliced and ref counted appropriately. http://crbug.com/255576.
   1079   const uint8* cur = static_cast<uint8*>(mapper.data());
   1080   size_t bytes_left = data_size;
   1081 
   1082   const int audio_bytes_per_frame =
   1083       media::SampleFormatToBytesPerChannel(sample_format) *
   1084       audio_channel_count_;
   1085   if (audio_bytes_per_frame <= 0)
   1086     return false;
   1087 
   1088   // Allocate space for the channel pointers given to AudioBuffer.
   1089   std::vector<const uint8*> channel_ptrs(audio_channel_count_,
   1090                                          static_cast<const uint8*>(NULL));
   1091   do {
   1092     int64 timestamp = 0;
   1093     int64 frame_size = -1;
   1094     const size_t kHeaderSize = sizeof(timestamp) + sizeof(frame_size);
   1095 
   1096     if (bytes_left < kHeaderSize)
   1097       return false;
   1098 
   1099     memcpy(&timestamp, cur, sizeof(timestamp));
   1100     cur += sizeof(timestamp);
   1101     bytes_left -= sizeof(timestamp);
   1102 
   1103     memcpy(&frame_size, cur, sizeof(frame_size));
   1104     cur += sizeof(frame_size);
   1105     bytes_left -= sizeof(frame_size);
   1106 
   1107     // We should *not* have empty frames in the list.
   1108     if (frame_size <= 0 ||
   1109         bytes_left < base::checked_cast<size_t>(frame_size)) {
   1110       return false;
   1111     }
   1112 
   1113     // Setup channel pointers.  AudioBuffer::CopyFrom() will only use the first
   1114     // one in the case of interleaved data.
   1115     const int size_per_channel = frame_size / audio_channel_count_;
   1116     for (int i = 0; i < audio_channel_count_; ++i)
   1117       channel_ptrs[i] = cur + i * size_per_channel;
   1118 
   1119     const int frame_count = frame_size / audio_bytes_per_frame;
   1120     scoped_refptr<media::AudioBuffer> frame = media::AudioBuffer::CopyFrom(
   1121         sample_format,
   1122         audio_channel_layout_,
   1123         audio_channel_count_,
   1124         audio_samples_per_second_,
   1125         frame_count,
   1126         &channel_ptrs[0],
   1127         base::TimeDelta::FromMicroseconds(timestamp));
   1128     frames->push_back(frame);
   1129 
   1130     cur += frame_size;
   1131     bytes_left -= frame_size;
   1132   } while (bytes_left > 0);
   1133 
   1134   return true;
   1135 }
   1136 
   1137 void ContentDecryptorDelegate::SatisfyAllPendingCallbacksOnError() {
   1138   if (!audio_decoder_init_cb_.is_null())
   1139     audio_decoder_init_cb_.ResetAndReturn().Run(false);
   1140 
   1141   if (!video_decoder_init_cb_.is_null())
   1142     video_decoder_init_cb_.ResetAndReturn().Run(false);
   1143 
   1144   audio_input_resource_ = NULL;
   1145   video_input_resource_ = NULL;
   1146 
   1147   if (!audio_decrypt_cb_.is_null())
   1148     audio_decrypt_cb_.ResetAndReturn().Run(media::Decryptor::kError, NULL);
   1149 
   1150   if (!video_decrypt_cb_.is_null())
   1151     video_decrypt_cb_.ResetAndReturn().Run(media::Decryptor::kError, NULL);
   1152 
   1153   if (!audio_decode_cb_.is_null()) {
   1154     const media::Decryptor::AudioBuffers empty_frames;
   1155     audio_decode_cb_.ResetAndReturn().Run(media::Decryptor::kError,
   1156                                           empty_frames);
   1157   }
   1158 
   1159   if (!video_decode_cb_.is_null())
   1160     video_decode_cb_.ResetAndReturn().Run(media::Decryptor::kError, NULL);
   1161 
   1162   // Reject all outstanding promises.
   1163   for (PromiseMap::iterator it = promises_.begin(); it != promises_.end();
   1164        ++it) {
   1165     it->second->reject(
   1166         media::MediaKeys::UNKNOWN_ERROR, 0, "Failure calling plugin.");
   1167   }
   1168   promises_.clear();
   1169 }
   1170 
   1171 uint32_t ContentDecryptorDelegate::SavePromise(scoped_ptr<CdmPromise> promise) {
   1172   uint32_t promise_id = next_promise_id_++;
   1173   promises_.add(promise_id, promise.Pass());
   1174   return promise_id;
   1175 }
   1176 
   1177 scoped_ptr<CdmPromise> ContentDecryptorDelegate::TakePromise(
   1178     uint32_t promise_id) {
   1179   PromiseMap::iterator it = promises_.find(promise_id);
   1180   if (it == promises_.end())
   1181     return scoped_ptr<CdmPromise>();
   1182   return promises_.take_and_erase(it);
   1183 }
   1184 
   1185 }  // namespace content
   1186