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("media", "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 media::SampleFormat PpDecryptedSampleFormatToMediaSampleFormat(
    222     PP_DecryptedSampleFormat result) {
    223   switch (result) {
    224     case PP_DECRYPTEDSAMPLEFORMAT_U8:
    225       return media::kSampleFormatU8;
    226     case PP_DECRYPTEDSAMPLEFORMAT_S16:
    227       return media::kSampleFormatS16;
    228     case PP_DECRYPTEDSAMPLEFORMAT_S32:
    229       return media::kSampleFormatS32;
    230     case PP_DECRYPTEDSAMPLEFORMAT_F32:
    231       return media::kSampleFormatF32;
    232     case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_S16:
    233       return media::kSampleFormatPlanarS16;
    234     case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_F32:
    235       return media::kSampleFormatPlanarF32;
    236     default:
    237       NOTREACHED();
    238       return media::kUnknownSampleFormat;
    239   }
    240 }
    241 
    242 }  // namespace
    243 
    244 ContentDecryptorDelegate::ContentDecryptorDelegate(
    245     PP_Instance pp_instance,
    246     const PPP_ContentDecryptor_Private* plugin_decryption_interface)
    247     : pp_instance_(pp_instance),
    248       plugin_decryption_interface_(plugin_decryption_interface),
    249       next_decryption_request_id_(1),
    250       pending_audio_decrypt_request_id_(0),
    251       pending_video_decrypt_request_id_(0),
    252       pending_audio_decoder_init_request_id_(0),
    253       pending_video_decoder_init_request_id_(0),
    254       pending_audio_decode_request_id_(0),
    255       pending_video_decode_request_id_(0),
    256       audio_samples_per_second_(0),
    257       audio_channel_count_(0),
    258       weak_ptr_factory_(this) {
    259   weak_this_ = weak_ptr_factory_.GetWeakPtr();
    260 }
    261 
    262 ContentDecryptorDelegate::~ContentDecryptorDelegate() {
    263 }
    264 
    265 void ContentDecryptorDelegate::Initialize(const std::string& key_system) {
    266   DCHECK(!key_system.empty());
    267   DCHECK(key_system_.empty());
    268   key_system_ = key_system;
    269 
    270   plugin_decryption_interface_->Initialize(
    271       pp_instance_,
    272       StringVar::StringToPPVar(key_system_));
    273 }
    274 
    275 void ContentDecryptorDelegate::SetSessionEventCallbacks(
    276     const media::SessionCreatedCB& session_created_cb,
    277     const media::SessionMessageCB& session_message_cb,
    278     const media::SessionReadyCB& session_ready_cb,
    279     const media::SessionClosedCB& session_closed_cb,
    280     const media::SessionErrorCB& session_error_cb) {
    281   session_created_cb_ = session_created_cb;
    282   session_message_cb_ = session_message_cb;
    283   session_ready_cb_ = session_ready_cb;
    284   session_closed_cb_ = session_closed_cb;
    285   session_error_cb_ = session_error_cb;
    286 }
    287 
    288 bool ContentDecryptorDelegate::CreateSession(uint32 session_id,
    289                                              const std::string& type,
    290                                              const uint8* init_data,
    291                                              int init_data_length) {
    292   PP_Var init_data_array =
    293       PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
    294           init_data_length, init_data);
    295 
    296   plugin_decryption_interface_->CreateSession(pp_instance_,
    297                                               session_id,
    298                                               StringVar::StringToPPVar(type),
    299                                               init_data_array);
    300   return true;
    301 }
    302 
    303 bool ContentDecryptorDelegate::UpdateSession(uint32 session_id,
    304                                              const uint8* response,
    305                                              int response_length) {
    306   PP_Var response_array =
    307       PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
    308           response_length, response);
    309   plugin_decryption_interface_->UpdateSession(
    310       pp_instance_, session_id, response_array);
    311   return true;
    312 }
    313 
    314 bool ContentDecryptorDelegate::ReleaseSession(uint32 session_id) {
    315   plugin_decryption_interface_->ReleaseSession(pp_instance_, session_id);
    316   return true;
    317 }
    318 
    319 // TODO(xhwang): Remove duplication of code in Decrypt(),
    320 // DecryptAndDecodeAudio() and DecryptAndDecodeVideo().
    321 bool ContentDecryptorDelegate::Decrypt(
    322     media::Decryptor::StreamType stream_type,
    323     const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
    324     const media::Decryptor::DecryptCB& decrypt_cb) {
    325   DVLOG(3) << "Decrypt() - stream_type: " << stream_type;
    326   // |{audio|video}_input_resource_| is not being used by the plugin
    327   // now because there is only one pending audio/video decrypt request at any
    328   // time. This is enforced by the media pipeline.
    329   scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
    330   if (!MakeMediaBufferResource(
    331           stream_type, encrypted_buffer, &encrypted_resource) ||
    332       !encrypted_resource.get()) {
    333     return false;
    334   }
    335   ScopedPPResource pp_resource(encrypted_resource.get());
    336 
    337   const uint32_t request_id = next_decryption_request_id_++;
    338   DVLOG(2) << "Decrypt() - request_id " << request_id;
    339 
    340   PP_EncryptedBlockInfo block_info = {};
    341   DCHECK(encrypted_buffer->decrypt_config());
    342   if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
    343     return false;
    344   }
    345 
    346   // There is only one pending decrypt request at any time per stream. This is
    347   // enforced by the media pipeline.
    348   switch (stream_type) {
    349     case media::Decryptor::kAudio:
    350       DCHECK_EQ(pending_audio_decrypt_request_id_, 0u);
    351       DCHECK(pending_audio_decrypt_cb_.is_null());
    352       pending_audio_decrypt_request_id_ = request_id;
    353       pending_audio_decrypt_cb_ = decrypt_cb;
    354       break;
    355     case media::Decryptor::kVideo:
    356       DCHECK_EQ(pending_video_decrypt_request_id_, 0u);
    357       DCHECK(pending_video_decrypt_cb_.is_null());
    358       pending_video_decrypt_request_id_ = request_id;
    359       pending_video_decrypt_cb_ = decrypt_cb;
    360       break;
    361     default:
    362       NOTREACHED();
    363       return false;
    364   }
    365 
    366   SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
    367 
    368   plugin_decryption_interface_->Decrypt(pp_instance_,
    369                                         pp_resource,
    370                                         &block_info);
    371   return true;
    372 }
    373 
    374 bool ContentDecryptorDelegate::CancelDecrypt(
    375     media::Decryptor::StreamType stream_type) {
    376   DVLOG(3) << "CancelDecrypt() - stream_type: " << stream_type;
    377 
    378   media::Decryptor::DecryptCB decrypt_cb;
    379   switch (stream_type) {
    380     case media::Decryptor::kAudio:
    381       // Release the shared memory as it can still be in use by the plugin.
    382       // The next Decrypt() call will need to allocate a new shared memory
    383       // buffer.
    384       audio_input_resource_ = NULL;
    385       pending_audio_decrypt_request_id_ = 0;
    386       decrypt_cb = base::ResetAndReturn(&pending_audio_decrypt_cb_);
    387       break;
    388     case media::Decryptor::kVideo:
    389       // Release the shared memory as it can still be in use by the plugin.
    390       // The next Decrypt() call will need to allocate a new shared memory
    391       // buffer.
    392       video_input_resource_ = NULL;
    393       pending_video_decrypt_request_id_ = 0;
    394       decrypt_cb = base::ResetAndReturn(&pending_video_decrypt_cb_);
    395       break;
    396     default:
    397       NOTREACHED();
    398       return false;
    399   }
    400 
    401   if (!decrypt_cb.is_null())
    402     decrypt_cb.Run(media::Decryptor::kSuccess, NULL);
    403 
    404   return true;
    405 }
    406 
    407 bool ContentDecryptorDelegate::InitializeAudioDecoder(
    408     const media::AudioDecoderConfig& decoder_config,
    409     const media::Decryptor::DecoderInitCB& init_cb) {
    410   PP_AudioDecoderConfig pp_decoder_config;
    411   pp_decoder_config.codec =
    412       MediaAudioCodecToPpAudioCodec(decoder_config.codec());
    413   pp_decoder_config.channel_count =
    414       media::ChannelLayoutToChannelCount(decoder_config.channel_layout());
    415   pp_decoder_config.bits_per_channel = decoder_config.bits_per_channel();
    416   pp_decoder_config.samples_per_second = decoder_config.samples_per_second();
    417   pp_decoder_config.request_id = next_decryption_request_id_++;
    418 
    419   audio_samples_per_second_ = pp_decoder_config.samples_per_second;
    420   audio_channel_count_ = pp_decoder_config.channel_count;
    421 
    422   scoped_refptr<PPB_Buffer_Impl> extra_data_resource;
    423   if (!MakeBufferResource(pp_instance_,
    424                           decoder_config.extra_data(),
    425                           decoder_config.extra_data_size(),
    426                           &extra_data_resource)) {
    427     return false;
    428   }
    429   ScopedPPResource pp_resource(extra_data_resource.get());
    430 
    431   DCHECK_EQ(pending_audio_decoder_init_request_id_, 0u);
    432   DCHECK(pending_audio_decoder_init_cb_.is_null());
    433   pending_audio_decoder_init_request_id_ = pp_decoder_config.request_id;
    434   pending_audio_decoder_init_cb_ = init_cb;
    435 
    436   plugin_decryption_interface_->InitializeAudioDecoder(pp_instance_,
    437                                                        &pp_decoder_config,
    438                                                        pp_resource);
    439   return true;
    440 }
    441 
    442 bool ContentDecryptorDelegate::InitializeVideoDecoder(
    443     const media::VideoDecoderConfig& decoder_config,
    444     const media::Decryptor::DecoderInitCB& init_cb) {
    445   PP_VideoDecoderConfig pp_decoder_config;
    446   pp_decoder_config.codec =
    447       MediaVideoCodecToPpVideoCodec(decoder_config.codec());
    448   pp_decoder_config.profile =
    449       MediaVideoCodecProfileToPpVideoCodecProfile(decoder_config.profile());
    450   pp_decoder_config.format =
    451       MediaVideoFormatToPpDecryptedFrameFormat(decoder_config.format());
    452   pp_decoder_config.width = decoder_config.coded_size().width();
    453   pp_decoder_config.height = decoder_config.coded_size().height();
    454   pp_decoder_config.request_id = next_decryption_request_id_++;
    455 
    456   scoped_refptr<PPB_Buffer_Impl> extra_data_resource;
    457   if (!MakeBufferResource(pp_instance_,
    458                           decoder_config.extra_data(),
    459                           decoder_config.extra_data_size(),
    460                           &extra_data_resource)) {
    461     return false;
    462   }
    463   ScopedPPResource pp_resource(extra_data_resource.get());
    464 
    465   DCHECK_EQ(pending_video_decoder_init_request_id_, 0u);
    466   DCHECK(pending_video_decoder_init_cb_.is_null());
    467   pending_video_decoder_init_request_id_ = pp_decoder_config.request_id;
    468   pending_video_decoder_init_cb_ = init_cb;
    469 
    470   natural_size_ = decoder_config.natural_size();
    471 
    472   plugin_decryption_interface_->InitializeVideoDecoder(pp_instance_,
    473                                                        &pp_decoder_config,
    474                                                        pp_resource);
    475   return true;
    476 }
    477 
    478 bool ContentDecryptorDelegate::DeinitializeDecoder(
    479     media::Decryptor::StreamType stream_type) {
    480   CancelDecode(stream_type);
    481 
    482   natural_size_ = gfx::Size();
    483 
    484   // TODO(tomfinegan): Add decoder deinitialize request tracking, and get
    485   // stream type from media stack.
    486   plugin_decryption_interface_->DeinitializeDecoder(
    487       pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0);
    488   return true;
    489 }
    490 
    491 bool ContentDecryptorDelegate::ResetDecoder(
    492     media::Decryptor::StreamType stream_type) {
    493   CancelDecode(stream_type);
    494 
    495   // TODO(tomfinegan): Add decoder reset request tracking.
    496   plugin_decryption_interface_->ResetDecoder(
    497       pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0);
    498   return true;
    499 }
    500 
    501 bool ContentDecryptorDelegate::DecryptAndDecodeAudio(
    502     const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
    503     const media::Decryptor::AudioDecodeCB& audio_decode_cb) {
    504   // |audio_input_resource_| is not being used by the plugin now
    505   // because there is only one pending audio decode request at any time.
    506   // This is enforced by the media pipeline.
    507   scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
    508   if (!MakeMediaBufferResource(media::Decryptor::kAudio,
    509                                encrypted_buffer,
    510                                &encrypted_resource)) {
    511     return false;
    512   }
    513 
    514   // The resource should not be NULL for non-EOS buffer.
    515   if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get())
    516     return false;
    517 
    518   const uint32_t request_id = next_decryption_request_id_++;
    519   DVLOG(2) << "DecryptAndDecodeAudio() - request_id " << request_id;
    520 
    521   PP_EncryptedBlockInfo block_info = {};
    522   if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
    523     return false;
    524   }
    525 
    526   SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
    527 
    528   // There is only one pending audio decode request at any time. This is
    529   // enforced by the media pipeline. If this DCHECK is violated, our buffer
    530   // reuse policy is not valid, and we may have race problems for the shared
    531   // buffer.
    532   DCHECK_EQ(pending_audio_decode_request_id_, 0u);
    533   DCHECK(pending_audio_decode_cb_.is_null());
    534   pending_audio_decode_request_id_ = request_id;
    535   pending_audio_decode_cb_ = audio_decode_cb;
    536 
    537   ScopedPPResource pp_resource(encrypted_resource.get());
    538   plugin_decryption_interface_->DecryptAndDecode(pp_instance_,
    539                                                  PP_DECRYPTORSTREAMTYPE_AUDIO,
    540                                                  pp_resource,
    541                                                  &block_info);
    542   return true;
    543 }
    544 
    545 bool ContentDecryptorDelegate::DecryptAndDecodeVideo(
    546     const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
    547     const media::Decryptor::VideoDecodeCB& video_decode_cb) {
    548   // |video_input_resource_| is not being used by the plugin now
    549   // because there is only one pending video decode request at any time.
    550   // This is enforced by the media pipeline.
    551   scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
    552   if (!MakeMediaBufferResource(media::Decryptor::kVideo,
    553                                encrypted_buffer,
    554                                &encrypted_resource)) {
    555     return false;
    556   }
    557 
    558   // The resource should not be 0 for non-EOS buffer.
    559   if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get())
    560     return false;
    561 
    562   const uint32_t request_id = next_decryption_request_id_++;
    563   DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id;
    564   TRACE_EVENT_ASYNC_BEGIN0(
    565       "media", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
    566 
    567   PP_EncryptedBlockInfo block_info = {};
    568   if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
    569     return false;
    570   }
    571 
    572   SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
    573 
    574   // Only one pending video decode request at any time. This is enforced by the
    575   // media pipeline. If this DCHECK is violated, our buffer
    576   // reuse policy is not valid, and we may have race problems for the shared
    577   // buffer.
    578   DCHECK_EQ(pending_video_decode_request_id_, 0u);
    579   DCHECK(pending_video_decode_cb_.is_null());
    580   pending_video_decode_request_id_ = request_id;
    581   pending_video_decode_cb_ = video_decode_cb;
    582 
    583   // TODO(tomfinegan): Need to get stream type from media stack.
    584   ScopedPPResource pp_resource(encrypted_resource.get());
    585   plugin_decryption_interface_->DecryptAndDecode(pp_instance_,
    586                                                  PP_DECRYPTORSTREAMTYPE_VIDEO,
    587                                                  pp_resource,
    588                                                  &block_info);
    589   return true;
    590 }
    591 
    592 void ContentDecryptorDelegate::OnSessionCreated(uint32 session_id,
    593                                                 PP_Var web_session_id_var) {
    594   if (session_created_cb_.is_null())
    595     return;
    596 
    597   StringVar* session_id_string = StringVar::FromPPVar(web_session_id_var);
    598 
    599   if (!session_id_string) {
    600     OnSessionError(session_id, media::MediaKeys::kUnknownError, 0);
    601     return;
    602   }
    603 
    604   session_created_cb_.Run(session_id, session_id_string->value());
    605 }
    606 
    607 void ContentDecryptorDelegate::OnSessionMessage(uint32 session_id,
    608                                                 PP_Var message_var,
    609                                                 PP_Var default_url_var) {
    610   if (session_message_cb_.is_null())
    611     return;
    612 
    613   ArrayBufferVar* message_array_buffer = ArrayBufferVar::FromPPVar(message_var);
    614 
    615   std::vector<uint8> message;
    616   if (message_array_buffer) {
    617     const uint8* data = static_cast<const uint8*>(message_array_buffer->Map());
    618     message.assign(data, data + message_array_buffer->ByteLength());
    619   }
    620 
    621   StringVar* default_url_string = StringVar::FromPPVar(default_url_var);
    622 
    623   if (!default_url_string) {
    624     OnSessionError(session_id, media::MediaKeys::kUnknownError, 0);
    625     return;
    626   }
    627 
    628   session_message_cb_.Run(session_id, message, default_url_string->value());
    629 }
    630 
    631 void ContentDecryptorDelegate::OnSessionReady(uint32 session_id) {
    632   if (session_ready_cb_.is_null())
    633     return;
    634 
    635   session_ready_cb_.Run(session_id);
    636 }
    637 
    638 void ContentDecryptorDelegate::OnSessionClosed(uint32 session_id) {
    639   if (session_closed_cb_.is_null())
    640     return;
    641 
    642   session_closed_cb_.Run(session_id);
    643 }
    644 
    645 void ContentDecryptorDelegate::OnSessionError(uint32 session_id,
    646                                               int32_t media_error,
    647                                               int32_t system_code) {
    648   if (session_error_cb_.is_null())
    649     return;
    650 
    651   session_error_cb_.Run(session_id,
    652                         static_cast<media::MediaKeys::KeyError>(media_error),
    653                         system_code);
    654 }
    655 
    656 void ContentDecryptorDelegate::DecoderInitializeDone(
    657      PP_DecryptorStreamType decoder_type,
    658      uint32_t request_id,
    659      PP_Bool success) {
    660   if (decoder_type == PP_DECRYPTORSTREAMTYPE_AUDIO) {
    661     // If the request ID is not valid or does not match what's saved, do
    662     // nothing.
    663     if (request_id == 0 ||
    664         request_id != pending_audio_decoder_init_request_id_)
    665       return;
    666 
    667       DCHECK(!pending_audio_decoder_init_cb_.is_null());
    668       pending_audio_decoder_init_request_id_ = 0;
    669       base::ResetAndReturn(
    670           &pending_audio_decoder_init_cb_).Run(PP_ToBool(success));
    671   } else {
    672     if (request_id == 0 ||
    673         request_id != pending_video_decoder_init_request_id_)
    674       return;
    675 
    676       if (!success)
    677         natural_size_ = gfx::Size();
    678 
    679       DCHECK(!pending_video_decoder_init_cb_.is_null());
    680       pending_video_decoder_init_request_id_ = 0;
    681       base::ResetAndReturn(
    682           &pending_video_decoder_init_cb_).Run(PP_ToBool(success));
    683   }
    684 }
    685 
    686 void ContentDecryptorDelegate::DecoderDeinitializeDone(
    687     PP_DecryptorStreamType decoder_type,
    688     uint32_t request_id) {
    689   // TODO(tomfinegan): Add decoder stop completion handling.
    690 }
    691 
    692 void ContentDecryptorDelegate::DecoderResetDone(
    693     PP_DecryptorStreamType decoder_type,
    694     uint32_t request_id) {
    695   // TODO(tomfinegan): Add decoder reset completion handling.
    696 }
    697 
    698 void ContentDecryptorDelegate::DeliverBlock(
    699     PP_Resource decrypted_block,
    700     const PP_DecryptedBlockInfo* block_info) {
    701   DCHECK(block_info);
    702 
    703   FreeBuffer(block_info->tracking_info.buffer_id);
    704 
    705   const uint32_t request_id = block_info->tracking_info.request_id;
    706   DVLOG(2) << "DeliverBlock() - request_id: " << request_id;
    707 
    708   // If the request ID is not valid or does not match what's saved, do nothing.
    709   if (request_id == 0) {
    710     DVLOG(1) << "DeliverBlock() - invalid request_id " << request_id;
    711     return;
    712   }
    713 
    714   media::Decryptor::DecryptCB decrypt_cb;
    715   if (request_id == pending_audio_decrypt_request_id_) {
    716     DCHECK(!pending_audio_decrypt_cb_.is_null());
    717     pending_audio_decrypt_request_id_ = 0;
    718     decrypt_cb = base::ResetAndReturn(&pending_audio_decrypt_cb_);
    719   } else if (request_id == pending_video_decrypt_request_id_) {
    720     DCHECK(!pending_video_decrypt_cb_.is_null());
    721     pending_video_decrypt_request_id_ = 0;
    722     decrypt_cb = base::ResetAndReturn(&pending_video_decrypt_cb_);
    723   } else {
    724     DVLOG(1) << "DeliverBlock() - request_id " << request_id << " not found";
    725     return;
    726   }
    727 
    728   media::Decryptor::Status status =
    729       PpDecryptResultToMediaDecryptorStatus(block_info->result);
    730   if (status != media::Decryptor::kSuccess) {
    731     decrypt_cb.Run(status, NULL);
    732     return;
    733   }
    734 
    735   EnterResourceNoLock<PPB_Buffer_API> enter(decrypted_block, true);
    736   if (!enter.succeeded()) {
    737     decrypt_cb.Run(media::Decryptor::kError, NULL);
    738     return;
    739   }
    740   BufferAutoMapper mapper(enter.object());
    741   if (!mapper.data() || !mapper.size() ||
    742       mapper.size() < block_info->data_size) {
    743     decrypt_cb.Run(media::Decryptor::kError, NULL);
    744     return;
    745   }
    746 
    747   // TODO(tomfinegan): Find a way to take ownership of the shared memory
    748   // managed by the PPB_Buffer_Dev, and avoid the extra copy.
    749   scoped_refptr<media::DecoderBuffer> decrypted_buffer(
    750       media::DecoderBuffer::CopyFrom(
    751           static_cast<uint8*>(mapper.data()), block_info->data_size));
    752   decrypted_buffer->set_timestamp(base::TimeDelta::FromMicroseconds(
    753       block_info->tracking_info.timestamp));
    754   decrypt_cb.Run(media::Decryptor::kSuccess, decrypted_buffer);
    755 }
    756 
    757 // Use a non-class-member function here so that if for some reason
    758 // ContentDecryptorDelegate is destroyed before VideoFrame calls this callback,
    759 // we can still get the shared memory unmapped.
    760 static void BufferNoLongerNeeded(
    761     const scoped_refptr<PPB_Buffer_Impl>& ppb_buffer,
    762     base::Closure buffer_no_longer_needed_cb) {
    763   ppb_buffer->Unmap();
    764   buffer_no_longer_needed_cb.Run();
    765 }
    766 
    767 // Enters |resource|, maps shared memory and returns pointer of mapped data.
    768 // Returns NULL if any error occurs.
    769 static uint8* GetMappedBuffer(PP_Resource resource,
    770                               scoped_refptr<PPB_Buffer_Impl>* ppb_buffer) {
    771   EnterResourceNoLock<PPB_Buffer_API> enter(resource, true);
    772   if (!enter.succeeded())
    773     return NULL;
    774 
    775   uint8* mapped_data = static_cast<uint8*>(enter.object()->Map());
    776   if (!enter.object()->IsMapped() || !mapped_data)
    777     return NULL;
    778 
    779   uint32_t mapped_size = 0;
    780   if (!enter.object()->Describe(&mapped_size) || !mapped_size) {
    781     enter.object()->Unmap();
    782     return NULL;
    783   }
    784 
    785   *ppb_buffer = static_cast<PPB_Buffer_Impl*>(enter.object());
    786 
    787   return mapped_data;
    788 }
    789 
    790 void ContentDecryptorDelegate::DeliverFrame(
    791     PP_Resource decrypted_frame,
    792     const PP_DecryptedFrameInfo* frame_info) {
    793   DCHECK(frame_info);
    794 
    795   const uint32_t request_id = frame_info->tracking_info.request_id;
    796   DVLOG(2) << "DeliverFrame() - request_id: " << request_id;
    797 
    798   // If the request ID is not valid or does not match what's saved, do nothing.
    799   if (request_id == 0 || request_id != pending_video_decode_request_id_) {
    800     DVLOG(1) << "DeliverFrame() - request_id " << request_id << " not found";
    801     FreeBuffer(frame_info->tracking_info.buffer_id);
    802     return;
    803   }
    804 
    805   TRACE_EVENT_ASYNC_END0(
    806       "media", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
    807 
    808   DCHECK(!pending_video_decode_cb_.is_null());
    809   pending_video_decode_request_id_ = 0;
    810   media::Decryptor::VideoDecodeCB video_decode_cb =
    811       base::ResetAndReturn(&pending_video_decode_cb_);
    812 
    813   media::Decryptor::Status status =
    814       PpDecryptResultToMediaDecryptorStatus(frame_info->result);
    815   if (status != media::Decryptor::kSuccess) {
    816     DCHECK(!frame_info->tracking_info.buffer_id);
    817     video_decode_cb.Run(status, NULL);
    818     return;
    819   }
    820 
    821   scoped_refptr<PPB_Buffer_Impl> ppb_buffer;
    822   uint8* frame_data = GetMappedBuffer(decrypted_frame, &ppb_buffer);
    823   if (!frame_data) {
    824     FreeBuffer(frame_info->tracking_info.buffer_id);
    825     video_decode_cb.Run(media::Decryptor::kError, NULL);
    826     return;
    827   }
    828 
    829   gfx::Size frame_size(frame_info->width, frame_info->height);
    830   DCHECK_EQ(frame_info->format, PP_DECRYPTEDFRAMEFORMAT_YV12);
    831 
    832   scoped_refptr<media::VideoFrame> decoded_frame =
    833       media::VideoFrame::WrapExternalYuvData(
    834           media::VideoFrame::YV12,
    835           frame_size,
    836           gfx::Rect(frame_size),
    837           natural_size_,
    838           frame_info->strides[PP_DECRYPTEDFRAMEPLANES_Y],
    839           frame_info->strides[PP_DECRYPTEDFRAMEPLANES_U],
    840           frame_info->strides[PP_DECRYPTEDFRAMEPLANES_V],
    841           frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y],
    842           frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_U],
    843           frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_V],
    844           base::TimeDelta::FromMicroseconds(
    845               frame_info->tracking_info.timestamp),
    846           media::BindToLoop(
    847               base::MessageLoopProxy::current(),
    848               base::Bind(&BufferNoLongerNeeded,
    849                          ppb_buffer,
    850                          base::Bind(&ContentDecryptorDelegate::FreeBuffer,
    851                                     weak_this_,
    852                                     frame_info->tracking_info.buffer_id))));
    853 
    854   video_decode_cb.Run(media::Decryptor::kSuccess, decoded_frame);
    855 }
    856 
    857 void ContentDecryptorDelegate::DeliverSamples(
    858     PP_Resource audio_frames,
    859     const PP_DecryptedSampleInfo* sample_info) {
    860   DCHECK(sample_info);
    861 
    862   FreeBuffer(sample_info->tracking_info.buffer_id);
    863 
    864   const uint32_t request_id = sample_info->tracking_info.request_id;
    865   DVLOG(2) << "DeliverSamples() - request_id: " << request_id;
    866 
    867   // If the request ID is not valid or does not match what's saved, do nothing.
    868   if (request_id == 0 || request_id != pending_audio_decode_request_id_) {
    869     DVLOG(1) << "DeliverSamples() - request_id " << request_id << " not found";
    870     return;
    871   }
    872 
    873   DCHECK(!pending_audio_decode_cb_.is_null());
    874   pending_audio_decode_request_id_ = 0;
    875   media::Decryptor::AudioDecodeCB audio_decode_cb =
    876       base::ResetAndReturn(&pending_audio_decode_cb_);
    877 
    878   const media::Decryptor::AudioBuffers empty_frames;
    879 
    880   media::Decryptor::Status status =
    881       PpDecryptResultToMediaDecryptorStatus(sample_info->result);
    882   if (status != media::Decryptor::kSuccess) {
    883     audio_decode_cb.Run(status, empty_frames);
    884     return;
    885   }
    886 
    887   media::SampleFormat sample_format =
    888       PpDecryptedSampleFormatToMediaSampleFormat(sample_info->format);
    889 
    890   media::Decryptor::AudioBuffers audio_frame_list;
    891   if (!DeserializeAudioFrames(audio_frames,
    892                               sample_info->data_size,
    893                               sample_format,
    894                               &audio_frame_list)) {
    895     NOTREACHED() << "CDM did not serialize the buffer correctly.";
    896     audio_decode_cb.Run(media::Decryptor::kError, empty_frames);
    897     return;
    898   }
    899 
    900   audio_decode_cb.Run(media::Decryptor::kSuccess, audio_frame_list);
    901 }
    902 
    903 // TODO(xhwang): Try to remove duplicate logic here and in CancelDecrypt().
    904 void ContentDecryptorDelegate::CancelDecode(
    905     media::Decryptor::StreamType stream_type) {
    906   switch (stream_type) {
    907     case media::Decryptor::kAudio:
    908       // Release the shared memory as it can still be in use by the plugin.
    909       // The next DecryptAndDecode() call will need to allocate a new shared
    910       // memory buffer.
    911       audio_input_resource_ = NULL;
    912       pending_audio_decode_request_id_ = 0;
    913       if (!pending_audio_decode_cb_.is_null())
    914         base::ResetAndReturn(&pending_audio_decode_cb_).Run(
    915             media::Decryptor::kSuccess, media::Decryptor::AudioBuffers());
    916       break;
    917     case media::Decryptor::kVideo:
    918       // Release the shared memory as it can still be in use by the plugin.
    919       // The next DecryptAndDecode() call will need to allocate a new shared
    920       // memory buffer.
    921       video_input_resource_ = NULL;
    922       pending_video_decode_request_id_ = 0;
    923       if (!pending_video_decode_cb_.is_null())
    924         base::ResetAndReturn(&pending_video_decode_cb_).Run(
    925             media::Decryptor::kSuccess, NULL);
    926       break;
    927     default:
    928       NOTREACHED();
    929   }
    930 }
    931 
    932 bool ContentDecryptorDelegate::MakeMediaBufferResource(
    933     media::Decryptor::StreamType stream_type,
    934     const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
    935     scoped_refptr<PPB_Buffer_Impl>* resource) {
    936   TRACE_EVENT0("media", "ContentDecryptorDelegate::MakeMediaBufferResource");
    937 
    938   // End of stream buffers are represented as null resources.
    939   if (encrypted_buffer->end_of_stream()) {
    940     *resource = NULL;
    941     return true;
    942   }
    943 
    944   DCHECK(stream_type == media::Decryptor::kAudio ||
    945          stream_type == media::Decryptor::kVideo);
    946   scoped_refptr<PPB_Buffer_Impl>& media_resource =
    947       (stream_type == media::Decryptor::kAudio) ? audio_input_resource_ :
    948                                                   video_input_resource_;
    949 
    950   const size_t data_size = static_cast<size_t>(encrypted_buffer->data_size());
    951   if (!media_resource.get() || media_resource->size() < data_size) {
    952     // Either the buffer hasn't been created yet, or we have one that isn't big
    953     // enough to fit |size| bytes.
    954 
    955     // Media resource size starts from |kMinimumMediaBufferSize| and grows
    956     // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl,
    957     // which is usually expensive. Since input media buffers are compressed,
    958     // they are usually small (compared to outputs). The over-allocated memory
    959     // should be negligible.
    960     const uint32_t kMinimumMediaBufferSize = 1024;
    961     uint32_t media_resource_size =
    962         media_resource.get() ? media_resource->size() : kMinimumMediaBufferSize;
    963     while (media_resource_size < data_size)
    964       media_resource_size *= 2;
    965 
    966     DVLOG(2) << "Size of media buffer for "
    967              << ((stream_type == media::Decryptor::kAudio) ? "audio" : "video")
    968              << " stream bumped to " << media_resource_size
    969              << " bytes to fit input.";
    970     media_resource = PPB_Buffer_Impl::CreateResource(pp_instance_,
    971                                                      media_resource_size);
    972     if (!media_resource.get())
    973       return false;
    974   }
    975 
    976   BufferAutoMapper mapper(media_resource.get());
    977   if (!mapper.data() || mapper.size() < data_size) {
    978     media_resource = NULL;
    979     return false;
    980   }
    981   memcpy(mapper.data(), encrypted_buffer->data(), data_size);
    982 
    983   *resource = media_resource;
    984   return true;
    985 }
    986 
    987 void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) {
    988   if (buffer_id)
    989     free_buffers_.push(buffer_id);
    990 }
    991 
    992 void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo(
    993     PP_DecryptTrackingInfo* tracking_info) {
    994   DCHECK_EQ(tracking_info->buffer_id, 0u);
    995 
    996   if (free_buffers_.empty())
    997     return;
    998 
    999   tracking_info->buffer_id = free_buffers_.front();
   1000   free_buffers_.pop();
   1001 }
   1002 
   1003 bool ContentDecryptorDelegate::DeserializeAudioFrames(
   1004     PP_Resource audio_frames,
   1005     size_t data_size,
   1006     media::SampleFormat sample_format,
   1007     media::Decryptor::AudioBuffers* frames) {
   1008   DCHECK(frames);
   1009   EnterResourceNoLock<PPB_Buffer_API> enter(audio_frames, true);
   1010   if (!enter.succeeded())
   1011     return false;
   1012 
   1013   BufferAutoMapper mapper(enter.object());
   1014   if (!mapper.data() || !mapper.size() ||
   1015       mapper.size() < static_cast<uint32_t>(data_size))
   1016     return false;
   1017 
   1018   // TODO(jrummell): Pass ownership of data() directly to AudioBuffer to avoid
   1019   // the copy. Since it is possible to get multiple buffers, it would need to be
   1020   // sliced and ref counted appropriately. http://crbug.com/255576.
   1021   const uint8* cur = static_cast<uint8*>(mapper.data());
   1022   size_t bytes_left = data_size;
   1023 
   1024   const int audio_bytes_per_frame =
   1025       media::SampleFormatToBytesPerChannel(sample_format) *
   1026       audio_channel_count_;
   1027 
   1028   // Allocate space for the channel pointers given to AudioBuffer.
   1029   std::vector<const uint8*> channel_ptrs(
   1030       audio_channel_count_, static_cast<const uint8*>(NULL));
   1031   do {
   1032     int64 timestamp = 0;
   1033     int64 frame_size = -1;
   1034     const size_t kHeaderSize = sizeof(timestamp) + sizeof(frame_size);
   1035 
   1036     if (bytes_left < kHeaderSize)
   1037       return false;
   1038 
   1039     memcpy(&timestamp, cur, sizeof(timestamp));
   1040     cur += sizeof(timestamp);
   1041     bytes_left -= sizeof(timestamp);
   1042 
   1043     memcpy(&frame_size, cur, sizeof(frame_size));
   1044     cur += sizeof(frame_size);
   1045     bytes_left -= sizeof(frame_size);
   1046 
   1047     // We should *not* have empty frames in the list.
   1048     if (frame_size <= 0 ||
   1049         bytes_left < base::checked_numeric_cast<size_t>(frame_size)) {
   1050       return false;
   1051     }
   1052 
   1053     // Setup channel pointers.  AudioBuffer::CopyFrom() will only use the first
   1054     // one in the case of interleaved data.
   1055     const int size_per_channel = frame_size / audio_channel_count_;
   1056     for (int i = 0; i < audio_channel_count_; ++i)
   1057       channel_ptrs[i] = cur + i * size_per_channel;
   1058 
   1059     const int frame_count = frame_size / audio_bytes_per_frame;
   1060     scoped_refptr<media::AudioBuffer> frame = media::AudioBuffer::CopyFrom(
   1061         sample_format,
   1062         audio_channel_count_,
   1063         frame_count,
   1064         &channel_ptrs[0],
   1065         base::TimeDelta::FromMicroseconds(timestamp),
   1066         base::TimeDelta::FromMicroseconds(audio_samples_per_second_ /
   1067                                           frame_count));
   1068     frames->push_back(frame);
   1069 
   1070     cur += frame_size;
   1071     bytes_left -= frame_size;
   1072   } while (bytes_left > 0);
   1073 
   1074   return true;
   1075 }
   1076 
   1077 }  // namespace content
   1078