| 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" | 13 #include "base/containers/hash_tables.h" |
| 14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/message_loop/message_loop_proxy.h" | 17 #include "base/message_loop/message_loop_proxy.h" |
| 18 #include "base/numerics/safe_conversions.h" | |
| 19 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
| 20 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 21 #include "base/sys_byteorder.h" | 20 #include "base/sys_byteorder.h" |
| 22 #include "base/sys_info.h" | 21 #include "base/sys_info.h" |
| 23 #include "jni/MediaDrmBridge_jni.h" | 22 #include "jni/MediaDrmBridge_jni.h" |
| 23 #include "media/base/android/media_client_android.h" |
| 24 #include "media/base/android/media_drm_bridge_delegate.h" |
| 24 #include "media/base/cdm_key_information.h" | 25 #include "media/base/cdm_key_information.h" |
| 25 | 26 |
| 26 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. | 27 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
| 27 | 28 |
| 28 using base::android::AttachCurrentThread; | 29 using base::android::AttachCurrentThread; |
| 29 using base::android::ConvertUTF8ToJavaString; | 30 using base::android::ConvertUTF8ToJavaString; |
| 30 using base::android::ConvertJavaStringToUTF8; | 31 using base::android::ConvertJavaStringToUTF8; |
| 31 using base::android::JavaByteArrayToByteVector; | 32 using base::android::JavaByteArrayToByteVector; |
| 32 using base::android::ScopedJavaLocalRef; | 33 using base::android::ScopedJavaLocalRef; |
| 33 | 34 |
| 34 namespace media { | 35 namespace media { |
| 35 | 36 |
| 36 namespace { | 37 namespace { |
| 37 | 38 |
| 38 // DrmBridge supports session expiration event but doesn't provide detailed | 39 // DrmBridge supports session expiration event but doesn't provide detailed |
| 39 // status for each key ID, which is required by the EME spec. Use a dummy key ID | 40 // status for each key ID, which is required by the EME spec. Use a dummy key ID |
| 40 // here to report session expiration info. | 41 // here to report session expiration info. |
| 41 const char kDummyKeyId[] = "Dummy Key Id"; | 42 const char kDummyKeyId[] = "Dummy Key Id"; |
| 42 | 43 |
| 43 uint32 ReadUint32(const uint8_t* data) { | |
| 44 uint32 value = 0; | |
| 45 for (int i = 0; i < 4; ++i) | |
| 46 value = (value << 8) | data[i]; | |
| 47 return value; | |
| 48 } | |
| 49 | |
| 50 uint64 ReadUint64(const uint8_t* data) { | |
| 51 uint64 value = 0; | |
| 52 for (int i = 0; i < 8; ++i) | |
| 53 value = (value << 8) | data[i]; | |
| 54 return value; | |
| 55 } | |
| 56 | |
| 57 // Returns string session ID from jbyteArray (byte[] in Java). | 44 // Returns string session ID from jbyteArray (byte[] in Java). |
| 58 std::string GetSessionId(JNIEnv* env, jbyteArray j_session_id) { | 45 std::string GetSessionId(JNIEnv* env, jbyteArray j_session_id) { |
| 59 std::vector<uint8> session_id_vector; | 46 std::vector<uint8> session_id_vector; |
| 60 JavaByteArrayToByteVector(env, j_session_id, &session_id_vector); | 47 JavaByteArrayToByteVector(env, j_session_id, &session_id_vector); |
| 61 return std::string(session_id_vector.begin(), session_id_vector.end()); | 48 return std::string(session_id_vector.begin(), session_id_vector.end()); |
| 62 } | 49 } |
| 63 | 50 |
| 64 // The structure of an ISO CENC Protection System Specific Header (PSSH) box is | |
| 65 // as follows. (See ISO/IEC FDIS 23001-7:2011(E).) | |
| 66 // Note: ISO boxes use big-endian values. | |
| 67 // | |
| 68 // PSSH { | |
| 69 // uint32 Size | |
| 70 // uint32 Type | |
| 71 // uint64 LargeSize # Field is only present if value(Size) == 1. | |
| 72 // uint32 VersionAndFlags | |
| 73 // uint8[16] SystemId | |
| 74 // uint32 DataSize | |
| 75 // uint8[DataSize] Data | |
| 76 // } | |
| 77 const int kBoxHeaderSize = 8; // Box's header contains Size and Type. | |
| 78 const int kBoxLargeSizeSize = 8; | |
| 79 const int kPsshVersionFlagSize = 4; | |
| 80 const int kPsshSystemIdSize = 16; | |
| 81 const int kPsshDataSizeSize = 4; | |
| 82 const uint32 kTencType = 0x74656e63; | |
| 83 const uint32 kPsshType = 0x70737368; | |
| 84 const uint8 kWidevineUuid[16] = { | 51 const uint8 kWidevineUuid[16] = { |
| 85 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, | 52 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, |
| 86 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; | 53 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; |
| 87 | 54 |
| 88 typedef std::vector<uint8> UUID; | |
| 89 | |
| 90 // Tries to find a PSSH box whose "SystemId" is |uuid| in |data|, parses the | |
| 91 // "Data" of the box and put it in |pssh_data|. Returns true if such a box is | |
| 92 // found and successfully parsed. Returns false otherwise. | |
| 93 // Notes: | |
| 94 // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box | |
| 95 // will be set in |pssh_data|. | |
| 96 // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped. | |
| 97 bool GetPsshData(const std::vector<uint8_t>& data, | |
| 98 const UUID& uuid, | |
| 99 std::vector<uint8>* pssh_data) { | |
| 100 int bytes_left = base::checked_cast<int>(data.size()); | |
| 101 const uint8_t* cur = &data[0]; | |
| 102 const uint8_t* data_end = cur + bytes_left; | |
| 103 | |
| 104 while (bytes_left > 0) { | |
| 105 const uint8* box_head = cur; | |
| 106 | |
| 107 if (bytes_left < kBoxHeaderSize) | |
| 108 return false; | |
| 109 | |
| 110 uint64_t box_size = ReadUint32(cur); | |
| 111 uint32 type = ReadUint32(cur + 4); | |
| 112 cur += kBoxHeaderSize; | |
| 113 bytes_left -= kBoxHeaderSize; | |
| 114 | |
| 115 if (box_size == 1) { // LargeSize is present. | |
| 116 if (bytes_left < kBoxLargeSizeSize) | |
| 117 return false; | |
| 118 | |
| 119 box_size = ReadUint64(cur); | |
| 120 cur += kBoxLargeSizeSize; | |
| 121 bytes_left -= kBoxLargeSizeSize; | |
| 122 } else if (box_size == 0) { | |
| 123 box_size = bytes_left + kBoxHeaderSize; | |
| 124 } | |
| 125 | |
| 126 const uint8* box_end = box_head + box_size; | |
| 127 if (data_end < box_end) | |
| 128 return false; | |
| 129 | |
| 130 if (type == kTencType) { | |
| 131 // Skip 'tenc' box. | |
| 132 cur = box_end; | |
| 133 bytes_left = data_end - cur; | |
| 134 continue; | |
| 135 } else if (type != kPsshType) { | |
| 136 return false; | |
| 137 } | |
| 138 | |
| 139 const int kPsshBoxMinimumSize = | |
| 140 kPsshVersionFlagSize + kPsshSystemIdSize + kPsshDataSizeSize; | |
| 141 if (box_end < cur + kPsshBoxMinimumSize) | |
| 142 return false; | |
| 143 | |
| 144 uint32 version_and_flags = ReadUint32(cur); | |
| 145 cur += kPsshVersionFlagSize; | |
| 146 bytes_left -= kPsshVersionFlagSize; | |
| 147 if (version_and_flags != 0) | |
| 148 return false; | |
| 149 | |
| 150 DCHECK_GE(bytes_left, kPsshSystemIdSize); | |
| 151 if (!std::equal(uuid.begin(), uuid.end(), cur)) { | |
| 152 cur = box_end; | |
| 153 bytes_left = data_end - cur; | |
| 154 continue; | |
| 155 } | |
| 156 | |
| 157 cur += kPsshSystemIdSize; | |
| 158 bytes_left -= kPsshSystemIdSize; | |
| 159 | |
| 160 uint32 data_size = ReadUint32(cur); | |
| 161 cur += kPsshDataSizeSize; | |
| 162 bytes_left -= kPsshDataSizeSize; | |
| 163 | |
| 164 if (box_end < cur + data_size) | |
| 165 return false; | |
| 166 | |
| 167 pssh_data->assign(cur, cur + data_size); | |
| 168 return true; | |
| 169 } | |
| 170 | |
| 171 return false; | |
| 172 } | |
| 173 | |
| 174 // Convert |init_data_type| to a string supported by MediaDRM. | 55 // Convert |init_data_type| to a string supported by MediaDRM. |
| 175 // "audio"/"video" does not matter, so use "video". | 56 // "audio"/"video" does not matter, so use "video". |
| 176 std::string ConvertInitDataType(media::EmeInitDataType init_data_type) { | 57 std::string ConvertInitDataType(media::EmeInitDataType init_data_type) { |
| 177 // TODO(jrummell): API level >=20 supports "webm" and "cenc", so switch | 58 // TODO(jrummell): API level >=20 supports "webm" and "cenc", so switch |
| 178 // to those strings. | 59 // to those strings. |
| 179 switch (init_data_type) { | 60 switch (init_data_type) { |
| 180 case media::EmeInitDataType::WEBM: | 61 case media::EmeInitDataType::WEBM: |
| 181 return "video/webm"; | 62 return "video/webm"; |
| 182 case media::EmeInitDataType::CENC: | 63 case media::EmeInitDataType::CENC: |
| 183 return "video/mp4"; | 64 return "video/mp4"; |
| 184 default: | 65 default: |
| 185 NOTREACHED(); | 66 NOTREACHED(); |
| 186 return "video/unknown"; | 67 return "video/unknown"; |
| 187 } | 68 } |
| 188 } | 69 } |
| 189 | 70 |
| 190 class KeySystemUuidManager { | 71 class KeySystemManager { |
| 191 public: | 72 public: |
| 192 KeySystemUuidManager(); | 73 KeySystemManager(); |
| 193 UUID GetUUID(const std::string& key_system); | 74 UUID GetUUID(const std::string& key_system); |
| 194 void AddMapping(const std::string& key_system, const UUID& uuid); | |
| 195 std::vector<std::string> GetPlatformKeySystemNames(); | 75 std::vector<std::string> GetPlatformKeySystemNames(); |
| 196 | 76 |
| 197 private: | 77 private: |
| 198 typedef base::hash_map<std::string, UUID> KeySystemUuidMap; | 78 using KeySystemUuidMap = MediaClientAndroid::KeySystemUuidMap; |
| 199 | 79 |
| 200 KeySystemUuidMap key_system_uuid_map_; | 80 KeySystemUuidMap key_system_uuid_map_; |
| 201 | 81 |
| 202 DISALLOW_COPY_AND_ASSIGN(KeySystemUuidManager); | 82 DISALLOW_COPY_AND_ASSIGN(KeySystemManager); |
| 203 }; | 83 }; |
| 204 | 84 |
| 205 KeySystemUuidManager::KeySystemUuidManager() { | 85 KeySystemManager::KeySystemManager() { |
| 206 // Widevine is always supported in Android. | 86 // Widevine is always supported in Android. |
| 207 key_system_uuid_map_[kWidevineKeySystem] = | 87 key_system_uuid_map_[kWidevineKeySystem] = |
| 208 UUID(kWidevineUuid, kWidevineUuid + arraysize(kWidevineUuid)); | 88 UUID(kWidevineUuid, kWidevineUuid + arraysize(kWidevineUuid)); |
| 89 MediaClientAndroid* client = GetMediaClientAndroid(); |
| 90 if (client) |
| 91 client->AddKeySystemUUIDMappings(&key_system_uuid_map_); |
| 209 } | 92 } |
| 210 | 93 |
| 211 UUID KeySystemUuidManager::GetUUID(const std::string& key_system) { | 94 UUID KeySystemManager::GetUUID(const std::string& key_system) { |
| 212 KeySystemUuidMap::iterator it = key_system_uuid_map_.find(key_system); | 95 KeySystemUuidMap::iterator it = key_system_uuid_map_.find(key_system); |
| 213 if (it == key_system_uuid_map_.end()) | 96 if (it == key_system_uuid_map_.end()) |
| 214 return UUID(); | 97 return UUID(); |
| 215 return it->second; | 98 return it->second; |
| 216 } | 99 } |
| 217 | 100 |
| 218 void KeySystemUuidManager::AddMapping(const std::string& key_system, | 101 std::vector<std::string> KeySystemManager::GetPlatformKeySystemNames() { |
| 219 const UUID& uuid) { | |
| 220 KeySystemUuidMap::iterator it = key_system_uuid_map_.find(key_system); | |
| 221 DCHECK(it == key_system_uuid_map_.end()) | |
| 222 << "Shouldn't overwrite an existing key system."; | |
| 223 if (it != key_system_uuid_map_.end()) | |
| 224 return; | |
| 225 key_system_uuid_map_[key_system] = uuid; | |
| 226 } | |
| 227 | |
| 228 std::vector<std::string> KeySystemUuidManager::GetPlatformKeySystemNames() { | |
| 229 std::vector<std::string> key_systems; | 102 std::vector<std::string> key_systems; |
| 230 for (KeySystemUuidMap::iterator it = key_system_uuid_map_.begin(); | 103 for (KeySystemUuidMap::iterator it = key_system_uuid_map_.begin(); |
| 231 it != key_system_uuid_map_.end(); ++it) { | 104 it != key_system_uuid_map_.end(); ++it) { |
| 232 // Rule out the key system handled by Chrome explicitly. | 105 // Rule out the key system handled by Chrome explicitly. |
| 233 if (it->first != kWidevineKeySystem) | 106 if (it->first != kWidevineKeySystem) |
| 234 key_systems.push_back(it->first); | 107 key_systems.push_back(it->first); |
| 235 } | 108 } |
| 236 return key_systems; | 109 return key_systems; |
| 237 } | 110 } |
| 238 | 111 |
| 239 base::LazyInstance<KeySystemUuidManager>::Leaky g_key_system_uuid_manager = | 112 base::LazyInstance<KeySystemManager>::Leaky g_key_system_manager = |
| 240 LAZY_INSTANCE_INITIALIZER; | 113 LAZY_INSTANCE_INITIALIZER; |
| 241 | 114 |
| 242 // Checks whether |key_system| is supported with |container_mime_type|. Only | 115 // Checks whether |key_system| is supported with |container_mime_type|. Only |
| 243 // checks |key_system| support if |container_mime_type| is empty. | 116 // checks |key_system| support if |container_mime_type| is empty. |
| 244 // TODO(xhwang): The |container_mime_type| is not the same as contentType in | 117 // TODO(xhwang): The |container_mime_type| is not the same as contentType in |
| 245 // the EME spec. Revisit this once the spec issue with initData type is | 118 // the EME spec. Revisit this once the spec issue with initData type is |
| 246 // resolved. | 119 // resolved. |
| 247 bool IsKeySystemSupportedWithTypeImpl(const std::string& key_system, | 120 bool IsKeySystemSupportedWithTypeImpl(const std::string& key_system, |
| 248 const std::string& container_mime_type) { | 121 const std::string& container_mime_type) { |
| 249 if (!MediaDrmBridge::IsAvailable()) | 122 if (!MediaDrmBridge::IsAvailable()) |
| 250 return false; | 123 return false; |
| 251 | 124 |
| 252 UUID scheme_uuid = g_key_system_uuid_manager.Get().GetUUID(key_system); | 125 UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system); |
| 253 if (scheme_uuid.empty()) | 126 if (scheme_uuid.empty()) |
| 254 return false; | 127 return false; |
| 255 | 128 |
| 256 JNIEnv* env = AttachCurrentThread(); | 129 JNIEnv* env = AttachCurrentThread(); |
| 257 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = | 130 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = |
| 258 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); | 131 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); |
| 259 ScopedJavaLocalRef<jstring> j_container_mime_type = | 132 ScopedJavaLocalRef<jstring> j_container_mime_type = |
| 260 ConvertUTF8ToJavaString(env, container_mime_type); | 133 ConvertUTF8ToJavaString(env, container_mime_type); |
| 261 return Java_MediaDrmBridge_isCryptoSchemeSupported( | 134 return Java_MediaDrmBridge_isCryptoSchemeSupported( |
| 262 env, j_scheme_uuid.obj(), j_container_mime_type.obj()); | 135 env, j_scheme_uuid.obj(), j_container_mime_type.obj()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 280 case MediaDrmBridge::SECURITY_LEVEL_1: | 153 case MediaDrmBridge::SECURITY_LEVEL_1: |
| 281 return "L1"; | 154 return "L1"; |
| 282 case MediaDrmBridge::SECURITY_LEVEL_3: | 155 case MediaDrmBridge::SECURITY_LEVEL_3: |
| 283 return "L3"; | 156 return "L3"; |
| 284 } | 157 } |
| 285 return ""; | 158 return ""; |
| 286 } | 159 } |
| 287 | 160 |
| 288 } // namespace | 161 } // namespace |
| 289 | 162 |
| 290 // Called by Java. | |
| 291 static void AddKeySystemUuidMapping(JNIEnv* env, | |
| 292 jclass clazz, | |
| 293 jstring j_key_system, | |
| 294 jobject j_buffer) { | |
| 295 std::string key_system = ConvertJavaStringToUTF8(env, j_key_system); | |
| 296 uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer)); | |
| 297 UUID uuid(buffer, buffer + 16); | |
| 298 g_key_system_uuid_manager.Get().AddMapping(key_system, uuid); | |
| 299 } | |
| 300 | |
| 301 // static | 163 // static |
| 302 bool MediaDrmBridge::IsAvailable() { | 164 bool MediaDrmBridge::IsAvailable() { |
| 303 if (base::android::BuildInfo::GetInstance()->sdk_int() < 19) | 165 if (base::android::BuildInfo::GetInstance()->sdk_int() < 19) |
| 304 return false; | 166 return false; |
| 305 | 167 |
| 306 int32 os_major_version = 0; | 168 int32 os_major_version = 0; |
| 307 int32 os_minor_version = 0; | 169 int32 os_minor_version = 0; |
| 308 int32 os_bugfix_version = 0; | 170 int32 os_bugfix_version = 0; |
| 309 base::SysInfo::OperatingSystemVersionNumbers(&os_major_version, | 171 base::SysInfo::OperatingSystemVersionNumbers(&os_major_version, |
| 310 &os_minor_version, | 172 &os_minor_version, |
| 311 &os_bugfix_version); | 173 &os_bugfix_version); |
| 312 if (os_major_version == 4 && os_minor_version == 4 && os_bugfix_version == 0) | 174 if (os_major_version == 4 && os_minor_version == 4 && os_bugfix_version == 0) |
| 313 return false; | 175 return false; |
| 314 | 176 |
| 315 return true; | 177 return true; |
| 316 } | 178 } |
| 317 | 179 |
| 318 // TODO(ddorwin): This is specific to Widevine. http://crbug.com/459400 | 180 // TODO(ddorwin): This is specific to Widevine. http://crbug.com/459400 |
| 319 // static | 181 // static |
| 320 bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) { | 182 bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) { |
| 321 DCHECK(IsAvailable()); | 183 DCHECK(IsAvailable()); |
| 322 return SECURITY_LEVEL_1 == security_level; | 184 return SECURITY_LEVEL_1 == security_level; |
| 323 } | 185 } |
| 324 | 186 |
| 325 // static | 187 // static |
| 326 std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() { | 188 std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() { |
| 327 return g_key_system_uuid_manager.Get().GetPlatformKeySystemNames(); | 189 return g_key_system_manager.Get().GetPlatformKeySystemNames(); |
| 328 } | 190 } |
| 329 | 191 |
| 330 // static | 192 // static |
| 331 bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) { | 193 bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) { |
| 332 DCHECK(!key_system.empty()); | 194 DCHECK(!key_system.empty()); |
| 333 return IsKeySystemSupportedWithTypeImpl(key_system, ""); | 195 return IsKeySystemSupportedWithTypeImpl(key_system, ""); |
| 334 } | 196 } |
| 335 | 197 |
| 336 // static | 198 // static |
| 337 bool MediaDrmBridge::IsKeySystemSupportedWithType( | 199 bool MediaDrmBridge::IsKeySystemSupportedWithType( |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 const std::string& key_system, | 240 const std::string& key_system, |
| 379 const SessionMessageCB& session_message_cb, | 241 const SessionMessageCB& session_message_cb, |
| 380 const SessionClosedCB& session_closed_cb, | 242 const SessionClosedCB& session_closed_cb, |
| 381 const LegacySessionErrorCB& legacy_session_error_cb, | 243 const LegacySessionErrorCB& legacy_session_error_cb, |
| 382 const SessionKeysChangeCB& session_keys_change_cb, | 244 const SessionKeysChangeCB& session_keys_change_cb, |
| 383 const SessionExpirationUpdateCB& /* session_expiration_update_cb */) { | 245 const SessionExpirationUpdateCB& /* session_expiration_update_cb */) { |
| 384 scoped_ptr<MediaDrmBridge> media_drm_bridge; | 246 scoped_ptr<MediaDrmBridge> media_drm_bridge; |
| 385 if (!IsAvailable()) | 247 if (!IsAvailable()) |
| 386 return media_drm_bridge.Pass(); | 248 return media_drm_bridge.Pass(); |
| 387 | 249 |
| 388 UUID scheme_uuid = g_key_system_uuid_manager.Get().GetUUID(key_system); | 250 UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system); |
| 389 if (scheme_uuid.empty()) | 251 if (scheme_uuid.empty()) |
| 390 return media_drm_bridge.Pass(); | 252 return media_drm_bridge.Pass(); |
| 391 | 253 |
| 392 media_drm_bridge.reset( | 254 media_drm_bridge.reset( |
| 393 new MediaDrmBridge(scheme_uuid, session_message_cb, session_closed_cb, | 255 new MediaDrmBridge(scheme_uuid, session_message_cb, session_closed_cb, |
| 394 legacy_session_error_cb, session_keys_change_cb)); | 256 legacy_session_error_cb, session_keys_change_cb)); |
| 395 | 257 |
| 396 if (media_drm_bridge->j_media_drm_.is_null()) | 258 if (media_drm_bridge->j_media_drm_.is_null()) |
| 397 media_drm_bridge.reset(); | 259 media_drm_bridge.reset(); |
| 398 | 260 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 DVLOG(1) << __FUNCTION__; | 304 DVLOG(1) << __FUNCTION__; |
| 443 | 305 |
| 444 if (session_type != media::MediaKeys::TEMPORARY_SESSION) { | 306 if (session_type != media::MediaKeys::TEMPORARY_SESSION) { |
| 445 promise->reject(NOT_SUPPORTED_ERROR, 0, | 307 promise->reject(NOT_SUPPORTED_ERROR, 0, |
| 446 "Only the temporary session type is supported."); | 308 "Only the temporary session type is supported."); |
| 447 return; | 309 return; |
| 448 } | 310 } |
| 449 | 311 |
| 450 JNIEnv* env = AttachCurrentThread(); | 312 JNIEnv* env = AttachCurrentThread(); |
| 451 ScopedJavaLocalRef<jbyteArray> j_init_data; | 313 ScopedJavaLocalRef<jbyteArray> j_init_data; |
| 314 ScopedJavaLocalRef<jobjectArray> j_optional_parameters; |
| 452 | 315 |
| 453 // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as | 316 MediaClientAndroid* client = GetMediaClientAndroid(); |
| 454 // the init data when using MP4 container. | 317 if (client) { |
| 455 if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid) && | 318 MediaDrmBridgeDelegate* delegate = |
| 456 init_data_type == media::EmeInitDataType::CENC) { | 319 client->GetMediaDrmBridgeDelegate(scheme_uuid_); |
| 457 std::vector<uint8> pssh_data; | 320 if (delegate) { |
| 458 if (!GetPsshData(init_data, scheme_uuid_, &pssh_data)) { | 321 std::vector<uint8> init_data_from_delegate; |
| 459 promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid PSSH data."); | 322 std::vector<std::string> optional_parameters_from_delegate; |
| 460 return; | 323 if (!delegate->OnCreateSession(init_data_type, init_data, |
| 324 &init_data_from_delegate, |
| 325 &optional_parameters_from_delegate)) { |
| 326 promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid init data."); |
| 327 } |
| 328 j_init_data = base::android::ToJavaByteArray( |
| 329 env, vector_as_array(&init_data_from_delegate), |
| 330 init_data_from_delegate.size()); |
| 331 if (!optional_parameters_from_delegate.empty()) { |
| 332 j_optional_parameters = base::android::ToJavaArrayOfStrings( |
| 333 env, optional_parameters_from_delegate); |
| 334 } |
| 461 } | 335 } |
| 462 j_init_data = base::android::ToJavaByteArray( | 336 } |
| 463 env, vector_as_array(&pssh_data), pssh_data.size()); | 337 |
| 464 } else { | 338 if (j_init_data.is_null()) { |
| 465 j_init_data = base::android::ToJavaByteArray( | 339 j_init_data = base::android::ToJavaByteArray( |
| 466 env, vector_as_array(&init_data), init_data.size()); | 340 env, vector_as_array(&init_data), init_data.size()); |
| 467 } | 341 } |
| 468 | 342 |
| 469 ScopedJavaLocalRef<jstring> j_mime = | 343 ScopedJavaLocalRef<jstring> j_mime = |
| 470 ConvertUTF8ToJavaString(env, ConvertInitDataType(init_data_type)); | 344 ConvertUTF8ToJavaString(env, ConvertInitDataType(init_data_type)); |
| 471 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); | 345 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); |
| 472 Java_MediaDrmBridge_createSession(env, j_media_drm_.obj(), j_init_data.obj(), | 346 Java_MediaDrmBridge_createSessionFromNative(env, j_media_drm_.obj(), |
| 473 j_mime.obj(), promise_id); | 347 j_init_data.obj(), j_mime.obj(), |
| 348 j_optional_parameters.obj(), |
| 349 promise_id); |
| 474 } | 350 } |
| 475 | 351 |
| 476 void MediaDrmBridge::LoadSession( | 352 void MediaDrmBridge::LoadSession( |
| 477 SessionType session_type, | 353 SessionType session_type, |
| 478 const std::string& session_id, | 354 const std::string& session_id, |
| 479 scoped_ptr<media::NewSessionCdmPromise> promise) { | 355 scoped_ptr<media::NewSessionCdmPromise> promise) { |
| 480 promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported."); | 356 promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported."); |
| 481 } | 357 } |
| 482 | 358 |
| 483 void MediaDrmBridge::UpdateSession( | 359 void MediaDrmBridge::UpdateSession( |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 JNIEnv* env = AttachCurrentThread(); | 533 JNIEnv* env = AttachCurrentThread(); |
| 658 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); | 534 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); |
| 659 } | 535 } |
| 660 | 536 |
| 661 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( | 537 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( |
| 662 JNIEnv* env, jobject, bool success) { | 538 JNIEnv* env, jobject, bool success) { |
| 663 base::ResetAndReturn(&reset_credentials_cb_).Run(success); | 539 base::ResetAndReturn(&reset_credentials_cb_).Run(success); |
| 664 } | 540 } |
| 665 | 541 |
| 666 } // namespace media | 542 } // namespace media |
| OLD | NEW |