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..276ede00f4021b14c267c7217b1d6d97a3e184ef 100644 |
--- a/media/base/android/media_drm_bridge.cc |
+++ b/media/base/android/media_drm_bridge.cc |
@@ -9,7 +9,9 @@ |
#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/command_line.h" |
#include "base/containers/hash_tables.h" |
#include "base/lazy_instance.h" |
#include "base/location.h" |
@@ -23,16 +25,30 @@ |
#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 "media/base/media_switches.h" |
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
+#define RUN_CB_ON_MEDIA_THREAD(cb, ...) \ |
+ do { \ |
+ if (use_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; |
using base::android::JavaByteArrayToByteVector; |
using base::android::ScopedJavaLocalRef; |
+using base::android::ScopedJavaGlobalRef; |
xhwang
2015/09/29 17:28:23
nit: order
Tima Vaisburd
2015/09/29 19:55:44
Done.
|
namespace media { |
@@ -254,6 +270,7 @@ bool MediaDrmBridge::IsKeySystemSupportedWithType( |
return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type); |
} |
+// static |
bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) { |
return RegisterNativesImpl(env); |
} |
@@ -270,7 +287,20 @@ 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), |
+ ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
+ use_media_thread_(false), |
+ weak_factory_(this) { |
+ DVLOG(1) << "MediaDrmBridge::MediaDrmBridge"; |
+ |
+ use_media_thread_ = base::CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kEnableMediaThreadForMediaPlayback); |
+ |
+ base::WeakPtr<MediaDrmBridge> weak_this = weak_factory_.GetWeakPtr(); |
+ |
+ internal_keys_added_cb_ = |
+ base::Bind(&MediaDrmBridge::InternalKeysAdded, weak_this); |
+ |
JNIEnv* env = AttachCurrentThread(); |
CHECK(env); |
@@ -280,22 +310,37 @@ MediaDrmBridge::MediaDrmBridge( |
env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); |
} |
-MediaDrmBridge::~MediaDrmBridge() { |
+void MediaDrmBridge::DeleteOnCorrectThread() { |
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__; |
+ |
JNIEnv* env = AttachCurrentThread(); |
- player_tracker_.NotifyCdmUnset(); |
if (!j_media_drm_.is_null()) |
Java_MediaDrmBridge_destroy(env, j_media_drm_.obj()); |
+ |
+ // Post deletion onto Media thread if we use it. |
+ if (use_media_thread_) |
+ GetMediaTaskRunner()->DeleteSoon(FROM_HERE, this); |
+ else |
+ delete this; |
+} |
+ |
+MediaDrmBridge::~MediaDrmBridge() { |
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__; |
xhwang
2015/09/29 17:28:23
nit: in media code (and the rest of this file) we
Tima Vaisburd
2015/09/29 19:55:43
Class name removed.
|
+ |
+ DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread()); |
+ |
+ player_tracker_.NotifyCdmUnset(); |
} |
// static |
-scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create( |
+scoped_ptr<MediaDrmBridge, BrowserCdmDeleter> MediaDrmBridge::Create( |
const std::string& key_system, |
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(); |
@@ -315,8 +360,8 @@ scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create( |
} |
// static |
-scoped_ptr<MediaDrmBridge> MediaDrmBridge::CreateWithoutSessionSupport( |
- const std::string& key_system) { |
+scoped_ptr<MediaDrmBridge, BrowserCdmDeleter> |
+MediaDrmBridge::CreateWithoutSessionSupport(const std::string& key_system) { |
return MediaDrmBridge::Create( |
key_system, SessionMessageCB(), SessionClosedCB(), LegacySessionErrorCB(), |
SessionKeysChangeCB(), SessionExpirationUpdateCB()); |
@@ -464,33 +509,79 @@ CdmContext* MediaDrmBridge::GetCdmContext() { |
int MediaDrmBridge::RegisterPlayer(const base::Closure& new_key_cb, |
const base::Closure& cdm_unset_cb) { |
+ DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread()); |
return player_tracker_.RegisterPlayer(new_key_cb, cdm_unset_cb); |
} |
void MediaDrmBridge::UnregisterPlayer(int registration_id) { |
+ DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread()); |
player_tracker_.UnregisterPlayer(registration_id); |
} |
-void MediaDrmBridge::SetMediaCryptoReadyCB(const base::Closure& closure) { |
- if (closure.is_null()) { |
- media_crypto_ready_cb_.Reset(); |
- return; |
+void MediaDrmBridge::SetMediaCryptoReadyCB(const MediaCryptoReadyCB& closure) { |
+ DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread()); |
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__; |
+ |
+ { |
+ base::AutoLock lock(media_crypto_ready_lock_); |
+ |
+ if (closure.is_null()) { |
+ media_crypto_ready_cb_.Reset(); |
+ return; |
+ } |
+ |
+ DCHECK(media_crypto_ready_cb_.is_null()); |
+ |
+ media_crypto_ready_cb_ = closure; |
} |
- DCHECK(media_crypto_ready_cb_.is_null()); |
+ ui_task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&MediaDrmBridge::CheckMediaCryptoAndInvokeCB, |
+ base::Unretained(this))); |
+} |
+ |
+void MediaDrmBridge::CheckMediaCryptoAndInvokeCB() { |
+ DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__; |
- if (!GetMediaCrypto().is_null()) { |
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure); |
+ ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto(); |
+ if (media_crypto.is_null()) { |
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ << ": no MediaCrypto"; |
return; |
} |
- media_crypto_ready_cb_ = closure; |
+ MediaCryptoReadyCB media_crypto_ready_cb; |
+ { |
+ base::AutoLock lock(media_crypto_ready_lock_); |
+ |
+ if (media_crypto_ready_cb_.is_null()) { |
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ << ": no callback"; |
+ return; |
+ } |
+ |
+ media_crypto_ready_cb = base::ResetAndReturn(&media_crypto_ready_cb_); |
+ } |
+ |
+ scoped_ptr<ScopedJavaGlobalRef<jobject>> j_object_ptr( |
+ new ScopedJavaGlobalRef<jobject>()); |
+ j_object_ptr->Reset(AttachCurrentThread(), media_crypto.obj()); |
+ |
+ if (use_media_thread_) { |
+ GetMediaTaskRunner()->PostTask( |
+ FROM_HERE, |
+ base::Bind(media_crypto_ready_cb, base::Passed(&j_object_ptr))); |
+ } else { |
+ media_crypto_ready_cb.Run(j_object_ptr.Pass()); |
+ } |
} |
-void MediaDrmBridge::OnMediaCryptoReady(JNIEnv* env, jobject) { |
+void MediaDrmBridge::OnMediaCryptoReady(JNIEnv* env, jobject j_media_drm) { |
+ DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
+ DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__; |
+ |
DCHECK(!GetMediaCrypto().is_null()); |
- if (!media_crypto_ready_cb_.is_null()) |
- base::ResetAndReturn(&media_crypto_ready_cb_).Run(); |
+ |
+ CheckMediaCryptoAndInvokeCB(); |
} |
void MediaDrmBridge::OnPromiseResolved(JNIEnv* env, |
@@ -544,8 +635,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 +669,18 @@ 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); |
+ |
+ session_keys_change_cb_.Run(session_id, has_additional_usable_key, |
+ cdm_keys_info.Pass()); |
+} |
+ |
+void MediaDrmBridge::InternalKeysAdded(bool has_additional_usable_key) { |
+ DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread()); |
+ if (has_additional_usable_key) |
+ player_tracker_.NotifyNewKey(); |
} |
// According to MeidaDrm documentation [1], zero |expiry_time_ms| means the keys |
@@ -613,6 +713,8 @@ void MediaDrmBridge::OnLegacySessionError(JNIEnv* env, |
} |
ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() { |
+ DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
+ |
JNIEnv* env = AttachCurrentThread(); |
return Java_MediaDrmBridge_getMediaCrypto(env, j_media_drm_.obj()); |
} |