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