| 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/callback_helpers.h" | 12 #include "base/callback_helpers.h" |
| 13 #include "base/containers/hash_tables.h" |
| 14 #include "base/lazy_instance.h" |
| 13 #include "base/location.h" | 15 #include "base/location.h" |
| 14 #include "base/logging.h" | 16 #include "base/logging.h" |
| 15 #include "base/message_loop/message_loop_proxy.h" | 17 #include "base/message_loop/message_loop_proxy.h" |
| 16 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 17 #include "jni/MediaDrmBridge_jni.h" | 19 #include "jni/MediaDrmBridge_jni.h" |
| 18 #include "media/base/android/media_player_manager.h" | 20 #include "media/base/android/media_player_manager.h" |
| 19 | 21 |
| 20 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. | 22 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
| 21 | 23 |
| 22 using base::android::AttachCurrentThread; | 24 using base::android::AttachCurrentThread; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 const int kBoxLargeSizeSize = 8; | 60 const int kBoxLargeSizeSize = 8; |
| 59 const int kPsshVersionFlagSize = 4; | 61 const int kPsshVersionFlagSize = 4; |
| 60 const int kPsshSystemIdSize = 16; | 62 const int kPsshSystemIdSize = 16; |
| 61 const int kPsshDataSizeSize = 4; | 63 const int kPsshDataSizeSize = 4; |
| 62 const uint32 kTencType = 0x74656e63; | 64 const uint32 kTencType = 0x74656e63; |
| 63 const uint32 kPsshType = 0x70737368; | 65 const uint32 kPsshType = 0x70737368; |
| 64 const uint8 kWidevineUuid[16] = { | 66 const uint8 kWidevineUuid[16] = { |
| 65 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, | 67 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, |
| 66 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; | 68 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; |
| 67 | 69 |
| 68 static std::vector<uint8> GetUUID(const std::string& key_system) { | 70 typedef std::vector<uint8> UUID; |
| 69 // For security reasons, we only do exact string comparisons here - we don't | 71 |
| 70 // try to parse the |key_system| in any way. | 72 class KeySystemUuidManager { |
| 71 if (key_system == kWidevineKeySystem) { | 73 public: |
| 72 return std::vector<uint8>(kWidevineUuid, | 74 KeySystemUuidManager(); |
| 73 kWidevineUuid + arraysize(kWidevineUuid)); | 75 UUID GetUUID(const std::string& key_system); |
| 74 } | 76 void AddMapping(const std::string& key_system, const UUID& uuid); |
| 75 return std::vector<uint8>(); | 77 |
| 78 private: |
| 79 typedef base::hash_map<std::string, UUID> KeySystemUuidMap; |
| 80 |
| 81 KeySystemUuidMap key_system_uuid_map_; |
| 82 |
| 83 DISALLOW_COPY_AND_ASSIGN(KeySystemUuidManager); |
| 84 }; |
| 85 |
| 86 KeySystemUuidManager::KeySystemUuidManager() { |
| 87 // Widevine is always supported in Android. |
| 88 key_system_uuid_map_[kWidevineKeySystem] = |
| 89 UUID(kWidevineUuid, kWidevineUuid + arraysize(kWidevineUuid)); |
| 76 } | 90 } |
| 77 | 91 |
| 92 UUID KeySystemUuidManager::GetUUID(const std::string& key_system) { |
| 93 KeySystemUuidMap::iterator it = key_system_uuid_map_.find(key_system); |
| 94 if (it == key_system_uuid_map_.end()) |
| 95 return UUID(); |
| 96 return it->second; |
| 97 } |
| 98 |
| 99 void KeySystemUuidManager::AddMapping(const std::string& key_system, |
| 100 const UUID& uuid) { |
| 101 KeySystemUuidMap::iterator it = key_system_uuid_map_.find(key_system); |
| 102 DCHECK(it == key_system_uuid_map_.end()) |
| 103 << "Shouldn't overwrite an existing key system."; |
| 104 if (it != key_system_uuid_map_.end()) |
| 105 return; |
| 106 key_system_uuid_map_[key_system] = uuid; |
| 107 } |
| 108 |
| 109 base::LazyInstance<KeySystemUuidManager>::Leaky g_key_system_uuid_manager = |
| 110 LAZY_INSTANCE_INITIALIZER; |
| 111 |
| 78 // Tries to find a PSSH box whose "SystemId" is |uuid| in |data|, parses the | 112 // Tries to find a PSSH box whose "SystemId" is |uuid| in |data|, parses the |
| 79 // "Data" of the box and put it in |pssh_data|. Returns true if such a box is | 113 // "Data" of the box and put it in |pssh_data|. Returns true if such a box is |
| 80 // found and successfully parsed. Returns false otherwise. | 114 // found and successfully parsed. Returns false otherwise. |
| 81 // Notes: | 115 // Notes: |
| 82 // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box | 116 // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box |
| 83 // will be set in |pssh_data|. | 117 // will be set in |pssh_data|. |
| 84 // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped. | 118 // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped. |
| 85 static bool GetPsshData(const uint8* data, int data_size, | 119 static bool GetPsshData(const uint8* data, int data_size, |
| 86 const std::vector<uint8>& uuid, | 120 const UUID& uuid, |
| 87 std::vector<uint8>* pssh_data) { | 121 std::vector<uint8>* pssh_data) { |
| 88 const uint8* cur = data; | 122 const uint8* cur = data; |
| 89 const uint8* data_end = data + data_size; | 123 const uint8* data_end = data + data_size; |
| 90 int bytes_left = data_size; | 124 int bytes_left = data_size; |
| 91 | 125 |
| 92 while (bytes_left > 0) { | 126 while (bytes_left > 0) { |
| 93 const uint8* box_head = cur; | 127 const uint8* box_head = cur; |
| 94 | 128 |
| 95 if (bytes_left < kBoxHeaderSize) | 129 if (bytes_left < kBoxHeaderSize) |
| 96 return false; | 130 return false; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 // checks |key_system| support if |container_mime_type| is empty. | 220 // checks |key_system| support if |container_mime_type| is empty. |
| 187 // TODO(xhwang): The |container_mime_type| is not the same as contentType in | 221 // TODO(xhwang): The |container_mime_type| is not the same as contentType in |
| 188 // the EME spec. Revisit this once the spec issue with initData type is | 222 // the EME spec. Revisit this once the spec issue with initData type is |
| 189 // resolved. | 223 // resolved. |
| 190 static bool IsKeySystemSupportedWithTypeImpl( | 224 static bool IsKeySystemSupportedWithTypeImpl( |
| 191 const std::string& key_system, | 225 const std::string& key_system, |
| 192 const std::string& container_mime_type) { | 226 const std::string& container_mime_type) { |
| 193 if (!MediaDrmBridge::IsAvailable()) | 227 if (!MediaDrmBridge::IsAvailable()) |
| 194 return false; | 228 return false; |
| 195 | 229 |
| 196 std::vector<uint8> scheme_uuid = GetUUID(key_system); | 230 UUID scheme_uuid = g_key_system_uuid_manager.Get().GetUUID(key_system); |
| 197 if (scheme_uuid.empty()) | 231 if (scheme_uuid.empty()) |
| 198 return false; | 232 return false; |
| 199 | 233 |
| 200 JNIEnv* env = AttachCurrentThread(); | 234 JNIEnv* env = AttachCurrentThread(); |
| 201 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = | 235 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = |
| 202 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); | 236 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); |
| 203 ScopedJavaLocalRef<jstring> j_container_mime_type = | 237 ScopedJavaLocalRef<jstring> j_container_mime_type = |
| 204 ConvertUTF8ToJavaString(env, container_mime_type); | 238 ConvertUTF8ToJavaString(env, container_mime_type); |
| 205 return Java_MediaDrmBridge_isCryptoSchemeSupported( | 239 return Java_MediaDrmBridge_isCryptoSchemeSupported( |
| 206 env, j_scheme_uuid.obj(), j_container_mime_type.obj()); | 240 env, j_scheme_uuid.obj(), j_container_mime_type.obj()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 226 // Pass 0 as |cdm_id| and NULL as |manager| as they are not used in | 260 // Pass 0 as |cdm_id| and NULL as |manager| as they are not used in |
| 227 // creation time of MediaDrmBridge. | 261 // creation time of MediaDrmBridge. |
| 228 scoped_ptr<MediaDrmBridge> media_drm_bridge = | 262 scoped_ptr<MediaDrmBridge> media_drm_bridge = |
| 229 MediaDrmBridge::Create(0, key_system, GURL(), NULL); | 263 MediaDrmBridge::Create(0, key_system, GURL(), NULL); |
| 230 if (!media_drm_bridge) | 264 if (!media_drm_bridge) |
| 231 return false; | 265 return false; |
| 232 | 266 |
| 233 return media_drm_bridge->SetSecurityLevel(security_level); | 267 return media_drm_bridge->SetSecurityLevel(security_level); |
| 234 } | 268 } |
| 235 | 269 |
| 270 //static |
| 271 void MediaDrmBridge::AddKeySystemUuidMapping(const std::string& key_system, |
| 272 const std::vector<uint8>& uuid) { |
| 273 g_key_system_uuid_manager.Get().AddMapping(key_system, uuid); |
| 274 } |
| 275 |
| 236 // static | 276 // static |
| 237 bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) { | 277 bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) { |
| 238 DCHECK(!key_system.empty()); | 278 DCHECK(!key_system.empty()); |
| 239 return IsKeySystemSupportedWithTypeImpl(key_system, ""); | 279 return IsKeySystemSupportedWithTypeImpl(key_system, ""); |
| 240 } | 280 } |
| 241 | 281 |
| 242 // static | 282 // static |
| 243 bool MediaDrmBridge::IsKeySystemSupportedWithType( | 283 bool MediaDrmBridge::IsKeySystemSupportedWithType( |
| 244 const std::string& key_system, | 284 const std::string& key_system, |
| 245 const std::string& container_mime_type) { | 285 const std::string& container_mime_type) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 276 | 316 |
| 277 // static | 317 // static |
| 278 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create(int cdm_id, | 318 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create(int cdm_id, |
| 279 const std::string& key_system, | 319 const std::string& key_system, |
| 280 const GURL& security_origin, | 320 const GURL& security_origin, |
| 281 MediaPlayerManager* manager) { | 321 MediaPlayerManager* manager) { |
| 282 scoped_ptr<MediaDrmBridge> media_drm_bridge; | 322 scoped_ptr<MediaDrmBridge> media_drm_bridge; |
| 283 if (!IsAvailable()) | 323 if (!IsAvailable()) |
| 284 return media_drm_bridge.Pass(); | 324 return media_drm_bridge.Pass(); |
| 285 | 325 |
| 286 std::vector<uint8> scheme_uuid = GetUUID(key_system); | 326 UUID scheme_uuid = g_key_system_uuid_manager.Get().GetUUID(key_system); |
| 287 if (scheme_uuid.empty()) | 327 if (scheme_uuid.empty()) |
| 288 return media_drm_bridge.Pass(); | 328 return media_drm_bridge.Pass(); |
| 289 | 329 |
| 290 media_drm_bridge.reset( | 330 media_drm_bridge.reset( |
| 291 new MediaDrmBridge(cdm_id, scheme_uuid, security_origin, manager)); | 331 new MediaDrmBridge(cdm_id, scheme_uuid, security_origin, manager)); |
| 292 if (media_drm_bridge->j_media_drm_.is_null()) | 332 if (media_drm_bridge->j_media_drm_.is_null()) |
| 293 media_drm_bridge.reset(); | 333 media_drm_bridge.reset(); |
| 294 | 334 |
| 295 return media_drm_bridge.Pass(); | 335 return media_drm_bridge.Pass(); |
| 296 } | 336 } |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 JNIEnv* env = AttachCurrentThread(); | 497 JNIEnv* env = AttachCurrentThread(); |
| 458 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); | 498 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); |
| 459 } | 499 } |
| 460 | 500 |
| 461 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( | 501 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( |
| 462 JNIEnv* env, jobject, bool success) { | 502 JNIEnv* env, jobject, bool success) { |
| 463 base::ResetAndReturn(&reset_credentials_cb_).Run(success); | 503 base::ResetAndReturn(&reset_credentials_cb_).Run(success); |
| 464 } | 504 } |
| 465 | 505 |
| 466 } // namespace media | 506 } // namespace media |
| OLD | NEW |