diff options
author | xhwang <xhwang@chromium.org> | 2014-11-18 16:16:34 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-19 00:17:00 +0000 |
commit | 16ff136e88d757f4ca92291e8e221682cb1e8c63 (patch) | |
tree | 3ad793cf6fcdb61dd32139849798ba95557ef4ed | |
parent | c69f9dc3d6256814736abcf5b3ef0df37c1406e2 (diff) | |
download | chromium_src-16ff136e88d757f4ca92291e8e221682cb1e8c63.zip chromium_src-16ff136e88d757f4ca92291e8e221682cb1e8c63.tar.gz chromium_src-16ff136e88d757f4ca92291e8e221682cb1e8c63.tar.bz2 |
Move EncryptedMediaPlayerSupport and ProxyDecryptor from content to media.
Summary of changes:
- Drop EncryptedMediaPlayerSupport interface.
- Move EncryptedMediaPlayerSupportImpl to media and rename it to
EncryptedMediaPlayerSupport.
- Drop NullEncryptedMediaPlayerSupport.
- Drop EncryptedMediaPlayerSupportCreateCB from WebMediaPlayerParams, and let WebMediaPlayerImpl always own a EncryptedMediaPlayerSupport.
- EncryptedMediaPlayerSupport takes an external CdmFactory.
- Pass a CdmFactory to WebMediaPlayerImpl's constructor.
- Move ProxyDecryptor to media.
BUG=422730
Review URL: https://codereview.chromium.org/737483002
Cr-Commit-Position: refs/heads/master@{#304712}
22 files changed, 608 insertions, 904 deletions
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 0ea1a4d..414754d 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -248,15 +248,11 @@ 'renderer/media/audio_message_filter.h', 'renderer/media/audio_renderer_mixer_manager.cc', 'renderer/media/audio_renderer_mixer_manager.h', - 'renderer/media/crypto/encrypted_media_player_support_impl.cc', - 'renderer/media/crypto/encrypted_media_player_support_impl.h', 'renderer/media/crypto/pepper_cdm_wrapper.h', 'renderer/media/crypto/pepper_cdm_wrapper_impl.cc', 'renderer/media/crypto/pepper_cdm_wrapper_impl.h', 'renderer/media/crypto/ppapi_decryptor.cc', 'renderer/media/crypto/ppapi_decryptor.h', - 'renderer/media/crypto/proxy_decryptor.cc', - 'renderer/media/crypto/proxy_decryptor.h', 'renderer/media/crypto/render_cdm_factory.cc', 'renderer/media/crypto/render_cdm_factory.h', 'renderer/media/media_stream_audio_level_calculator.cc', @@ -744,7 +740,6 @@ ['OS=="android"', { 'sources!': [ 'renderer/media/audio_decoder.cc', - 'renderer/media/crypto/encrypted_media_player_support_impl.cc', ], 'sources': [ 'renderer/external_popup_menu.cc', diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 22acf49b..bfe9605 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn @@ -83,7 +83,6 @@ source_set("renderer") { if (is_android) { sources -= [ "media/audio_decoder.cc", - "media/crypto/encrypted_media_player_support_impl.cc", ] sources += [ "external_popup_menu.cc", diff --git a/content/renderer/media/android/webmediaplayer_android.cc b/content/renderer/media/android/webmediaplayer_android.cc index 196b9a7..deb3417 100644 --- a/content/renderer/media/android/webmediaplayer_android.cc +++ b/content/renderer/media/android/webmediaplayer_android.cc @@ -1508,7 +1508,7 @@ WebMediaPlayerAndroid::GenerateKeyRequestInternal( // We do not support run-time switching between key systems for now. if (current_key_system_.empty()) { if (!proxy_decryptor_) { - proxy_decryptor_.reset(new ProxyDecryptor( + proxy_decryptor_.reset(new media::ProxyDecryptor( base::Bind(&WebMediaPlayerAndroid::OnKeyAdded, weak_factory_.GetWeakPtr()), base::Bind(&WebMediaPlayerAndroid::OnKeyError, diff --git a/content/renderer/media/android/webmediaplayer_android.h b/content/renderer/media/android/webmediaplayer_android.h index 771074d..0da37eb 100644 --- a/content/renderer/media/android/webmediaplayer_android.h +++ b/content/renderer/media/android/webmediaplayer_android.h @@ -22,12 +22,12 @@ #include "content/renderer/media/android/media_info_loader.h" #include "content/renderer/media/android/media_source_delegate.h" #include "content/renderer/media/android/stream_texture_factory.h" -#include "content/renderer/media/crypto/proxy_decryptor.h" #include "gpu/command_buffer/common/mailbox.h" #include "media/base/android/media_player_android.h" #include "media/base/demuxer_stream.h" #include "media/base/media_keys.h" #include "media/base/time_delta_interpolator.h" +#include "media/cdm/proxy_decryptor.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" #include "third_party/WebKit/public/platform/WebMediaPlayer.h" #include "third_party/WebKit/public/platform/WebSize.h" @@ -473,7 +473,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer, std::string init_data_type_; // Manages decryption keys and decrypts encrypted frames. - scoped_ptr<ProxyDecryptor> proxy_decryptor_; + scoped_ptr<media::ProxyDecryptor> proxy_decryptor_; // Non-owned pointer to the CDM. Updated via calls to // setContentDecryptionModule(). diff --git a/content/renderer/media/crypto/encrypted_media_player_support_impl.cc b/content/renderer/media/crypto/encrypted_media_player_support_impl.cc deleted file mode 100644 index 86e3329..0000000 --- a/content/renderer/media/crypto/encrypted_media_player_support_impl.cc +++ /dev/null @@ -1,475 +0,0 @@ -// Copyright 2014 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 "content/renderer/media/crypto/encrypted_media_player_support_impl.h" - -#include <string> - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/metrics/histogram.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "content/renderer/media/crypto/render_cdm_factory.h" -#include "media/base/bind_to_current_loop.h" -#include "media/base/key_systems.h" -#include "media/blink/encrypted_media_player_support.h" -#include "media/blink/webcontentdecryptionmodule_impl.h" -#include "third_party/WebKit/public/platform/WebContentDecryptionModule.h" -#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h" -#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebRuntimeFeatures.h" - -#if defined(ENABLE_PEPPER_CDMS) -#include "content/renderer/media/crypto/pepper_cdm_wrapper_impl.h" -#elif defined(ENABLE_BROWSER_CDMS) -#error Browser side CDM in WMPI for prefixed EME API not supported yet. -#endif - -using blink::WebMediaPlayer; -using blink::WebMediaPlayerClient; -using blink::WebString; - -namespace content { - -#define BIND_TO_RENDER_LOOP(function) \ - (media::BindToCurrentLoop(base::Bind(function, AsWeakPtr()))) - -#define BIND_TO_RENDER_LOOP1(function, arg1) \ - (media::BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1))) - -// Prefix for histograms related to Encrypted Media Extensions. -static const char* kMediaEme = "Media.EME."; - -// Used for calls to decryptor_ready_cb where the result can be ignored. -static void DoNothing(bool success) { -} - -// Convert a WebString to ASCII, falling back on an empty string in the case -// of a non-ASCII string. -static std::string ToASCIIOrEmpty(const WebString& string) { - return base::IsStringASCII(string) ? base::UTF16ToASCII(string) - : std::string(); -} - -// Helper functions to report media EME related stats to UMA. They follow the -// convention of more commonly used macros UMA_HISTOGRAM_ENUMERATION and -// UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is -// that UMA_* macros require the names to be constant throughout the process' -// lifetime. -static void EmeUMAHistogramEnumeration(const std::string& key_system, - const std::string& method, - int sample, - int boundary_value) { - base::LinearHistogram::FactoryGet( - kMediaEme + media::GetKeySystemNameForUMA(key_system) + "." + method, - 1, boundary_value, boundary_value + 1, - base::Histogram::kUmaTargetedHistogramFlag)->Add(sample); -} - -static void EmeUMAHistogramCounts(const std::string& key_system, - const std::string& method, - int sample) { - // Use the same parameters as UMA_HISTOGRAM_COUNTS. - base::Histogram::FactoryGet( - kMediaEme + media::GetKeySystemNameForUMA(key_system) + "." + method, - 1, 1000000, 50, base::Histogram::kUmaTargetedHistogramFlag)->Add(sample); -} - -// Helper enum for reporting generateKeyRequest/addKey histograms. -enum MediaKeyException { - kUnknownResultId, - kSuccess, - kKeySystemNotSupported, - kInvalidPlayerState, - kMaxMediaKeyException -}; - -static MediaKeyException MediaKeyExceptionForUMA( - WebMediaPlayer::MediaKeyException e) { - switch (e) { - case WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported: - return kKeySystemNotSupported; - case WebMediaPlayer::MediaKeyExceptionInvalidPlayerState: - return kInvalidPlayerState; - case WebMediaPlayer::MediaKeyExceptionNoError: - return kSuccess; - default: - return kUnknownResultId; - } -} - -// Helper for converting |key_system| name and exception |e| to a pair of enum -// values from above, for reporting to UMA. -static void ReportMediaKeyExceptionToUMA(const std::string& method, - const std::string& key_system, - WebMediaPlayer::MediaKeyException e) { - MediaKeyException result_id = MediaKeyExceptionForUMA(e); - DCHECK_NE(result_id, kUnknownResultId) << e; - EmeUMAHistogramEnumeration( - key_system, method, result_id, kMaxMediaKeyException); -} - -// Guess the type of |init_data|. This is only used to handle some corner cases -// so we keep it as simple as possible without breaking major use cases. -static std::string GuessInitDataType(const unsigned char* init_data, - unsigned init_data_length) { - // Most WebM files use KeyId of 16 bytes. CENC init data is always >16 bytes. - if (init_data_length == 16) - return "webm"; - - return "cenc"; -} - -scoped_ptr<media::EncryptedMediaPlayerSupport> -EncryptedMediaPlayerSupportImpl::Create(blink::WebMediaPlayerClient* client) { - return scoped_ptr<EncryptedMediaPlayerSupport>( - new EncryptedMediaPlayerSupportImpl(client)); -} - -EncryptedMediaPlayerSupportImpl::EncryptedMediaPlayerSupportImpl( - blink::WebMediaPlayerClient* client) - : client_(client), - web_cdm_(NULL) { -} - -EncryptedMediaPlayerSupportImpl::~EncryptedMediaPlayerSupportImpl() { -} - -WebMediaPlayer::MediaKeyException -EncryptedMediaPlayerSupportImpl::GenerateKeyRequest( - blink::WebLocalFrame* frame, - const WebString& key_system, - const unsigned char* init_data, - unsigned init_data_length) { - DVLOG(1) << "generateKeyRequest: " << base::string16(key_system) << ": " - << std::string(reinterpret_cast<const char*>(init_data), - static_cast<size_t>(init_data_length)); - - std::string ascii_key_system = - media::GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system)); - - WebMediaPlayer::MediaKeyException e = - GenerateKeyRequestInternal(frame, ascii_key_system, init_data, - init_data_length); - ReportMediaKeyExceptionToUMA("generateKeyRequest", ascii_key_system, e); - return e; -} - -WebMediaPlayer::MediaKeyException -EncryptedMediaPlayerSupportImpl::GenerateKeyRequestInternal( - blink::WebLocalFrame* frame, - const std::string& key_system, - const unsigned char* init_data, - unsigned init_data_length) { - if (!media::IsConcreteSupportedKeySystem(key_system)) - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; - - // We do not support run-time switching between key systems for now. - if (current_key_system_.empty()) { - if (!proxy_decryptor_) { - proxy_decryptor_.reset(new ProxyDecryptor( - BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnKeyAdded), - BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnKeyError), - BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnKeyMessage))); - } - - GURL security_origin(frame->document().securityOrigin().toString()); - -#if defined(ENABLE_PEPPER_CDMS) - RenderCdmFactory cdm_factory( - base::Bind(&PepperCdmWrapperImpl::Create, frame)); -#else - RenderCdmFactory cdm_factory; -#endif - - if (!proxy_decryptor_->InitializeCDM(&cdm_factory, key_system, - security_origin)) { - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; - } - - if (proxy_decryptor_ && !decryptor_ready_cb_.is_null()) { - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(proxy_decryptor_->GetDecryptor(), base::Bind(DoNothing)); - } - - current_key_system_ = key_system; - } else if (key_system != current_key_system_) { - return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; - } - - std::string init_data_type = init_data_type_; - if (init_data_type.empty()) - init_data_type = GuessInitDataType(init_data, init_data_length); - - // TODO(xhwang): We assume all streams are from the same container (thus have - // the same "type") for now. In the future, the "type" should be passed down - // from the application. - if (!proxy_decryptor_->GenerateKeyRequest( - init_data_type, init_data, init_data_length)) { - current_key_system_.clear(); - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; - } - - return WebMediaPlayer::MediaKeyExceptionNoError; -} - -WebMediaPlayer::MediaKeyException EncryptedMediaPlayerSupportImpl::AddKey( - const WebString& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const WebString& session_id) { - DVLOG(1) << "addKey: " << base::string16(key_system) << ": " - << std::string(reinterpret_cast<const char*>(key), - static_cast<size_t>(key_length)) << ", " - << std::string(reinterpret_cast<const char*>(init_data), - static_cast<size_t>(init_data_length)) << " [" - << base::string16(session_id) << "]"; - - std::string ascii_key_system = - media::GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system)); - std::string ascii_session_id = ToASCIIOrEmpty(session_id); - - WebMediaPlayer::MediaKeyException e = AddKeyInternal(ascii_key_system, - key, - key_length, - init_data, - init_data_length, - ascii_session_id); - ReportMediaKeyExceptionToUMA("addKey", ascii_key_system, e); - return e; -} - -WebMediaPlayer::MediaKeyException -EncryptedMediaPlayerSupportImpl::AddKeyInternal( - const std::string& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const std::string& session_id) { - DCHECK(key); - DCHECK_GT(key_length, 0u); - - if (!media::IsConcreteSupportedKeySystem(key_system)) - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; - - if (current_key_system_.empty() || key_system != current_key_system_) - return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; - - proxy_decryptor_->AddKey( - key, key_length, init_data, init_data_length, session_id); - return WebMediaPlayer::MediaKeyExceptionNoError; -} - -WebMediaPlayer::MediaKeyException -EncryptedMediaPlayerSupportImpl::CancelKeyRequest( - const WebString& key_system, - const WebString& session_id) { - DVLOG(1) << "cancelKeyRequest: " << base::string16(key_system) << ": " - << " [" << base::string16(session_id) << "]"; - - std::string ascii_key_system = - media::GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system)); - std::string ascii_session_id = ToASCIIOrEmpty(session_id); - - WebMediaPlayer::MediaKeyException e = - CancelKeyRequestInternal(ascii_key_system, ascii_session_id); - ReportMediaKeyExceptionToUMA("cancelKeyRequest", ascii_key_system, e); - return e; -} - -WebMediaPlayer::MediaKeyException -EncryptedMediaPlayerSupportImpl::CancelKeyRequestInternal( - const std::string& key_system, - const std::string& session_id) { - if (!media::IsConcreteSupportedKeySystem(key_system)) - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; - - if (current_key_system_.empty() || key_system != current_key_system_) - return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; - - proxy_decryptor_->CancelKeyRequest(session_id); - return WebMediaPlayer::MediaKeyExceptionNoError; -} - -void EncryptedMediaPlayerSupportImpl::SetInitialContentDecryptionModule( - blink::WebContentDecryptionModule* initial_cdm) { - // Used when loading media and no pipeline/decoder attached yet. - DCHECK(decryptor_ready_cb_.is_null()); - - web_cdm_ = media::ToWebContentDecryptionModuleImpl(initial_cdm); -} - -void EncryptedMediaPlayerSupportImpl::SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm) { - // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324 - if (!cdm) - return; - - web_cdm_ = media::ToWebContentDecryptionModuleImpl(cdm); - - if (web_cdm_ && !decryptor_ready_cb_.is_null()) - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing)); -} - -void EncryptedMediaPlayerSupportImpl::SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result) { - // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324 - if (!cdm) { - result.completeWithError( - blink::WebContentDecryptionModuleExceptionNotSupportedError, - 0, - "Null MediaKeys object is not supported."); - return; - } - - web_cdm_ = media::ToWebContentDecryptionModuleImpl(cdm); - - if (web_cdm_ && !decryptor_ready_cb_.is_null()) { - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(web_cdm_->GetDecryptor(), BIND_TO_RENDER_LOOP1( - &EncryptedMediaPlayerSupportImpl::ContentDecryptionModuleAttached, - result)); - } else { - // No pipeline/decoder connected, so resolve the promise. When something - // is connected, setting the CDM will happen in SetDecryptorReadyCB(). - ContentDecryptionModuleAttached(result, true); - } -} - -void EncryptedMediaPlayerSupportImpl::ContentDecryptionModuleAttached( - blink::WebContentDecryptionModuleResult result, - bool success) { - if (success) { - result.complete(); - return; - } - - result.completeWithError( - blink::WebContentDecryptionModuleExceptionNotSupportedError, - 0, - "Unable to set MediaKeys object"); -} - -media::SetDecryptorReadyCB -EncryptedMediaPlayerSupportImpl::CreateSetDecryptorReadyCB() { - return BIND_TO_RENDER_LOOP( - &EncryptedMediaPlayerSupportImpl::SetDecryptorReadyCB); -} - -media::Demuxer::NeedKeyCB -EncryptedMediaPlayerSupportImpl::CreateNeedKeyCB() { - return BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnNeedKey); -} - -void EncryptedMediaPlayerSupportImpl::OnPipelineDecryptError() { - EmeUMAHistogramCounts(current_key_system_, "DecryptError", 1); -} - -void EncryptedMediaPlayerSupportImpl::OnNeedKey(const std::string& type, - const std::vector<uint8>& init_data) { - // Do not fire NeedKey event if encrypted media is not enabled. - if (!blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled() && - !blink::WebRuntimeFeatures::isEncryptedMediaEnabled()) { - return; - } - - UMA_HISTOGRAM_COUNTS(kMediaEme + std::string("NeedKey"), 1); - - DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_); - if (init_data_type_.empty()) - init_data_type_ = type; - - const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0]; - client_->encrypted( - WebString::fromUTF8(type), init_data_ptr, init_data.size()); -} - -void EncryptedMediaPlayerSupportImpl::OnKeyAdded( - const std::string& session_id) { - EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1); - client_->keyAdded( - WebString::fromUTF8(media::GetPrefixedKeySystemName(current_key_system_)), - WebString::fromUTF8(session_id)); -} - -void EncryptedMediaPlayerSupportImpl::OnKeyError(const std::string& session_id, - media::MediaKeys::KeyError error_code, - uint32 system_code) { - EmeUMAHistogramEnumeration(current_key_system_, "KeyError", - error_code, media::MediaKeys::kMaxKeyError); - - uint16 short_system_code = 0; - if (system_code > std::numeric_limits<uint16>::max()) { - LOG(WARNING) << "system_code exceeds unsigned short limit."; - short_system_code = std::numeric_limits<uint16>::max(); - } else { - short_system_code = static_cast<uint16>(system_code); - } - - client_->keyError( - WebString::fromUTF8(media::GetPrefixedKeySystemName(current_key_system_)), - WebString::fromUTF8(session_id), - static_cast<WebMediaPlayerClient::MediaKeyErrorCode>(error_code), - short_system_code); -} - -void EncryptedMediaPlayerSupportImpl::OnKeyMessage( - const std::string& session_id, - const std::vector<uint8>& message, - const GURL& destination_url) { - DCHECK(destination_url.is_empty() || destination_url.is_valid()); - - client_->keyMessage( - WebString::fromUTF8(media::GetPrefixedKeySystemName(current_key_system_)), - WebString::fromUTF8(session_id), - message.empty() ? NULL : &message[0], - message.size(), - destination_url); -} - -void EncryptedMediaPlayerSupportImpl::SetDecryptorReadyCB( - const media::DecryptorReadyCB& decryptor_ready_cb) { - // Cancels the previous decryptor request. - if (decryptor_ready_cb.is_null()) { - if (!decryptor_ready_cb_.is_null()) { - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(NULL, base::Bind(DoNothing)); - } - return; - } - - // TODO(xhwang): Support multiple decryptor notification request (e.g. from - // video and audio). The current implementation is okay for the current - // media pipeline since we initialize audio and video decoders in sequence. - // But WebMediaPlayerImpl should not depend on media pipeline's implementation - // detail. - DCHECK(decryptor_ready_cb_.is_null()); - - // Mixed use of prefixed and unprefixed EME APIs is disallowed by Blink. - DCHECK(!proxy_decryptor_ || !web_cdm_); - - if (proxy_decryptor_) { - decryptor_ready_cb.Run(proxy_decryptor_->GetDecryptor(), - base::Bind(DoNothing)); - return; - } - - if (web_cdm_) { - decryptor_ready_cb.Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing)); - return; - } - - decryptor_ready_cb_ = decryptor_ready_cb; -} - -} // namespace content diff --git a/content/renderer/media/crypto/encrypted_media_player_support_impl.h b/content/renderer/media/crypto/encrypted_media_player_support_impl.h deleted file mode 100644 index 88d55d1..0000000 --- a/content/renderer/media/crypto/encrypted_media_player_support_impl.h +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2014 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. - -#ifndef CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_IMPL_H_ -#define CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_IMPL_H_ - -#include <string> -#include <vector> - -#include "base/memory/weak_ptr.h" -#include "content/renderer/media/crypto/proxy_decryptor.h" -#include "media/blink/encrypted_media_player_support.h" -#include "media/blink/webcontentdecryptionmodule_impl.h" - -namespace blink { -class WebMediaPlayerClient; -} - -namespace content { - -class WebContentDecryptionModuleImpl; - -class EncryptedMediaPlayerSupportImpl - : public media::EncryptedMediaPlayerSupport, - public base::SupportsWeakPtr<EncryptedMediaPlayerSupportImpl> { - public: - static scoped_ptr<EncryptedMediaPlayerSupport> Create( - blink::WebMediaPlayerClient* client); - - ~EncryptedMediaPlayerSupportImpl() override; - - // EncryptedMediaPlayerSupport implementation. - blink::WebMediaPlayer::MediaKeyException GenerateKeyRequest( - blink::WebLocalFrame* frame, - const blink::WebString& key_system, - const unsigned char* init_data, - unsigned init_data_length) override; - - blink::WebMediaPlayer::MediaKeyException AddKey( - const blink::WebString& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const blink::WebString& session_id) override; - - blink::WebMediaPlayer::MediaKeyException CancelKeyRequest( - const blink::WebString& key_system, - const blink::WebString& session_id) override; - - void SetInitialContentDecryptionModule( - blink::WebContentDecryptionModule* initial_cdm) override; - - void SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm) override; - void SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result) override; - - media::SetDecryptorReadyCB CreateSetDecryptorReadyCB() override; - media::Demuxer::NeedKeyCB CreateNeedKeyCB() override; - - void OnPipelineDecryptError() override; - - private: - explicit EncryptedMediaPlayerSupportImpl(blink::WebMediaPlayerClient* client); - - // Requests that this object notifies when a decryptor is ready through the - // |decryptor_ready_cb| provided. - // If |decryptor_ready_cb| is null, the existing callback will be fired with - // NULL immediately and reset. - void SetDecryptorReadyCB(const media::DecryptorReadyCB& decryptor_ready_cb); - - blink::WebMediaPlayer::MediaKeyException GenerateKeyRequestInternal( - blink::WebLocalFrame* frame, - const std::string& key_system, - const unsigned char* init_data, - unsigned init_data_length); - - blink::WebMediaPlayer::MediaKeyException AddKeyInternal( - const std::string& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const std::string& session_id); - - blink::WebMediaPlayer::MediaKeyException CancelKeyRequestInternal( - const std::string& key_system, - const std::string& session_id); - - void OnNeedKey(const std::string& type, - const std::vector<uint8>& init_data); - - void OnKeyAdded(const std::string& session_id); - void OnKeyError(const std::string& session_id, - media::MediaKeys::KeyError error_code, - uint32 system_code); - void OnKeyMessage(const std::string& session_id, - const std::vector<uint8>& message, - const GURL& destination_url); - - void ContentDecryptionModuleAttached( - blink::WebContentDecryptionModuleResult result, - bool success); - - blink::WebMediaPlayerClient* client_; - - // The currently selected key system. Empty string means that no key system - // has been selected. - std::string current_key_system_; - - // Temporary for EME v0.1. In the future the init data type should be passed - // through GenerateKeyRequest() directly from WebKit. - std::string init_data_type_; - - // Manages decryption keys and decrypts encrypted frames. - scoped_ptr<ProxyDecryptor> proxy_decryptor_; - - // Non-owned pointer to the CDM. Updated via calls to - // setContentDecryptionModule(). - media::WebContentDecryptionModuleImpl* web_cdm_; - - media::DecryptorReadyCB decryptor_ready_cb_; - - DISALLOW_COPY_AND_ASSIGN(EncryptedMediaPlayerSupportImpl); -}; -} - -#endif // CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_IMPL_H_ diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 8e70202..8678b58 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc @@ -70,7 +70,6 @@ #include "content/renderer/internal_document_state_data.h" #include "content/renderer/manifest/manifest_manager.h" #include "content/renderer/media/audio_renderer_mixer_manager.h" -#include "content/renderer/media/crypto/encrypted_media_player_support_impl.h" #include "content/renderer/media/crypto/render_cdm_factory.h" #include "content/renderer/media/media_stream_dispatcher.h" #include "content/renderer/media/media_stream_renderer_factory.h" @@ -97,6 +96,7 @@ #include "gin/modules/module_registry.h" #include "media/base/audio_renderer_mixer_input.h" #include "media/base/renderer.h" +#include "media/blink/encrypted_media_player_support.h" #include "media/blink/webcontentdecryptionmodule_impl.h" #include "media/blink/webmediaplayer_impl.h" #include "media/blink/webmediaplayer_params.h" @@ -1773,15 +1773,22 @@ blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer( render_thread->GetGpuFactories(), render_thread->GetMediaThreadTaskRunner(), render_thread->compositor_message_loop_proxy(), - base::Bind(&EncryptedMediaPlayerSupportImpl::Create), initial_cdm); +#if defined(ENABLE_PEPPER_CDMS) + scoped_ptr<media::CdmFactory> cdm_factory( + new RenderCdmFactory(base::Bind(&PepperCdmWrapperImpl::Create, frame))); +#else + scoped_ptr<media::CdmFactory> cdm_factory(new RenderCdmFactory()); +#endif + scoped_ptr<media::Renderer> media_renderer = GetContentClient()->renderer()->CreateMediaRenderer( this, render_thread->GetMediaThreadTaskRunner()); return new media::WebMediaPlayerImpl( - frame, client, weak_factory_.GetWeakPtr(), media_renderer.Pass(), params); + frame, client, weak_factory_.GetWeakPtr(), media_renderer.Pass(), + cdm_factory.Pass(), params); #endif // defined(OS_ANDROID) } diff --git a/media/BUILD.gn b/media/BUILD.gn index 2496984..20f1eaa 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn @@ -73,6 +73,8 @@ component("media") { "cdm/key_system_names.h", "cdm/player_tracker_impl.cc", "cdm/player_tracker_impl.h", + "cdm/proxy_decryptor.cc", + "cdm/proxy_decyrptor.h", "ffmpeg/ffmpeg_deleters.h", "filters/audio_clock.cc", "filters/audio_clock.h", diff --git a/media/blink/BUILD.gn b/media/blink/BUILD.gn index e842fb1..fbf06dc 100644 --- a/media/blink/BUILD.gn +++ b/media/blink/BUILD.gn @@ -39,8 +39,6 @@ component("blink") { "encrypted_media_player_support.h", "new_session_cdm_result_promise.cc", "new_session_cdm_result_promise.h", - "null_encrypted_media_player_support.cc", - "null_encrypted_media_player_support.h", "texttrack_impl.cc", "texttrack_impl.h", "video_frame_compositor.cc", @@ -68,6 +66,8 @@ component("blink") { if (is_android) { sources -= [ + "encrypted_media_player_support.cc", + "encrypted_media_player_support.h", "webmediaplayer_impl.cc", "webmediaplayer_impl.h", ] diff --git a/media/blink/encrypted_media_player_support.cc b/media/blink/encrypted_media_player_support.cc index 663141f..0d91279 100644 --- a/media/blink/encrypted_media_player_support.cc +++ b/media/blink/encrypted_media_player_support.cc @@ -4,12 +4,445 @@ #include "media/blink/encrypted_media_player_support.h" +#include <string> + +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/metrics/histogram.h" +#include "base/numerics/safe_conversions.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "media/base/bind_to_current_loop.h" +#include "media/base/key_systems.h" +#include "media/blink/webcontentdecryptionmodule_impl.h" +#include "third_party/WebKit/public/platform/WebContentDecryptionModule.h" +#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/WebKit/public/web/WebRuntimeFeatures.h" + +using blink::WebMediaPlayer; +using blink::WebMediaPlayerClient; +using blink::WebString; + namespace media { -EncryptedMediaPlayerSupport::EncryptedMediaPlayerSupport() { +#define BIND_TO_RENDER_LOOP(function) \ + (BindToCurrentLoop(base::Bind(function, AsWeakPtr()))) + +#define BIND_TO_RENDER_LOOP1(function, arg1) \ + (BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1))) + +// Prefix for histograms related to Encrypted Media Extensions. +static const char* kMediaEme = "Media.EME."; + +// Used for calls to decryptor_ready_cb where the result can be ignored. +static void DoNothing(bool success) { +} + +// Convert a WebString to ASCII, falling back on an empty string in the case +// of a non-ASCII string. +static std::string ToASCIIOrEmpty(const WebString& string) { + return base::IsStringASCII(string) ? base::UTF16ToASCII(string) + : std::string(); +} + +// Helper functions to report media EME related stats to UMA. They follow the +// convention of more commonly used macros UMA_HISTOGRAM_ENUMERATION and +// UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is +// that UMA_* macros require the names to be constant throughout the process' +// lifetime. +static void EmeUMAHistogramEnumeration(const std::string& key_system, + const std::string& method, + int sample, + int boundary_value) { + base::LinearHistogram::FactoryGet( + kMediaEme + GetKeySystemNameForUMA(key_system) + "." + method, + 1, boundary_value, boundary_value + 1, + base::Histogram::kUmaTargetedHistogramFlag)->Add(sample); +} + +static void EmeUMAHistogramCounts(const std::string& key_system, + const std::string& method, + int sample) { + // Use the same parameters as UMA_HISTOGRAM_COUNTS. + base::Histogram::FactoryGet( + kMediaEme + GetKeySystemNameForUMA(key_system) + "." + method, + 1, 1000000, 50, base::Histogram::kUmaTargetedHistogramFlag)->Add(sample); +} + +// Helper enum for reporting generateKeyRequest/addKey histograms. +enum MediaKeyException { + kUnknownResultId, + kSuccess, + kKeySystemNotSupported, + kInvalidPlayerState, + kMaxMediaKeyException +}; + +static MediaKeyException MediaKeyExceptionForUMA( + WebMediaPlayer::MediaKeyException e) { + switch (e) { + case WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported: + return kKeySystemNotSupported; + case WebMediaPlayer::MediaKeyExceptionInvalidPlayerState: + return kInvalidPlayerState; + case WebMediaPlayer::MediaKeyExceptionNoError: + return kSuccess; + default: + return kUnknownResultId; + } +} + +// Helper for converting |key_system| name and exception |e| to a pair of enum +// values from above, for reporting to UMA. +static void ReportMediaKeyExceptionToUMA(const std::string& method, + const std::string& key_system, + WebMediaPlayer::MediaKeyException e) { + MediaKeyException result_id = MediaKeyExceptionForUMA(e); + DCHECK_NE(result_id, kUnknownResultId) << e; + EmeUMAHistogramEnumeration( + key_system, method, result_id, kMaxMediaKeyException); +} + +// Guess the type of |init_data|. This is only used to handle some corner cases +// so we keep it as simple as possible without breaking major use cases. +static std::string GuessInitDataType(const unsigned char* init_data, + unsigned init_data_length) { + // Most WebM files use KeyId of 16 bytes. CENC init data is always >16 bytes. + if (init_data_length == 16) + return "webm"; + + return "cenc"; +} + +EncryptedMediaPlayerSupport::EncryptedMediaPlayerSupport( + scoped_ptr<CdmFactory> cdm_factory, + blink::WebMediaPlayerClient* client, + blink::WebContentDecryptionModule* initial_cdm) + : cdm_factory_(cdm_factory.Pass()), + client_(client), + web_cdm_(ToWebContentDecryptionModuleImpl(initial_cdm)) { } EncryptedMediaPlayerSupport::~EncryptedMediaPlayerSupport() { } +WebMediaPlayer::MediaKeyException +EncryptedMediaPlayerSupport::GenerateKeyRequest( + blink::WebLocalFrame* frame, + const WebString& key_system, + const unsigned char* init_data, + unsigned init_data_length) { + DVLOG(1) << "generateKeyRequest: " << base::string16(key_system) << ": " + << std::string(reinterpret_cast<const char*>(init_data), + static_cast<size_t>(init_data_length)); + + std::string ascii_key_system = + GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system)); + + WebMediaPlayer::MediaKeyException e = + GenerateKeyRequestInternal(frame, ascii_key_system, init_data, + init_data_length); + ReportMediaKeyExceptionToUMA("generateKeyRequest", ascii_key_system, e); + return e; +} + +WebMediaPlayer::MediaKeyException +EncryptedMediaPlayerSupport::GenerateKeyRequestInternal( + blink::WebLocalFrame* frame, + const std::string& key_system, + const unsigned char* init_data, + unsigned init_data_length) { + if (!IsConcreteSupportedKeySystem(key_system)) + return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; + + // We do not support run-time switching between key systems for now. + if (current_key_system_.empty()) { + if (!proxy_decryptor_) { + proxy_decryptor_.reset(new ProxyDecryptor( + BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupport::OnKeyAdded), + BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupport::OnKeyError), + BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupport::OnKeyMessage))); + } + + GURL security_origin(frame->document().securityOrigin().toString()); + + if (!cdm_factory_.get() || + !proxy_decryptor_->InitializeCDM(cdm_factory_.get(), key_system, + security_origin)) { + return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; + } + + if (proxy_decryptor_ && !decryptor_ready_cb_.is_null()) { + base::ResetAndReturn(&decryptor_ready_cb_) + .Run(proxy_decryptor_->GetDecryptor(), base::Bind(DoNothing)); + } + + current_key_system_ = key_system; + } else if (key_system != current_key_system_) { + return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; + } + + std::string init_data_type = init_data_type_; + if (init_data_type.empty()) + init_data_type = GuessInitDataType(init_data, init_data_length); + + // TODO(xhwang): We assume all streams are from the same container (thus have + // the same "type") for now. In the future, the "type" should be passed down + // from the application. + if (!proxy_decryptor_->GenerateKeyRequest( + init_data_type, init_data, init_data_length)) { + current_key_system_.clear(); + return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; + } + + return WebMediaPlayer::MediaKeyExceptionNoError; +} + +WebMediaPlayer::MediaKeyException EncryptedMediaPlayerSupport::AddKey( + const WebString& key_system, + const unsigned char* key, + unsigned key_length, + const unsigned char* init_data, + unsigned init_data_length, + const WebString& session_id) { + DVLOG(1) << "addKey: " << base::string16(key_system) << ": " + << std::string(reinterpret_cast<const char*>(key), + static_cast<size_t>(key_length)) << ", " + << std::string(reinterpret_cast<const char*>(init_data), + static_cast<size_t>(init_data_length)) << " [" + << base::string16(session_id) << "]"; + + std::string ascii_key_system = + GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system)); + std::string ascii_session_id = ToASCIIOrEmpty(session_id); + + WebMediaPlayer::MediaKeyException e = AddKeyInternal(ascii_key_system, + key, + key_length, + init_data, + init_data_length, + ascii_session_id); + ReportMediaKeyExceptionToUMA("addKey", ascii_key_system, e); + return e; +} + +WebMediaPlayer::MediaKeyException +EncryptedMediaPlayerSupport::AddKeyInternal( + const std::string& key_system, + const unsigned char* key, + unsigned key_length, + const unsigned char* init_data, + unsigned init_data_length, + const std::string& session_id) { + DCHECK(key); + DCHECK_GT(key_length, 0u); + + if (!IsConcreteSupportedKeySystem(key_system)) + return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; + + if (current_key_system_.empty() || key_system != current_key_system_) + return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; + + proxy_decryptor_->AddKey( + key, key_length, init_data, init_data_length, session_id); + return WebMediaPlayer::MediaKeyExceptionNoError; +} + +WebMediaPlayer::MediaKeyException +EncryptedMediaPlayerSupport::CancelKeyRequest( + const WebString& key_system, + const WebString& session_id) { + DVLOG(1) << "cancelKeyRequest: " << base::string16(key_system) << ": " + << " [" << base::string16(session_id) << "]"; + + std::string ascii_key_system = + GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system)); + std::string ascii_session_id = ToASCIIOrEmpty(session_id); + + WebMediaPlayer::MediaKeyException e = + CancelKeyRequestInternal(ascii_key_system, ascii_session_id); + ReportMediaKeyExceptionToUMA("cancelKeyRequest", ascii_key_system, e); + return e; +} + +WebMediaPlayer::MediaKeyException +EncryptedMediaPlayerSupport::CancelKeyRequestInternal( + const std::string& key_system, + const std::string& session_id) { + if (!IsConcreteSupportedKeySystem(key_system)) + return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; + + if (current_key_system_.empty() || key_system != current_key_system_) + return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; + + proxy_decryptor_->CancelKeyRequest(session_id); + return WebMediaPlayer::MediaKeyExceptionNoError; +} + +void EncryptedMediaPlayerSupport::SetContentDecryptionModule( + blink::WebContentDecryptionModule* cdm) { + // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324 + if (!cdm) + return; + + web_cdm_ = ToWebContentDecryptionModuleImpl(cdm); + + if (web_cdm_ && !decryptor_ready_cb_.is_null()) + base::ResetAndReturn(&decryptor_ready_cb_) + .Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing)); +} + +void EncryptedMediaPlayerSupport::SetContentDecryptionModule( + blink::WebContentDecryptionModule* cdm, + blink::WebContentDecryptionModuleResult result) { + // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324 + if (!cdm) { + result.completeWithError( + blink::WebContentDecryptionModuleExceptionNotSupportedError, + 0, + "Null MediaKeys object is not supported."); + return; + } + + web_cdm_ = ToWebContentDecryptionModuleImpl(cdm); + + if (web_cdm_ && !decryptor_ready_cb_.is_null()) { + base::ResetAndReturn(&decryptor_ready_cb_) + .Run(web_cdm_->GetDecryptor(), BIND_TO_RENDER_LOOP1( + &EncryptedMediaPlayerSupport::ContentDecryptionModuleAttached, + result)); + } else { + // No pipeline/decoder connected, so resolve the promise. When something + // is connected, setting the CDM will happen in SetDecryptorReadyCallback(). + ContentDecryptionModuleAttached(result, true); + } +} + +void EncryptedMediaPlayerSupport::ContentDecryptionModuleAttached( + blink::WebContentDecryptionModuleResult result, + bool success) { + if (success) { + result.complete(); + return; + } + + result.completeWithError( + blink::WebContentDecryptionModuleExceptionNotSupportedError, + 0, + "Unable to set MediaKeys object"); +} + +SetDecryptorReadyCB EncryptedMediaPlayerSupport::CreateSetDecryptorReadyCB() { + return BIND_TO_RENDER_LOOP( + &EncryptedMediaPlayerSupport::SetDecryptorReadyCallback); +} + +Demuxer::NeedKeyCB EncryptedMediaPlayerSupport::CreateNeedKeyCB() { + return BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupport::OnNeedKey); +} + +void EncryptedMediaPlayerSupport::OnPipelineDecryptError() { + EmeUMAHistogramCounts(current_key_system_, "DecryptError", 1); +} + +void EncryptedMediaPlayerSupport::OnNeedKey( + const std::string& type, + const std::vector<uint8>& init_data) { + // Do not fire NeedKey event if encrypted media is not enabled. + if (!blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled() && + !blink::WebRuntimeFeatures::isEncryptedMediaEnabled()) { + return; + } + + UMA_HISTOGRAM_COUNTS(kMediaEme + std::string("NeedKey"), 1); + + DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_); + if (init_data_type_.empty()) + init_data_type_ = type; + + const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0]; + client_->encrypted(WebString::fromUTF8(type), init_data_ptr, + base::saturated_cast<unsigned int>(init_data.size())); +} + +void EncryptedMediaPlayerSupport::OnKeyAdded(const std::string& session_id) { + EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1); + client_->keyAdded( + WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)), + WebString::fromUTF8(session_id)); +} + +void EncryptedMediaPlayerSupport::OnKeyError(const std::string& session_id, + MediaKeys::KeyError error_code, + uint32 system_code) { + EmeUMAHistogramEnumeration(current_key_system_, "KeyError", + error_code, MediaKeys::kMaxKeyError); + + uint16 short_system_code = 0; + if (system_code > std::numeric_limits<uint16>::max()) { + LOG(WARNING) << "system_code exceeds unsigned short limit."; + short_system_code = std::numeric_limits<uint16>::max(); + } else { + short_system_code = static_cast<uint16>(system_code); + } + + client_->keyError( + WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)), + WebString::fromUTF8(session_id), + static_cast<WebMediaPlayerClient::MediaKeyErrorCode>(error_code), + short_system_code); +} + +void EncryptedMediaPlayerSupport::OnKeyMessage( + const std::string& session_id, + const std::vector<uint8>& message, + const GURL& destination_url) { + DCHECK(destination_url.is_empty() || destination_url.is_valid()); + + client_->keyMessage( + WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)), + WebString::fromUTF8(session_id), + message.empty() ? NULL : &message[0], + base::saturated_cast<unsigned int>(message.size()), + destination_url); +} + +void EncryptedMediaPlayerSupport::SetDecryptorReadyCallback( + const DecryptorReadyCB& decryptor_ready_cb) { + // Cancels the previous decryptor request. + if (decryptor_ready_cb.is_null()) { + if (!decryptor_ready_cb_.is_null()) { + base::ResetAndReturn(&decryptor_ready_cb_) + .Run(NULL, base::Bind(DoNothing)); + } + return; + } + + // TODO(xhwang): Support multiple decryptor notification request (e.g. from + // video and audio). The current implementation is okay for the current + // media pipeline since we initialize audio and video decoders in sequence. + // But WebMediaPlayerImpl should not depend on media pipeline's implementation + // detail. + DCHECK(decryptor_ready_cb_.is_null()); + + // Mixed use of prefixed and unprefixed EME APIs is disallowed by Blink. + DCHECK(!proxy_decryptor_ || !web_cdm_); + + if (proxy_decryptor_) { + decryptor_ready_cb.Run(proxy_decryptor_->GetDecryptor(), + base::Bind(DoNothing)); + return; + } + + if (web_cdm_) { + decryptor_ready_cb.Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing)); + return; + } + + decryptor_ready_cb_ = decryptor_ready_cb; +} + } // namespace media diff --git a/media/blink/encrypted_media_player_support.h b/media/blink/encrypted_media_player_support.h index 737720d..4f4c937 100644 --- a/media/blink/encrypted_media_player_support.h +++ b/media/blink/encrypted_media_player_support.h @@ -5,14 +5,19 @@ #ifndef MEDIA_BLINK_ENCRYPTED_MEDIA_PLAYER_SUPPORT_H_ #define MEDIA_BLINK_ENCRYPTED_MEDIA_PLAYER_SUPPORT_H_ -#include "media/base/decryptor.h" +#include <string> +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "media/base/cdm_factory.h" #include "media/base/demuxer.h" -#include "media/base/media_export.h" +#include "media/cdm/proxy_decryptor.h" +#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h" #include "third_party/WebKit/public/platform/WebMediaPlayer.h" namespace blink { class WebContentDecryptionModule; -class WebContentDecryptionModuleResult; class WebLocalFrame; class WebMediaPlayerClient; class WebString; @@ -20,58 +25,106 @@ class WebString; namespace media { -class MEDIA_EXPORT EncryptedMediaPlayerSupport { +class WebContentDecryptionModuleImpl; + +class EncryptedMediaPlayerSupport + : public base::SupportsWeakPtr<EncryptedMediaPlayerSupport> { public: - EncryptedMediaPlayerSupport(); - virtual ~EncryptedMediaPlayerSupport(); + EncryptedMediaPlayerSupport(scoped_ptr<CdmFactory> cdm_factory, + blink::WebMediaPlayerClient* client, + blink::WebContentDecryptionModule* initial_cdm); + ~EncryptedMediaPlayerSupport(); - // Prefixed API methods. - virtual blink::WebMediaPlayer::MediaKeyException GenerateKeyRequest( + blink::WebMediaPlayer::MediaKeyException GenerateKeyRequest( blink::WebLocalFrame* frame, const blink::WebString& key_system, const unsigned char* init_data, - unsigned init_data_length) = 0; + unsigned init_data_length); - virtual blink::WebMediaPlayer::MediaKeyException AddKey( + blink::WebMediaPlayer::MediaKeyException AddKey( const blink::WebString& key_system, const unsigned char* key, unsigned key_length, const unsigned char* init_data, unsigned init_data_length, - const blink::WebString& session_id) = 0; + const blink::WebString& session_id); - virtual blink::WebMediaPlayer::MediaKeyException CancelKeyRequest( + blink::WebMediaPlayer::MediaKeyException CancelKeyRequest( const blink::WebString& key_system, - const blink::WebString& session_id) = 0; - + const blink::WebString& session_id); - // Unprefixed API methods. - virtual void SetInitialContentDecryptionModule( - blink::WebContentDecryptionModule* initial_cdm) = 0; - virtual void SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm) = 0; - virtual void SetContentDecryptionModule( + void SetContentDecryptionModule( + blink::WebContentDecryptionModule* cdm); + void SetContentDecryptionModule( blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result) = 0; + blink::WebContentDecryptionModuleResult result); + SetDecryptorReadyCB CreateSetDecryptorReadyCB(); + Demuxer::NeedKeyCB CreateNeedKeyCB(); - // Callback factory and notification methods used by WebMediaPlayerImpl. + void OnPipelineDecryptError(); - // Creates a callback that Demuxers can use to signal that the content - // requires a key. This method make sure the callback returned can be safely - // invoked from any thread. - virtual Demuxer::NeedKeyCB CreateNeedKeyCB() = 0; + private: + // Requests that this object notifies when a decryptor is ready through the + // |decryptor_ready_cb| provided. + // If |decryptor_ready_cb| is null, the existing callback will be fired with + // NULL immediately and reset. + void SetDecryptorReadyCallback(const DecryptorReadyCB& decryptor_ready_cb); - // Creates a callback that renderers can use to set decryptor - // ready callback. This method make sure the callback returned can be safely - // invoked from any thread. - virtual SetDecryptorReadyCB CreateSetDecryptorReadyCB() = 0; + blink::WebMediaPlayer::MediaKeyException GenerateKeyRequestInternal( + blink::WebLocalFrame* frame, + const std::string& key_system, + const unsigned char* init_data, + unsigned init_data_length); - // Called to inform this object that the media pipeline encountered - // and handled a decryption error. - virtual void OnPipelineDecryptError() = 0; + blink::WebMediaPlayer::MediaKeyException AddKeyInternal( + const std::string& key_system, + const unsigned char* key, + unsigned key_length, + const unsigned char* init_data, + unsigned init_data_length, + const std::string& session_id); + + blink::WebMediaPlayer::MediaKeyException CancelKeyRequestInternal( + const std::string& key_system, + const std::string& session_id); + + void OnNeedKey(const std::string& type, + const std::vector<uint8>& init_data); + + void OnKeyAdded(const std::string& session_id); + void OnKeyError(const std::string& session_id, + MediaKeys::KeyError error_code, + uint32 system_code); + void OnKeyMessage(const std::string& session_id, + const std::vector<uint8>& message, + const GURL& destination_url); + + void ContentDecryptionModuleAttached( + blink::WebContentDecryptionModuleResult result, + bool success); + + scoped_ptr<CdmFactory> cdm_factory_; + + blink::WebMediaPlayerClient* client_; + + // The currently selected key system. Empty string means that no key system + // has been selected. + std::string current_key_system_; + + // Temporary for EME v0.1. In the future the init data type should be passed + // through GenerateKeyRequest() directly from WebKit. + std::string init_data_type_; + + // Manages decryption keys and decrypts encrypted frames. + scoped_ptr<ProxyDecryptor> proxy_decryptor_; + + // Non-owned pointer to the CDM. Updated via calls to + // setContentDecryptionModule(). + WebContentDecryptionModuleImpl* web_cdm_; + + DecryptorReadyCB decryptor_ready_cb_; - private: DISALLOW_COPY_AND_ASSIGN(EncryptedMediaPlayerSupport); }; diff --git a/media/blink/media_blink.gyp b/media/blink/media_blink.gyp index 32239ec..5307971 100644 --- a/media/blink/media_blink.gyp +++ b/media/blink/media_blink.gyp @@ -43,8 +43,6 @@ 'encrypted_media_player_support.h', 'new_session_cdm_result_promise.cc', 'new_session_cdm_result_promise.h', - 'null_encrypted_media_player_support.cc', - 'null_encrypted_media_player_support.h', 'texttrack_impl.cc', 'texttrack_impl.h', 'video_frame_compositor.cc', @@ -72,6 +70,8 @@ 'conditions': [ ['OS=="android"', { 'sources!': [ + 'encrypted_media_player_support.cc', + 'encrypted_media_player_support.h', 'webmediaplayer_impl.cc', 'webmediaplayer_impl.h', ], diff --git a/media/blink/null_encrypted_media_player_support.cc b/media/blink/null_encrypted_media_player_support.cc deleted file mode 100644 index 240e23e..0000000 --- a/media/blink/null_encrypted_media_player_support.cc +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2014 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 "media/blink/null_encrypted_media_player_support.h" - -#include "base/bind.h" -#include "third_party/WebKit/public/platform/WebContentDecryptionModule.h" -#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h" - -namespace media { - -static void NeedKeyHandler(const std::string& type, - const std::vector<uint8>& init_data) { - NOTIMPLEMENTED(); -} - -scoped_ptr<EncryptedMediaPlayerSupport> -NullEncryptedMediaPlayerSupport::Create(blink::WebMediaPlayerClient* client) { - return scoped_ptr<EncryptedMediaPlayerSupport>( - new NullEncryptedMediaPlayerSupport()); -} - -NullEncryptedMediaPlayerSupport::NullEncryptedMediaPlayerSupport() { -} - -NullEncryptedMediaPlayerSupport::~NullEncryptedMediaPlayerSupport() { -} - -blink::WebMediaPlayer::MediaKeyException -NullEncryptedMediaPlayerSupport::GenerateKeyRequest( - blink::WebLocalFrame* frame, - const blink::WebString& key_system, - const unsigned char* init_data, - unsigned init_data_length) { - return blink::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; -} - -blink::WebMediaPlayer::MediaKeyException -NullEncryptedMediaPlayerSupport::AddKey( - const blink::WebString& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const blink::WebString& session_id) { - return blink::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; -} - -blink::WebMediaPlayer::MediaKeyException -NullEncryptedMediaPlayerSupport::CancelKeyRequest( - const blink::WebString& key_system, - const blink::WebString& session_id) { - return blink::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; -} - -void NullEncryptedMediaPlayerSupport::SetInitialContentDecryptionModule( - blink::WebContentDecryptionModule* initial_cdm) { -} - -void NullEncryptedMediaPlayerSupport::SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm) { -} - -void NullEncryptedMediaPlayerSupport::SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result) { - result.completeWithError( - blink::WebContentDecryptionModuleExceptionNotSupportedError, - 0, - "Null MediaKeys object is not supported."); -} - -Demuxer::NeedKeyCB NullEncryptedMediaPlayerSupport::CreateNeedKeyCB() { - return base::Bind(&NeedKeyHandler); -} - -SetDecryptorReadyCB -NullEncryptedMediaPlayerSupport::CreateSetDecryptorReadyCB() { - return SetDecryptorReadyCB(); -} - -void NullEncryptedMediaPlayerSupport::OnPipelineDecryptError() { -} - -} // namespace media diff --git a/media/blink/null_encrypted_media_player_support.h b/media/blink/null_encrypted_media_player_support.h deleted file mode 100644 index 3b53ad2..0000000 --- a/media/blink/null_encrypted_media_player_support.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2014 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. - -#ifndef MEDIA_BLINK_NULL_ENCRYPTED_MEDIA_PLAYER_SUPPORT_H_ -#define MEDIA_BLINK_NULL_ENCRYPTED_MEDIA_PLAYER_SUPPORT_H_ - -#include "media/base/media_export.h" -#include "media/blink/encrypted_media_player_support.h" - -namespace media { - -// A "null" implementation of the EncryptedMediaPlayerSupport interface -// that indicates all key systems are not supported. This makes sure that -// any attempts to play encrypted content always fail. -class MEDIA_EXPORT NullEncryptedMediaPlayerSupport - : public EncryptedMediaPlayerSupport { - public: - static scoped_ptr<EncryptedMediaPlayerSupport> Create( - blink::WebMediaPlayerClient* client); - - ~NullEncryptedMediaPlayerSupport() override; - - // Prefixed API methods. - blink::WebMediaPlayer::MediaKeyException GenerateKeyRequest( - blink::WebLocalFrame* frame, - const blink::WebString& key_system, - const unsigned char* init_data, - unsigned init_data_length) override; - - blink::WebMediaPlayer::MediaKeyException AddKey( - const blink::WebString& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const blink::WebString& session_id) override; - - blink::WebMediaPlayer::MediaKeyException CancelKeyRequest( - const blink::WebString& key_system, - const blink::WebString& session_id) override; - - // Unprefixed API methods. - void SetInitialContentDecryptionModule( - blink::WebContentDecryptionModule* initial_cdm) override; - void SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm) override; - void SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result) override; - - // Callback factory and notification methods used by WebMediaPlayerImpl. - - // Creates a callback that Demuxers can use to signal that the content - // requires a key. This method makes sure the callback returned can be safely - // invoked from any thread. - Demuxer::NeedKeyCB CreateNeedKeyCB() override; - - // Creates a callback that renderers can use to set decryptor - // ready callback. This method makes sure the callback returned can be safely - // invoked from any thread. - SetDecryptorReadyCB CreateSetDecryptorReadyCB() override; - - // Called to inform this object that the media pipeline encountered - // and handled a decryption error. - void OnPipelineDecryptError() override; - - private: - NullEncryptedMediaPlayerSupport(); - - DISALLOW_COPY_AND_ASSIGN(NullEncryptedMediaPlayerSupport); -}; - -} // namespace media - -#endif // MEDIA_BLINK_NULL_ENCRYPTED_MEDIA_PLAYER_SUPPORT_H_ diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 0aaf1f0..68c17fb 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc @@ -138,6 +138,7 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( blink::WebMediaPlayerClient* client, base::WeakPtr<WebMediaPlayerDelegate> delegate, scoped_ptr<Renderer> renderer, + scoped_ptr<CdmFactory> cdm_factory, const WebMediaPlayerParams& params) : frame_(frame), network_state_(WebMediaPlayer::NetworkStateEmpty), @@ -167,12 +168,11 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged), BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))), text_track_index_(0), - encrypted_media_support_( - params.CreateEncryptedMediaPlayerSupport(client)), + encrypted_media_support_(cdm_factory.Pass(), + client, + params.initial_cdm()), audio_hardware_config_(params.audio_hardware_config()), renderer_(renderer.Pass()) { - DCHECK(encrypted_media_support_); - // Threaded compositing isn't enabled universally yet. if (!compositor_task_runner_.get()) compositor_task_runner_ = base::MessageLoopProxy::current(); @@ -648,7 +648,7 @@ WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system, unsigned init_data_length) { DCHECK(main_task_runner_->BelongsToCurrentThread()); - return encrypted_media_support_->GenerateKeyRequest( + return encrypted_media_support_.GenerateKeyRequest( frame_, key_system, init_data, init_data_length); } @@ -661,7 +661,7 @@ WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey( const WebString& session_id) { DCHECK(main_task_runner_->BelongsToCurrentThread()); - return encrypted_media_support_->AddKey( + return encrypted_media_support_.AddKey( key_system, key, key_length, init_data, init_data_length, session_id); } @@ -670,14 +670,14 @@ WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest( const WebString& session_id) { DCHECK(main_task_runner_->BelongsToCurrentThread()); - return encrypted_media_support_->CancelKeyRequest(key_system, session_id); + return encrypted_media_support_.CancelKeyRequest(key_system, session_id); } void WebMediaPlayerImpl::setContentDecryptionModule( blink::WebContentDecryptionModule* cdm) { DCHECK(main_task_runner_->BelongsToCurrentThread()); - encrypted_media_support_->SetContentDecryptionModule(cdm); + encrypted_media_support_.SetContentDecryptionModule(cdm); } void WebMediaPlayerImpl::setContentDecryptionModule( @@ -685,7 +685,7 @@ void WebMediaPlayerImpl::setContentDecryptionModule( blink::WebContentDecryptionModuleResult result) { DCHECK(main_task_runner_->BelongsToCurrentThread()); - encrypted_media_support_->SetContentDecryptionModule(cdm, result); + encrypted_media_support_.SetContentDecryptionModule(cdm, result); } void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed, @@ -737,7 +737,7 @@ void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) { SetNetworkState(PipelineErrorToNetworkState(error)); if (error == PIPELINE_ERROR_DECRYPT) - encrypted_media_support_->OnPipelineDecryptError(); + encrypted_media_support_.OnPipelineDecryptError(); } void WebMediaPlayerImpl::OnPipelineMetadata( @@ -842,14 +842,14 @@ void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { // renderers. scoped_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() { SetDecryptorReadyCB set_decryptor_ready_cb = - encrypted_media_support_->CreateSetDecryptorReadyCB(); + encrypted_media_support_.CreateSetDecryptorReadyCB(); // Create our audio decoders and renderer. ScopedVector<AudioDecoder> audio_decoders; - audio_decoders.push_back(new media::FFmpegAudioDecoder( + audio_decoders.push_back(new FFmpegAudioDecoder( media_task_runner_, base::Bind(&LogMediaSourceError, media_log_))); - audio_decoders.push_back(new media::OpusAudioDecoder(media_task_runner_)); + audio_decoders.push_back(new OpusAudioDecoder(media_task_runner_)); scoped_ptr<AudioRenderer> audio_renderer( new AudioRendererImpl(media_task_runner_, @@ -892,7 +892,7 @@ void WebMediaPlayerImpl::StartPipeline() { LogCB mse_log_cb; Demuxer::NeedKeyCB need_key_cb = - encrypted_media_support_->CreateNeedKeyCB(); + encrypted_media_support_.CreateNeedKeyCB(); // Figure out which demuxer to use. if (load_type_ != LoadTypeMediaSource) { diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index bec5747..674a378 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h @@ -15,12 +15,14 @@ #include "base/memory/weak_ptr.h" #include "base/threading/thread.h" #include "media/base/audio_renderer_sink.h" +#include "media/base/cdm_factory.h" #include "media/base/media_export.h" #include "media/base/pipeline.h" #include "media/base/renderer.h" #include "media/base/text_track.h" #include "media/blink/buffered_data_source.h" #include "media/blink/buffered_data_source_host_impl.h" +#include "media/blink/encrypted_media_player_support.h" #include "media/blink/video_frame_compositor.h" #include "media/filters/skcanvas_video_renderer.h" #include "third_party/WebKit/public/platform/WebAudioSourceProvider.h" @@ -46,7 +48,6 @@ namespace media { class AudioHardwareConfig; class ChunkDemuxer; -class EncryptedMediaPlayerSupport; class GpuVideoAcceleratorFactories; class MediaLog; class VideoFrameCompositor; @@ -71,6 +72,7 @@ class MEDIA_EXPORT WebMediaPlayerImpl blink::WebMediaPlayerClient* client, base::WeakPtr<WebMediaPlayerDelegate> delegate, scoped_ptr<Renderer> renderer, + scoped_ptr<CdmFactory> cdm_factory, const WebMediaPlayerParams& params); virtual ~WebMediaPlayerImpl(); @@ -305,7 +307,7 @@ class MEDIA_EXPORT WebMediaPlayerImpl // Text track objects get a unique index value when they're created. int text_track_index_; - scoped_ptr<EncryptedMediaPlayerSupport> encrypted_media_support_; + EncryptedMediaPlayerSupport encrypted_media_support_; const AudioHardwareConfig& audio_hardware_config_; diff --git a/media/blink/webmediaplayer_params.cc b/media/blink/webmediaplayer_params.cc index 1fd2b8a..ff3ed60 100644 --- a/media/blink/webmediaplayer_params.cc +++ b/media/blink/webmediaplayer_params.cc @@ -19,8 +19,6 @@ WebMediaPlayerParams::WebMediaPlayerParams( const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories, const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner, - const EncryptedMediaPlayerSupportCreateCB& - encrypted_media_player_support_cb, blink::WebContentDecryptionModule* initial_cdm) : defer_load_cb_(defer_load_cb), audio_renderer_sink_(audio_renderer_sink), @@ -29,20 +27,9 @@ WebMediaPlayerParams::WebMediaPlayerParams( gpu_factories_(gpu_factories), media_task_runner_(media_task_runner), compositor_task_runner_(compositor_task_runner), - encrypted_media_player_support_cb_(encrypted_media_player_support_cb), initial_cdm_(initial_cdm) { } WebMediaPlayerParams::~WebMediaPlayerParams() {} -scoped_ptr<EncryptedMediaPlayerSupport> -WebMediaPlayerParams::CreateEncryptedMediaPlayerSupport( - blink::WebMediaPlayerClient* client) const { - scoped_ptr<EncryptedMediaPlayerSupport> encrypted_media_support = - encrypted_media_player_support_cb_.Run(client); - if (encrypted_media_support) - encrypted_media_support->SetInitialContentDecryptionModule(initial_cdm_); - return encrypted_media_support.Pass(); -} - } // namespace media diff --git a/media/blink/webmediaplayer_params.h b/media/blink/webmediaplayer_params.h index c765548..3b7d343 100644 --- a/media/blink/webmediaplayer_params.h +++ b/media/blink/webmediaplayer_params.h @@ -8,17 +8,18 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" #include "media/base/media_export.h" -#include "media/blink/encrypted_media_player_support.h" namespace base { class SingleThreadTaskRunner; } namespace blink { +class WebContentDecryptionModule; class WebMediaPlayerClient; } namespace media { + class AudioHardwareConfig; class AudioRendererSink; class GpuVideoAcceleratorFactories; @@ -28,10 +29,6 @@ class MediaLog; // to plumb arguments through various abstraction layers. class MEDIA_EXPORT WebMediaPlayerParams { public: - // Callback used to create EncryptedMediaPlayerSupport instances. This - // callback must always return a valid EncryptedMediaPlayerSupport object. - typedef base::Callback<scoped_ptr<EncryptedMediaPlayerSupport>( - blink::WebMediaPlayerClient*)> EncryptedMediaPlayerSupportCreateCB; typedef base::Callback<void(const base::Closure&)> DeferLoadCB; // |defer_load_cb|, |audio_renderer_sink|, and |compositor_task_runner| may be @@ -44,8 +41,6 @@ class MEDIA_EXPORT WebMediaPlayerParams { const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories, const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner, - const EncryptedMediaPlayerSupportCreateCB& - encrypted_media_player_support_cb, blink::WebContentDecryptionModule* initial_cdm); ~WebMediaPlayerParams(); @@ -81,8 +76,9 @@ class MEDIA_EXPORT WebMediaPlayerParams { return compositor_task_runner_; } - scoped_ptr<EncryptedMediaPlayerSupport> - CreateEncryptedMediaPlayerSupport(blink::WebMediaPlayerClient* client) const; + blink::WebContentDecryptionModule* initial_cdm() const { + return initial_cdm_; + } private: base::Callback<void(const base::Closure&)> defer_load_cb_; @@ -92,7 +88,6 @@ class MEDIA_EXPORT WebMediaPlayerParams { scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories_; scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; - EncryptedMediaPlayerSupportCreateCB encrypted_media_player_support_cb_; blink::WebContentDecryptionModule* initial_cdm_; DISALLOW_IMPLICIT_CONSTRUCTORS(WebMediaPlayerParams); diff --git a/content/renderer/media/crypto/proxy_decryptor.cc b/media/cdm/proxy_decryptor.cc index 44a30fd..44c07e8 100644 --- a/content/renderer/media/crypto/proxy_decryptor.cc +++ b/media/cdm/proxy_decryptor.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/crypto/proxy_decryptor.h" +#include "media/cdm/proxy_decryptor.h" #include <cstring> @@ -15,7 +15,7 @@ #include "media/cdm/json_web_key.h" #include "media/cdm/key_system_names.h" -namespace content { +namespace media { // Special system code to signal a closed persistent session in a SessionError() // call. This is needed because there is no SessionClosed() call in the prefixed @@ -40,7 +40,7 @@ ProxyDecryptor::~ProxyDecryptor() { media_keys_.reset(); } -media::Decryptor* ProxyDecryptor::GetDecryptor() { +Decryptor* ProxyDecryptor::GetDecryptor() { return media_keys_ ? media_keys_->GetDecryptor() : NULL; } @@ -50,7 +50,7 @@ int ProxyDecryptor::GetCdmId() { } #endif -bool ProxyDecryptor::InitializeCDM(media::CdmFactory* cdm_factory, +bool ProxyDecryptor::InitializeCDM(CdmFactory* cdm_factory, const std::string& key_system, const GURL& security_origin) { DVLOG(1) << "InitializeCDM: key_system = " << key_system; @@ -61,7 +61,7 @@ bool ProxyDecryptor::InitializeCDM(media::CdmFactory* cdm_factory, return false; is_clear_key_ = - media::IsClearKey(key_system) || media::IsExternalClearKey(key_system); + IsClearKey(key_system) || IsExternalClearKey(key_system); return true; } @@ -96,8 +96,8 @@ bool ProxyDecryptor::GenerateKeyRequest(const std::string& init_data_type, StripHeader(init_data_vector, strlen(kPrefixedApiPersistentSessionHeader)); } - scoped_ptr<media::NewSessionCdmPromise> promise( - new media::CdmCallbackPromise<std::string>( + scoped_ptr<NewSessionCdmPromise> promise( + new CdmCallbackPromise<std::string>( base::Bind(&ProxyDecryptor::SetSessionId, weak_ptr_factory_.GetWeakPtr(), session_creation_type), @@ -115,10 +115,10 @@ bool ProxyDecryptor::GenerateKeyRequest(const std::string& init_data_type, return true; } - media::MediaKeys::SessionType session_type = + MediaKeys::SessionType session_type = session_creation_type == PersistentSession - ? media::MediaKeys::PERSISTENT_SESSION - : media::MediaKeys::TEMPORARY_SESSION; + ? MediaKeys::PERSISTENT_SESSION + : MediaKeys::TEMPORARY_SESSION; media_keys_->CreateSession(init_data_type, init_data_vector_data, @@ -145,14 +145,14 @@ void ProxyDecryptor::AddKey(const uint8* key, session_id = it->first; } else { OnSessionError(std::string(), - media::MediaKeys::NOT_SUPPORTED_ERROR, + MediaKeys::NOT_SUPPORTED_ERROR, 0, "SessionId not specified."); return; } } - scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( + scoped_ptr<SimpleCdmPromise> promise(new CdmCallbackPromise<>( base::Bind(&ProxyDecryptor::OnSessionReady, weak_ptr_factory_.GetWeakPtr(), web_session_id), @@ -174,7 +174,7 @@ void ProxyDecryptor::AddKey(const uint8* key, } std::string jwk = - media::GenerateJWKSet(key, key_length, init_data, init_data_length); + GenerateJWKSet(key, key_length, init_data, init_data_length); DCHECK(!jwk.empty()); media_keys_->UpdateSession(session_id, reinterpret_cast<const uint8*>(jwk.data()), @@ -189,7 +189,7 @@ void ProxyDecryptor::AddKey(const uint8* key, void ProxyDecryptor::CancelKeyRequest(const std::string& web_session_id) { DVLOG(1) << "CancelKeyRequest()"; - scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( + scoped_ptr<SimpleCdmPromise> promise(new CdmCallbackPromise<>( base::Bind(&ProxyDecryptor::OnSessionClosed, weak_ptr_factory_.GetWeakPtr(), web_session_id), @@ -199,8 +199,8 @@ void ProxyDecryptor::CancelKeyRequest(const std::string& web_session_id) { media_keys_->RemoveSession(web_session_id, promise.Pass()); } -scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys( - media::CdmFactory* cdm_factory, +scoped_ptr<MediaKeys> ProxyDecryptor::CreateMediaKeys( + CdmFactory* cdm_factory, const std::string& key_system, const GURL& security_origin) { base::WeakPtr<ProxyDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr(); @@ -224,7 +224,7 @@ void ProxyDecryptor::OnSessionMessage(const std::string& web_session_id, // as the message. If unable to extract the key, return the message unchanged. if (is_clear_key_) { std::vector<uint8> key; - if (media::ExtractFirstKeyIdFromLicenseRequest(message, &key)) { + if (ExtractFirstKeyIdFromLicenseRequest(message, &key)) { key_message_cb_.Run(web_session_id, key, destination_url); return; } @@ -265,8 +265,7 @@ void ProxyDecryptor::OnSessionClosed(const std::string& web_session_id) { return; if (it->second) { - OnSessionError(web_session_id, - media::MediaKeys::NOT_SUPPORTED_ERROR, + OnSessionError(web_session_id, MediaKeys::NOT_SUPPORTED_ERROR, kSessionClosedSystemCode, "Do not close persistent sessions."); } @@ -274,24 +273,24 @@ void ProxyDecryptor::OnSessionClosed(const std::string& web_session_id) { } void ProxyDecryptor::OnSessionError(const std::string& web_session_id, - media::MediaKeys::Exception exception_code, + MediaKeys::Exception exception_code, uint32 system_code, const std::string& error_message) { // Convert |error_name| back to MediaKeys::KeyError if possible. Prefixed // EME has different error message, so all the specific error events will // get lost. - media::MediaKeys::KeyError error_code; + MediaKeys::KeyError error_code; switch (exception_code) { - case media::MediaKeys::CLIENT_ERROR: - error_code = media::MediaKeys::kClientError; + case MediaKeys::CLIENT_ERROR: + error_code = MediaKeys::kClientError; break; - case media::MediaKeys::OUTPUT_ERROR: - error_code = media::MediaKeys::kOutputError; + case MediaKeys::OUTPUT_ERROR: + error_code = MediaKeys::kOutputError; break; default: // This will include all other CDM4 errors and any error generated // by CDM5 or later. - error_code = media::MediaKeys::kUnknownError; + error_code = MediaKeys::kUnknownError; break; } key_error_cb_.Run(web_session_id, error_code, system_code); @@ -309,4 +308,4 @@ void ProxyDecryptor::SetSessionId(SessionCreationType session_type, OnSessionReady(web_session_id); } -} // namespace content +} // namespace media diff --git a/content/renderer/media/crypto/proxy_decryptor.h b/media/cdm/proxy_decryptor.h index 62f2e8e..193c6b0 100644 --- a/content/renderer/media/crypto/proxy_decryptor.h +++ b/media/cdm/proxy_decryptor.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_CRYPTO_PROXY_DECRYPTOR_H_ -#define CONTENT_RENDERER_MEDIA_CRYPTO_PROXY_DECRYPTOR_H_ +#ifndef MEDIA_CDM_PROXY_DECRYPTOR_H_ +#define MEDIA_CDM_PROXY_DECRYPTOR_H_ #include <string> #include <vector> @@ -13,15 +13,14 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "media/base/decryptor.h" +#include "media/base/media_export.h" #include "media/base/media_keys.h" class GURL; namespace media { -class CdmFactory; -} -namespace content { +class CdmFactory; // ProxyDecryptor is for EME v0.1b only. It should not be used for the WD API. // A decryptor proxy that creates a real decryptor object on demand and @@ -30,13 +29,13 @@ namespace content { // TODO(xhwang): Currently we don't support run-time switching among decryptor // objects. Fix this when needed. // TODO(xhwang): The ProxyDecryptor is not a Decryptor. Find a better name! -class ProxyDecryptor { +class MEDIA_EXPORT ProxyDecryptor { public: // These are similar to the callbacks in media_keys.h, but pass back the // web session ID rather than the internal session ID. typedef base::Callback<void(const std::string& session_id)> KeyAddedCB; typedef base::Callback<void(const std::string& session_id, - media::MediaKeys::KeyError error_code, + MediaKeys::KeyError error_code, uint32 system_code)> KeyErrorCB; typedef base::Callback<void(const std::string& session_id, const std::vector<uint8>& message, @@ -49,7 +48,7 @@ class ProxyDecryptor { // Returns the Decryptor associated with this object. May be NULL if no // Decryptor is associated. - media::Decryptor* GetDecryptor(); + Decryptor* GetDecryptor(); #if defined(ENABLE_BROWSER_CDMS) // Returns the CDM ID associated with this object. May be kInvalidCdmId if no @@ -58,7 +57,7 @@ class ProxyDecryptor { #endif // Only call this once. - bool InitializeCDM(media::CdmFactory* cdm_factory, + bool InitializeCDM(CdmFactory* cdm_factory, const std::string& key_system, const GURL& security_origin); @@ -73,8 +72,8 @@ class ProxyDecryptor { private: // Helper function to create MediaKeys to handle the given |key_system|. - scoped_ptr<media::MediaKeys> CreateMediaKeys( - media::CdmFactory* cdm_factory, + scoped_ptr<MediaKeys> CreateMediaKeys( + CdmFactory* cdm_factory, const std::string& key_system, const GURL& security_origin); @@ -89,7 +88,7 @@ class ProxyDecryptor { void OnSessionReady(const std::string& web_session_id); void OnSessionClosed(const std::string& web_session_id); void OnSessionError(const std::string& web_session_id, - media::MediaKeys::Exception exception_code, + MediaKeys::Exception exception_code, uint32 system_code, const std::string& error_message); @@ -104,7 +103,7 @@ class ProxyDecryptor { const std::string& web_session_id); // The real MediaKeys that manages key operations for the ProxyDecryptor. - scoped_ptr<media::MediaKeys> media_keys_; + scoped_ptr<MediaKeys> media_keys_; // Callbacks for firing key events. KeyAddedCB key_added_cb_; @@ -126,6 +125,6 @@ class ProxyDecryptor { DISALLOW_COPY_AND_ASSIGN(ProxyDecryptor); }; -} // namespace content +} // namespace media -#endif // CONTENT_RENDERER_MEDIA_CRYPTO_PROXY_DECRYPTOR_H_ +#endif // MEDIA_CDM_PROXY_DECRYPTOR_H_ diff --git a/media/media.gyp b/media/media.gyp index 3c438db..e60d4f8 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -388,6 +388,8 @@ 'cdm/key_system_names.h', 'cdm/player_tracker_impl.cc', 'cdm/player_tracker_impl.h', + 'cdm/proxy_decryptor.cc', + 'cdm/proxy_decryptor.h', 'ffmpeg/ffmpeg_common.cc', 'ffmpeg/ffmpeg_common.h', 'ffmpeg/ffmpeg_deleters.h', diff --git a/mojo/services/html_viewer/webmediaplayer_factory.cc b/mojo/services/html_viewer/webmediaplayer_factory.cc index fbb8e9d..6c4653a 100644 --- a/mojo/services/html_viewer/webmediaplayer_factory.cc +++ b/mojo/services/html_viewer/webmediaplayer_factory.cc @@ -15,7 +15,6 @@ #include "media/base/media.h" #include "media/base/media_log.h" #include "media/base/renderer.h" -#include "media/blink/null_encrypted_media_player_support.h" #include "media/blink/webmediaplayer_impl.h" #include "media/blink/webmediaplayer_params.h" #include "media/filters/gpu_video_accelerator_factories.h" @@ -72,12 +71,12 @@ blink::WebMediaPlayer* WebMediaPlayerFactory::CreateMediaPlayer( scoped_refptr<media::GpuVideoAcceleratorFactories>(), GetMediaThreadTaskRunner(), compositor_task_runner_, - base::Bind(&media::NullEncryptedMediaPlayerSupport::Create), NULL); base::WeakPtr<media::WebMediaPlayerDelegate> delegate; - return new media::WebMediaPlayerImpl( - frame, client, delegate, renderer.Pass(), params); + // TODO(xhwang): Provide a media based CdmFactory implementation. + return new media::WebMediaPlayerImpl(frame, client, delegate, renderer.Pass(), + nullptr, params); #endif } |