Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Unified Diff: webkit/plugins/ppapi/content_decryptor_delegate.cc

Issue 20165002: Move webkit/plugins/ppapi to content/renderer/pepper. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: more more clang fun Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webkit/plugins/ppapi/content_decryptor_delegate.h ('k') | webkit/plugins/ppapi/event_conversion.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/plugins/ppapi/content_decryptor_delegate.cc
===================================================================
--- webkit/plugins/ppapi/content_decryptor_delegate.cc (revision 213561)
+++ webkit/plugins/ppapi/content_decryptor_delegate.cc (working copy)
@@ -1,1048 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/plugins/ppapi/content_decryptor_delegate.h"
-
-#include "base/callback_helpers.h"
-#include "base/debug/trace_event.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/safe_numerics.h"
-#include "media/base/audio_buffer.h"
-#include "media/base/audio_decoder_config.h"
-#include "media/base/bind_to_loop.h"
-#include "media/base/channel_layout.h"
-#include "media/base/data_buffer.h"
-#include "media/base/decoder_buffer.h"
-#include "media/base/decrypt_config.h"
-#include "media/base/video_decoder_config.h"
-#include "media/base/video_frame.h"
-#include "media/base/video_util.h"
-#include "ppapi/shared_impl/scoped_pp_resource.h"
-#include "ppapi/shared_impl/var.h"
-#include "ppapi/shared_impl/var_tracker.h"
-#include "ppapi/thunk/enter.h"
-#include "ppapi/thunk/ppb_buffer_api.h"
-#include "ui/gfx/rect.h"
-#include "webkit/plugins/ppapi/ppb_buffer_impl.h"
-
-using ppapi::ArrayBufferVar;
-using ppapi::PpapiGlobals;
-using ppapi::ScopedPPResource;
-using ppapi::StringVar;
-using ppapi::thunk::EnterResourceNoLock;
-using ppapi::thunk::PPB_Buffer_API;
-
-namespace webkit {
-namespace ppapi {
-
-namespace {
-
-// Fills |resource| with a PPB_Buffer_Impl and copies |data| into the buffer
-// resource. The |*resource|, if valid, will be in the ResourceTracker with a
-// reference-count of 0. If |data| is NULL, sets |*resource| to NULL. Returns
-// true upon success and false if any error happened.
-bool MakeBufferResource(PP_Instance instance,
- const uint8* data, uint32_t size,
- scoped_refptr<PPB_Buffer_Impl>* resource) {
- TRACE_EVENT0("eme", "ContentDecryptorDelegate - MakeBufferResource");
- DCHECK(resource);
-
- if (!data || !size) {
- DCHECK(!data && !size);
- resource = NULL;
- return true;
- }
-
- scoped_refptr<PPB_Buffer_Impl> buffer(
- PPB_Buffer_Impl::CreateResource(instance, size));
- if (!buffer.get())
- return false;
-
- BufferAutoMapper mapper(buffer.get());
- if (!mapper.data() || mapper.size() < size)
- return false;
- memcpy(mapper.data(), data, size);
-
- *resource = buffer;
- return true;
-}
-
-// Copies the content of |str| into |array|.
-// Returns true if copy succeeded. Returns false if copy failed, e.g. if the
-// |array_size| is smaller than the |str| length.
-template <uint32_t array_size>
-bool CopyStringToArray(const std::string& str, uint8 (&array)[array_size]) {
- if (array_size < str.size())
- return false;
-
- memcpy(array, str.data(), str.size());
- return true;
-}
-
-// Fills the |block_info| with information from |encrypted_buffer|.
-//
-// Returns true if |block_info| is successfully filled. Returns false
-// otherwise.
-static bool MakeEncryptedBlockInfo(
- const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
- uint32_t request_id,
- PP_EncryptedBlockInfo* block_info) {
- // TODO(xhwang): Fix initialization of PP_EncryptedBlockInfo here and
- // anywhere else.
- memset(block_info, 0, sizeof(*block_info));
- block_info->tracking_info.request_id = request_id;
-
- // EOS buffers need a request ID and nothing more.
- if (encrypted_buffer->end_of_stream())
- return true;
-
- DCHECK(encrypted_buffer->data_size())
- << "DecryptConfig is set on an empty buffer";
-
- block_info->tracking_info.timestamp =
- encrypted_buffer->timestamp().InMicroseconds();
- block_info->data_size = encrypted_buffer->data_size();
-
- const media::DecryptConfig* decrypt_config =
- encrypted_buffer->decrypt_config();
- block_info->data_offset = decrypt_config->data_offset();
-
- if (!CopyStringToArray(decrypt_config->key_id(), block_info->key_id) ||
- !CopyStringToArray(decrypt_config->iv(), block_info->iv))
- return false;
-
- block_info->key_id_size = decrypt_config->key_id().size();
- block_info->iv_size = decrypt_config->iv().size();
-
- if (decrypt_config->subsamples().size() > arraysize(block_info->subsamples))
- return false;
-
- block_info->num_subsamples = decrypt_config->subsamples().size();
- for (uint32_t i = 0; i < block_info->num_subsamples; ++i) {
- block_info->subsamples[i].clear_bytes =
- decrypt_config->subsamples()[i].clear_bytes;
- block_info->subsamples[i].cipher_bytes =
- decrypt_config->subsamples()[i].cypher_bytes;
- }
-
- return true;
-}
-
-PP_AudioCodec MediaAudioCodecToPpAudioCodec(media::AudioCodec codec) {
- switch (codec) {
- case media::kCodecVorbis:
- return PP_AUDIOCODEC_VORBIS;
- case media::kCodecAAC:
- return PP_AUDIOCODEC_AAC;
- default:
- return PP_AUDIOCODEC_UNKNOWN;
- }
-}
-
-PP_VideoCodec MediaVideoCodecToPpVideoCodec(media::VideoCodec codec) {
- switch (codec) {
- case media::kCodecVP8:
- return PP_VIDEOCODEC_VP8;
- case media::kCodecH264:
- return PP_VIDEOCODEC_H264;
- default:
- return PP_VIDEOCODEC_UNKNOWN;
- }
-}
-
-PP_VideoCodecProfile MediaVideoCodecProfileToPpVideoCodecProfile(
- media::VideoCodecProfile profile) {
- switch (profile) {
- case media::VP8PROFILE_MAIN:
- return PP_VIDEOCODECPROFILE_VP8_MAIN;
- case media::H264PROFILE_BASELINE:
- return PP_VIDEOCODECPROFILE_H264_BASELINE;
- case media::H264PROFILE_MAIN:
- return PP_VIDEOCODECPROFILE_H264_MAIN;
- case media::H264PROFILE_EXTENDED:
- return PP_VIDEOCODECPROFILE_H264_EXTENDED;
- case media::H264PROFILE_HIGH:
- return PP_VIDEOCODECPROFILE_H264_HIGH;
- case media::H264PROFILE_HIGH10PROFILE:
- return PP_VIDEOCODECPROFILE_H264_HIGH_10;
- case media::H264PROFILE_HIGH422PROFILE:
- return PP_VIDEOCODECPROFILE_H264_HIGH_422;
- case media::H264PROFILE_HIGH444PREDICTIVEPROFILE:
- return PP_VIDEOCODECPROFILE_H264_HIGH_444_PREDICTIVE;
- default:
- return PP_VIDEOCODECPROFILE_UNKNOWN;
- }
-}
-
-PP_DecryptedFrameFormat MediaVideoFormatToPpDecryptedFrameFormat(
- media::VideoFrame::Format format) {
- switch (format) {
- case media::VideoFrame::YV12:
- return PP_DECRYPTEDFRAMEFORMAT_YV12;
- case media::VideoFrame::I420:
- return PP_DECRYPTEDFRAMEFORMAT_I420;
- default:
- return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN;
- }
-}
-
-media::Decryptor::Status PpDecryptResultToMediaDecryptorStatus(
- PP_DecryptResult result) {
- switch (result) {
- case PP_DECRYPTRESULT_SUCCESS:
- return media::Decryptor::kSuccess;
- case PP_DECRYPTRESULT_DECRYPT_NOKEY:
- return media::Decryptor::kNoKey;
- case PP_DECRYPTRESULT_NEEDMOREDATA:
- return media::Decryptor::kNeedMoreData;
- case PP_DECRYPTRESULT_DECRYPT_ERROR:
- return media::Decryptor::kError;
- case PP_DECRYPTRESULT_DECODE_ERROR:
- return media::Decryptor::kError;
- default:
- NOTREACHED();
- return media::Decryptor::kError;
- }
-}
-
-PP_DecryptorStreamType MediaDecryptorStreamTypeToPpStreamType(
- media::Decryptor::StreamType stream_type) {
- switch (stream_type) {
- case media::Decryptor::kAudio:
- return PP_DECRYPTORSTREAMTYPE_AUDIO;
- case media::Decryptor::kVideo:
- return PP_DECRYPTORSTREAMTYPE_VIDEO;
- default:
- NOTREACHED();
- return PP_DECRYPTORSTREAMTYPE_VIDEO;
- }
-}
-
-} // namespace
-
-ContentDecryptorDelegate::ContentDecryptorDelegate(
- PP_Instance pp_instance,
- const PPP_ContentDecryptor_Private* plugin_decryption_interface)
- : pp_instance_(pp_instance),
- plugin_decryption_interface_(plugin_decryption_interface),
- next_decryption_request_id_(1),
- pending_audio_decrypt_request_id_(0),
- pending_video_decrypt_request_id_(0),
- pending_audio_decoder_init_request_id_(0),
- pending_video_decoder_init_request_id_(0),
- pending_audio_decode_request_id_(0),
- pending_video_decode_request_id_(0),
- weak_ptr_factory_(this),
- weak_this_(weak_ptr_factory_.GetWeakPtr()),
- audio_sample_format_(media::kUnknownSampleFormat),
- audio_samples_per_second_(0),
- audio_channel_count_(0),
- audio_bytes_per_frame_(0) {
-}
-
-void ContentDecryptorDelegate::Initialize(const std::string& key_system) {
- // TODO(ddorwin): Add an Initialize method to PPP_ContentDecryptor_Private.
- DCHECK(!key_system.empty());
- key_system_ = key_system;
-}
-
-void ContentDecryptorDelegate::SetKeyEventCallbacks(
- const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb) {
- key_added_cb_ = key_added_cb;
- key_error_cb_ = key_error_cb;
- key_message_cb_ = key_message_cb;
-}
-
-bool ContentDecryptorDelegate::GenerateKeyRequest(const std::string& type,
- const uint8* init_data,
- int init_data_length) {
- PP_Var init_data_array =
- PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
- init_data_length, init_data);
-
- plugin_decryption_interface_->GenerateKeyRequest(
- pp_instance_,
- StringVar::StringToPPVar(key_system_), // TODO(ddorwin): Remove.
- StringVar::StringToPPVar(type),
- init_data_array);
- return true;
-}
-
-bool ContentDecryptorDelegate::AddKey(const std::string& session_id,
- const uint8* key,
- int key_length,
- const uint8* init_data,
- int init_data_length) {
- PP_Var key_array =
- PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(key_length,
- key);
- PP_Var init_data_array =
- PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
- init_data_length, init_data);
-
- plugin_decryption_interface_->AddKey(
- pp_instance_,
- StringVar::StringToPPVar(session_id),
- key_array,
- init_data_array);
- return true;
-}
-
-bool ContentDecryptorDelegate::CancelKeyRequest(const std::string& session_id) {
- plugin_decryption_interface_->CancelKeyRequest(
- pp_instance_,
- StringVar::StringToPPVar(session_id));
- return true;
-}
-
-// TODO(xhwang): Remove duplication of code in Decrypt(),
-// DecryptAndDecodeAudio() and DecryptAndDecodeVideo().
-bool ContentDecryptorDelegate::Decrypt(
- media::Decryptor::StreamType stream_type,
- const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
- const media::Decryptor::DecryptCB& decrypt_cb) {
- DVLOG(3) << "Decrypt() - stream_type: " << stream_type;
- // |{audio|video}_input_resource_| is not being used by the plugin
- // now because there is only one pending audio/video decrypt request at any
- // time. This is enforced by the media pipeline.
- scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
- if (!MakeMediaBufferResource(
- stream_type, encrypted_buffer, &encrypted_resource) ||
- !encrypted_resource.get()) {
- return false;
- }
- ScopedPPResource pp_resource(encrypted_resource.get());
-
- const uint32_t request_id = next_decryption_request_id_++;
- DVLOG(2) << "Decrypt() - request_id " << request_id;
-
- PP_EncryptedBlockInfo block_info = {};
- DCHECK(encrypted_buffer->decrypt_config());
- if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
- return false;
- }
-
- // There is only one pending decrypt request at any time per stream. This is
- // enforced by the media pipeline.
- switch (stream_type) {
- case media::Decryptor::kAudio:
- DCHECK_EQ(pending_audio_decrypt_request_id_, 0u);
- DCHECK(pending_audio_decrypt_cb_.is_null());
- pending_audio_decrypt_request_id_ = request_id;
- pending_audio_decrypt_cb_ = decrypt_cb;
- break;
- case media::Decryptor::kVideo:
- DCHECK_EQ(pending_video_decrypt_request_id_, 0u);
- DCHECK(pending_video_decrypt_cb_.is_null());
- pending_video_decrypt_request_id_ = request_id;
- pending_video_decrypt_cb_ = decrypt_cb;
- break;
- default:
- NOTREACHED();
- return false;
- }
-
- SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
-
- plugin_decryption_interface_->Decrypt(pp_instance_,
- pp_resource,
- &block_info);
- return true;
-}
-
-bool ContentDecryptorDelegate::CancelDecrypt(
- media::Decryptor::StreamType stream_type) {
- DVLOG(3) << "CancelDecrypt() - stream_type: " << stream_type;
-
- media::Decryptor::DecryptCB decrypt_cb;
- switch (stream_type) {
- case media::Decryptor::kAudio:
- // Release the shared memory as it can still be in use by the plugin.
- // The next Decrypt() call will need to allocate a new shared memory
- // buffer.
- audio_input_resource_ = NULL;
- pending_audio_decrypt_request_id_ = 0;
- decrypt_cb = base::ResetAndReturn(&pending_audio_decrypt_cb_);
- break;
- case media::Decryptor::kVideo:
- // Release the shared memory as it can still be in use by the plugin.
- // The next Decrypt() call will need to allocate a new shared memory
- // buffer.
- video_input_resource_ = NULL;
- pending_video_decrypt_request_id_ = 0;
- decrypt_cb = base::ResetAndReturn(&pending_video_decrypt_cb_);
- break;
- default:
- NOTREACHED();
- return false;
- }
-
- if (!decrypt_cb.is_null())
- decrypt_cb.Run(media::Decryptor::kSuccess, NULL);
-
- return true;
-}
-
-bool ContentDecryptorDelegate::InitializeAudioDecoder(
- const media::AudioDecoderConfig& decoder_config,
- const media::Decryptor::DecoderInitCB& init_cb) {
- PP_AudioDecoderConfig pp_decoder_config;
- pp_decoder_config.codec =
- MediaAudioCodecToPpAudioCodec(decoder_config.codec());
- pp_decoder_config.channel_count =
- media::ChannelLayoutToChannelCount(decoder_config.channel_layout());
- pp_decoder_config.bits_per_channel = decoder_config.bits_per_channel();
- pp_decoder_config.samples_per_second = decoder_config.samples_per_second();
- pp_decoder_config.request_id = next_decryption_request_id_++;
-
- audio_sample_format_ = decoder_config.sample_format();
- audio_samples_per_second_ = pp_decoder_config.samples_per_second;
- audio_channel_count_ = pp_decoder_config.channel_count;
- audio_bytes_per_frame_ = decoder_config.bytes_per_frame();
-
- scoped_refptr<PPB_Buffer_Impl> extra_data_resource;
- if (!MakeBufferResource(pp_instance_,
- decoder_config.extra_data(),
- decoder_config.extra_data_size(),
- &extra_data_resource)) {
- return false;
- }
- ScopedPPResource pp_resource(extra_data_resource.get());
-
- DCHECK_EQ(pending_audio_decoder_init_request_id_, 0u);
- DCHECK(pending_audio_decoder_init_cb_.is_null());
- pending_audio_decoder_init_request_id_ = pp_decoder_config.request_id;
- pending_audio_decoder_init_cb_ = init_cb;
-
- plugin_decryption_interface_->InitializeAudioDecoder(pp_instance_,
- &pp_decoder_config,
- pp_resource);
- return true;
-}
-
-bool ContentDecryptorDelegate::InitializeVideoDecoder(
- const media::VideoDecoderConfig& decoder_config,
- const media::Decryptor::DecoderInitCB& init_cb) {
- PP_VideoDecoderConfig pp_decoder_config;
- pp_decoder_config.codec =
- MediaVideoCodecToPpVideoCodec(decoder_config.codec());
- pp_decoder_config.profile =
- MediaVideoCodecProfileToPpVideoCodecProfile(decoder_config.profile());
- pp_decoder_config.format =
- MediaVideoFormatToPpDecryptedFrameFormat(decoder_config.format());
- pp_decoder_config.width = decoder_config.coded_size().width();
- pp_decoder_config.height = decoder_config.coded_size().height();
- pp_decoder_config.request_id = next_decryption_request_id_++;
-
- scoped_refptr<PPB_Buffer_Impl> extra_data_resource;
- if (!MakeBufferResource(pp_instance_,
- decoder_config.extra_data(),
- decoder_config.extra_data_size(),
- &extra_data_resource)) {
- return false;
- }
- ScopedPPResource pp_resource(extra_data_resource.get());
-
- DCHECK_EQ(pending_video_decoder_init_request_id_, 0u);
- DCHECK(pending_video_decoder_init_cb_.is_null());
- pending_video_decoder_init_request_id_ = pp_decoder_config.request_id;
- pending_video_decoder_init_cb_ = init_cb;
-
- natural_size_ = decoder_config.natural_size();
-
- plugin_decryption_interface_->InitializeVideoDecoder(pp_instance_,
- &pp_decoder_config,
- pp_resource);
- return true;
-}
-
-bool ContentDecryptorDelegate::DeinitializeDecoder(
- media::Decryptor::StreamType stream_type) {
- CancelDecode(stream_type);
-
- natural_size_ = gfx::Size();
-
- // TODO(tomfinegan): Add decoder deinitialize request tracking, and get
- // stream type from media stack.
- plugin_decryption_interface_->DeinitializeDecoder(
- pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0);
- return true;
-}
-
-bool ContentDecryptorDelegate::ResetDecoder(
- media::Decryptor::StreamType stream_type) {
- CancelDecode(stream_type);
-
- // TODO(tomfinegan): Add decoder reset request tracking.
- plugin_decryption_interface_->ResetDecoder(
- pp_instance_, MediaDecryptorStreamTypeToPpStreamType(stream_type), 0);
- return true;
-}
-
-bool ContentDecryptorDelegate::DecryptAndDecodeAudio(
- const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
- const media::Decryptor::AudioDecodeCB& audio_decode_cb) {
- // |audio_input_resource_| is not being used by the plugin now
- // because there is only one pending audio decode request at any time.
- // This is enforced by the media pipeline.
- scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
- if (!MakeMediaBufferResource(media::Decryptor::kAudio,
- encrypted_buffer,
- &encrypted_resource)) {
- return false;
- }
-
- // The resource should not be NULL for non-EOS buffer.
- if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get())
- return false;
-
- const uint32_t request_id = next_decryption_request_id_++;
- DVLOG(2) << "DecryptAndDecodeAudio() - request_id " << request_id;
-
- PP_EncryptedBlockInfo block_info = {};
- if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
- return false;
- }
-
- SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
-
- // There is only one pending audio decode request at any time. This is
- // enforced by the media pipeline. If this DCHECK is violated, our buffer
- // reuse policy is not valid, and we may have race problems for the shared
- // buffer.
- DCHECK_EQ(pending_audio_decode_request_id_, 0u);
- DCHECK(pending_audio_decode_cb_.is_null());
- pending_audio_decode_request_id_ = request_id;
- pending_audio_decode_cb_ = audio_decode_cb;
-
- ScopedPPResource pp_resource(encrypted_resource.get());
- plugin_decryption_interface_->DecryptAndDecode(pp_instance_,
- PP_DECRYPTORSTREAMTYPE_AUDIO,
- pp_resource,
- &block_info);
- return true;
-}
-
-bool ContentDecryptorDelegate::DecryptAndDecodeVideo(
- const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
- const media::Decryptor::VideoDecodeCB& video_decode_cb) {
- // |video_input_resource_| is not being used by the plugin now
- // because there is only one pending video decode request at any time.
- // This is enforced by the media pipeline.
- scoped_refptr<PPB_Buffer_Impl> encrypted_resource;
- if (!MakeMediaBufferResource(media::Decryptor::kVideo,
- encrypted_buffer,
- &encrypted_resource)) {
- return false;
- }
-
- // The resource should not be 0 for non-EOS buffer.
- if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get())
- return false;
-
- const uint32_t request_id = next_decryption_request_id_++;
- DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id;
- TRACE_EVENT_ASYNC_BEGIN0(
- "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
-
- PP_EncryptedBlockInfo block_info = {};
- if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
- return false;
- }
-
- SetBufferToFreeInTrackingInfo(&block_info.tracking_info);
-
- // Only one pending video decode request at any time. This is enforced by the
- // media pipeline. If this DCHECK is violated, our buffer
- // reuse policy is not valid, and we may have race problems for the shared
- // buffer.
- DCHECK_EQ(pending_video_decode_request_id_, 0u);
- DCHECK(pending_video_decode_cb_.is_null());
- pending_video_decode_request_id_ = request_id;
- pending_video_decode_cb_ = video_decode_cb;
-
- // TODO(tomfinegan): Need to get stream type from media stack.
- ScopedPPResource pp_resource(encrypted_resource.get());
- plugin_decryption_interface_->DecryptAndDecode(pp_instance_,
- PP_DECRYPTORSTREAMTYPE_VIDEO,
- pp_resource,
- &block_info);
- return true;
-}
-
-void ContentDecryptorDelegate::NeedKey(PP_Var key_system_var,
- PP_Var session_id_var,
- PP_Var init_data_var) {
- // TODO(ddorwin): Remove from PPB_ContentDecryptor_Private.
- NOTREACHED();
-}
-
-void ContentDecryptorDelegate::KeyAdded(PP_Var key_system_var,
- PP_Var session_id_var) {
- if (key_added_cb_.is_null())
- return;
-
- StringVar* session_id_string = StringVar::FromPPVar(session_id_var);
- if (!session_id_string) {
- key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0);
- return;
- }
-
- key_added_cb_.Run(session_id_string->value());
-}
-
-void ContentDecryptorDelegate::KeyMessage(PP_Var key_system_var,
- PP_Var session_id_var,
- PP_Var message_var,
- PP_Var default_url_var) {
- if (key_message_cb_.is_null())
- return;
-
- StringVar* session_id_string = StringVar::FromPPVar(session_id_var);
-
- ArrayBufferVar* message_array_buffer =
- ArrayBufferVar::FromPPVar(message_var);
-
- std::vector<uint8> message;
- if (message_array_buffer) {
- const uint8* data = static_cast<const uint8*>(message_array_buffer->Map());
- message.assign(data, data + message_array_buffer->ByteLength());
- }
-
- StringVar* default_url_string = StringVar::FromPPVar(default_url_var);
-
- if (!session_id_string || !default_url_string) {
- key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0);
- return;
- }
-
- key_message_cb_.Run(session_id_string->value(),
- message,
- default_url_string->value());
-}
-
-void ContentDecryptorDelegate::KeyError(PP_Var key_system_var,
- PP_Var session_id_var,
- int32_t media_error,
- int32_t system_code) {
- if (key_error_cb_.is_null())
- return;
-
- StringVar* session_id_string = StringVar::FromPPVar(session_id_var);
- if (!session_id_string) {
- key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0);
- return;
- }
-
- key_error_cb_.Run(session_id_string->value(),
- static_cast<media::MediaKeys::KeyError>(media_error),
- system_code);
-}
-
-void ContentDecryptorDelegate::DecoderInitializeDone(
- PP_DecryptorStreamType decoder_type,
- uint32_t request_id,
- PP_Bool success) {
- if (decoder_type == PP_DECRYPTORSTREAMTYPE_AUDIO) {
- // If the request ID is not valid or does not match what's saved, do
- // nothing.
- if (request_id == 0 ||
- request_id != pending_audio_decoder_init_request_id_)
- return;
-
- DCHECK(!pending_audio_decoder_init_cb_.is_null());
- pending_audio_decoder_init_request_id_ = 0;
- base::ResetAndReturn(
- &pending_audio_decoder_init_cb_).Run(PP_ToBool(success));
- } else {
- if (request_id == 0 ||
- request_id != pending_video_decoder_init_request_id_)
- return;
-
- if (!success)
- natural_size_ = gfx::Size();
-
- DCHECK(!pending_video_decoder_init_cb_.is_null());
- pending_video_decoder_init_request_id_ = 0;
- base::ResetAndReturn(
- &pending_video_decoder_init_cb_).Run(PP_ToBool(success));
- }
-}
-
-void ContentDecryptorDelegate::DecoderDeinitializeDone(
- PP_DecryptorStreamType decoder_type,
- uint32_t request_id) {
- // TODO(tomfinegan): Add decoder stop completion handling.
-}
-
-void ContentDecryptorDelegate::DecoderResetDone(
- PP_DecryptorStreamType decoder_type,
- uint32_t request_id) {
- // TODO(tomfinegan): Add decoder reset completion handling.
-}
-
-void ContentDecryptorDelegate::DeliverBlock(
- PP_Resource decrypted_block,
- const PP_DecryptedBlockInfo* block_info) {
- DCHECK(block_info);
-
- FreeBuffer(block_info->tracking_info.buffer_id);
-
- const uint32_t request_id = block_info->tracking_info.request_id;
- DVLOG(2) << "DeliverBlock() - request_id: " << request_id;
-
- // If the request ID is not valid or does not match what's saved, do nothing.
- if (request_id == 0) {
- DVLOG(1) << "DeliverBlock() - invalid request_id " << request_id;
- return;
- }
-
- media::Decryptor::DecryptCB decrypt_cb;
- if (request_id == pending_audio_decrypt_request_id_) {
- DCHECK(!pending_audio_decrypt_cb_.is_null());
- pending_audio_decrypt_request_id_ = 0;
- decrypt_cb = base::ResetAndReturn(&pending_audio_decrypt_cb_);
- } else if (request_id == pending_video_decrypt_request_id_) {
- DCHECK(!pending_video_decrypt_cb_.is_null());
- pending_video_decrypt_request_id_ = 0;
- decrypt_cb = base::ResetAndReturn(&pending_video_decrypt_cb_);
- } else {
- DVLOG(1) << "DeliverBlock() - request_id " << request_id << " not found";
- return;
- }
-
- media::Decryptor::Status status =
- PpDecryptResultToMediaDecryptorStatus(block_info->result);
- if (status != media::Decryptor::kSuccess) {
- decrypt_cb.Run(status, NULL);
- return;
- }
-
- EnterResourceNoLock<PPB_Buffer_API> enter(decrypted_block, true);
- if (!enter.succeeded()) {
- decrypt_cb.Run(media::Decryptor::kError, NULL);
- return;
- }
- BufferAutoMapper mapper(enter.object());
- if (!mapper.data() || !mapper.size() ||
- mapper.size() < block_info->data_size) {
- decrypt_cb.Run(media::Decryptor::kError, NULL);
- return;
- }
-
- // TODO(tomfinegan): Find a way to take ownership of the shared memory
- // managed by the PPB_Buffer_Dev, and avoid the extra copy.
- scoped_refptr<media::DecoderBuffer> decrypted_buffer(
- media::DecoderBuffer::CopyFrom(
- static_cast<uint8*>(mapper.data()), block_info->data_size));
- decrypted_buffer->set_timestamp(base::TimeDelta::FromMicroseconds(
- block_info->tracking_info.timestamp));
- decrypt_cb.Run(media::Decryptor::kSuccess, decrypted_buffer);
-}
-
-// Use a non-class-member function here so that if for some reason
-// ContentDecryptorDelegate is destroyed before VideoFrame calls this callback,
-// we can still get the shared memory unmapped.
-static void BufferNoLongerNeeded(
- const scoped_refptr<PPB_Buffer_Impl>& ppb_buffer,
- base::Closure buffer_no_longer_needed_cb) {
- ppb_buffer->Unmap();
- buffer_no_longer_needed_cb.Run();
-}
-
-// Enters |resource|, maps shared memory and returns pointer of mapped data.
-// Returns NULL if any error occurs.
-static uint8* GetMappedBuffer(PP_Resource resource,
- scoped_refptr<PPB_Buffer_Impl>* ppb_buffer) {
- EnterResourceNoLock<PPB_Buffer_API> enter(resource, true);
- if (!enter.succeeded())
- return NULL;
-
- uint8* mapped_data = static_cast<uint8*>(enter.object()->Map());
- if (!enter.object()->IsMapped() || !mapped_data)
- return NULL;
-
- uint32_t mapped_size = 0;
- if (!enter.object()->Describe(&mapped_size) || !mapped_size) {
- enter.object()->Unmap();
- return NULL;
- }
-
- *ppb_buffer = static_cast<PPB_Buffer_Impl*>(enter.object());
-
- return mapped_data;
-}
-
-void ContentDecryptorDelegate::DeliverFrame(
- PP_Resource decrypted_frame,
- const PP_DecryptedFrameInfo* frame_info) {
- DCHECK(frame_info);
-
- const uint32_t request_id = frame_info->tracking_info.request_id;
- DVLOG(2) << "DeliverFrame() - request_id: " << request_id;
-
- // If the request ID is not valid or does not match what's saved, do nothing.
- if (request_id == 0 || request_id != pending_video_decode_request_id_) {
- DVLOG(1) << "DeliverFrame() - request_id " << request_id << " not found";
- FreeBuffer(frame_info->tracking_info.buffer_id);
- return;
- }
-
- TRACE_EVENT_ASYNC_END0(
- "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
-
- DCHECK(!pending_video_decode_cb_.is_null());
- pending_video_decode_request_id_ = 0;
- media::Decryptor::VideoDecodeCB video_decode_cb =
- base::ResetAndReturn(&pending_video_decode_cb_);
-
- media::Decryptor::Status status =
- PpDecryptResultToMediaDecryptorStatus(frame_info->result);
- if (status != media::Decryptor::kSuccess) {
- DCHECK(!frame_info->tracking_info.buffer_id);
- video_decode_cb.Run(status, NULL);
- return;
- }
-
- scoped_refptr<PPB_Buffer_Impl> ppb_buffer;
- uint8* frame_data = GetMappedBuffer(decrypted_frame, &ppb_buffer);
- if (!frame_data) {
- FreeBuffer(frame_info->tracking_info.buffer_id);
- video_decode_cb.Run(media::Decryptor::kError, NULL);
- return;
- }
-
- gfx::Size frame_size(frame_info->width, frame_info->height);
- DCHECK_EQ(frame_info->format, PP_DECRYPTEDFRAMEFORMAT_YV12);
-
- scoped_refptr<media::VideoFrame> decoded_frame =
- media::VideoFrame::WrapExternalYuvData(
- media::VideoFrame::YV12,
- frame_size, gfx::Rect(frame_size), natural_size_,
- frame_info->strides[PP_DECRYPTEDFRAMEPLANES_Y],
- frame_info->strides[PP_DECRYPTEDFRAMEPLANES_U],
- frame_info->strides[PP_DECRYPTEDFRAMEPLANES_V],
- frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y],
- frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_U],
- frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_V],
- base::TimeDelta::FromMicroseconds(
- frame_info->tracking_info.timestamp),
- ppb_buffer->shared_memory()->handle(),
- media::BindToLoop(
- base::MessageLoopProxy::current(),
- base::Bind(&BufferNoLongerNeeded, ppb_buffer,
- base::Bind(&ContentDecryptorDelegate::FreeBuffer,
- weak_this_,
- frame_info->tracking_info.buffer_id))));
-
- video_decode_cb.Run(media::Decryptor::kSuccess, decoded_frame);
-}
-
-void ContentDecryptorDelegate::DeliverSamples(
- PP_Resource audio_frames,
- const PP_DecryptedBlockInfo* block_info) {
- DCHECK(block_info);
-
- FreeBuffer(block_info->tracking_info.buffer_id);
-
- const uint32_t request_id = block_info->tracking_info.request_id;
- DVLOG(2) << "DeliverSamples() - request_id: " << request_id;
-
- // If the request ID is not valid or does not match what's saved, do nothing.
- if (request_id == 0 || request_id != pending_audio_decode_request_id_) {
- DVLOG(1) << "DeliverSamples() - request_id " << request_id << " not found";
- return;
- }
-
- DCHECK(!pending_audio_decode_cb_.is_null());
- pending_audio_decode_request_id_ = 0;
- media::Decryptor::AudioDecodeCB audio_decode_cb =
- base::ResetAndReturn(&pending_audio_decode_cb_);
-
- const media::Decryptor::AudioBuffers empty_frames;
-
- media::Decryptor::Status status =
- PpDecryptResultToMediaDecryptorStatus(block_info->result);
- if (status != media::Decryptor::kSuccess) {
- audio_decode_cb.Run(status, empty_frames);
- return;
- }
-
- media::Decryptor::AudioBuffers audio_frame_list;
- if (!DeserializeAudioFrames(audio_frames,
- block_info->data_size,
- &audio_frame_list)) {
- NOTREACHED() << "CDM did not serialize the buffer correctly.";
- audio_decode_cb.Run(media::Decryptor::kError, empty_frames);
- return;
- }
-
- audio_decode_cb.Run(media::Decryptor::kSuccess, audio_frame_list);
-}
-
-// TODO(xhwang): Try to remove duplicate logic here and in CancelDecrypt().
-void ContentDecryptorDelegate::CancelDecode(
- media::Decryptor::StreamType stream_type) {
- switch (stream_type) {
- case media::Decryptor::kAudio:
- // Release the shared memory as it can still be in use by the plugin.
- // The next DecryptAndDecode() call will need to allocate a new shared
- // memory buffer.
- audio_input_resource_ = NULL;
- pending_audio_decode_request_id_ = 0;
- if (!pending_audio_decode_cb_.is_null())
- base::ResetAndReturn(&pending_audio_decode_cb_).Run(
- media::Decryptor::kSuccess, media::Decryptor::AudioBuffers());
- break;
- case media::Decryptor::kVideo:
- // Release the shared memory as it can still be in use by the plugin.
- // The next DecryptAndDecode() call will need to allocate a new shared
- // memory buffer.
- video_input_resource_ = NULL;
- pending_video_decode_request_id_ = 0;
- if (!pending_video_decode_cb_.is_null())
- base::ResetAndReturn(&pending_video_decode_cb_).Run(
- media::Decryptor::kSuccess, NULL);
- break;
- default:
- NOTREACHED();
- }
-}
-
-bool ContentDecryptorDelegate::MakeMediaBufferResource(
- media::Decryptor::StreamType stream_type,
- const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
- scoped_refptr<PPB_Buffer_Impl>* resource) {
- TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource");
-
- // End of stream buffers are represented as null resources.
- if (encrypted_buffer->end_of_stream()) {
- *resource = NULL;
- return true;
- }
-
- DCHECK(stream_type == media::Decryptor::kAudio ||
- stream_type == media::Decryptor::kVideo);
- scoped_refptr<PPB_Buffer_Impl>& media_resource =
- (stream_type == media::Decryptor::kAudio) ? audio_input_resource_ :
- video_input_resource_;
-
- const size_t data_size = static_cast<size_t>(encrypted_buffer->data_size());
- if (!media_resource.get() || media_resource->size() < data_size) {
- // Either the buffer hasn't been created yet, or we have one that isn't big
- // enough to fit |size| bytes.
-
- // Media resource size starts from |kMinimumMediaBufferSize| and grows
- // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl,
- // which is usually expensive. Since input media buffers are compressed,
- // they are usually small (compared to outputs). The over-allocated memory
- // should be negligible.
- const uint32_t kMinimumMediaBufferSize = 1024;
- uint32_t media_resource_size =
- media_resource.get() ? media_resource->size() : kMinimumMediaBufferSize;
- while (media_resource_size < data_size)
- media_resource_size *= 2;
-
- DVLOG(2) << "Size of media buffer for "
- << ((stream_type == media::Decryptor::kAudio) ? "audio" : "video")
- << " stream bumped to " << media_resource_size
- << " bytes to fit input.";
- media_resource = PPB_Buffer_Impl::CreateResource(pp_instance_,
- media_resource_size);
- if (!media_resource.get())
- return false;
- }
-
- BufferAutoMapper mapper(media_resource.get());
- if (!mapper.data() || mapper.size() < data_size) {
- media_resource = NULL;
- return false;
- }
- memcpy(mapper.data(), encrypted_buffer->data(), data_size);
-
- *resource = media_resource;
- return true;
-}
-
-void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) {
- if (buffer_id)
- free_buffers_.push(buffer_id);
-}
-
-void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo(
- PP_DecryptTrackingInfo* tracking_info) {
- DCHECK_EQ(tracking_info->buffer_id, 0u);
-
- if (free_buffers_.empty())
- return;
-
- tracking_info->buffer_id = free_buffers_.front();
- free_buffers_.pop();
-}
-
-bool ContentDecryptorDelegate::DeserializeAudioFrames(
- PP_Resource audio_frames,
- size_t data_size,
- media::Decryptor::AudioBuffers* frames) {
- DCHECK(frames);
- EnterResourceNoLock<PPB_Buffer_API> enter(audio_frames, true);
- if (!enter.succeeded())
- return false;
-
- BufferAutoMapper mapper(enter.object());
- if (!mapper.data() || !mapper.size() ||
- mapper.size() < static_cast<uint32_t>(data_size))
- return false;
-
- // TODO(jrummell): Pass ownership of data() directly to AudioBuffer to avoid
- // the copy. Since it is possible to get multiple buffers, it would need to be
- // sliced and ref counted appropriately. http://crbug.com/255576.
- const uint8* cur = static_cast<uint8*>(mapper.data());
- size_t bytes_left = data_size;
-
- do {
- int64 timestamp = 0;
- int64 frame_size = -1;
- const size_t kHeaderSize = sizeof(timestamp) + sizeof(frame_size);
-
- if (bytes_left < kHeaderSize)
- return false;
-
- memcpy(&timestamp, cur, sizeof(timestamp));
- cur += sizeof(timestamp);
- bytes_left -= sizeof(timestamp);
-
- memcpy(&frame_size, cur, sizeof(frame_size));
- cur += sizeof(frame_size);
- bytes_left -= sizeof(frame_size);
-
- // We should *not* have empty frames in the list.
- if (frame_size <= 0 ||
- bytes_left < base::checked_numeric_cast<size_t>(frame_size)) {
- return false;
- }
-
- const uint8* data[] = {cur};
- int frame_count = frame_size / audio_bytes_per_frame_;
- scoped_refptr<media::AudioBuffer> frame = media::AudioBuffer::CopyFrom(
- audio_sample_format_,
- audio_channel_count_,
- frame_count,
- data,
- base::TimeDelta::FromMicroseconds(timestamp),
- base::TimeDelta::FromMicroseconds(audio_samples_per_second_ /
- frame_count));
- frames->push_back(frame);
-
- cur += frame_size;
- bytes_left -= frame_size;
- } while (bytes_left > 0);
-
- return true;
-}
-
-} // namespace ppapi
-} // namespace webkit
« no previous file with comments | « webkit/plugins/ppapi/content_decryptor_delegate.h ('k') | webkit/plugins/ppapi/event_conversion.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698