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