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 <stddef.h> | 7 #include <stddef.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/android/build_info.h" | 11 #include "base/android/build_info.h" |
12 #include "base/android/jni_array.h" | 12 #include "base/android/jni_array.h" |
13 #include "base/android/jni_string.h" | 13 #include "base/android/jni_string.h" |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/callback_helpers.h" | 15 #include "base/callback_helpers.h" |
16 #include "base/containers/hash_tables.h" | 16 #include "base/containers/hash_tables.h" |
17 #include "base/feature_list.h" | 17 #include "base/feature_list.h" |
18 #include "base/location.h" | 18 #include "base/location.h" |
19 #include "base/logging.h" | 19 #include "base/logging.h" |
20 #include "base/macros.h" | 20 #include "base/macros.h" |
21 #include "base/single_thread_task_runner.h" | 21 #include "base/single_thread_task_runner.h" |
22 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
23 #include "base/strings/string_util.h" | 23 #include "base/strings/string_util.h" |
24 #include "base/sys_byteorder.h" | 24 #include "base/sys_byteorder.h" |
25 #include "base/sys_info.h" | 25 #include "base/sys_info.h" |
26 #include "base/threading/thread_task_runner_handle.h" | 26 #include "base/threading/thread_task_runner_handle.h" |
27 #include "jni/MediaDrmBridge_jni.h" | 27 #include "jni/MediaDrmBridge_jni.h" |
| 28 #include "media/base/android/android_util.h" |
28 #include "media/base/android/media_codec_util.h" | 29 #include "media/base/android/media_codec_util.h" |
29 #include "media/base/android/media_drm_bridge_client.h" | 30 #include "media/base/android/media_drm_bridge_client.h" |
30 #include "media/base/android/media_drm_bridge_delegate.h" | 31 #include "media/base/android/media_drm_bridge_delegate.h" |
31 #include "media/base/cdm_key_information.h" | 32 #include "media/base/cdm_key_information.h" |
32 #include "media/base/media_switches.h" | 33 #include "media/base/media_switches.h" |
33 #include "media/base/provision_fetcher.h" | 34 #include "media/base/provision_fetcher.h" |
34 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. | 35 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
35 | 36 |
36 using base::android::AttachCurrentThread; | 37 using base::android::AttachCurrentThread; |
37 using base::android::ConvertUTF8ToJavaString; | 38 using base::android::ConvertUTF8ToJavaString; |
(...skipping 26 matching lines...) Expand all Loading... |
64 }; | 65 }; |
65 | 66 |
66 // These must be in sync with Android MediaDrm KEY_TYPE_XXX constants: | 67 // These must be in sync with Android MediaDrm KEY_TYPE_XXX constants: |
67 // https://developer.android.com/reference/android/media/MediaDrm.html#KEY_TYPE_
OFFLINE | 68 // https://developer.android.com/reference/android/media/MediaDrm.html#KEY_TYPE_
OFFLINE |
68 // KEY_TYPE_RELEASE is handled internally in Java. | 69 // KEY_TYPE_RELEASE is handled internally in Java. |
69 enum class KeyType : uint32_t { | 70 enum class KeyType : uint32_t { |
70 KEY_TYPE_STREAMING = 1, | 71 KEY_TYPE_STREAMING = 1, |
71 KEY_TYPE_OFFLINE = 2, | 72 KEY_TYPE_OFFLINE = 2, |
72 }; | 73 }; |
73 | 74 |
74 // Converts jbyteArray (byte[] in Java) into std::string. | |
75 std::string AsString(JNIEnv* env, jbyteArray j_byte_array) { | |
76 std::vector<uint8_t> byte_vector; | |
77 JavaByteArrayToByteVector(env, j_byte_array, &byte_vector); | |
78 return std::string(byte_vector.begin(), byte_vector.end()); | |
79 } | |
80 | |
81 const uint8_t kWidevineUuid[16] = { | 75 const uint8_t kWidevineUuid[16] = { |
82 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, // | 76 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, // |
83 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED}; | 77 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED}; |
84 | 78 |
85 // Convert |init_data_type| to a string supported by MediaDRM. | 79 // Convert |init_data_type| to a string supported by MediaDRM. |
86 // "audio"/"video" does not matter, so use "video". | 80 // "audio"/"video" does not matter, so use "video". |
87 std::string ConvertInitDataType(media::EmeInitDataType init_data_type) { | 81 std::string ConvertInitDataType(media::EmeInitDataType init_data_type) { |
88 // TODO(jrummell/xhwang): EME init data types like "webm" and "cenc" are | 82 // TODO(jrummell/xhwang): EME init data types like "webm" and "cenc" are |
89 // supported in API level >=21 for Widevine key system. Switch to use those | 83 // supported in API level >=21 for Widevine key system. Switch to use those |
90 // strings when they are officially supported in Android for all key systems. | 84 // strings when they are officially supported in Android for all key systems. |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 JNIEnv* env, | 623 JNIEnv* env, |
630 const JavaParamRef<jobject>& j_media_drm, | 624 const JavaParamRef<jobject>& j_media_drm, |
631 const JavaParamRef<jstring>& j_default_url, | 625 const JavaParamRef<jstring>& j_default_url, |
632 const JavaParamRef<jbyteArray>& j_request_data) { | 626 const JavaParamRef<jbyteArray>& j_request_data) { |
633 DVLOG(1) << __func__; | 627 DVLOG(1) << __func__; |
634 | 628 |
635 task_runner_->PostTask(FROM_HERE, | 629 task_runner_->PostTask(FROM_HERE, |
636 base::Bind(&MediaDrmBridge::SendProvisioningRequest, | 630 base::Bind(&MediaDrmBridge::SendProvisioningRequest, |
637 weak_factory_.GetWeakPtr(), | 631 weak_factory_.GetWeakPtr(), |
638 ConvertJavaStringToUTF8(env, j_default_url), | 632 ConvertJavaStringToUTF8(env, j_default_url), |
639 AsString(env, j_request_data))); | 633 JavaBytesToString(env, j_request_data))); |
640 } | 634 } |
641 | 635 |
642 void MediaDrmBridge::OnPromiseResolved(JNIEnv* env, | 636 void MediaDrmBridge::OnPromiseResolved(JNIEnv* env, |
643 const JavaParamRef<jobject>& j_media_drm, | 637 const JavaParamRef<jobject>& j_media_drm, |
644 jint j_promise_id) { | 638 jint j_promise_id) { |
645 task_runner_->PostTask(FROM_HERE, | 639 task_runner_->PostTask(FROM_HERE, |
646 base::Bind(&MediaDrmBridge::ResolvePromise, | 640 base::Bind(&MediaDrmBridge::ResolvePromise, |
647 weak_factory_.GetWeakPtr(), j_promise_id)); | 641 weak_factory_.GetWeakPtr(), j_promise_id)); |
648 } | 642 } |
649 | 643 |
650 void MediaDrmBridge::OnPromiseResolvedWithSession( | 644 void MediaDrmBridge::OnPromiseResolvedWithSession( |
651 JNIEnv* env, | 645 JNIEnv* env, |
652 const JavaParamRef<jobject>& j_media_drm, | 646 const JavaParamRef<jobject>& j_media_drm, |
653 jint j_promise_id, | 647 jint j_promise_id, |
654 const JavaParamRef<jbyteArray>& j_session_id) { | 648 const JavaParamRef<jbyteArray>& j_session_id) { |
655 task_runner_->PostTask(FROM_HERE, | 649 task_runner_->PostTask(FROM_HERE, |
656 base::Bind(&MediaDrmBridge::ResolvePromiseWithSession, | 650 base::Bind(&MediaDrmBridge::ResolvePromiseWithSession, |
657 weak_factory_.GetWeakPtr(), j_promise_id, | 651 weak_factory_.GetWeakPtr(), j_promise_id, |
658 AsString(env, j_session_id))); | 652 JavaBytesToString(env, j_session_id))); |
659 } | 653 } |
660 | 654 |
661 void MediaDrmBridge::OnPromiseRejected( | 655 void MediaDrmBridge::OnPromiseRejected( |
662 JNIEnv* env, | 656 JNIEnv* env, |
663 const JavaParamRef<jobject>& j_media_drm, | 657 const JavaParamRef<jobject>& j_media_drm, |
664 jint j_promise_id, | 658 jint j_promise_id, |
665 const JavaParamRef<jstring>& j_error_message) { | 659 const JavaParamRef<jstring>& j_error_message) { |
666 task_runner_->PostTask( | 660 task_runner_->PostTask( |
667 FROM_HERE, | 661 FROM_HERE, |
668 base::Bind(&MediaDrmBridge::RejectPromise, weak_factory_.GetWeakPtr(), | 662 base::Bind(&MediaDrmBridge::RejectPromise, weak_factory_.GetWeakPtr(), |
669 j_promise_id, ConvertJavaStringToUTF8(env, j_error_message))); | 663 j_promise_id, ConvertJavaStringToUTF8(env, j_error_message))); |
670 } | 664 } |
671 | 665 |
672 void MediaDrmBridge::OnSessionMessage( | 666 void MediaDrmBridge::OnSessionMessage( |
673 JNIEnv* env, | 667 JNIEnv* env, |
674 const JavaParamRef<jobject>& j_media_drm, | 668 const JavaParamRef<jobject>& j_media_drm, |
675 const JavaParamRef<jbyteArray>& j_session_id, | 669 const JavaParamRef<jbyteArray>& j_session_id, |
676 jint j_message_type, | 670 jint j_message_type, |
677 const JavaParamRef<jbyteArray>& j_message) { | 671 const JavaParamRef<jbyteArray>& j_message) { |
678 DVLOG(2) << __func__; | 672 DVLOG(2) << __func__; |
679 | 673 |
680 std::vector<uint8_t> message; | 674 std::vector<uint8_t> message; |
681 JavaByteArrayToByteVector(env, j_message, &message); | 675 JavaByteArrayToByteVector(env, j_message, &message); |
682 ContentDecryptionModule::MessageType message_type = | 676 ContentDecryptionModule::MessageType message_type = |
683 GetMessageType(static_cast<RequestType>(j_message_type)); | 677 GetMessageType(static_cast<RequestType>(j_message_type)); |
684 | 678 |
685 task_runner_->PostTask( | 679 task_runner_->PostTask( |
686 FROM_HERE, base::Bind(session_message_cb_, AsString(env, j_session_id), | 680 FROM_HERE, |
687 message_type, message)); | 681 base::Bind(session_message_cb_, JavaBytesToString(env, j_session_id), |
| 682 message_type, message)); |
688 } | 683 } |
689 | 684 |
690 void MediaDrmBridge::OnSessionClosed( | 685 void MediaDrmBridge::OnSessionClosed( |
691 JNIEnv* env, | 686 JNIEnv* env, |
692 const JavaParamRef<jobject>& j_media_drm, | 687 const JavaParamRef<jobject>& j_media_drm, |
693 const JavaParamRef<jbyteArray>& j_session_id) { | 688 const JavaParamRef<jbyteArray>& j_session_id) { |
694 DVLOG(2) << __func__; | 689 DVLOG(2) << __func__; |
695 std::string session_id = AsString(env, j_session_id); | 690 std::string session_id = JavaBytesToString(env, j_session_id); |
696 task_runner_->PostTask(FROM_HERE, base::Bind(session_closed_cb_, session_id)); | 691 task_runner_->PostTask(FROM_HERE, base::Bind(session_closed_cb_, session_id)); |
697 } | 692 } |
698 | 693 |
699 void MediaDrmBridge::OnSessionKeysChange( | 694 void MediaDrmBridge::OnSessionKeysChange( |
700 JNIEnv* env, | 695 JNIEnv* env, |
701 const JavaParamRef<jobject>& j_media_drm, | 696 const JavaParamRef<jobject>& j_media_drm, |
702 const JavaParamRef<jbyteArray>& j_session_id, | 697 const JavaParamRef<jbyteArray>& j_session_id, |
703 const JavaParamRef<jobjectArray>& j_keys_info, | 698 const JavaParamRef<jobjectArray>& j_keys_info, |
704 bool has_additional_usable_key) { | 699 bool has_additional_usable_key) { |
705 DVLOG(2) << __func__; | 700 DVLOG(2) << __func__; |
(...skipping 19 matching lines...) Expand all Loading... |
725 | 720 |
726 DVLOG(2) << __func__ << "Key status change: " | 721 DVLOG(2) << __func__ << "Key status change: " |
727 << base::HexEncode(&key_id[0], key_id.size()) << ", " | 722 << base::HexEncode(&key_id[0], key_id.size()) << ", " |
728 << key_status; | 723 << key_status; |
729 | 724 |
730 cdm_keys_info.push_back(new CdmKeyInformation(key_id, key_status, 0)); | 725 cdm_keys_info.push_back(new CdmKeyInformation(key_id, key_status, 0)); |
731 } | 726 } |
732 | 727 |
733 task_runner_->PostTask( | 728 task_runner_->PostTask( |
734 FROM_HERE, | 729 FROM_HERE, |
735 base::Bind(session_keys_change_cb_, AsString(env, j_session_id), | 730 base::Bind(session_keys_change_cb_, JavaBytesToString(env, j_session_id), |
736 has_additional_usable_key, base::Passed(&cdm_keys_info))); | 731 has_additional_usable_key, base::Passed(&cdm_keys_info))); |
737 | 732 |
738 if (has_additional_usable_key) { | 733 if (has_additional_usable_key) { |
739 task_runner_->PostTask(FROM_HERE, | 734 task_runner_->PostTask(FROM_HERE, |
740 base::Bind(&MediaDrmBridge::OnHasAdditionalUsableKey, | 735 base::Bind(&MediaDrmBridge::OnHasAdditionalUsableKey, |
741 weak_factory_.GetWeakPtr())); | 736 weak_factory_.GetWeakPtr())); |
742 } | 737 } |
743 } | 738 } |
744 | 739 |
745 // According to MeidaDrm documentation [1], zero |expiry_time_ms| means the keys | 740 // According to MeidaDrm documentation [1], zero |expiry_time_ms| means the keys |
746 // will never expire. This will be translated into a NULL base::Time() [2], | 741 // will never expire. This will be translated into a NULL base::Time() [2], |
747 // which will then be mapped to a zero Java time [3]. The zero Java time is | 742 // which will then be mapped to a zero Java time [3]. The zero Java time is |
748 // passed to Blink which will then be translated to NaN [4], which is what the | 743 // passed to Blink which will then be translated to NaN [4], which is what the |
749 // spec uses to indicate that the license will never expire [5]. | 744 // spec uses to indicate that the license will never expire [5]. |
750 // [1] | 745 // [1] |
751 // http://developer.android.com/reference/android/media/MediaDrm.OnExpirationUpd
ateListener.html | 746 // http://developer.android.com/reference/android/media/MediaDrm.OnExpirationUpd
ateListener.html |
752 // [2] See base::Time::FromDoubleT() | 747 // [2] See base::Time::FromDoubleT() |
753 // [3] See base::Time::ToJavaTime() | 748 // [3] See base::Time::ToJavaTime() |
754 // [4] See MediaKeySession::expirationChanged() | 749 // [4] See MediaKeySession::expirationChanged() |
755 // [5] https://github.com/w3c/encrypted-media/issues/58 | 750 // [5] https://github.com/w3c/encrypted-media/issues/58 |
756 void MediaDrmBridge::OnSessionExpirationUpdate( | 751 void MediaDrmBridge::OnSessionExpirationUpdate( |
757 JNIEnv* env, | 752 JNIEnv* env, |
758 const JavaParamRef<jobject>& j_media_drm, | 753 const JavaParamRef<jobject>& j_media_drm, |
759 const JavaParamRef<jbyteArray>& j_session_id, | 754 const JavaParamRef<jbyteArray>& j_session_id, |
760 jlong expiry_time_ms) { | 755 jlong expiry_time_ms) { |
761 DVLOG(2) << __func__ << ": " << expiry_time_ms << " ms"; | 756 DVLOG(2) << __func__ << ": " << expiry_time_ms << " ms"; |
762 task_runner_->PostTask( | 757 task_runner_->PostTask( |
763 FROM_HERE, | 758 FROM_HERE, base::Bind(session_expiration_update_cb_, |
764 base::Bind(session_expiration_update_cb_, AsString(env, j_session_id), | 759 JavaBytesToString(env, j_session_id), |
765 base::Time::FromDoubleT(expiry_time_ms / 1000.0))); | 760 base::Time::FromDoubleT(expiry_time_ms / 1000.0))); |
766 } | 761 } |
767 | 762 |
768 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( | 763 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( |
769 JNIEnv* env, | 764 JNIEnv* env, |
770 const JavaParamRef<jobject>&, | 765 const JavaParamRef<jobject>&, |
771 bool success) { | 766 bool success) { |
772 DVLOG(2) << __func__ << ": success:" << success; | 767 DVLOG(2) << __func__ << ": success:" << success; |
773 DCHECK(!reset_credentials_cb_.is_null()); | 768 DCHECK(!reset_credentials_cb_.is_null()); |
774 task_runner_->PostTask( | 769 task_runner_->PostTask( |
775 FROM_HERE, | 770 FROM_HERE, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 | 815 |
821 // TODO(yucliu): Per EME spec on individualization, implementation should not | 816 // TODO(yucliu): Per EME spec on individualization, implementation should not |
822 // expose application-specific information. Considering encode origin before | 817 // expose application-specific information. Considering encode origin before |
823 // passing to MediaDrm. | 818 // passing to MediaDrm. |
824 ScopedJavaLocalRef<jstring> j_security_origin = ConvertUTF8ToJavaString( | 819 ScopedJavaLocalRef<jstring> j_security_origin = ConvertUTF8ToJavaString( |
825 env, use_origin_isolated_storage ? security_origin.spec() : ""); | 820 env, use_origin_isolated_storage ? security_origin.spec() : ""); |
826 | 821 |
827 // Note: OnMediaCryptoReady() could be called in this call. | 822 // Note: OnMediaCryptoReady() could be called in this call. |
828 j_media_drm_.Reset(Java_MediaDrmBridge_create( | 823 j_media_drm_.Reset(Java_MediaDrmBridge_create( |
829 env, j_scheme_uuid, j_security_origin, j_security_level, | 824 env, j_scheme_uuid, j_security_origin, j_security_level, |
830 reinterpret_cast<intptr_t>(this))); | 825 reinterpret_cast<intptr_t>(this), reinterpret_cast<intptr_t>(&storage_))); |
831 } | 826 } |
832 | 827 |
833 MediaDrmBridge::~MediaDrmBridge() { | 828 MediaDrmBridge::~MediaDrmBridge() { |
834 DCHECK(task_runner_->BelongsToCurrentThread()); | 829 DCHECK(task_runner_->BelongsToCurrentThread()); |
835 DVLOG(1) << __func__; | 830 DVLOG(1) << __func__; |
836 | 831 |
837 JNIEnv* env = AttachCurrentThread(); | 832 JNIEnv* env = AttachCurrentThread(); |
838 | 833 |
839 // After the call to Java_MediaDrmBridge_destroy() Java won't call native | 834 // After the call to Java_MediaDrmBridge_destroy() Java won't call native |
840 // methods anymore, this is ensured by MediaDrmBridge.java. | 835 // methods anymore, this is ensured by MediaDrmBridge.java. |
(...skipping 20 matching lines...) Expand all Loading... |
861 | 856 |
862 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() { | 857 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() { |
863 JNIEnv* env = AttachCurrentThread(); | 858 JNIEnv* env = AttachCurrentThread(); |
864 ScopedJavaLocalRef<jstring> j_security_level = | 859 ScopedJavaLocalRef<jstring> j_security_level = |
865 Java_MediaDrmBridge_getSecurityLevel(env, j_media_drm_); | 860 Java_MediaDrmBridge_getSecurityLevel(env, j_media_drm_); |
866 std::string security_level_str = | 861 std::string security_level_str = |
867 ConvertJavaStringToUTF8(env, j_security_level.obj()); | 862 ConvertJavaStringToUTF8(env, j_security_level.obj()); |
868 return GetSecurityLevelFromString(security_level_str); | 863 return GetSecurityLevelFromString(security_level_str); |
869 } | 864 } |
870 | 865 |
871 // We have to use scoped_ptr to pass ScopedJavaGlobalRef with a callback. | |
872 // TODO(timav): Check whether we can simply pass j_media_crypto_->obj() in the | |
873 // callback. | |
874 MediaDrmBridge::JavaObjectPtr MediaDrmBridge::CreateJavaObjectPtr( | |
875 jobject object) { | |
876 JavaObjectPtr j_object_ptr(new ScopedJavaGlobalRef<jobject>()); | |
877 j_object_ptr->Reset(AttachCurrentThread(), object); | |
878 return j_object_ptr; | |
879 } | |
880 | |
881 void MediaDrmBridge::NotifyMediaCryptoReady(JavaObjectPtr j_media_crypto) { | 866 void MediaDrmBridge::NotifyMediaCryptoReady(JavaObjectPtr j_media_crypto) { |
882 DCHECK(task_runner_->BelongsToCurrentThread()); | 867 DCHECK(task_runner_->BelongsToCurrentThread()); |
883 DCHECK(j_media_crypto); | 868 DCHECK(j_media_crypto); |
884 DCHECK(!j_media_crypto_); | 869 DCHECK(!j_media_crypto_); |
885 | 870 |
886 j_media_crypto_ = std::move(j_media_crypto); | 871 j_media_crypto_ = std::move(j_media_crypto); |
887 | 872 |
888 if (media_crypto_ready_cb_.is_null()) | 873 if (media_crypto_ready_cb_.is_null()) |
889 return; | 874 return; |
890 | 875 |
| 876 // We have to use scoped_ptr to pass ScopedJavaGlobalRef with a callback. |
| 877 // TODO(yucliu): Check whether we can simply pass j_media_crypto_->obj() in th
e |
| 878 // callback. |
891 base::ResetAndReturn(&media_crypto_ready_cb_) | 879 base::ResetAndReturn(&media_crypto_ready_cb_) |
892 .Run(CreateJavaObjectPtr(j_media_crypto_->obj()), | 880 .Run(CreateJavaObjectPtr(j_media_crypto_->obj()), |
893 IsProtectedSurfaceRequired()); | 881 IsProtectedSurfaceRequired()); |
894 } | 882 } |
895 | 883 |
896 void MediaDrmBridge::SendProvisioningRequest(const std::string& default_url, | 884 void MediaDrmBridge::SendProvisioningRequest(const std::string& default_url, |
897 const std::string& request_data) { | 885 const std::string& request_data) { |
898 DCHECK(task_runner_->BelongsToCurrentThread()); | 886 DCHECK(task_runner_->BelongsToCurrentThread()); |
899 DVLOG(1) << __func__; | 887 DVLOG(1) << __func__; |
900 | 888 |
(...skipping 27 matching lines...) Expand all Loading... |
928 } | 916 } |
929 | 917 |
930 void MediaDrmBridge::OnHasAdditionalUsableKey() { | 918 void MediaDrmBridge::OnHasAdditionalUsableKey() { |
931 DCHECK(task_runner_->BelongsToCurrentThread()); | 919 DCHECK(task_runner_->BelongsToCurrentThread()); |
932 DVLOG(1) << __func__; | 920 DVLOG(1) << __func__; |
933 | 921 |
934 player_tracker_.NotifyNewKey(); | 922 player_tracker_.NotifyNewKey(); |
935 } | 923 } |
936 | 924 |
937 } // namespace media | 925 } // namespace media |
OLD | NEW |