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