summaryrefslogtreecommitdiffstats
path: root/media/blink
diff options
context:
space:
mode:
authorxhwang <xhwang@chromium.org>2014-11-18 16:16:34 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-19 00:17:00 +0000
commit16ff136e88d757f4ca92291e8e221682cb1e8c63 (patch)
tree3ad793cf6fcdb61dd32139849798ba95557ef4ed /media/blink
parentc69f9dc3d6256814736abcf5b3ef0df37c1406e2 (diff)
downloadchromium_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.gn4
-rw-r--r--media/blink/encrypted_media_player_support.cc435
-rw-r--r--media/blink/encrypted_media_player_support.h121
-rw-r--r--media/blink/media_blink.gyp4
-rw-r--r--media/blink/null_encrypted_media_player_support.cc86
-rw-r--r--media/blink/null_encrypted_media_player_support.h76
-rw-r--r--media/blink/webmediaplayer_impl.cc28
-rw-r--r--media/blink/webmediaplayer_impl.h6
-rw-r--r--media/blink/webmediaplayer_params.cc13
-rw-r--r--media/blink/webmediaplayer_params.h15
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);