summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorddorwin <ddorwin@chromium.org>2016-03-02 21:06:29 -0800
committerCommit bot <commit-bot@chromium.org>2016-03-03 05:07:51 +0000
commitf1f20728a18fff332af52c0e60726a8b34510ba6 (patch)
treef4c5b710675a1a3787b404cd2a31a7d7b7532067
parentfee5771921b6f93f36a3b102c30b3711db8b7b5b (diff)
downloadchromium_src-f1f20728a18fff332af52c0e60726a8b34510ba6.zip
chromium_src-f1f20728a18fff332af52c0e60726a8b34510ba6.tar.gz
chromium_src-f1f20728a18fff332af52c0e60726a8b34510ba6.tar.bz2
EME on Android: Improve accuracy of Key System availability.
Implemented per https://crbug.com/582618#c7. BUG=559236,582618 Review URL: https://codereview.chromium.org/1747073003 Cr-Commit-Position: refs/heads/master@{#378959}
-rw-r--r--media/base/android/media_drm_bridge.cc67
-rw-r--r--media/base/android/media_drm_bridge.h16
-rw-r--r--media/base/key_systems.cc11
-rw-r--r--media/base/media.cc6
-rw-r--r--media/base/media.h6
-rw-r--r--media/base/mime_util_internal.cc5
-rw-r--r--media/blink/key_system_config_selector.cc27
7 files changed, 109 insertions, 29 deletions
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc
index 0633c31..a5975f3 100644
--- a/media/base/android/media_drm_bridge.cc
+++ b/media/base/android/media_drm_bridge.cc
@@ -26,6 +26,7 @@
#include "base/thread_task_runner_handle.h"
#include "jni/MediaDrmBridge_jni.h"
#include "media/base/android/media_client_android.h"
+#include "media/base/android/media_codec_util.h"
#include "media/base/android/media_drm_bridge_delegate.h"
#include "media/base/android/provision_fetcher.h"
#include "media/base/cdm_key_information.h"
@@ -174,8 +175,12 @@ base::LazyInstance<KeySystemManager>::Leaky g_key_system_manager =
// resolved.
bool IsKeySystemSupportedWithTypeImpl(const std::string& key_system,
const std::string& container_mime_type) {
- if (!MediaDrmBridge::IsAvailable())
+ DCHECK(MediaDrmBridge::IsAvailable());
+
+ if (key_system.empty()) {
+ NOTREACHED();
return false;
+ }
UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system);
if (scheme_uuid.empty())
@@ -215,10 +220,7 @@ std::string GetSecurityLevelString(
return "";
}
-} // namespace
-
-// static
-bool MediaDrmBridge::IsAvailable() {
+bool AreMediaDrmApisAvailable() {
if (base::android::BuildInfo::GetInstance()->sdk_int() < 19)
return false;
@@ -233,6 +235,15 @@ bool MediaDrmBridge::IsAvailable() {
return true;
}
+} // namespace
+
+// MediaDrm is not generally usable without MediaCodec. Thus, both the MediaDrm
+// APIs and MediaCodec APIs must be enabled and not blacklisted.
+// static
+bool MediaDrmBridge::IsAvailable() {
+ return AreMediaDrmApisAvailable() && MediaCodecUtil::IsMediaCodecAvailable();
+}
+
// static
bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) {
return RegisterNativesImpl(env);
@@ -240,7 +251,9 @@ bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) {
// static
bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) {
- DCHECK(!key_system.empty());
+ if (!MediaDrmBridge::IsAvailable())
+ return false;
+
return IsKeySystemSupportedWithTypeImpl(key_system, "");
}
@@ -248,17 +261,24 @@ bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) {
bool MediaDrmBridge::IsKeySystemSupportedWithType(
const std::string& key_system,
const std::string& container_mime_type) {
- DCHECK(!key_system.empty() && !container_mime_type.empty());
+ DCHECK(!container_mime_type.empty()) << "Call IsKeySystemSupported instead";
+
+ if (!MediaDrmBridge::IsAvailable())
+ return false;
+
return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type);
}
// static
std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() {
+ if (!MediaDrmBridge::IsAvailable())
+ return std::vector<std::string>();
+
return g_key_system_manager.Get().GetPlatformKeySystemNames();
}
// static
-scoped_refptr<MediaDrmBridge> MediaDrmBridge::Create(
+scoped_refptr<MediaDrmBridge> MediaDrmBridge::CreateInternal(
const std::string& key_system,
SecurityLevel security_level,
const CreateFetcherCB& create_fetcher_cb,
@@ -267,10 +287,8 @@ scoped_refptr<MediaDrmBridge> MediaDrmBridge::Create(
const LegacySessionErrorCB& legacy_session_error_cb,
const SessionKeysChangeCB& session_keys_change_cb,
const SessionExpirationUpdateCB& session_expiration_update_cb) {
- DVLOG(1) << __FUNCTION__;
-
- if (!IsAvailable())
- return nullptr;
+ // All paths requires the MediaDrmApis.
+ DCHECK(AreMediaDrmApisAvailable());
UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system);
if (scheme_uuid.empty())
@@ -288,12 +306,37 @@ scoped_refptr<MediaDrmBridge> MediaDrmBridge::Create(
}
// static
+scoped_refptr<MediaDrmBridge> MediaDrmBridge::Create(
+ const std::string& key_system,
+ SecurityLevel security_level,
+ const CreateFetcherCB& create_fetcher_cb,
+ const SessionMessageCB& session_message_cb,
+ const SessionClosedCB& session_closed_cb,
+ const LegacySessionErrorCB& legacy_session_error_cb,
+ const SessionKeysChangeCB& session_keys_change_cb,
+ const SessionExpirationUpdateCB& session_expiration_update_cb) {
+ DVLOG(1) << __FUNCTION__;
+
+ if (!IsAvailable())
+ return nullptr;
+
+ return CreateInternal(key_system, security_level, create_fetcher_cb,
+ session_message_cb, session_closed_cb,
+ legacy_session_error_cb, session_keys_change_cb,
+ session_expiration_update_cb);
+}
+
+// static
scoped_refptr<MediaDrmBridge> MediaDrmBridge::CreateWithoutSessionSupport(
const std::string& key_system,
SecurityLevel security_level,
const CreateFetcherCB& create_fetcher_cb) {
DVLOG(1) << __FUNCTION__;
+ // Sessions won't be used so decoding capability is not required.
+ if (!AreMediaDrmApisAvailable())
+ return nullptr;
+
return MediaDrmBridge::Create(key_system, security_level, create_fetcher_cb,
SessionMessageCB(), SessionClosedCB(),
LegacySessionErrorCB(), SessionKeysChangeCB(),
diff --git a/media/base/android/media_drm_bridge.h b/media/base/android/media_drm_bridge.h
index 04e57fc..d5408c1 100644
--- a/media/base/android/media_drm_bridge.h
+++ b/media/base/android/media_drm_bridge.h
@@ -55,9 +55,9 @@ class MEDIA_EXPORT MediaDrmBridge : public MediaKeys, public PlayerTracker {
using MediaCryptoReadyCB = base::Callback<void(JavaObjectPtr media_crypto,
bool needs_protected_surface)>;
- // Checks whether MediaDRM is available.
- // All other static methods check IsAvailable() internally. There's no need
- // to check IsAvailable() explicitly before calling them.
+ // Checks whether MediaDRM is available and usable, including for decoding.
+ // All other static methods check IsAvailable() or equivalent internally.
+ // There is no need to check IsAvailable() explicitly before calling them.
static bool IsAvailable();
static bool RegisterMediaDrmBridge(JNIEnv* env);
@@ -243,6 +243,16 @@ class MEDIA_EXPORT MediaDrmBridge : public MediaKeys, public PlayerTracker {
// For DeleteSoon() in DeleteOnCorrectThread().
friend class base::DeleteHelper<MediaDrmBridge>;
+ static scoped_refptr<MediaDrmBridge> CreateInternal(
+ const std::string& key_system,
+ SecurityLevel security_level,
+ const CreateFetcherCB& create_fetcher_cb,
+ const SessionMessageCB& session_message_cb,
+ const SessionClosedCB& session_closed_cb,
+ const LegacySessionErrorCB& legacy_session_error_cb,
+ const SessionKeysChangeCB& session_keys_change_cb,
+ const SessionExpirationUpdateCB& session_expiration_update_cb);
+
// Constructs a MediaDrmBridge for |scheme_uuid| and |security_level|. The
// default security level will be used if |security_level| is
// SECURITY_LEVEL_DEFAULT. Sessions should not be created if session callbacks
diff --git a/media/base/key_systems.cc b/media/base/key_systems.cc
index 914661f..8a3ae69 100644
--- a/media/base/key_systems.cc
+++ b/media/base/key_systems.cc
@@ -15,6 +15,7 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/base/key_system_info.h"
+#include "media/base/media.h"
#include "media/base/media_client.h"
#include "media/cdm/key_system_names.h"
#include "third_party/widevine/cdm/widevine_cdm_common.h"
@@ -409,6 +410,16 @@ void KeySystemsImpl::AddSupportedKeySystems(
DCHECK_EQ(key_system_map_.count(info.key_system), 0u)
<< "Key system '" << info.key_system << "' already registered";
+
+#if defined(OS_ANDROID)
+ // Ensure that the renderer can access the decoders necessary to use the
+ // key system.
+ if (!info.use_aes_decryptor && !ArePlatformDecodersAvailable()) {
+ DLOG(WARNING) << info.key_system << " not registered";
+ continue;
+ }
+#endif // defined(OS_ANDROID)
+
key_system_map_[info.key_system] = info;
}
}
diff --git a/media/base/media.cc b/media/base/media.cc
index efc495b..b2e1c45 100644
--- a/media/base/media.cc
+++ b/media/base/media.cc
@@ -115,6 +115,12 @@ bool IsUnifiedMediaPipelineEnabledForMse() {
switches::kEnableUnifiedMediaPipeline) ||
!MediaCodecUtil::IsMediaCodecAvailable();
}
+
+bool ArePlatformDecodersAvailable() {
+ return IsUnifiedMediaPipelineEnabled()
+ ? HasPlatformDecoderSupport()
+ : MediaCodecUtil::IsMediaCodecAvailable();
+}
#endif
} // namespace media
diff --git a/media/base/media.h b/media/base/media.h
index 65a7a69..b6cccc4 100644
--- a/media/base/media.h
+++ b/media/base/media.h
@@ -46,6 +46,12 @@ MEDIA_EXPORT bool IsUnifiedMediaPipelineEnabled();
// cases where existing pipeline has no support). As above, codecs requiring
// platform support may not be available.
MEDIA_EXPORT bool IsUnifiedMediaPipelineEnabledForMse();
+
+// Returns whether the platform decoders are available for use.
+// This includes decoders being available on the platform and accessible, such
+// as via the GPU process. Should only be used for actual decoders
+// (e.g. MediaCodec) and not full-featured players (e.g. MediaPlayer).
+MEDIA_EXPORT bool ArePlatformDecodersAvailable();
#endif
} // namespace media
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc
index a0ce3c4..7e7f004 100644
--- a/media/base/mime_util_internal.cc
+++ b/media/base/mime_util_internal.cc
@@ -274,10 +274,7 @@ MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) {
// When the unified media pipeline is enabled, we need support for both GPU
// video decoders and MediaCodec; indicated by HasPlatformDecoderSupport().
// When the Android pipeline is used, we only need access to MediaCodec.
- platform_info_.has_platform_decoders =
- platform_info_.is_unified_media_pipeline_enabled
- ? HasPlatformDecoderSupport()
- : MediaCodecUtil::IsMediaCodecAvailable();
+ platform_info_.has_platform_decoders = ArePlatformDecodersAvailable();
platform_info_.has_platform_vp8_decoder =
MediaCodecUtil::IsVp8DecoderAvailable();
platform_info_.supports_opus = PlatformHasOpusSupport();
diff --git a/media/blink/key_system_config_selector.cc b/media/blink/key_system_config_selector.cc
index 766feda..885049c 100644
--- a/media/blink/key_system_config_selector.cc
+++ b/media/blink/key_system_config_selector.cc
@@ -277,20 +277,25 @@ KeySystemConfigSelector::KeySystemConfigSelector(
KeySystemConfigSelector::~KeySystemConfigSelector() {
}
-bool IsSupportedClearMediaFormat(const std::string& container_mime_type,
- const std::string& codecs) {
+bool IsSupportedMediaFormat(const std::string& container_mime_type,
+ const std::string& codecs,
+ bool use_aes_decryptor) {
std::vector<std::string> codec_vector;
- media::ParseCodecString(codecs, &codec_vector, false);
- media::SupportsType support_result =
- media::IsSupportedEncryptedMediaFormat(container_mime_type, codec_vector);
+ ParseCodecString(codecs, &codec_vector, false);
+ // AesDecryptor decrypts the stream in the demuxer before it reaches the
+ // decoder so check whether the media format is supported when clear.
+ SupportsType support_result =
+ use_aes_decryptor
+ ? IsSupportedMediaFormat(container_mime_type, codec_vector)
+ : IsSupportedEncryptedMediaFormat(container_mime_type, codec_vector);
switch (support_result) {
- case media::IsSupported:
+ case IsSupported:
return true;
- case media::MayBeSupported:
+ case MayBeSupported:
// If no codecs were specified, the best possible result is
// MayBeSupported, indicating support for the container.
return codec_vector.empty();
- case media::IsNotSupported:
+ case IsNotSupported:
return false;
}
NOTREACHED();
@@ -309,8 +314,10 @@ bool KeySystemConfigSelector::IsSupportedContentType(
// is done primarily to validate extended codecs, but it also ensures that the
// CDM cannot support codecs that Chrome does not (which could complicate the
// robustness algorithm).
- if (!IsSupportedClearMediaFormat(container_mime_type, codecs))
+ if (!IsSupportedMediaFormat(container_mime_type, codecs,
+ CanUseAesDecryptor(key_system))) {
return false;
+ }
// TODO(servolk): Converting |container_mime_type| to lower-case could be
// moved to KeySystemsImpl::GetContentTypeConfigRule, plus we could add some
@@ -321,7 +328,7 @@ bool KeySystemConfigSelector::IsSupportedContentType(
// This check does not handle extended codecs, so extended codec information
// is stripped (extended codec information was checked above).
std::vector<std::string> stripped_codec_vector;
- media::ParseCodecString(codecs, &stripped_codec_vector, true);
+ ParseCodecString(codecs, &stripped_codec_vector, true);
EmeConfigRule codecs_rule = key_systems_->GetContentTypeConfigRule(
key_system, media_type, container_lower, stripped_codec_vector);
if (!config_state->IsRuleSupported(codecs_rule))