Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Unified Diff: media/base/android/media_drm_bridge.cc

Issue 1341883003: Prepare MediaDrmBridge to work with MediaCodecPlayer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@bug526755
Patch Set: Addressed Min's comments Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/base/android/media_drm_bridge.cc
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc
index 14bdbda03f0ac81e2f32ea958d02103f3b91e3d1..5ff49ee017c02f024aa8c6aafd2b8f11490ff21c 100644
--- a/media/base/android/media_drm_bridge.cc
+++ b/media/base/android/media_drm_bridge.cc
@@ -9,6 +9,7 @@
#include "base/android/build_info.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
+#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
@@ -23,11 +24,23 @@
#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_player.h" // for GetMediaTaskRunner()
#include "media/base/android/media_drm_bridge_delegate.h"
#include "media/base/cdm_key_information.h"
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
+#define RUN_CB_ON_MEDIA_THREAD(cb, ...) \
+ do { \
+ if (run_on_media_thread_ && \
+ !GetMediaTaskRunner()->BelongsToCurrentThread()) { \
+ GetMediaTaskRunner()->PostTask(FROM_HERE, \
+ base::Bind(cb, ##__VA_ARGS__)); \
+ } else { \
+ cb.Run(__VA_ARGS__); \
+ } \
+ } while (0)
+
using base::android::AttachCurrentThread;
using base::android::ConvertUTF8ToJavaString;
using base::android::ConvertJavaStringToUTF8;
@@ -228,6 +241,31 @@ bool MediaDrmBridge::IsAvailable() {
return true;
}
+// static
+bool MediaDrmBridge::CanCreate(const std::string& key_system,
+ SecurityLevel widevine_security_level) {
+ if (!IsAvailable()) {
+ DVLOG(1) << __FUNCTION__ << ": DRM is not available";
+ return false;
+ }
+
+ UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system);
+ if (scheme_uuid.empty()) {
+ DVLOG(1) << __FUNCTION__ << ": key system " << key_system
+ << " not supported";
+ return false;
+ }
+
+ if (key_system == kWidevineKeySystem &&
+ widevine_security_level != SECURITY_LEVEL_NONE &&
+ !std::equal(scheme_uuid.begin(), scheme_uuid.end(), kWidevineUuid)) {
+ NOTREACHED() << "Widevine security level " << widevine_security_level
+ << "used with another key system";
+ return false;
+ }
+ return true;
+}
+
// TODO(ddorwin): This is specific to Widevine. http://crbug.com/459400
// static
bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) {
@@ -254,6 +292,7 @@ bool MediaDrmBridge::IsKeySystemSupportedWithType(
return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type);
}
+// static
bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) {
return RegisterNativesImpl(env);
}
@@ -270,7 +309,29 @@ MediaDrmBridge::MediaDrmBridge(
session_closed_cb_(session_closed_cb),
legacy_session_error_cb_(legacy_session_error_cb),
session_keys_change_cb_(session_keys_change_cb),
- session_expiration_update_cb_(session_expiration_update_cb) {
+ session_expiration_update_cb_(session_expiration_update_cb),
+ run_on_media_thread_(false),
+ weak_factory_(this) {
+ DVLOG(1) << "MediaDrmBridge::MediaDrmBridge";
+
+ // When this flag is set we need to repost the notifications about
+ // crypto became ready and a key had been added to the Media thread.
+ run_on_media_thread_ = GetMediaTaskRunner()->BelongsToCurrentThread();
+
+ // Create internal callbacks to repost Java new key notification and
+ // promise related notifications to the media thread.
+
+ base::WeakPtr<MediaDrmBridge> weak_this = weak_factory_.GetWeakPtr();
+
+ internal_keys_added_cb_ =
+ base::Bind(&MediaDrmBridge::InternalKeysAdded, weak_this);
+ internal_promise_resolved_cb_ =
+ base::Bind(&MediaDrmBridge::InternalPromiseResolved, weak_this);
+ internal_promise_resolved_with_session_cb_ = base::Bind(
+ &MediaDrmBridge::InternalPromiseResolvedWithSession, weak_this);
+ internal_promise_rejected_cb_ =
+ base::Bind(&MediaDrmBridge::InternalPromiseRejected, weak_this);
+
JNIEnv* env = AttachCurrentThread();
CHECK(env);
@@ -288,14 +349,15 @@ MediaDrmBridge::~MediaDrmBridge() {
}
// static
-scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create(
+scoped_ptr<MediaDrmBridge, BrowserCdmDeleter> MediaDrmBridge::Create(
const std::string& key_system,
+ SecurityLevel widevine_security_level,
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) {
- scoped_ptr<MediaDrmBridge> media_drm_bridge;
+ scoped_ptr<MediaDrmBridge, BrowserCdmDeleter> media_drm_bridge;
if (!IsAvailable())
return media_drm_bridge.Pass();
@@ -311,15 +373,24 @@ scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create(
if (media_drm_bridge->j_media_drm_.is_null())
media_drm_bridge.reset();
+ if (key_system == kWidevineKeySystem &&
ddorwin 2015/09/16 20:42:21 We shouldn't need the WV check here again.
+ widevine_security_level != SECURITY_LEVEL_NONE &&
+ !media_drm_bridge->SetSecurityLevel(widevine_security_level)) {
+ DVLOG(1) << __FUNCTION__ << ": failed to set security level "
+ << widevine_security_level;
+ media_drm_bridge.reset();
+ }
+
return media_drm_bridge.Pass();
}
// static
-scoped_ptr<MediaDrmBridge> MediaDrmBridge::CreateWithoutSessionSupport(
- const std::string& key_system) {
- return MediaDrmBridge::Create(
- key_system, SessionMessageCB(), SessionClosedCB(), LegacySessionErrorCB(),
- SessionKeysChangeCB(), SessionExpirationUpdateCB());
+scoped_ptr<MediaDrmBridge, BrowserCdmDeleter>
+MediaDrmBridge::CreateWithoutSessionSupport(const std::string& key_system) {
+ return MediaDrmBridge::Create(key_system, SECURITY_LEVEL_NONE,
+ SessionMessageCB(), SessionClosedCB(),
+ LegacySessionErrorCB(), SessionKeysChangeCB(),
+ SessionExpirationUpdateCB());
}
bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) {
@@ -425,7 +496,7 @@ void MediaDrmBridge::UpdateSession(
const std::string& session_id,
const std::vector<uint8_t>& response,
scoped_ptr<media::SimpleCdmPromise> promise) {
- DVLOG(1) << __FUNCTION__;
+ DVLOG(1) << __FUNCTION__ << " session_id:" << session_id;
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jbyteArray> j_response = base::android::ToJavaByteArray(
@@ -441,6 +512,7 @@ void MediaDrmBridge::UpdateSession(
void MediaDrmBridge::CloseSession(const std::string& session_id,
scoped_ptr<media::SimpleCdmPromise> promise) {
DVLOG(1) << __FUNCTION__;
+
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jbyteArray> j_session_id = base::android::ToJavaByteArray(
env, reinterpret_cast<const uint8_t*>(session_id.data()),
@@ -472,6 +544,8 @@ void MediaDrmBridge::UnregisterPlayer(int registration_id) {
}
void MediaDrmBridge::SetMediaCryptoReadyCB(const base::Closure& closure) {
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__;
+
if (closure.is_null()) {
media_crypto_ready_cb_.Reset();
return;
@@ -487,32 +561,62 @@ void MediaDrmBridge::SetMediaCryptoReadyCB(const base::Closure& closure) {
media_crypto_ready_cb_ = closure;
}
-void MediaDrmBridge::OnMediaCryptoReady(JNIEnv* env, jobject) {
+void MediaDrmBridge::OnMediaCryptoReady(JNIEnv* env, jobject j_media_drm) {
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__;
+
DCHECK(!GetMediaCrypto().is_null());
- if (!media_crypto_ready_cb_.is_null())
- base::ResetAndReturn(&media_crypto_ready_cb_).Run();
+
+ if (media_crypto_ready_cb_.is_null())
+ return;
+
+ RUN_CB_ON_MEDIA_THREAD(base::ResetAndReturn(&media_crypto_ready_cb_));
}
void MediaDrmBridge::OnPromiseResolved(JNIEnv* env,
jobject j_media_drm,
jint j_promise_id) {
- cdm_promise_adapter_.ResolvePromise(j_promise_id);
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__;
+ RUN_CB_ON_MEDIA_THREAD(internal_promise_resolved_cb_, j_promise_id);
+}
+
+void MediaDrmBridge::InternalPromiseResolved(uint32_t promise_id) {
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__
+ << ": promise_id:" << promise_id;
+ cdm_promise_adapter_.ResolvePromise(promise_id);
}
void MediaDrmBridge::OnPromiseResolvedWithSession(JNIEnv* env,
jobject j_media_drm,
jint j_promise_id,
jbyteArray j_session_id) {
- cdm_promise_adapter_.ResolvePromise(j_promise_id,
- GetSessionId(env, j_session_id));
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__;
+ RUN_CB_ON_MEDIA_THREAD(internal_promise_resolved_with_session_cb_,
+ j_promise_id, GetSessionId(env, j_session_id));
+}
+
+void MediaDrmBridge::InternalPromiseResolvedWithSession(
+ uint32_t promise_id,
+ const std::string& session_id) {
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__
+ << ": promise_id:" << promise_id << " session_id:" << session_id;
+ cdm_promise_adapter_.ResolvePromise(promise_id, session_id);
}
void MediaDrmBridge::OnPromiseRejected(JNIEnv* env,
jobject j_media_drm,
jint j_promise_id,
jstring j_error_message) {
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__;
std::string error_message = ConvertJavaStringToUTF8(env, j_error_message);
- cdm_promise_adapter_.RejectPromise(j_promise_id, MediaKeys::UNKNOWN_ERROR, 0,
+ RUN_CB_ON_MEDIA_THREAD(internal_promise_rejected_cb_, j_promise_id,
+ error_message);
+}
+
+void MediaDrmBridge::InternalPromiseRejected(uint32_t promise_id,
+ const std::string& error_message) {
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__
+ << ": promise_id:" << promise_id << " error:" << error_message;
+ cdm_promise_adapter_.RejectPromise(promise_id, MediaKeys::UNKNOWN_ERROR, 0,
error_message);
}
@@ -529,14 +633,26 @@ void MediaDrmBridge::OnSessionMessage(JNIEnv* env,
MediaKeys::MessageType message_type =
GetMessageType(static_cast<RequestType>(j_message_type));
- session_message_cb_.Run(GetSessionId(env, j_session_id), message_type,
- message, legacy_destination_url);
+ std::string session_id = GetSessionId(env, j_session_id);
+
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__
+ << " session_id:" << session_id;
+
+ // We need to preserve the order of messages. If the promise-related
+ // callbacks are posted to the Media thread, we have to do the same with
+ // all callbacks. See the comment in media_drm_proxy.h.
+ RUN_CB_ON_MEDIA_THREAD(session_message_cb_, session_id, message_type, message,
+ legacy_destination_url);
}
void MediaDrmBridge::OnSessionClosed(JNIEnv* env,
jobject j_media_drm,
jbyteArray j_session_id) {
- session_closed_cb_.Run(GetSessionId(env, j_session_id));
+ std::string session_id = GetSessionId(env, j_session_id);
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__
+ << " session_id:" << session_id;
+
+ RUN_CB_ON_MEDIA_THREAD(session_closed_cb_, session_id);
ddorwin 2015/09/16 20:42:21 Should it be up to the caller to ensure this? At w
}
void MediaDrmBridge::OnSessionKeysChange(JNIEnv* env,
@@ -544,8 +660,7 @@ void MediaDrmBridge::OnSessionKeysChange(JNIEnv* env,
jbyteArray j_session_id,
jobjectArray j_keys_info,
bool has_additional_usable_key) {
- if (has_additional_usable_key)
- player_tracker_.NotifyNewKey();
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__;
CdmKeysInfo cdm_keys_info;
@@ -579,8 +694,24 @@ void MediaDrmBridge::OnSessionKeysChange(JNIEnv* env,
cdm_keys_info.push_back(cdm_key_information.release());
}
- session_keys_change_cb_.Run(GetSessionId(env, j_session_id),
- has_additional_usable_key, cdm_keys_info.Pass());
+ RUN_CB_ON_MEDIA_THREAD(internal_keys_added_cb_, has_additional_usable_key);
+
+ std::string session_id = GetSessionId(env, j_session_id);
+
+ if (run_on_media_thread_ && !GetMediaTaskRunner()->BelongsToCurrentThread()) {
+ GetMediaTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(session_keys_change_cb_, session_id,
+ has_additional_usable_key, base::Passed(&cdm_keys_info)));
+ } else {
+ session_keys_change_cb_.Run(session_id, has_additional_usable_key,
+ cdm_keys_info.Pass());
+ }
+}
+
+void MediaDrmBridge::InternalKeysAdded(bool has_additional_usable_key) {
+ if (has_additional_usable_key)
+ player_tracker_.NotifyNewKey();
}
// According to MeidaDrm documentation [1], zero |expiry_time_ms| means the keys
@@ -597,19 +728,27 @@ void MediaDrmBridge::OnSessionExpirationUpdate(JNIEnv* env,
jobject j_media_drm,
jbyteArray j_session_id,
jlong expiry_time_ms) {
- DVLOG(2) << __FUNCTION__ << ": " << expiry_time_ms << " ms";
- session_expiration_update_cb_.Run(
- GetSessionId(env, j_session_id),
- base::Time::FromDoubleT(expiry_time_ms / 1000.0));
+ std::string session_id = GetSessionId(env, j_session_id);
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__
+ << ": session_id:" << session_id << " expiration:" << expiry_time_ms
+ << " ms";
+
+ RUN_CB_ON_MEDIA_THREAD(session_expiration_update_cb_, session_id,
+ base::Time::FromDoubleT(expiry_time_ms / 1000.0));
}
void MediaDrmBridge::OnLegacySessionError(JNIEnv* env,
jobject j_media_drm,
jbyteArray j_session_id,
jstring j_error_message) {
+ std::string session_id = GetSessionId(env, j_session_id);
std::string error_message = ConvertJavaStringToUTF8(env, j_error_message);
- legacy_session_error_cb_.Run(GetSessionId(env, j_session_id),
- MediaKeys::UNKNOWN_ERROR, 0, error_message);
+
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ << " session_id:" << session_id
+ << " error:" << error_message;
+
+ RUN_CB_ON_MEDIA_THREAD(legacy_session_error_cb_, session_id,
+ MediaKeys::UNKNOWN_ERROR, 0, error_message);
}
ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() {
@@ -645,7 +784,9 @@ void MediaDrmBridge::ResetDeviceCredentials(
void MediaDrmBridge::OnResetDeviceCredentialsCompleted(
JNIEnv* env, jobject, bool success) {
- base::ResetAndReturn(&reset_credentials_cb_).Run(success);
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ << ": success:" << success;
+
+ RUN_CB_ON_MEDIA_THREAD(base::ResetAndReturn(&reset_credentials_cb_), success);
}
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698