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