OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/base/android/media_drm_bridge.h" | 5 #include "media/base/android/media_drm_bridge.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
10 #include "base/android/jni_array.h" | 10 #include "base/android/jni_array.h" |
11 #include "base/android/jni_string.h" | 11 #include "base/android/jni_string.h" |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
14 #include "base/containers/hash_tables.h" | 14 #include "base/containers/hash_tables.h" |
15 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
16 #include "base/location.h" | 16 #include "base/location.h" |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/single_thread_task_runner.h" | 18 #include "base/single_thread_task_runner.h" |
19 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
20 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
21 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
22 #include "base/sys_byteorder.h" | 22 #include "base/sys_byteorder.h" |
23 #include "base/sys_info.h" | 23 #include "base/sys_info.h" |
24 #include "base/thread_task_runner_handle.h" | 24 #include "base/thread_task_runner_handle.h" |
25 #include "jni/MediaDrmBridge_jni.h" | 25 #include "jni/MediaDrmBridge_jni.h" |
26 #include "media/base/android/media_client_android.h" | 26 #include "media/base/android/media_client_android.h" |
27 #include "media/base/android/media_drm_bridge_delegate.h" | 27 #include "media/base/android/media_drm_bridge_delegate.h" |
28 #include "media/base/android/media_task_runner.h" | |
29 #include "media/base/cdm_key_information.h" | 28 #include "media/base/cdm_key_information.h" |
30 | 29 |
31 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. | 30 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
32 | 31 |
33 using base::android::AttachCurrentThread; | 32 using base::android::AttachCurrentThread; |
34 using base::android::ConvertUTF8ToJavaString; | 33 using base::android::ConvertUTF8ToJavaString; |
35 using base::android::ConvertJavaStringToUTF8; | 34 using base::android::ConvertJavaStringToUTF8; |
36 using base::android::JavaByteArrayToByteVector; | 35 using base::android::JavaByteArrayToByteVector; |
37 using base::android::ScopedJavaGlobalRef; | 36 using base::android::ScopedJavaGlobalRef; |
38 using base::android::ScopedJavaLocalRef; | 37 using base::android::ScopedJavaLocalRef; |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 case MediaDrmBridge::SECURITY_LEVEL_1: | 206 case MediaDrmBridge::SECURITY_LEVEL_1: |
208 return "L1"; | 207 return "L1"; |
209 case MediaDrmBridge::SECURITY_LEVEL_3: | 208 case MediaDrmBridge::SECURITY_LEVEL_3: |
210 return "L3"; | 209 return "L3"; |
211 } | 210 } |
212 return ""; | 211 return ""; |
213 } | 212 } |
214 | 213 |
215 } // namespace | 214 } // namespace |
216 | 215 |
217 MediaDrmBridge::~MediaDrmBridge() { | |
218 DVLOG(1) << __FUNCTION__; | |
219 | |
220 DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread()); | |
221 | |
222 player_tracker_.NotifyCdmUnset(); | |
223 } | |
224 | |
225 void MediaDrmBridge::DeleteOnCorrectThread() { | |
226 DCHECK(task_runner_->BelongsToCurrentThread()); | |
227 DVLOG(1) << __FUNCTION__; | |
228 | |
229 JNIEnv* env = AttachCurrentThread(); | |
230 if (!j_media_drm_.is_null()) | |
231 Java_MediaDrmBridge_destroy(env, j_media_drm_.obj()); | |
232 | |
233 // After the call to Java_MediaDrmBridge_destroy() Java won't call native | |
234 // methods anymore, this is ensured by MediaDrmBridge.java. | |
235 | |
236 // CdmPromiseAdapter must be destroyed on the UI thread. | |
237 cdm_promise_adapter_.reset(); | |
238 | |
239 // Post deletion onto Media thread if we use it. | |
240 if (use_media_thread_) { | |
241 weak_factory_.InvalidateWeakPtrs(); | |
242 GetMediaTaskRunner()->DeleteSoon(FROM_HERE, this); | |
243 } else { | |
244 delete this; | |
245 } | |
246 } | |
247 | |
248 // static | 216 // static |
249 bool MediaDrmBridge::IsAvailable() { | 217 bool MediaDrmBridge::IsAvailable() { |
250 if (base::android::BuildInfo::GetInstance()->sdk_int() < 19) | 218 if (base::android::BuildInfo::GetInstance()->sdk_int() < 19) |
251 return false; | 219 return false; |
252 | 220 |
253 int32 os_major_version = 0; | 221 int32 os_major_version = 0; |
254 int32 os_minor_version = 0; | 222 int32 os_minor_version = 0; |
255 int32 os_bugfix_version = 0; | 223 int32 os_bugfix_version = 0; |
256 base::SysInfo::OperatingSystemVersionNumbers( | 224 base::SysInfo::OperatingSystemVersionNumbers( |
257 &os_major_version, &os_minor_version, &os_bugfix_version); | 225 &os_major_version, &os_minor_version, &os_bugfix_version); |
(...skipping 21 matching lines...) Expand all Loading... |
279 DCHECK(!key_system.empty() && !container_mime_type.empty()); | 247 DCHECK(!key_system.empty() && !container_mime_type.empty()); |
280 return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type); | 248 return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type); |
281 } | 249 } |
282 | 250 |
283 // static | 251 // static |
284 std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() { | 252 std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() { |
285 return g_key_system_manager.Get().GetPlatformKeySystemNames(); | 253 return g_key_system_manager.Get().GetPlatformKeySystemNames(); |
286 } | 254 } |
287 | 255 |
288 // static | 256 // static |
289 ScopedMediaDrmBridgePtr MediaDrmBridge::Create( | 257 scoped_refptr<MediaDrmBridge> MediaDrmBridge::Create( |
290 const std::string& key_system, | 258 const std::string& key_system, |
291 const SessionMessageCB& session_message_cb, | 259 const SessionMessageCB& session_message_cb, |
292 const SessionClosedCB& session_closed_cb, | 260 const SessionClosedCB& session_closed_cb, |
293 const LegacySessionErrorCB& legacy_session_error_cb, | 261 const LegacySessionErrorCB& legacy_session_error_cb, |
294 const SessionKeysChangeCB& session_keys_change_cb, | 262 const SessionKeysChangeCB& session_keys_change_cb, |
295 const SessionExpirationUpdateCB& session_expiration_update_cb) { | 263 const SessionExpirationUpdateCB& session_expiration_update_cb) { |
296 DVLOG(1) << __FUNCTION__; | 264 DVLOG(1) << __FUNCTION__; |
297 | 265 |
298 scoped_ptr<MediaDrmBridge, BrowserCdmDeleter> media_drm_bridge; | |
299 if (!IsAvailable()) | 266 if (!IsAvailable()) |
300 return media_drm_bridge.Pass(); | 267 return nullptr; |
301 | 268 |
302 UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system); | 269 UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system); |
303 if (scheme_uuid.empty()) | 270 if (scheme_uuid.empty()) |
304 return media_drm_bridge.Pass(); | 271 return nullptr; |
305 | 272 |
306 media_drm_bridge.reset( | 273 scoped_refptr<MediaDrmBridge> media_drm_bridge( |
307 new MediaDrmBridge(scheme_uuid, session_message_cb, session_closed_cb, | 274 new MediaDrmBridge(scheme_uuid, session_message_cb, session_closed_cb, |
308 legacy_session_error_cb, session_keys_change_cb, | 275 legacy_session_error_cb, session_keys_change_cb, |
309 session_expiration_update_cb)); | 276 session_expiration_update_cb)); |
310 | 277 |
311 if (media_drm_bridge->j_media_drm_.is_null()) | 278 if (media_drm_bridge->j_media_drm_.is_null()) |
312 media_drm_bridge.reset(); | 279 media_drm_bridge = nullptr; |
313 | 280 |
314 return media_drm_bridge.Pass(); | 281 return media_drm_bridge; |
315 } | 282 } |
316 | 283 |
317 // static | 284 // static |
318 ScopedMediaDrmBridgePtr MediaDrmBridge::CreateWithoutSessionSupport( | 285 scoped_refptr<MediaDrmBridge> MediaDrmBridge::CreateWithoutSessionSupport( |
319 const std::string& key_system) { | 286 const std::string& key_system) { |
320 return MediaDrmBridge::Create( | 287 return MediaDrmBridge::Create( |
321 key_system, SessionMessageCB(), SessionClosedCB(), LegacySessionErrorCB(), | 288 key_system, SessionMessageCB(), SessionClosedCB(), LegacySessionErrorCB(), |
322 SessionKeysChangeCB(), SessionExpirationUpdateCB()); | 289 SessionKeysChangeCB(), SessionExpirationUpdateCB()); |
323 } | 290 } |
324 | 291 |
325 base::WeakPtr<MediaDrmBridge> MediaDrmBridge::WeakPtr() { | |
326 return weak_factory_.GetWeakPtr(); | |
327 } | |
328 | |
329 void MediaDrmBridge::SetServerCertificate( | 292 void MediaDrmBridge::SetServerCertificate( |
330 const std::vector<uint8_t>& certificate, | 293 const std::vector<uint8_t>& certificate, |
331 scoped_ptr<media::SimpleCdmPromise> promise) { | 294 scoped_ptr<media::SimpleCdmPromise> promise) { |
332 DVLOG(2) << __FUNCTION__; | 295 DVLOG(2) << __FUNCTION__; |
333 | 296 |
334 DCHECK(!certificate.empty()); | 297 DCHECK(!certificate.empty()); |
335 | 298 |
336 JNIEnv* env = AttachCurrentThread(); | 299 JNIEnv* env = AttachCurrentThread(); |
337 ScopedJavaLocalRef<jbyteArray> j_certificate; | 300 ScopedJavaLocalRef<jbyteArray> j_certificate; |
338 if (Java_MediaDrmBridge_setServerCertificate(env, j_media_drm_.obj(), | 301 if (Java_MediaDrmBridge_setServerCertificate(env, j_media_drm_.obj(), |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 | 408 |
446 NOTIMPLEMENTED() << "EME persistent sessions not yet supported on Android."; | 409 NOTIMPLEMENTED() << "EME persistent sessions not yet supported on Android."; |
447 promise->reject(NOT_SUPPORTED_ERROR, 0, "RemoveSession() is not supported."); | 410 promise->reject(NOT_SUPPORTED_ERROR, 0, "RemoveSession() is not supported."); |
448 } | 411 } |
449 | 412 |
450 CdmContext* MediaDrmBridge::GetCdmContext() { | 413 CdmContext* MediaDrmBridge::GetCdmContext() { |
451 NOTREACHED(); | 414 NOTREACHED(); |
452 return nullptr; | 415 return nullptr; |
453 } | 416 } |
454 | 417 |
| 418 void MediaDrmBridge::DeleteOnCorrectThread() const { |
| 419 DVLOG(1) << __FUNCTION__; |
| 420 |
| 421 if (!task_runner_->BelongsToCurrentThread()) { |
| 422 // When DeleteSoon returns false, |this| will be leaked, which is okay. |
| 423 task_runner_->DeleteSoon(FROM_HERE, this); |
| 424 } else { |
| 425 delete this; |
| 426 } |
| 427 } |
| 428 |
455 int MediaDrmBridge::RegisterPlayer(const base::Closure& new_key_cb, | 429 int MediaDrmBridge::RegisterPlayer(const base::Closure& new_key_cb, |
456 const base::Closure& cdm_unset_cb) { | 430 const base::Closure& cdm_unset_cb) { |
457 DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread()); | 431 // |player_tracker_| can be accessed from any thread. |
458 return player_tracker_.RegisterPlayer(new_key_cb, cdm_unset_cb); | 432 return player_tracker_.RegisterPlayer(new_key_cb, cdm_unset_cb); |
459 } | 433 } |
460 | 434 |
461 void MediaDrmBridge::UnregisterPlayer(int registration_id) { | 435 void MediaDrmBridge::UnregisterPlayer(int registration_id) { |
462 DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread()); | 436 // |player_tracker_| can be accessed from any thread. |
463 player_tracker_.UnregisterPlayer(registration_id); | 437 player_tracker_.UnregisterPlayer(registration_id); |
464 } | 438 } |
465 | 439 |
466 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { | 440 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { |
467 if (security_level != SECURITY_LEVEL_NONE && | 441 if (security_level != SECURITY_LEVEL_NONE && |
468 !std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid)) { | 442 !std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid)) { |
469 NOTREACHED() << "Widevine security level " << security_level | 443 NOTREACHED() << "Widevine security level " << security_level |
470 << "used with another key system"; | 444 << "used with another key system"; |
471 return false; | 445 return false; |
472 } | 446 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 | 494 |
521 ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() { | 495 ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() { |
522 DCHECK(task_runner_->BelongsToCurrentThread()); | 496 DCHECK(task_runner_->BelongsToCurrentThread()); |
523 | 497 |
524 JNIEnv* env = AttachCurrentThread(); | 498 JNIEnv* env = AttachCurrentThread(); |
525 return Java_MediaDrmBridge_getMediaCrypto(env, j_media_drm_.obj()); | 499 return Java_MediaDrmBridge_getMediaCrypto(env, j_media_drm_.obj()); |
526 } | 500 } |
527 | 501 |
528 void MediaDrmBridge::SetMediaCryptoReadyCB( | 502 void MediaDrmBridge::SetMediaCryptoReadyCB( |
529 const MediaCryptoReadyCB& media_crypto_ready_cb) { | 503 const MediaCryptoReadyCB& media_crypto_ready_cb) { |
530 DCHECK(task_runner_->BelongsToCurrentThread()); | 504 if (!task_runner_->BelongsToCurrentThread()) { |
| 505 task_runner_->PostTask( |
| 506 FROM_HERE, |
| 507 base::Bind(&MediaDrmBridge::SetMediaCryptoReadyCB, |
| 508 weak_factory_.GetWeakPtr(), media_crypto_ready_cb)); |
| 509 return; |
| 510 } |
| 511 |
531 DVLOG(1) << __FUNCTION__; | 512 DVLOG(1) << __FUNCTION__; |
532 | 513 |
533 if (media_crypto_ready_cb.is_null()) { | 514 if (media_crypto_ready_cb.is_null()) { |
534 media_crypto_ready_cb_.Reset(); | 515 media_crypto_ready_cb_.Reset(); |
535 return; | 516 return; |
536 } | 517 } |
537 | 518 |
538 DCHECK(media_crypto_ready_cb_.is_null()); | 519 DCHECK(media_crypto_ready_cb_.is_null()); |
539 | 520 |
540 // |media_crypto_ready_cb| is already bound to the correct thread | 521 // |media_crypto_ready_cb| is already bound to the correct thread |
(...skipping 10 matching lines...) Expand all Loading... |
551 // only do minimal work and then post tasks to avoid reentrancy issues. | 532 // only do minimal work and then post tasks to avoid reentrancy issues. |
552 | 533 |
553 void MediaDrmBridge::OnMediaCryptoReady(JNIEnv* env, jobject j_media_drm) { | 534 void MediaDrmBridge::OnMediaCryptoReady(JNIEnv* env, jobject j_media_drm) { |
554 DCHECK(task_runner_->BelongsToCurrentThread()); | 535 DCHECK(task_runner_->BelongsToCurrentThread()); |
555 DVLOG(1) << __FUNCTION__; | 536 DVLOG(1) << __FUNCTION__; |
556 | 537 |
557 if (media_crypto_ready_cb_.is_null()) | 538 if (media_crypto_ready_cb_.is_null()) |
558 return; | 539 return; |
559 | 540 |
560 task_runner_->PostTask( | 541 task_runner_->PostTask( |
561 FROM_HERE, base::Bind(&MediaDrmBridge::NotifyMediaCryptoReady, WeakPtr(), | 542 FROM_HERE, base::Bind(&MediaDrmBridge::NotifyMediaCryptoReady, |
| 543 weak_factory_.GetWeakPtr(), |
562 base::ResetAndReturn(&media_crypto_ready_cb_))); | 544 base::ResetAndReturn(&media_crypto_ready_cb_))); |
563 } | 545 } |
564 | 546 |
565 void MediaDrmBridge::OnPromiseResolved(JNIEnv* env, | 547 void MediaDrmBridge::OnPromiseResolved(JNIEnv* env, |
566 jobject j_media_drm, | 548 jobject j_media_drm, |
567 jint j_promise_id) { | 549 jint j_promise_id) { |
568 task_runner_->PostTask(FROM_HERE, base::Bind(&MediaDrmBridge::ResolvePromise, | 550 task_runner_->PostTask(FROM_HERE, |
569 WeakPtr(), j_promise_id)); | 551 base::Bind(&MediaDrmBridge::ResolvePromise, |
| 552 weak_factory_.GetWeakPtr(), j_promise_id)); |
570 } | 553 } |
571 | 554 |
572 void MediaDrmBridge::OnPromiseResolvedWithSession(JNIEnv* env, | 555 void MediaDrmBridge::OnPromiseResolvedWithSession(JNIEnv* env, |
573 jobject j_media_drm, | 556 jobject j_media_drm, |
574 jint j_promise_id, | 557 jint j_promise_id, |
575 jbyteArray j_session_id) { | 558 jbyteArray j_session_id) { |
576 task_runner_->PostTask( | 559 task_runner_->PostTask(FROM_HERE, |
577 FROM_HERE, | 560 base::Bind(&MediaDrmBridge::ResolvePromiseWithSession, |
578 base::Bind(&MediaDrmBridge::ResolvePromiseWithSession, WeakPtr(), | 561 weak_factory_.GetWeakPtr(), j_promise_id, |
579 j_promise_id, GetSessionId(env, j_session_id))); | 562 GetSessionId(env, j_session_id))); |
580 } | 563 } |
581 | 564 |
582 void MediaDrmBridge::OnPromiseRejected(JNIEnv* env, | 565 void MediaDrmBridge::OnPromiseRejected(JNIEnv* env, |
583 jobject j_media_drm, | 566 jobject j_media_drm, |
584 jint j_promise_id, | 567 jint j_promise_id, |
585 jstring j_error_message) { | 568 jstring j_error_message) { |
586 task_runner_->PostTask( | 569 task_runner_->PostTask( |
587 FROM_HERE, | 570 FROM_HERE, |
588 base::Bind(&MediaDrmBridge::RejectPromise, WeakPtr(), j_promise_id, | 571 base::Bind(&MediaDrmBridge::RejectPromise, weak_factory_.GetWeakPtr(), |
589 ConvertJavaStringToUTF8(env, j_error_message))); | 572 j_promise_id, ConvertJavaStringToUTF8(env, j_error_message))); |
590 } | 573 } |
591 | 574 |
592 void MediaDrmBridge::OnSessionMessage(JNIEnv* env, | 575 void MediaDrmBridge::OnSessionMessage(JNIEnv* env, |
593 jobject j_media_drm, | 576 jobject j_media_drm, |
594 jbyteArray j_session_id, | 577 jbyteArray j_session_id, |
595 jint j_message_type, | 578 jint j_message_type, |
596 jbyteArray j_message, | 579 jbyteArray j_message, |
597 jstring j_legacy_destination_url) { | 580 jstring j_legacy_destination_url) { |
598 DVLOG(2) << __FUNCTION__; | 581 DVLOG(2) << __FUNCTION__; |
599 | 582 |
(...skipping 19 matching lines...) Expand all Loading... |
619 } | 602 } |
620 | 603 |
621 void MediaDrmBridge::OnSessionKeysChange(JNIEnv* env, | 604 void MediaDrmBridge::OnSessionKeysChange(JNIEnv* env, |
622 jobject j_media_drm, | 605 jobject j_media_drm, |
623 jbyteArray j_session_id, | 606 jbyteArray j_session_id, |
624 jobjectArray j_keys_info, | 607 jobjectArray j_keys_info, |
625 bool has_additional_usable_key) { | 608 bool has_additional_usable_key) { |
626 DVLOG(2) << __FUNCTION__; | 609 DVLOG(2) << __FUNCTION__; |
627 | 610 |
628 if (has_additional_usable_key) | 611 if (has_additional_usable_key) |
629 NotifyNewKeyOnCorrectThread(); | 612 player_tracker_.NotifyNewKey(); |
630 | 613 |
631 CdmKeysInfo cdm_keys_info; | 614 CdmKeysInfo cdm_keys_info; |
632 | 615 |
633 size_t size = env->GetArrayLength(j_keys_info); | 616 size_t size = env->GetArrayLength(j_keys_info); |
634 DCHECK_GT(size, 0u); | 617 DCHECK_GT(size, 0u); |
635 | 618 |
636 for (size_t i = 0; i < size; ++i) { | 619 for (size_t i = 0; i < size; ++i) { |
637 ScopedJavaLocalRef<jobject> j_key_status( | 620 ScopedJavaLocalRef<jobject> j_key_status( |
638 env, env->GetObjectArrayElement(j_keys_info, i)); | 621 env, env->GetObjectArrayElement(j_keys_info, i)); |
639 | 622 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 const SessionKeysChangeCB& session_keys_change_cb, | 698 const SessionKeysChangeCB& session_keys_change_cb, |
716 const SessionExpirationUpdateCB& session_expiration_update_cb) | 699 const SessionExpirationUpdateCB& session_expiration_update_cb) |
717 : scheme_uuid_(scheme_uuid), | 700 : scheme_uuid_(scheme_uuid), |
718 session_message_cb_(session_message_cb), | 701 session_message_cb_(session_message_cb), |
719 session_closed_cb_(session_closed_cb), | 702 session_closed_cb_(session_closed_cb), |
720 legacy_session_error_cb_(legacy_session_error_cb), | 703 legacy_session_error_cb_(legacy_session_error_cb), |
721 session_keys_change_cb_(session_keys_change_cb), | 704 session_keys_change_cb_(session_keys_change_cb), |
722 session_expiration_update_cb_(session_expiration_update_cb), | 705 session_expiration_update_cb_(session_expiration_update_cb), |
723 cdm_promise_adapter_(new CdmPromiseAdapter()), | 706 cdm_promise_adapter_(new CdmPromiseAdapter()), |
724 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 707 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
725 use_media_thread_(UseMediaThreadForMediaPlayback()), | |
726 media_weak_factory_(this), | |
727 weak_factory_(this) { | 708 weak_factory_(this) { |
728 DVLOG(1) << __FUNCTION__; | 709 DVLOG(1) << __FUNCTION__; |
729 | 710 |
730 JNIEnv* env = AttachCurrentThread(); | 711 JNIEnv* env = AttachCurrentThread(); |
731 CHECK(env); | 712 CHECK(env); |
732 | 713 |
733 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = | 714 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = |
734 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); | 715 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); |
735 j_media_drm_.Reset(Java_MediaDrmBridge_create( | 716 j_media_drm_.Reset(Java_MediaDrmBridge_create( |
736 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); | 717 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); |
737 } | 718 } |
738 | 719 |
| 720 MediaDrmBridge::~MediaDrmBridge() { |
| 721 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 722 DVLOG(1) << __FUNCTION__; |
| 723 |
| 724 JNIEnv* env = AttachCurrentThread(); |
| 725 |
| 726 // After the call to Java_MediaDrmBridge_destroy() Java won't call native |
| 727 // methods anymore, this is ensured by MediaDrmBridge.java. |
| 728 if (!j_media_drm_.is_null()) |
| 729 Java_MediaDrmBridge_destroy(env, j_media_drm_.obj()); |
| 730 |
| 731 player_tracker_.NotifyCdmUnset(); |
| 732 } |
| 733 |
739 // TODO(ddorwin): This is specific to Widevine. http://crbug.com/459400 | 734 // TODO(ddorwin): This is specific to Widevine. http://crbug.com/459400 |
740 // static | 735 // static |
741 bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) { | 736 bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) { |
742 DCHECK(IsAvailable()); | 737 DCHECK(IsAvailable()); |
743 return SECURITY_LEVEL_1 == security_level; | 738 return SECURITY_LEVEL_1 == security_level; |
744 } | 739 } |
745 | 740 |
746 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() { | 741 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() { |
747 JNIEnv* env = AttachCurrentThread(); | 742 JNIEnv* env = AttachCurrentThread(); |
748 ScopedJavaLocalRef<jstring> j_security_level = | 743 ScopedJavaLocalRef<jstring> j_security_level = |
749 Java_MediaDrmBridge_getSecurityLevel(env, j_media_drm_.obj()); | 744 Java_MediaDrmBridge_getSecurityLevel(env, j_media_drm_.obj()); |
750 std::string security_level_str = | 745 std::string security_level_str = |
751 ConvertJavaStringToUTF8(env, j_security_level.obj()); | 746 ConvertJavaStringToUTF8(env, j_security_level.obj()); |
752 return GetSecurityLevelFromString(security_level_str); | 747 return GetSecurityLevelFromString(security_level_str); |
753 } | 748 } |
754 | 749 |
755 void MediaDrmBridge::NotifyNewKeyOnCorrectThread() { | |
756 // Repost this method onto the Media thread if |use_media_thread_| is true. | |
757 if (use_media_thread_ && !GetMediaTaskRunner()->BelongsToCurrentThread()) { | |
758 GetMediaTaskRunner()->PostTask( | |
759 FROM_HERE, base::Bind(&MediaDrmBridge::NotifyNewKeyOnCorrectThread, | |
760 media_weak_factory_.GetWeakPtr())); | |
761 return; | |
762 } | |
763 | |
764 DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread()); | |
765 DVLOG(1) << __FUNCTION__; | |
766 | |
767 player_tracker_.NotifyNewKey(); | |
768 } | |
769 | |
770 void MediaDrmBridge::NotifyMediaCryptoReady(const MediaCryptoReadyCB& cb) { | 750 void MediaDrmBridge::NotifyMediaCryptoReady(const MediaCryptoReadyCB& cb) { |
771 DCHECK(task_runner_->BelongsToCurrentThread()); | 751 DCHECK(task_runner_->BelongsToCurrentThread()); |
772 | 752 |
773 DCHECK(!cb.is_null()); | 753 DCHECK(!cb.is_null()); |
774 DCHECK(!GetMediaCrypto().is_null()); | 754 DCHECK(!GetMediaCrypto().is_null()); |
775 | 755 |
776 // We can use scoped_ptr to pass ScopedJavaGlobalRef with a callback. | 756 // We can use scoped_ptr to pass ScopedJavaGlobalRef with a callback. |
777 scoped_ptr<ScopedJavaGlobalRef<jobject>> j_object_ptr( | 757 scoped_ptr<ScopedJavaGlobalRef<jobject>> j_object_ptr( |
778 new ScopedJavaGlobalRef<jobject>()); | 758 new ScopedJavaGlobalRef<jobject>()); |
779 j_object_ptr->Reset(AttachCurrentThread(), GetMediaCrypto().obj()); | 759 j_object_ptr->Reset(AttachCurrentThread(), GetMediaCrypto().obj()); |
780 | 760 |
781 cb.Run(j_object_ptr.Pass(), IsProtectedSurfaceRequired()); | 761 cb.Run(j_object_ptr.Pass(), IsProtectedSurfaceRequired()); |
782 } | 762 } |
783 | 763 |
784 } // namespace media | 764 } // namespace media |
OLD | NEW |