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/location.h" | 13 #include "base/location.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/message_loop/message_loop_proxy.h" | 15 #include "base/message_loop/message_loop_proxy.h" |
16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
17 #include "jni/MediaDrmBridge_jni.h" | 17 #include "jni/MediaDrmBridge_jni.h" |
18 #include "media/base/android/media_player_manager.h" | |
19 | 18 |
20 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. | 19 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
21 | 20 |
22 using base::android::AttachCurrentThread; | 21 using base::android::AttachCurrentThread; |
23 using base::android::ConvertUTF8ToJavaString; | 22 using base::android::ConvertUTF8ToJavaString; |
24 using base::android::ConvertJavaStringToUTF8; | 23 using base::android::ConvertJavaStringToUTF8; |
25 using base::android::JavaByteArrayToByteVector; | 24 using base::android::JavaByteArrayToByteVector; |
26 using base::android::ScopedJavaLocalRef; | 25 using base::android::ScopedJavaLocalRef; |
27 | 26 |
28 namespace media { | 27 namespace media { |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 DCHECK(IsAvailable()); | 215 DCHECK(IsAvailable()); |
217 return SECURITY_LEVEL_1 == security_level; | 216 return SECURITY_LEVEL_1 == security_level; |
218 } | 217 } |
219 | 218 |
220 // static | 219 // static |
221 bool MediaDrmBridge::IsSecurityLevelSupported(const std::string& key_system, | 220 bool MediaDrmBridge::IsSecurityLevelSupported(const std::string& key_system, |
222 SecurityLevel security_level) { | 221 SecurityLevel security_level) { |
223 if (!IsAvailable()) | 222 if (!IsAvailable()) |
224 return false; | 223 return false; |
225 | 224 |
226 // Pass 0 as |cdm_id| and NULL as |manager| as they are not used in | |
227 // creation time of MediaDrmBridge. | |
228 scoped_ptr<MediaDrmBridge> media_drm_bridge = | 225 scoped_ptr<MediaDrmBridge> media_drm_bridge = |
229 MediaDrmBridge::Create(0, key_system, GURL(), NULL); | 226 MediaDrmBridge::CreateSessionless(key_system); |
230 if (!media_drm_bridge) | 227 if (!media_drm_bridge) |
231 return false; | 228 return false; |
232 | 229 |
233 return media_drm_bridge->SetSecurityLevel(security_level); | 230 return media_drm_bridge->SetSecurityLevel(security_level); |
234 } | 231 } |
235 | 232 |
236 // static | 233 // static |
237 bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) { | 234 bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) { |
238 DCHECK(!key_system.empty()); | 235 DCHECK(!key_system.empty()); |
239 return IsKeySystemSupportedWithTypeImpl(key_system, ""); | 236 return IsKeySystemSupportedWithTypeImpl(key_system, ""); |
240 } | 237 } |
241 | 238 |
242 // static | 239 // static |
243 bool MediaDrmBridge::IsKeySystemSupportedWithType( | 240 bool MediaDrmBridge::IsKeySystemSupportedWithType( |
244 const std::string& key_system, | 241 const std::string& key_system, |
245 const std::string& container_mime_type) { | 242 const std::string& container_mime_type) { |
246 DCHECK(!key_system.empty() && !container_mime_type.empty()); | 243 DCHECK(!key_system.empty() && !container_mime_type.empty()); |
247 return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type); | 244 return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type); |
248 } | 245 } |
249 | 246 |
250 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) { | 247 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) { |
251 return RegisterNativesImpl(env); | 248 return RegisterNativesImpl(env); |
252 } | 249 } |
253 | 250 |
254 MediaDrmBridge::MediaDrmBridge(int cdm_id, | 251 MediaDrmBridge::MediaDrmBridge(const std::vector<uint8>& scheme_uuid, |
255 const std::vector<uint8>& scheme_uuid, | 252 const SessionCreatedCB& session_created_cb, |
256 const GURL& security_origin, | 253 const SessionMessageCB& session_message_cb, |
257 MediaPlayerManager* manager) | 254 const SessionReadyCB& session_ready_cb, |
258 : cdm_id_(cdm_id), | 255 const SessionClosedCB& session_closed_cb, |
259 scheme_uuid_(scheme_uuid), | 256 const SessionErrorCB& session_error_cb) |
260 security_origin_(security_origin), | 257 : scheme_uuid_(scheme_uuid), |
261 manager_(manager) { | 258 session_created_cb_(session_created_cb), |
| 259 session_message_cb_(session_message_cb), |
| 260 session_ready_cb_(session_ready_cb), |
| 261 session_closed_cb_(session_closed_cb), |
| 262 session_error_cb_(session_error_cb) { |
262 JNIEnv* env = AttachCurrentThread(); | 263 JNIEnv* env = AttachCurrentThread(); |
263 CHECK(env); | 264 CHECK(env); |
264 | 265 |
265 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = | 266 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = |
266 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); | 267 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); |
267 j_media_drm_.Reset(Java_MediaDrmBridge_create( | 268 j_media_drm_.Reset(Java_MediaDrmBridge_create( |
268 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); | 269 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); |
269 } | 270 } |
270 | 271 |
271 MediaDrmBridge::~MediaDrmBridge() { | 272 MediaDrmBridge::~MediaDrmBridge() { |
272 JNIEnv* env = AttachCurrentThread(); | 273 JNIEnv* env = AttachCurrentThread(); |
273 if (!j_media_drm_.is_null()) | 274 if (!j_media_drm_.is_null()) |
274 Java_MediaDrmBridge_release(env, j_media_drm_.obj()); | 275 Java_MediaDrmBridge_release(env, j_media_drm_.obj()); |
275 } | 276 } |
276 | 277 |
277 // static | 278 // static |
278 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create(int cdm_id, | 279 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create( |
279 const std::string& key_system, | 280 const std::string& key_system, |
280 const GURL& security_origin, | 281 const SessionCreatedCB& session_created_cb, |
281 MediaPlayerManager* manager) { | 282 const SessionMessageCB& session_message_cb, |
| 283 const SessionReadyCB& session_ready_cb, |
| 284 const SessionClosedCB& session_closed_cb, |
| 285 const SessionErrorCB& session_error_cb) { |
282 scoped_ptr<MediaDrmBridge> media_drm_bridge; | 286 scoped_ptr<MediaDrmBridge> media_drm_bridge; |
283 if (!IsAvailable()) | 287 if (!IsAvailable()) |
284 return media_drm_bridge.Pass(); | 288 return media_drm_bridge.Pass(); |
285 | 289 |
286 std::vector<uint8> scheme_uuid = GetUUID(key_system); | 290 std::vector<uint8> scheme_uuid = GetUUID(key_system); |
287 if (scheme_uuid.empty()) | 291 if (scheme_uuid.empty()) |
288 return media_drm_bridge.Pass(); | 292 return media_drm_bridge.Pass(); |
289 | 293 |
290 media_drm_bridge.reset( | 294 media_drm_bridge.reset(new MediaDrmBridge(scheme_uuid, |
291 new MediaDrmBridge(cdm_id, scheme_uuid, security_origin, manager)); | 295 session_created_cb, |
| 296 session_message_cb, |
| 297 session_ready_cb, |
| 298 session_closed_cb, |
| 299 session_error_cb)); |
| 300 |
292 if (media_drm_bridge->j_media_drm_.is_null()) | 301 if (media_drm_bridge->j_media_drm_.is_null()) |
293 media_drm_bridge.reset(); | 302 media_drm_bridge.reset(); |
294 | 303 |
295 return media_drm_bridge.Pass(); | 304 return media_drm_bridge.Pass(); |
296 } | 305 } |
297 | 306 |
| 307 // static |
| 308 scoped_ptr<MediaDrmBridge> MediaDrmBridge::CreateSessionless( |
| 309 const std::string& key_system) { |
| 310 return MediaDrmBridge::Create(key_system, |
| 311 SessionCreatedCB(), |
| 312 SessionMessageCB(), |
| 313 SessionReadyCB(), |
| 314 SessionClosedCB(), |
| 315 SessionErrorCB()); |
| 316 } |
| 317 |
298 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { | 318 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { |
299 JNIEnv* env = AttachCurrentThread(); | 319 JNIEnv* env = AttachCurrentThread(); |
300 | 320 |
301 std::string security_level_str = GetSecurityLevelString(security_level); | 321 std::string security_level_str = GetSecurityLevelString(security_level); |
302 if (security_level_str.empty()) | 322 if (security_level_str.empty()) |
303 return false; | 323 return false; |
304 | 324 |
305 ScopedJavaLocalRef<jstring> j_security_level = | 325 ScopedJavaLocalRef<jstring> j_security_level = |
306 ConvertUTF8ToJavaString(env, security_level_str); | 326 ConvertUTF8ToJavaString(env, security_level_str); |
307 return Java_MediaDrmBridge_setSecurityLevel( | 327 return Java_MediaDrmBridge_setSecurityLevel( |
308 env, j_media_drm_.obj(), j_security_level.obj()); | 328 env, j_media_drm_.obj(), j_security_level.obj()); |
309 } | 329 } |
310 | 330 |
311 bool MediaDrmBridge::CreateSession(uint32 session_id, | 331 bool MediaDrmBridge::CreateSession(uint32 session_id, |
312 const std::string& content_type, | 332 const std::string& content_type, |
313 const uint8* init_data, | 333 const uint8* init_data, |
314 int init_data_length) { | 334 int init_data_length) { |
| 335 DVLOG(1) << __FUNCTION__; |
| 336 |
| 337 DCHECK(!session_created_cb_.is_null()) |
| 338 << "CreateSession called on a sessionless MediaDrmBridge object."; |
| 339 |
315 JNIEnv* env = AttachCurrentThread(); | 340 JNIEnv* env = AttachCurrentThread(); |
316 ScopedJavaLocalRef<jbyteArray> j_init_data; | 341 ScopedJavaLocalRef<jbyteArray> j_init_data; |
317 // Caller should always use "video/*" content types. | 342 // Caller should always use "video/*" content types. |
318 DCHECK_EQ(0u, content_type.find("video/")); | 343 DCHECK_EQ(0u, content_type.find("video/")); |
319 | 344 |
320 // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as | 345 // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as |
321 // the init data when using MP4 container. | 346 // the init data when using MP4 container. |
322 if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid) && | 347 if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid) && |
323 content_type == "video/mp4") { | 348 content_type == "video/mp4") { |
324 std::vector<uint8> pssh_data; | 349 std::vector<uint8> pssh_data; |
(...skipping 16 matching lines...) Expand all Loading... |
341 void MediaDrmBridge::LoadSession(uint32 session_id, | 366 void MediaDrmBridge::LoadSession(uint32 session_id, |
342 const std::string& web_session_id) { | 367 const std::string& web_session_id) { |
343 // MediaDrmBridge doesn't support loading sessions. | 368 // MediaDrmBridge doesn't support loading sessions. |
344 NOTREACHED(); | 369 NOTREACHED(); |
345 } | 370 } |
346 | 371 |
347 void MediaDrmBridge::UpdateSession(uint32 session_id, | 372 void MediaDrmBridge::UpdateSession(uint32 session_id, |
348 const uint8* response, | 373 const uint8* response, |
349 int response_length) { | 374 int response_length) { |
350 DVLOG(1) << __FUNCTION__; | 375 DVLOG(1) << __FUNCTION__; |
| 376 |
| 377 DCHECK(!session_ready_cb_.is_null()) |
| 378 << __FUNCTION__ << " called on a sessionless MediaDrmBridge object."; |
| 379 |
351 JNIEnv* env = AttachCurrentThread(); | 380 JNIEnv* env = AttachCurrentThread(); |
352 ScopedJavaLocalRef<jbyteArray> j_response = | 381 ScopedJavaLocalRef<jbyteArray> j_response = |
353 base::android::ToJavaByteArray(env, response, response_length); | 382 base::android::ToJavaByteArray(env, response, response_length); |
354 Java_MediaDrmBridge_updateSession( | 383 Java_MediaDrmBridge_updateSession( |
355 env, j_media_drm_.obj(), session_id, j_response.obj()); | 384 env, j_media_drm_.obj(), session_id, j_response.obj()); |
356 } | 385 } |
357 | 386 |
358 void MediaDrmBridge::ReleaseSession(uint32 session_id) { | 387 void MediaDrmBridge::ReleaseSession(uint32 session_id) { |
359 DVLOG(1) << __FUNCTION__; | 388 DVLOG(1) << __FUNCTION__; |
| 389 |
| 390 DCHECK(!session_closed_cb_.is_null()) |
| 391 << __FUNCTION__ << " called on a sessionless MediaDrmBridge object."; |
| 392 |
360 JNIEnv* env = AttachCurrentThread(); | 393 JNIEnv* env = AttachCurrentThread(); |
361 Java_MediaDrmBridge_releaseSession(env, j_media_drm_.obj(), session_id); | 394 Java_MediaDrmBridge_releaseSession(env, j_media_drm_.obj(), session_id); |
362 } | 395 } |
363 | 396 |
364 void MediaDrmBridge::SetMediaCryptoReadyCB(const base::Closure& closure) { | 397 void MediaDrmBridge::SetMediaCryptoReadyCB(const base::Closure& closure) { |
365 if (closure.is_null()) { | 398 if (closure.is_null()) { |
366 media_crypto_ready_cb_.Reset(); | 399 media_crypto_ready_cb_.Reset(); |
367 return; | 400 return; |
368 } | 401 } |
369 | 402 |
(...skipping 12 matching lines...) Expand all Loading... |
382 if (!media_crypto_ready_cb_.is_null()) | 415 if (!media_crypto_ready_cb_.is_null()) |
383 base::ResetAndReturn(&media_crypto_ready_cb_).Run(); | 416 base::ResetAndReturn(&media_crypto_ready_cb_).Run(); |
384 } | 417 } |
385 | 418 |
386 void MediaDrmBridge::OnSessionCreated(JNIEnv* env, | 419 void MediaDrmBridge::OnSessionCreated(JNIEnv* env, |
387 jobject j_media_drm, | 420 jobject j_media_drm, |
388 jint j_session_id, | 421 jint j_session_id, |
389 jstring j_web_session_id) { | 422 jstring j_web_session_id) { |
390 uint32 session_id = j_session_id; | 423 uint32 session_id = j_session_id; |
391 std::string web_session_id = ConvertJavaStringToUTF8(env, j_web_session_id); | 424 std::string web_session_id = ConvertJavaStringToUTF8(env, j_web_session_id); |
392 manager_->OnSessionCreated(cdm_id_, session_id, web_session_id); | 425 session_created_cb_.Run(session_id, web_session_id); |
393 } | 426 } |
394 | 427 |
395 void MediaDrmBridge::OnSessionMessage(JNIEnv* env, | 428 void MediaDrmBridge::OnSessionMessage(JNIEnv* env, |
396 jobject j_media_drm, | 429 jobject j_media_drm, |
397 jint j_session_id, | 430 jint j_session_id, |
398 jbyteArray j_message, | 431 jbyteArray j_message, |
399 jstring j_destination_url) { | 432 jstring j_destination_url) { |
400 uint32 session_id = j_session_id; | 433 uint32 session_id = j_session_id; |
401 std::vector<uint8> message; | 434 std::vector<uint8> message; |
402 JavaByteArrayToByteVector(env, j_message, &message); | 435 JavaByteArrayToByteVector(env, j_message, &message); |
403 std::string destination_url = ConvertJavaStringToUTF8(env, j_destination_url); | 436 std::string destination_url = ConvertJavaStringToUTF8(env, j_destination_url); |
404 GURL destination_gurl(destination_url); | 437 session_message_cb_.Run(session_id, message, destination_url); |
405 if (!destination_gurl.is_valid() && !destination_gurl.is_empty()) { | |
406 DLOG(WARNING) << "SessionMessage destination_url is invalid : " | |
407 << destination_gurl.possibly_invalid_spec(); | |
408 destination_gurl = GURL::EmptyGURL(); // Replace invalid destination_url. | |
409 } | |
410 | |
411 manager_->OnSessionMessage(cdm_id_, session_id, message, destination_gurl); | |
412 } | 438 } |
413 | 439 |
414 void MediaDrmBridge::OnSessionReady(JNIEnv* env, | 440 void MediaDrmBridge::OnSessionReady(JNIEnv* env, |
415 jobject j_media_drm, | 441 jobject j_media_drm, |
416 jint j_session_id) { | 442 jint j_session_id) { |
417 uint32 session_id = j_session_id; | 443 uint32 session_id = j_session_id; |
418 manager_->OnSessionReady(cdm_id_, session_id); | 444 session_ready_cb_.Run(session_id); |
419 } | 445 } |
420 | 446 |
421 void MediaDrmBridge::OnSessionClosed(JNIEnv* env, | 447 void MediaDrmBridge::OnSessionClosed(JNIEnv* env, |
422 jobject j_media_drm, | 448 jobject j_media_drm, |
423 jint j_session_id) { | 449 jint j_session_id) { |
424 uint32 session_id = j_session_id; | 450 uint32 session_id = j_session_id; |
425 manager_->OnSessionClosed(cdm_id_, session_id); | 451 session_closed_cb_.Run(session_id); |
426 } | 452 } |
427 | 453 |
428 void MediaDrmBridge::OnSessionError(JNIEnv* env, | 454 void MediaDrmBridge::OnSessionError(JNIEnv* env, |
429 jobject j_media_drm, | 455 jobject j_media_drm, |
430 jint j_session_id) { | 456 jint j_session_id) { |
431 uint32 session_id = j_session_id; | 457 uint32 session_id = j_session_id; |
432 manager_->OnSessionError(cdm_id_, session_id, MediaKeys::kUnknownError, 0); | 458 session_error_cb_.Run(session_id, MediaKeys::kUnknownError, 0); |
433 } | 459 } |
434 | 460 |
435 ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() { | 461 ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() { |
436 JNIEnv* env = AttachCurrentThread(); | 462 JNIEnv* env = AttachCurrentThread(); |
437 return Java_MediaDrmBridge_getMediaCrypto(env, j_media_drm_.obj()); | 463 return Java_MediaDrmBridge_getMediaCrypto(env, j_media_drm_.obj()); |
438 } | 464 } |
439 | 465 |
440 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() { | 466 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() { |
441 JNIEnv* env = AttachCurrentThread(); | 467 JNIEnv* env = AttachCurrentThread(); |
442 ScopedJavaLocalRef<jstring> j_security_level = | 468 ScopedJavaLocalRef<jstring> j_security_level = |
(...skipping 14 matching lines...) Expand all Loading... |
457 JNIEnv* env = AttachCurrentThread(); | 483 JNIEnv* env = AttachCurrentThread(); |
458 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); | 484 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); |
459 } | 485 } |
460 | 486 |
461 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( | 487 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( |
462 JNIEnv* env, jobject, bool success) { | 488 JNIEnv* env, jobject, bool success) { |
463 base::ResetAndReturn(&reset_credentials_cb_).Run(success); | 489 base::ResetAndReturn(&reset_credentials_cb_).Run(success); |
464 } | 490 } |
465 | 491 |
466 } // namespace media | 492 } // namespace media |
OLD | NEW |