Upstream version 6.35.121.0
[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/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
29 using media::Decryptor;
30 using ppapi::ArrayBufferVar;
31 using ppapi::PpapiGlobals;
32 using ppapi::ScopedPPResource;
33 using ppapi::StringVar;
34 using ppapi::thunk::EnterResourceNoLock;
35 using ppapi::thunk::PPB_Buffer_API;
36
37 namespace content {
38
39 namespace {
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.
45 bool 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.
74 template <uint32_t array_size>
75 bool 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.
87 static 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
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 Decryptor::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
208 PP_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
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       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
257 ContentDecryptorDelegate::~ContentDecryptorDelegate() {
258   SatisfyAllPendingCallbacksOnError();
259 }
260
261 void 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
284 void ContentDecryptorDelegate::InstanceCrashed() {
285   fatal_plugin_error_cb_.Run();
286   SatisfyAllPendingCallbacksOnError();
287 }
288
289 bool 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
305 void 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
311 bool 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
322 bool 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().
329 bool 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
377 bool 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
408 bool 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
440 bool 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
472 bool 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
486 bool 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
495 bool 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
535 bool 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
578 void 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
593 void 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
617 void ContentDecryptorDelegate::OnSessionReady(uint32 session_id) {
618   if (session_ready_cb_.is_null())
619     return;
620
621   session_ready_cb_.Run(session_id);
622 }
623
624 void ContentDecryptorDelegate::OnSessionClosed(uint32 session_id) {
625   if (session_closed_cb_.is_null())
626     return;
627
628   session_closed_cb_.Run(session_id);
629 }
630
631 void 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
642 void 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
664 void ContentDecryptorDelegate::DecoderDeinitializeDone(
665     PP_DecryptorStreamType decoder_type,
666     uint32_t request_id) {
667   // TODO(tomfinegan): Add decoder stop completion handling.
668 }
669
670 void ContentDecryptorDelegate::DecoderResetDone(
671     PP_DecryptorStreamType decoder_type,
672     uint32_t request_id) {
673   // TODO(tomfinegan): Add decoder reset completion handling.
674 }
675
676 void 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.
734 static 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.
743 static 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
764 void 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
827 void 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().
871 void 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
895 bool 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
949 void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) {
950   if (buffer_id)
951     free_buffers_.push(buffer_id);
952 }
953
954 void 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
965 bool 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
1043 void 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