Commit e2ea5183 authored by acolwell's avatar acolwell Committed by Commit bot

Move EME code out of WebMediaPlayerImpl.

This change moves all the encrypted media code out of WebMediaPlayerImpl
and into a EncryptedMediaSupportImpl class. This removes the encrypted
media related content/ depencencies from WebMediaPlayerImpl so that it
will be easier to move WebMediaPlayerImpl to a location where it can
be reused by Mojo.

Review URL: https://codereview.chromium.org/501473003

Cr-Commit-Position: refs/heads/master@{#291776}
parent cc256f49
...@@ -251,6 +251,10 @@ ...@@ -251,6 +251,10 @@
'renderer/media/cdm_session_adapter.h', 'renderer/media/cdm_session_adapter.h',
'renderer/media/crypto/content_decryption_module_factory.cc', 'renderer/media/crypto/content_decryption_module_factory.cc',
'renderer/media/crypto/content_decryption_module_factory.h', 'renderer/media/crypto/content_decryption_module_factory.h',
'renderer/media/crypto/encrypted_media_player_support.cc',
'renderer/media/crypto/encrypted_media_player_support.h',
'renderer/media/crypto/encrypted_media_player_support_impl.cc',
'renderer/media/crypto/encrypted_media_player_support_impl.h',
'renderer/media/crypto/key_systems.cc', 'renderer/media/crypto/key_systems.cc',
'renderer/media/crypto/key_systems.h', 'renderer/media/crypto/key_systems.h',
'renderer/media/crypto/key_systems_support_uma.cc', 'renderer/media/crypto/key_systems_support_uma.cc',
...@@ -756,6 +760,7 @@ ...@@ -756,6 +760,7 @@
'renderer/accessibility/renderer_accessibility_focus_only.cc', 'renderer/accessibility/renderer_accessibility_focus_only.cc',
'renderer/media/audio_decoder.cc', 'renderer/media/audio_decoder.cc',
'renderer/media/filter_helpers.cc', 'renderer/media/filter_helpers.cc',
'renderer/media/crypto/encrypted_media_player_support_impl.cc',
'renderer/media/webmediaplayer_impl.cc', 'renderer/media/webmediaplayer_impl.cc',
], ],
'sources': [ 'sources': [
......
// 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.h"
namespace content {
EncryptedMediaPlayerSupport::EncryptedMediaPlayerSupport() {
}
EncryptedMediaPlayerSupport::~EncryptedMediaPlayerSupport() {
}
}
// 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_H_
#define CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_H_
#include "media/base/decryptor.h"
#include "media/base/demuxer.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
namespace blink {
class WebContentDecryptionModule;
class WebContentDecryptionModuleResult;
class WebLocalFrame;
class WebMediaPlayerClient;
class WebString;
}
namespace content {
class EncryptedMediaPlayerSupport {
public:
// Creates a new instance of EncryptedMediaPlayerSupport for |client|. This
// method must always return a valid pointer.
static scoped_ptr<EncryptedMediaPlayerSupport> Create(
blink::WebMediaPlayerClient* client);
EncryptedMediaPlayerSupport();
virtual ~EncryptedMediaPlayerSupport();
// Prefixed API methods.
virtual blink::WebMediaPlayer::MediaKeyException GenerateKeyRequest(
blink::WebLocalFrame* frame,
const blink::WebString& key_system,
const unsigned char* init_data,
unsigned init_data_length) = 0;
virtual 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;
virtual blink::WebMediaPlayer::MediaKeyException CancelKeyRequest(
const blink::WebString& key_system,
const blink::WebString& session_id) = 0;
// Unprefixed API methods.
virtual void SetContentDecryptionModule(
blink::WebContentDecryptionModule* cdm) = 0;
virtual void SetContentDecryptionModule(
blink::WebContentDecryptionModule* cdm,
blink::WebContentDecryptionModuleResult result) = 0;
virtual void SetContentDecryptionModuleSync(
blink::WebContentDecryptionModule* cdm) = 0;
// 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 make sure the callback returned can be safely
// invoked from any thread.
virtual media::Demuxer::NeedKeyCB CreateNeedKeyCB() = 0;
// 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 media::SetDecryptorReadyCB CreateSetDecryptorReadyCB() = 0;
// Called to inform this object that the media pipeline encountered
// and handled a decryption error.
virtual void OnPipelineDecryptError() = 0;
private:
DISALLOW_COPY_AND_ASSIGN(EncryptedMediaPlayerSupport);
};
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_H_
// 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/key_systems.h"
#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
#include "content/renderer/pepper/pepper_webplugin_impl.h"
#include "media/base/bind_to_current_loop.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"
#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 + KeySystemNameForUMA(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 + KeySystemNameForUMA(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. MP4 init data are always >16 bytes.
if (init_data_length == 16)
return "video/webm";
return "video/mp4";
}
scoped_ptr<EncryptedMediaPlayerSupport> EncryptedMediaPlayerSupport::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 =
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 (!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(
#if defined(ENABLE_PEPPER_CDMS)
// Create() must be called synchronously as |frame| may not be
// valid afterwards.
base::Bind(&PepperCdmWrapperImpl::Create, frame),
#elif defined(ENABLE_BROWSER_CDMS)
#error Browser side CDM in WMPI for prefixed EME API not supported yet.
#endif
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 (!proxy_decryptor_->InitializeCDM(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 =
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 (!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 =
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 (!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::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 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_ = 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::SetContentDecryptionModuleSync(
blink::WebContentDecryptionModule* cdm) {
// Used when loading media and no pipeline/decoder attached yet.
DCHECK(decryptor_ready_cb_.is_null());
web_cdm_ = ToWebContentDecryptionModuleImpl(cdm);
}
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_->keyNeeded(
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(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(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(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
// 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/encrypted_media_player_support.h"
#include "content/renderer/media/crypto/proxy_decryptor.h"
namespace content {
class WebContentDecryptionModuleImpl;
class EncryptedMediaPlayerSupportImpl
: public EncryptedMediaPlayerSupport,
public base::SupportsWeakPtr<EncryptedMediaPlayerSupportImpl> {
public:
explicit EncryptedMediaPlayerSupportImpl(blink::WebMediaPlayerClient* client);
virtual ~EncryptedMediaPlayerSupportImpl();
// EncryptedMediaPlayerSupport implementation.
virtual blink::WebMediaPlayer::MediaKeyException GenerateKeyRequest(
blink::WebLocalFrame* frame,
const blink::WebString& key_system,
const unsigned char* init_data,
unsigned init_data_length) OVERRIDE;
virtual 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;
virtual blink::WebMediaPlayer::MediaKeyException CancelKeyRequest(
const blink::WebString& key_system,
const blink::WebString& session_id) OVERRIDE;
virtual void SetContentDecryptionModule(
blink::WebContentDecryptionModule* cdm) OVERRIDE;
virtual void SetContentDecryptionModule(
blink::WebContentDecryptionModule* cdm,
blink::WebContentDecryptionModuleResult result) OVERRIDE;
virtual void SetContentDecryptionModuleSync(
blink::WebContentDecryptionModule* cdm) OVERRIDE;
virtual media::SetDecryptorReadyCB CreateSetDecryptorReadyCB() OVERRIDE;
virtual media::Demuxer::NeedKeyCB CreateNeedKeyCB() OVERRIDE;
virtual void OnPipelineDecryptError() OVERRIDE;
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 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().
WebContentDecryptionModuleImpl* web_cdm_;
media::DecryptorReadyCB decryptor_ready_cb_;
DISALLOW_COPY_AND_ASSIGN(EncryptedMediaPlayerSupportImpl);
};
}
#endif // CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_IMPL_H_
...@@ -18,25 +18,21 @@ ...@@ -18,25 +18,21 @@
#include "base/debug/trace_event.h" #include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h" #include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h" #include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "cc/blink/web_layer_impl.h" #include "cc/blink/web_layer_impl.h"
#include "cc/layers/video_layer.h" #include "cc/layers/video_layer.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_frame.h"
#include "content/renderer/media/buffered_data_source.h" #include "content/renderer/media/buffered_data_source.h"
#include "content/renderer/media/crypto/key_systems.h" #include "content/renderer/media/crypto/encrypted_media_player_support.h"
#include "content/renderer/media/render_media_log.h" #include "content/renderer/media/render_media_log.h"
#include "content/renderer/media/texttrack_impl.h" #include "content/renderer/media/texttrack_impl.h"
#include "content/renderer/media/webaudiosourceprovider_impl.h" #include "content/renderer/media/webaudiosourceprovider_impl.h"
#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
#include "content/renderer/media/webinbandtexttrack_impl.h" #include "content/renderer/media/webinbandtexttrack_impl.h"
#include "content/renderer/media/webmediaplayer_delegate.h" #include "content/renderer/media/webmediaplayer_delegate.h"
#include "content/renderer/media/webmediaplayer_params.h" #include "content/renderer/media/webmediaplayer_params.h"
#include "content/renderer/media/webmediaplayer_util.h" #include "content/renderer/media/webmediaplayer_util.h"
#include "content/renderer/media/webmediasource_impl.h" #include "content/renderer/media/webmediasource_impl.h"
#include "content/renderer/pepper/pepper_webplugin_impl.h"
#include "content/renderer/render_thread_impl.h" #include "content/renderer/render_thread_impl.h"
#include "gpu/GLES2/gl2extchromium.h" #include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/common/mailbox_holder.h" #include "gpu/command_buffer/common/mailbox_holder.h"
...@@ -61,24 +57,16 @@ ...@@ -61,24 +57,16 @@
#include "media/filters/renderer_impl.h" #include "media/filters/renderer_impl.h"
#include "media/filters/video_renderer_impl.h" #include "media/filters/video_renderer_impl.h"
#include "media/filters/vpx_video_decoder.h" #include "media/filters/vpx_video_decoder.h"
#include "third_party/WebKit/public/platform/WebContentDecryptionModule.h"
#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
#include "third_party/WebKit/public/platform/WebMediaSource.h" #include "third_party/WebKit/public/platform/WebMediaSource.h"
#include "third_party/WebKit/public/platform/WebRect.h" #include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h" #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebView.h" #include "third_party/WebKit/public/web/WebView.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
#if defined(ENABLE_PEPPER_CDMS)
#include "content/renderer/media/crypto/pepper_cdm_wrapper_impl.h"
#endif
using blink::WebCanvas; using blink::WebCanvas;
using blink::WebMediaPlayer; using blink::WebMediaPlayer;
using blink::WebRect; using blink::WebRect;
...@@ -117,9 +105,6 @@ const int kPlayerExtraMemory = 1024 * 1024; ...@@ -117,9 +105,6 @@ const int kPlayerExtraMemory = 1024 * 1024;
const double kMinRate = 0.0625; const double kMinRate = 0.0625;
const double kMaxRate = 16.0; const double kMaxRate = 16.0;
// Prefix for histograms related to Encrypted Media Extensions.
const char* kMediaEme = "Media.EME.";
class SyncPointClientImpl : public media::VideoFrame::SyncPointClient { class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
public: public:
explicit SyncPointClientImpl( explicit SyncPointClientImpl(
...@@ -137,10 +122,6 @@ class SyncPointClientImpl : public media::VideoFrame::SyncPointClient { ...@@ -137,10 +122,6 @@ class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
blink::WebGraphicsContext3D* web_graphics_context_; blink::WebGraphicsContext3D* web_graphics_context_;
}; };
// Used for calls to decryptor_ready_cb where the result can be ignored.
void DoNothing(bool) {
}
} // namespace } // namespace
namespace content { namespace content {
...@@ -207,7 +188,9 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( ...@@ -207,7 +188,9 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged), BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged),
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))), BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))),
text_track_index_(0), text_track_index_(0),
web_cdm_(NULL) { encrypted_media_support_(EncryptedMediaPlayerSupport::Create(client)) {
DCHECK(encrypted_media_support_);
media_log_->AddEvent( media_log_->AddEvent(
media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED)); media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED));
...@@ -670,152 +653,14 @@ bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture( ...@@ -670,152 +653,14 @@ bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
return true; return true;
} }
// 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 + KeySystemNameForUMA(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 + KeySystemNameForUMA(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);
}
// Convert a WebString to ASCII, falling back on an empty string in the case
// of a non-ASCII string.
static std::string ToASCIIOrEmpty(const blink::WebString& string) {
return base::IsStringASCII(string) ? base::UTF16ToASCII(string)
: std::string();
}
WebMediaPlayer::MediaKeyException WebMediaPlayer::MediaKeyException
WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system, WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system,
const unsigned char* init_data, const unsigned char* init_data,
unsigned init_data_length) { 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(ascii_key_system, init_data, init_data_length);
ReportMediaKeyExceptionToUMA("generateKeyRequest", ascii_key_system, e);
return e;
}
// 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. MP4 init data are always >16 bytes.
if (init_data_length == 16)
return "video/webm";
return "video/mp4";
}
WebMediaPlayer::MediaKeyException
WebMediaPlayerImpl::GenerateKeyRequestInternal(const std::string& key_system,
const unsigned char* init_data,
unsigned init_data_length) {
DCHECK(main_loop_->BelongsToCurrentThread()); DCHECK(main_loop_->BelongsToCurrentThread());
if (!IsConcreteSupportedKeySystem(key_system)) return encrypted_media_support_->GenerateKeyRequest(
return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; frame_, key_system, init_data, init_data_length);
// 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(
#if defined(ENABLE_PEPPER_CDMS)
// Create() must be called synchronously as |frame_| may not be
// valid afterwards.
base::Bind(&PepperCdmWrapperImpl::Create, frame_),
#elif defined(ENABLE_BROWSER_CDMS)
#error Browser side CDM in WMPI for prefixed EME API not supported yet.
#endif
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyAdded),
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyError),
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyMessage)));
}
GURL security_origin(frame_->document().securityOrigin().toString());
if (!proxy_decryptor_->InitializeCDM(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 WebMediaPlayerImpl::addKey( WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey(
...@@ -825,90 +670,25 @@ WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey( ...@@ -825,90 +670,25 @@ WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey(
const unsigned char* init_data, const unsigned char* init_data,
unsigned init_data_length, unsigned init_data_length,
const WebString& session_id) { const WebString& session_id) {
DVLOG(1) << "addKey: " << base::string16(key_system) << ": " DCHECK(main_loop_->BelongsToCurrentThread());
<< 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 WebMediaPlayerImpl::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( return encrypted_media_support_->AddKey(
key, key_length, init_data, init_data_length, session_id); key_system, key, key_length, init_data, init_data_length, session_id);
return WebMediaPlayer::MediaKeyExceptionNoError;
} }
WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest( WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest(
const WebString& key_system, const WebString& key_system,
const WebString& session_id) { const WebString& session_id) {
DVLOG(1) << "cancelKeyRequest: " << base::string16(key_system) << ": " DCHECK(main_loop_->BelongsToCurrentThread());
<< " [" << 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 WebMediaPlayerImpl::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 encrypted_media_support_->CancelKeyRequest(key_system, session_id);
return WebMediaPlayer::MediaKeyExceptionNoError;
} }
void WebMediaPlayerImpl::setContentDecryptionModule( void WebMediaPlayerImpl::setContentDecryptionModule(
blink::WebContentDecryptionModule* cdm) { blink::WebContentDecryptionModule* cdm) {
DCHECK(main_loop_->BelongsToCurrentThread()); DCHECK(main_loop_->BelongsToCurrentThread());
// TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324 encrypted_media_support_->SetContentDecryptionModule(cdm);
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 WebMediaPlayerImpl::setContentDecryptionModule( void WebMediaPlayerImpl::setContentDecryptionModule(
...@@ -916,51 +696,14 @@ void WebMediaPlayerImpl::setContentDecryptionModule( ...@@ -916,51 +696,14 @@ void WebMediaPlayerImpl::setContentDecryptionModule(
blink::WebContentDecryptionModuleResult result) { blink::WebContentDecryptionModuleResult result) {
DCHECK(main_loop_->BelongsToCurrentThread()); DCHECK(main_loop_->BelongsToCurrentThread());
// TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324 encrypted_media_support_->SetContentDecryptionModule(cdm, result);
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(
&WebMediaPlayerImpl::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 WebMediaPlayerImpl::setContentDecryptionModuleSync( void WebMediaPlayerImpl::setContentDecryptionModuleSync(
blink::WebContentDecryptionModule* cdm) { blink::WebContentDecryptionModule* cdm) {
DCHECK(main_loop_->BelongsToCurrentThread()); DCHECK(main_loop_->BelongsToCurrentThread());
// Used when loading media and no pipeline/decoder attached yet. encrypted_media_support_->SetContentDecryptionModuleSync(cdm);
DCHECK(decryptor_ready_cb_.is_null());
web_cdm_ = ToWebContentDecryptionModuleImpl(cdm);
}
void WebMediaPlayerImpl::ContentDecryptionModuleAttached(
blink::WebContentDecryptionModuleResult result,
bool success) {
if (success) {
result.complete();
return;
}
result.completeWithError(
blink::WebContentDecryptionModuleExceptionNotSupportedError,
0,
"Unable to set MediaKeys object");
} }
void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed, void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed,
...@@ -1006,7 +749,7 @@ void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) { ...@@ -1006,7 +749,7 @@ void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
SetNetworkState(PipelineErrorToNetworkState(error)); SetNetworkState(PipelineErrorToNetworkState(error));
if (error == media::PIPELINE_ERROR_DECRYPT) if (error == media::PIPELINE_ERROR_DECRYPT)
EmeUMAHistogramCounts(current_key_system_, "DecryptError", 1); encrypted_media_support_->OnPipelineDecryptError();
} }
void WebMediaPlayerImpl::OnPipelineMetadata( void WebMediaPlayerImpl::OnPipelineMetadata(
...@@ -1061,35 +804,6 @@ void WebMediaPlayerImpl::OnDemuxerOpened() { ...@@ -1061,35 +804,6 @@ void WebMediaPlayerImpl::OnDemuxerOpened() {
chunk_demuxer_, base::Bind(&LogMediaSourceError, media_log_))); chunk_demuxer_, base::Bind(&LogMediaSourceError, media_log_)));
} }
void WebMediaPlayerImpl::OnKeyAdded(const std::string& session_id) {
DCHECK(main_loop_->BelongsToCurrentThread());
EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1);
client_->keyAdded(
WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)),
WebString::fromUTF8(session_id));
}
void WebMediaPlayerImpl::OnNeedKey(const std::string& type,
const std::vector<uint8>& init_data) {
DCHECK(main_loop_->BelongsToCurrentThread());
// 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_->keyNeeded(
WebString::fromUTF8(type), init_data_ptr, init_data.size());
}
void WebMediaPlayerImpl::OnAddTextTrack( void WebMediaPlayerImpl::OnAddTextTrack(
const media::TextTrackConfig& config, const media::TextTrackConfig& config,
const media::AddTextTrackDoneCB& done_cb) { const media::AddTextTrackDoneCB& done_cb) {
...@@ -1114,44 +828,6 @@ void WebMediaPlayerImpl::OnAddTextTrack( ...@@ -1114,44 +828,6 @@ void WebMediaPlayerImpl::OnAddTextTrack(
done_cb.Run(text_track.Pass()); done_cb.Run(text_track.Pass());
} }
void WebMediaPlayerImpl::OnKeyError(const std::string& session_id,
media::MediaKeys::KeyError error_code,
uint32 system_code) {
DCHECK(main_loop_->BelongsToCurrentThread());
EmeUMAHistogramEnumeration(current_key_system_, "KeyError",
error_code, media::MediaKeys::kMaxKeyError);
unsigned short short_system_code = 0;
if (system_code > std::numeric_limits<unsigned short>::max()) {
LOG(WARNING) << "system_code exceeds unsigned short limit.";
short_system_code = std::numeric_limits<unsigned short>::max();
} else {
short_system_code = static_cast<unsigned short>(system_code);
}
client_->keyError(
WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)),
WebString::fromUTF8(session_id),
static_cast<blink::WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
short_system_code);
}
void WebMediaPlayerImpl::OnKeyMessage(const std::string& session_id,
const std::vector<uint8>& message,
const GURL& destination_url) {
DCHECK(main_loop_->BelongsToCurrentThread());
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],
message.size(),
destination_url);
}
void WebMediaPlayerImpl::DataSourceInitialized(bool success) { void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
DCHECK(main_loop_->BelongsToCurrentThread()); DCHECK(main_loop_->BelongsToCurrentThread());
...@@ -1178,7 +854,7 @@ void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { ...@@ -1178,7 +854,7 @@ void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
// renderers. // renderers.
scoped_ptr<media::Renderer> WebMediaPlayerImpl::CreateRenderer() { scoped_ptr<media::Renderer> WebMediaPlayerImpl::CreateRenderer() {
media::SetDecryptorReadyCB set_decryptor_ready_cb = media::SetDecryptorReadyCB set_decryptor_ready_cb =
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetDecryptorReadyCB); encrypted_media_support_->CreateSetDecryptorReadyCB();
// Create our audio decoders and renderer. // Create our audio decoders and renderer.
ScopedVector<media::AudioDecoder> audio_decoders; ScopedVector<media::AudioDecoder> audio_decoders;
...@@ -1233,6 +909,8 @@ void WebMediaPlayerImpl::StartPipeline() { ...@@ -1233,6 +909,8 @@ void WebMediaPlayerImpl::StartPipeline() {
(load_type_ == LoadTypeMediaSource)); (load_type_ == LoadTypeMediaSource));
media::LogCB mse_log_cb; media::LogCB mse_log_cb;
media::Demuxer::NeedKeyCB need_key_cb =
encrypted_media_support_->CreateNeedKeyCB();
// Figure out which demuxer to use. // Figure out which demuxer to use.
if (load_type_ != LoadTypeMediaSource) { if (load_type_ != LoadTypeMediaSource) {
...@@ -1241,7 +919,7 @@ void WebMediaPlayerImpl::StartPipeline() { ...@@ -1241,7 +919,7 @@ void WebMediaPlayerImpl::StartPipeline() {
demuxer_.reset(new media::FFmpegDemuxer( demuxer_.reset(new media::FFmpegDemuxer(
media_loop_, data_source_.get(), media_loop_, data_source_.get(),
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNeedKey), need_key_cb,
media_log_)); media_log_));
} else { } else {
DCHECK(!chunk_demuxer_); DCHECK(!chunk_demuxer_);
...@@ -1251,7 +929,7 @@ void WebMediaPlayerImpl::StartPipeline() { ...@@ -1251,7 +929,7 @@ void WebMediaPlayerImpl::StartPipeline() {
chunk_demuxer_ = new media::ChunkDemuxer( chunk_demuxer_ = new media::ChunkDemuxer(
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened), BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNeedKey), need_key_cb,
mse_log_cb, mse_log_cb,
true); true);
demuxer_.reset(chunk_demuxer_); demuxer_.reset(chunk_demuxer_);
...@@ -1364,43 +1042,6 @@ void WebMediaPlayerImpl::FrameReady( ...@@ -1364,43 +1042,6 @@ void WebMediaPlayerImpl::FrameReady(
frame)); frame));
} }
void WebMediaPlayerImpl::SetDecryptorReadyCB(
const media::DecryptorReadyCB& decryptor_ready_cb) {
DCHECK(main_loop_->BelongsToCurrentThread());
// 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;
}
static void GetCurrentFrameAndSignal( static void GetCurrentFrameAndSignal(
VideoFrameCompositor* compositor, VideoFrameCompositor* compositor,
scoped_refptr<media::VideoFrame>* video_frame_out, scoped_refptr<media::VideoFrame>* video_frame_out,
......
...@@ -14,10 +14,8 @@ ...@@ -14,10 +14,8 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "content/renderer/media/buffered_data_source_host_impl.h" #include "content/renderer/media/buffered_data_source_host_impl.h"
#include "content/renderer/media/crypto/proxy_decryptor.h"
#include "content/renderer/media/video_frame_compositor.h" #include "content/renderer/media/video_frame_compositor.h"
#include "media/base/audio_renderer_sink.h" #include "media/base/audio_renderer_sink.h"
#include "media/base/decryptor.h"
// TODO(xhwang): Remove when we remove prefixed EME implementation. // TODO(xhwang): Remove when we remove prefixed EME implementation.
#include "media/base/media_keys.h" #include "media/base/media_keys.h"
#include "media/base/pipeline.h" #include "media/base/pipeline.h"
...@@ -25,16 +23,13 @@ ...@@ -25,16 +23,13 @@
#include "media/filters/skcanvas_video_renderer.h" #include "media/filters/skcanvas_video_renderer.h"
#include "skia/ext/platform_canvas.h" #include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h" #include "third_party/WebKit/public/platform/WebAudioSourceProvider.h"
#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h" #include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
#include "url/gurl.h" #include "url/gurl.h"
class RenderAudioSourceProvider;
namespace blink { namespace blink {
class WebContentDecryptionModule;
class WebContentDecryptionModuleResult;
class WebLocalFrame; class WebLocalFrame;
} }
...@@ -55,9 +50,9 @@ class MediaLog; ...@@ -55,9 +50,9 @@ class MediaLog;
namespace content { namespace content {
class BufferedDataSource; class BufferedDataSource;
class EncryptedMediaPlayerSupport;
class VideoFrameCompositor; class VideoFrameCompositor;
class WebAudioSourceProviderImpl; class WebAudioSourceProviderImpl;
class WebContentDecryptionModuleImpl;
class WebMediaPlayerDelegate; class WebMediaPlayerDelegate;
class WebMediaPlayerParams; class WebMediaPlayerParams;
class WebTextTrackImpl; class WebTextTrackImpl;
...@@ -177,15 +172,6 @@ class WebMediaPlayerImpl ...@@ -177,15 +172,6 @@ class WebMediaPlayerImpl
void OnPipelineMetadata(media::PipelineMetadata metadata); void OnPipelineMetadata(media::PipelineMetadata metadata);
void OnPipelineBufferingStateChanged(media::BufferingState buffering_state); void OnPipelineBufferingStateChanged(media::BufferingState buffering_state);
void OnDemuxerOpened(); void OnDemuxerOpened();
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 OnNeedKey(const std::string& type,
const std::vector<uint8>& init_data);
void OnAddTextTrack(const media::TextTrackConfig& config, void OnAddTextTrack(const media::TextTrackConfig& config,
const media::AddTextTrackDoneCB& done_cb); const media::AddTextTrackDoneCB& done_cb);
...@@ -216,20 +202,6 @@ class WebMediaPlayerImpl ...@@ -216,20 +202,6 @@ class WebMediaPlayerImpl
// Lets V8 know that player uses extra resources not managed by V8. // Lets V8 know that player uses extra resources not managed by V8.
void IncrementExternallyAllocatedMemory(); void IncrementExternallyAllocatedMemory();
// Actually do the work for generateKeyRequest/addKey so they can easily
// report results to UMA.
MediaKeyException GenerateKeyRequestInternal(const std::string& key_system,
const unsigned char* init_data,
unsigned init_data_length);
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);
MediaKeyException CancelKeyRequestInternal(const std::string& key_system,
const std::string& session_id);
// Gets the duration value reported by the pipeline. // Gets the duration value reported by the pipeline.
double GetPipelineDuration() const; double GetPipelineDuration() const;
...@@ -242,12 +214,6 @@ class WebMediaPlayerImpl ...@@ -242,12 +214,6 @@ class WebMediaPlayerImpl
// painted. // painted.
void FrameReady(const scoped_refptr<media::VideoFrame>& frame); void FrameReady(const scoped_refptr<media::VideoFrame>& frame);
// 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);
// Called when the ContentDecryptionModule has been attached to the // Called when the ContentDecryptionModule has been attached to the
// pipeline/decoders. // pipeline/decoders.
void ContentDecryptionModuleAttached( void ContentDecryptionModuleAttached(
...@@ -275,10 +241,6 @@ class WebMediaPlayerImpl ...@@ -275,10 +241,6 @@ class WebMediaPlayerImpl
scoped_refptr<media::MediaLog> media_log_; scoped_refptr<media::MediaLog> media_log_;
media::Pipeline pipeline_; media::Pipeline pipeline_;
// The currently selected key system. Empty string means that no key system
// has been selected.
std::string current_key_system_;
// The LoadType passed in the |load_type| parameter of the load() call. // The LoadType passed in the |load_type| parameter of the load() call.
LoadType load_type_; LoadType load_type_;
...@@ -342,10 +304,6 @@ class WebMediaPlayerImpl ...@@ -342,10 +304,6 @@ class WebMediaPlayerImpl
BufferedDataSourceHostImpl buffered_data_source_host_; BufferedDataSourceHostImpl buffered_data_source_host_;
// 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_;
// Video rendering members. // Video rendering members.
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
VideoFrameCompositor* compositor_; // Deleted on |compositor_task_runner_|. VideoFrameCompositor* compositor_; // Deleted on |compositor_task_runner_|.
...@@ -358,14 +316,7 @@ class WebMediaPlayerImpl ...@@ -358,14 +316,7 @@ class WebMediaPlayerImpl
// Text track objects get a unique index value when they're created. // Text track objects get a unique index value when they're created.
int text_track_index_; int text_track_index_;
// Manages decryption keys and decrypts encrypted frames. scoped_ptr<EncryptedMediaPlayerSupport> encrypted_media_support_;
scoped_ptr<ProxyDecryptor> proxy_decryptor_;
// Non-owned pointer to the CDM. Updated via calls to
// setContentDecryptionModule().
WebContentDecryptionModuleImpl* web_cdm_;
media::DecryptorReadyCB decryptor_ready_cb_;
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl); DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl);
}; };
......
...@@ -39,6 +39,6 @@ class WebMediaPlayerParams { ...@@ -39,6 +39,6 @@ class WebMediaPlayerParams {
DISALLOW_IMPLICIT_CONSTRUCTORS(WebMediaPlayerParams); DISALLOW_IMPLICIT_CONSTRUCTORS(WebMediaPlayerParams);
}; };
} // namespace media } // namespace content
#endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_PARAMS_H_ #endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_PARAMS_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment