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