| 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 "base/android/build_info.h" | 7 #include "base/android/build_info.h" |
| 8 #include "base/android/jni_array.h" | 8 #include "base/android/jni_array.h" |
| 9 #include "base/android/jni_string.h" | 9 #include "base/android/jni_string.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/message_loop/message_loop_proxy.h" | 13 #include "base/message_loop/message_loop_proxy.h" |
| 14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 15 #include "jni/MediaDrmBridge_jni.h" | 15 #include "jni/MediaDrmBridge_jni.h" |
| 16 #include "media/base/android/media_player_manager.h" | 16 #include "media/base/android/media_player_manager.h" |
| 17 | 17 |
| 18 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
| 19 |
| 18 using base::android::AttachCurrentThread; | 20 using base::android::AttachCurrentThread; |
| 19 using base::android::ConvertUTF8ToJavaString; | 21 using base::android::ConvertUTF8ToJavaString; |
| 20 using base::android::ConvertJavaStringToUTF8; | 22 using base::android::ConvertJavaStringToUTF8; |
| 21 using base::android::JavaByteArrayToByteVector; | 23 using base::android::JavaByteArrayToByteVector; |
| 22 using base::android::ScopedJavaLocalRef; | 24 using base::android::ScopedJavaLocalRef; |
| 23 | 25 |
| 24 namespace media { | 26 namespace media { |
| 25 | 27 |
| 26 static uint32 ReadUint32(const uint8_t* data) { | 28 static uint32 ReadUint32(const uint8_t* data) { |
| 27 uint32 value = 0; | 29 uint32 value = 0; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 43 // | 45 // |
| 44 // PSSH { | 46 // PSSH { |
| 45 // uint32 Size | 47 // uint32 Size |
| 46 // uint32 Type | 48 // uint32 Type |
| 47 // uint64 LargeSize # Field is only present if value(Size) == 1. | 49 // uint64 LargeSize # Field is only present if value(Size) == 1. |
| 48 // uint32 VersionAndFlags | 50 // uint32 VersionAndFlags |
| 49 // uint8[16] SystemId | 51 // uint8[16] SystemId |
| 50 // uint32 DataSize | 52 // uint32 DataSize |
| 51 // uint8[DataSize] Data | 53 // uint8[DataSize] Data |
| 52 // } | 54 // } |
| 53 static const int kBoxHeaderSize = 8; // Box's header contains Size and Type. | 55 const int kBoxHeaderSize = 8; // Box's header contains Size and Type. |
| 54 static const int kBoxLargeSizeSize = 8; | 56 const int kBoxLargeSizeSize = 8; |
| 55 static const int kPsshVersionFlagSize = 4; | 57 const int kPsshVersionFlagSize = 4; |
| 56 static const int kPsshSystemIdSize = 16; | 58 const int kPsshSystemIdSize = 16; |
| 57 static const int kPsshDataSizeSize = 4; | 59 const int kPsshDataSizeSize = 4; |
| 58 static const uint32 kTencType = 0x74656e63; | 60 const uint32 kTencType = 0x74656e63; |
| 59 static const uint32 kPsshType = 0x70737368; | 61 const uint32 kPsshType = 0x70737368; |
| 62 const uint8 kWidevineUuid[16] = { |
| 63 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, |
| 64 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; |
| 65 |
| 66 static std::vector<uint8> GetUUID(const std::string& key_system) { |
| 67 // For security reasons, we only do exact string comparisons here - we don't |
| 68 // try to parse the |key_system| in any way. |
| 69 if (key_system == kWidevineKeySystem) { |
| 70 return std::vector<uint8>(kWidevineUuid, |
| 71 kWidevineUuid + arraysize(kWidevineUuid)); |
| 72 } |
| 73 return std::vector<uint8>(); |
| 74 } |
| 60 | 75 |
| 61 // Tries to find a PSSH box whose "SystemId" is |uuid| in |data|, parses the | 76 // Tries to find a PSSH box whose "SystemId" is |uuid| in |data|, parses the |
| 62 // "Data" of the box and put it in |pssh_data|. Returns true if such a box is | 77 // "Data" of the box and put it in |pssh_data|. Returns true if such a box is |
| 63 // found and successfully parsed. Returns false otherwise. | 78 // found and successfully parsed. Returns false otherwise. |
| 64 // Notes: | 79 // Notes: |
| 65 // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box | 80 // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box |
| 66 // will be set in |pssh_data|. | 81 // will be set in |pssh_data|. |
| 67 // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped. | 82 // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped. |
| 68 static bool GetPsshData(const uint8* data, int data_size, | 83 static bool GetPsshData(const uint8* data, int data_size, |
| 69 const std::vector<uint8>& uuid, | 84 const std::vector<uint8>& uuid, |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 // static | 183 // static |
| 169 bool MediaDrmBridge::IsAvailable() { | 184 bool MediaDrmBridge::IsAvailable() { |
| 170 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; | 185 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; |
| 171 } | 186 } |
| 172 | 187 |
| 173 // static | 188 // static |
| 174 bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) { | 189 bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) { |
| 175 return SECURITY_LEVEL_1 == security_level; | 190 return SECURITY_LEVEL_1 == security_level; |
| 176 } | 191 } |
| 177 | 192 |
| 178 bool MediaDrmBridge::IsSecurityLevelSupported( | 193 bool MediaDrmBridge::IsSecurityLevelSupported(const std::string& key_system, |
| 179 const std::vector<uint8>& scheme_uuid, | 194 SecurityLevel security_level) { |
| 180 SecurityLevel security_level) { | |
| 181 // Pass 0 as |cdm_id| and NULL as |manager| as they are not used in | 195 // Pass 0 as |cdm_id| and NULL as |manager| as they are not used in |
| 182 // creation time of MediaDrmBridge. | 196 // creation time of MediaDrmBridge. |
| 183 scoped_ptr<MediaDrmBridge> media_drm_bridge = | 197 scoped_ptr<MediaDrmBridge> media_drm_bridge = |
| 184 MediaDrmBridge::Create(0, scheme_uuid, GURL(), NULL); | 198 MediaDrmBridge::Create(0, key_system, GURL(), NULL); |
| 185 if (!media_drm_bridge) | 199 if (!media_drm_bridge) |
| 186 return false; | 200 return false; |
| 187 | 201 |
| 188 return media_drm_bridge->SetSecurityLevel(security_level); | 202 return media_drm_bridge->SetSecurityLevel(security_level); |
| 189 } | 203 } |
| 190 | 204 |
| 191 bool MediaDrmBridge::IsCryptoSchemeSupported( | 205 bool MediaDrmBridge::IsKeySystemSupportedWithType( |
| 192 const std::vector<uint8>& scheme_uuid, | 206 const std::string& key_system, |
| 193 const std::string& container_mime_type) { | 207 const std::string& container_mime_type) { |
| 208 std::vector<uint8> scheme_uuid = GetUUID(key_system); |
| 209 if (scheme_uuid.empty()) |
| 210 return false; |
| 211 |
| 194 JNIEnv* env = AttachCurrentThread(); | 212 JNIEnv* env = AttachCurrentThread(); |
| 195 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = | 213 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = |
| 196 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); | 214 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); |
| 197 ScopedJavaLocalRef<jstring> j_container_mime_type = | 215 ScopedJavaLocalRef<jstring> j_container_mime_type = |
| 198 ConvertUTF8ToJavaString(env, container_mime_type); | 216 ConvertUTF8ToJavaString(env, container_mime_type); |
| 199 return Java_MediaDrmBridge_isCryptoSchemeSupported( | 217 return Java_MediaDrmBridge_isCryptoSchemeSupported( |
| 200 env, j_scheme_uuid.obj(), j_container_mime_type.obj()); | 218 env, j_scheme_uuid.obj(), j_container_mime_type.obj()); |
| 201 } | 219 } |
| 202 | 220 |
| 203 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) { | 221 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 221 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); | 239 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); |
| 222 } | 240 } |
| 223 | 241 |
| 224 MediaDrmBridge::~MediaDrmBridge() { | 242 MediaDrmBridge::~MediaDrmBridge() { |
| 225 JNIEnv* env = AttachCurrentThread(); | 243 JNIEnv* env = AttachCurrentThread(); |
| 226 if (!j_media_drm_.is_null()) | 244 if (!j_media_drm_.is_null()) |
| 227 Java_MediaDrmBridge_release(env, j_media_drm_.obj()); | 245 Java_MediaDrmBridge_release(env, j_media_drm_.obj()); |
| 228 } | 246 } |
| 229 | 247 |
| 230 // static | 248 // static |
| 231 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create( | 249 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create(int cdm_id, |
| 232 int cdm_id, | 250 const std::string& key_system, |
| 233 const std::vector<uint8>& scheme_uuid, | 251 const GURL& frame_url, |
| 234 const GURL& frame_url, | 252 MediaPlayerManager* manager) { |
| 235 MediaPlayerManager* manager) { | |
| 236 scoped_ptr<MediaDrmBridge> media_drm_bridge; | 253 scoped_ptr<MediaDrmBridge> media_drm_bridge; |
| 254 if (!IsAvailable()) |
| 255 return media_drm_bridge.Pass(); |
| 237 | 256 |
| 238 if (IsAvailable() && !scheme_uuid.empty()) { | 257 std::vector<uint8> scheme_uuid = GetUUID(key_system); |
| 239 // TODO(qinmin): check whether the uuid is valid. | 258 if (scheme_uuid.empty()) |
| 240 media_drm_bridge.reset( | 259 return media_drm_bridge.Pass(); |
| 241 new MediaDrmBridge(cdm_id, scheme_uuid, frame_url, manager)); | 260 |
| 242 if (media_drm_bridge->j_media_drm_.is_null()) | 261 media_drm_bridge.reset( |
| 243 media_drm_bridge.reset(); | 262 new MediaDrmBridge(cdm_id, scheme_uuid, frame_url, manager)); |
| 244 } | 263 if (media_drm_bridge->j_media_drm_.is_null()) |
| 264 media_drm_bridge.reset(); |
| 245 | 265 |
| 246 return media_drm_bridge.Pass(); | 266 return media_drm_bridge.Pass(); |
| 247 } | 267 } |
| 248 | 268 |
| 249 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { | 269 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { |
| 250 JNIEnv* env = AttachCurrentThread(); | 270 JNIEnv* env = AttachCurrentThread(); |
| 251 | 271 |
| 252 std::string security_level_str = GetSecurityLevelString(security_level); | 272 std::string security_level_str = GetSecurityLevelString(security_level); |
| 253 if (security_level_str.empty()) | 273 if (security_level_str.empty()) |
| 254 return false; | 274 return false; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 JNIEnv* env = AttachCurrentThread(); | 416 JNIEnv* env = AttachCurrentThread(); |
| 397 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); | 417 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); |
| 398 } | 418 } |
| 399 | 419 |
| 400 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( | 420 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( |
| 401 JNIEnv* env, jobject, bool success) { | 421 JNIEnv* env, jobject, bool success) { |
| 402 base::ResetAndReturn(&reset_credentials_cb_).Run(success); | 422 base::ResetAndReturn(&reset_credentials_cb_).Run(success); |
| 403 } | 423 } |
| 404 | 424 |
| 405 } // namespace media | 425 } // namespace media |
| OLD | NEW |