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 "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 if (key_system == kWidevineKeySystem) { | |
|
ddorwin
2014/03/04 20:00:56
We should probably state that for security reasons
xhwang
2014/03/05 21:52:33
IsSupportedKeySystem() will actually call into thi
| |
| 68 return std::vector<uint8>(kWidevineUuid, | |
| 69 kWidevineUuid + arraysize(kWidevineUuid)); | |
| 70 } | |
| 71 return std::vector<uint8>(); | |
| 72 } | |
| 60 | 73 |
| 61 // Tries to find a PSSH box whose "SystemId" is |uuid| in |data|, parses the | 74 // 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 | 75 // "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. | 76 // found and successfully parsed. Returns false otherwise. |
| 64 // Notes: | 77 // Notes: |
| 65 // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box | 78 // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box |
| 66 // will be set in |pssh_data|. | 79 // will be set in |pssh_data|. |
| 67 // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped. | 80 // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped. |
| 68 static bool GetPsshData(const uint8* data, int data_size, | 81 static bool GetPsshData(const uint8* data, int data_size, |
| 69 const std::vector<uint8>& uuid, | 82 const std::vector<uint8>& uuid, |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 // static | 181 // static |
| 169 bool MediaDrmBridge::IsAvailable() { | 182 bool MediaDrmBridge::IsAvailable() { |
| 170 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; | 183 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; |
| 171 } | 184 } |
| 172 | 185 |
| 173 // static | 186 // static |
| 174 bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) { | 187 bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) { |
| 175 return SECURITY_LEVEL_1 == security_level; | 188 return SECURITY_LEVEL_1 == security_level; |
| 176 } | 189 } |
| 177 | 190 |
| 178 bool MediaDrmBridge::IsSecurityLevelSupported( | 191 bool MediaDrmBridge::IsSecurityLevelSupported(const std::string& key_system, |
| 179 const std::vector<uint8>& scheme_uuid, | 192 SecurityLevel security_level) { |
| 180 SecurityLevel security_level) { | |
| 181 // Pass 0 as |cdm_id| and NULL as |manager| as they are not used in | 193 // Pass 0 as |cdm_id| and NULL as |manager| as they are not used in |
| 182 // creation time of MediaDrmBridge. | 194 // creation time of MediaDrmBridge. |
| 183 scoped_ptr<MediaDrmBridge> media_drm_bridge = | 195 scoped_ptr<MediaDrmBridge> media_drm_bridge = |
| 184 MediaDrmBridge::Create(0, scheme_uuid, GURL(), NULL); | 196 MediaDrmBridge::Create(0, key_system, GURL(), NULL); |
| 185 if (!media_drm_bridge) | 197 if (!media_drm_bridge) |
| 186 return false; | 198 return false; |
| 187 | 199 |
| 188 return media_drm_bridge->SetSecurityLevel(security_level); | 200 return media_drm_bridge->SetSecurityLevel(security_level); |
| 189 } | 201 } |
| 190 | 202 |
| 191 bool MediaDrmBridge::IsCryptoSchemeSupported( | 203 bool MediaDrmBridge::IsCryptoSchemeSupported( |
| 192 const std::vector<uint8>& scheme_uuid, | 204 const std::string& key_system, |
| 193 const std::string& container_mime_type) { | 205 const std::string& container_mime_type) { |
| 206 std::vector<uint8> scheme_uuid = GetUUID(key_system); | |
| 207 if (scheme_uuid.empty()) | |
| 208 return false; | |
| 209 | |
| 194 JNIEnv* env = AttachCurrentThread(); | 210 JNIEnv* env = AttachCurrentThread(); |
| 195 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = | 211 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = |
| 196 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); | 212 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); |
| 197 ScopedJavaLocalRef<jstring> j_container_mime_type = | 213 ScopedJavaLocalRef<jstring> j_container_mime_type = |
| 198 ConvertUTF8ToJavaString(env, container_mime_type); | 214 ConvertUTF8ToJavaString(env, container_mime_type); |
| 199 return Java_MediaDrmBridge_isCryptoSchemeSupported( | 215 return Java_MediaDrmBridge_isCryptoSchemeSupported( |
| 200 env, j_scheme_uuid.obj(), j_container_mime_type.obj()); | 216 env, j_scheme_uuid.obj(), j_container_mime_type.obj()); |
| 201 } | 217 } |
| 202 | 218 |
| 203 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) { | 219 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 221 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); | 237 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); |
| 222 } | 238 } |
| 223 | 239 |
| 224 MediaDrmBridge::~MediaDrmBridge() { | 240 MediaDrmBridge::~MediaDrmBridge() { |
| 225 JNIEnv* env = AttachCurrentThread(); | 241 JNIEnv* env = AttachCurrentThread(); |
| 226 if (!j_media_drm_.is_null()) | 242 if (!j_media_drm_.is_null()) |
| 227 Java_MediaDrmBridge_release(env, j_media_drm_.obj()); | 243 Java_MediaDrmBridge_release(env, j_media_drm_.obj()); |
| 228 } | 244 } |
| 229 | 245 |
| 230 // static | 246 // static |
| 231 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create( | 247 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create(int cdm_id, |
| 232 int cdm_id, | 248 const std::string& key_system, |
| 233 const std::vector<uint8>& scheme_uuid, | 249 const GURL& frame_url, |
| 234 const GURL& frame_url, | 250 MediaPlayerManager* manager) { |
| 235 MediaPlayerManager* manager) { | |
| 236 scoped_ptr<MediaDrmBridge> media_drm_bridge; | 251 scoped_ptr<MediaDrmBridge> media_drm_bridge; |
| 252 if (!IsAvailable()) | |
| 253 return media_drm_bridge.Pass(); | |
| 237 | 254 |
| 238 if (IsAvailable() && !scheme_uuid.empty()) { | 255 std::vector<uint8> scheme_uuid = GetUUID(key_system); |
| 239 // TODO(qinmin): check whether the uuid is valid. | 256 if (scheme_uuid.empty()) |
| 240 media_drm_bridge.reset( | 257 return media_drm_bridge.Pass(); |
| 241 new MediaDrmBridge(cdm_id, scheme_uuid, frame_url, manager)); | 258 |
| 242 if (media_drm_bridge->j_media_drm_.is_null()) | 259 media_drm_bridge.reset( |
| 243 media_drm_bridge.reset(); | 260 new MediaDrmBridge(cdm_id, scheme_uuid, frame_url, manager)); |
| 244 } | 261 if (media_drm_bridge->j_media_drm_.is_null()) |
| 262 media_drm_bridge.reset(); | |
| 245 | 263 |
| 246 return media_drm_bridge.Pass(); | 264 return media_drm_bridge.Pass(); |
| 247 } | 265 } |
| 248 | 266 |
| 249 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { | 267 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { |
| 250 JNIEnv* env = AttachCurrentThread(); | 268 JNIEnv* env = AttachCurrentThread(); |
| 251 | 269 |
| 252 std::string security_level_str = GetSecurityLevelString(security_level); | 270 std::string security_level_str = GetSecurityLevelString(security_level); |
| 253 if (security_level_str.empty()) | 271 if (security_level_str.empty()) |
| 254 return false; | 272 return false; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 JNIEnv* env = AttachCurrentThread(); | 414 JNIEnv* env = AttachCurrentThread(); |
| 397 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); | 415 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); |
| 398 } | 416 } |
| 399 | 417 |
| 400 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( | 418 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( |
| 401 JNIEnv* env, jobject, bool success) { | 419 JNIEnv* env, jobject, bool success) { |
| 402 base::ResetAndReturn(&reset_credentials_cb_).Run(success); | 420 base::ResetAndReturn(&reset_credentials_cb_).Run(success); |
| 403 } | 421 } |
| 404 | 422 |
| 405 } // namespace media | 423 } // namespace media |
| OLD | NEW |