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