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