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 /media/blink | |
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}
Diffstat (limited to 'media/blink')
-rw-r--r-- | media/blink/BUILD.gn | 4 | ||||
-rw-r--r-- | media/blink/encrypted_media_player_support.cc | 435 | ||||
-rw-r--r-- | media/blink/encrypted_media_player_support.h | 121 | ||||
-rw-r--r-- | media/blink/media_blink.gyp | 4 | ||||
-rw-r--r-- | media/blink/null_encrypted_media_player_support.cc | 86 | ||||
-rw-r--r-- | media/blink/null_encrypted_media_player_support.h | 76 | ||||
-rw-r--r-- | media/blink/webmediaplayer_impl.cc | 28 | ||||
-rw-r--r-- | media/blink/webmediaplayer_impl.h | 6 | ||||
-rw-r--r-- | media/blink/webmediaplayer_params.cc | 13 | ||||
-rw-r--r-- | media/blink/webmediaplayer_params.h | 15 |
10 files changed, 548 insertions, 240 deletions
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); |