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/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
19 #include "base/sys_byteorder.h" | 21 #include "base/sys_byteorder.h" |
20 #include "base/sys_info.h" | 22 #include "base/sys_info.h" |
21 #include "jni/MediaDrmBridge_jni.h" | 23 #include "jni/MediaDrmBridge_jni.h" |
22 #include "media/base/cdm_key_information.h" | 24 #include "media/base/cdm_key_information.h" |
23 | 25 |
24 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. | 26 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
25 | 27 |
26 using base::android::AttachCurrentThread; | 28 using base::android::AttachCurrentThread; |
27 using base::android::ConvertUTF8ToJavaString; | 29 using base::android::ConvertUTF8ToJavaString; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 | 87 |
86 typedef std::vector<uint8> UUID; | 88 typedef std::vector<uint8> UUID; |
87 | 89 |
88 // Tries to find a PSSH box whose "SystemId" is |uuid| in |data|, parses the | 90 // 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 | 91 // "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. | 92 // found and successfully parsed. Returns false otherwise. |
91 // Notes: | 93 // Notes: |
92 // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box | 94 // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box |
93 // will be set in |pssh_data|. | 95 // will be set in |pssh_data|. |
94 // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped. | 96 // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped. |
95 bool GetPsshData(const uint8* data, | 97 bool GetPsshData(const std::vector<uint8_t>& data, |
96 int data_size, | |
97 const UUID& uuid, | 98 const UUID& uuid, |
98 std::vector<uint8>* pssh_data) { | 99 std::vector<uint8>* pssh_data) { |
99 const uint8* cur = data; | 100 int bytes_left = base::checked_cast<int>(data.size()); |
100 const uint8* data_end = data + data_size; | 101 const uint8_t* cur = &data[0]; |
101 int bytes_left = data_size; | 102 const uint8_t* data_end = cur + bytes_left; |
102 | 103 |
103 while (bytes_left > 0) { | 104 while (bytes_left > 0) { |
104 const uint8* box_head = cur; | 105 const uint8* box_head = cur; |
105 | 106 |
106 if (bytes_left < kBoxHeaderSize) | 107 if (bytes_left < kBoxHeaderSize) |
107 return false; | 108 return false; |
108 | 109 |
109 uint64_t box_size = ReadUint32(cur); | 110 uint64_t box_size = ReadUint32(cur); |
110 uint32 type = ReadUint32(cur + 4); | 111 uint32 type = ReadUint32(cur + 4); |
111 cur += kBoxHeaderSize; | 112 cur += kBoxHeaderSize; |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 if (security_level_str.empty()) | 421 if (security_level_str.empty()) |
421 return false; | 422 return false; |
422 | 423 |
423 ScopedJavaLocalRef<jstring> j_security_level = | 424 ScopedJavaLocalRef<jstring> j_security_level = |
424 ConvertUTF8ToJavaString(env, security_level_str); | 425 ConvertUTF8ToJavaString(env, security_level_str); |
425 return Java_MediaDrmBridge_setSecurityLevel( | 426 return Java_MediaDrmBridge_setSecurityLevel( |
426 env, j_media_drm_.obj(), j_security_level.obj()); | 427 env, j_media_drm_.obj(), j_security_level.obj()); |
427 } | 428 } |
428 | 429 |
429 void MediaDrmBridge::SetServerCertificate( | 430 void MediaDrmBridge::SetServerCertificate( |
430 const uint8* certificate_data, | 431 const std::vector<uint8_t>& certificate, |
431 int certificate_data_length, | |
432 scoped_ptr<media::SimpleCdmPromise> promise) { | 432 scoped_ptr<media::SimpleCdmPromise> promise) { |
433 promise->reject(NOT_SUPPORTED_ERROR, 0, | 433 promise->reject(NOT_SUPPORTED_ERROR, 0, |
434 "SetServerCertificate() is not supported."); | 434 "SetServerCertificate() is not supported."); |
435 } | 435 } |
436 | 436 |
437 void MediaDrmBridge::CreateSessionAndGenerateRequest( | 437 void MediaDrmBridge::CreateSessionAndGenerateRequest( |
438 SessionType session_type, | 438 SessionType session_type, |
439 media::EmeInitDataType init_data_type, | 439 media::EmeInitDataType init_data_type, |
440 const uint8* init_data, | 440 const std::vector<uint8_t>& init_data, |
441 int init_data_length, | |
442 scoped_ptr<media::NewSessionCdmPromise> promise) { | 441 scoped_ptr<media::NewSessionCdmPromise> promise) { |
443 DVLOG(1) << __FUNCTION__; | 442 DVLOG(1) << __FUNCTION__; |
444 | 443 |
445 if (session_type != media::MediaKeys::TEMPORARY_SESSION) { | 444 if (session_type != media::MediaKeys::TEMPORARY_SESSION) { |
446 promise->reject(NOT_SUPPORTED_ERROR, 0, | 445 promise->reject(NOT_SUPPORTED_ERROR, 0, |
447 "Only the temporary session type is supported."); | 446 "Only the temporary session type is supported."); |
448 return; | 447 return; |
449 } | 448 } |
450 | 449 |
451 JNIEnv* env = AttachCurrentThread(); | 450 JNIEnv* env = AttachCurrentThread(); |
452 ScopedJavaLocalRef<jbyteArray> j_init_data; | 451 ScopedJavaLocalRef<jbyteArray> j_init_data; |
453 | 452 |
454 // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as | 453 // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as |
455 // the init data when using MP4 container. | 454 // the init data when using MP4 container. |
456 if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid) && | 455 if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid) && |
457 init_data_type == media::EmeInitDataType::CENC) { | 456 init_data_type == media::EmeInitDataType::CENC) { |
458 std::vector<uint8> pssh_data; | 457 std::vector<uint8> pssh_data; |
459 if (!GetPsshData(init_data, init_data_length, scheme_uuid_, &pssh_data)) { | 458 if (!GetPsshData(init_data, scheme_uuid_, &pssh_data)) { |
460 promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid PSSH data."); | 459 promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid PSSH data."); |
461 return; | 460 return; |
462 } | 461 } |
463 j_init_data = | 462 j_init_data = base::android::ToJavaByteArray( |
464 base::android::ToJavaByteArray(env, &pssh_data[0], pssh_data.size()); | 463 env, vector_as_array(&pssh_data), pssh_data.size()); |
465 } else { | 464 } else { |
466 j_init_data = | 465 j_init_data = base::android::ToJavaByteArray( |
467 base::android::ToJavaByteArray(env, init_data, init_data_length); | 466 env, vector_as_array(&init_data), init_data.size()); |
468 } | 467 } |
469 | 468 |
470 ScopedJavaLocalRef<jstring> j_mime = | 469 ScopedJavaLocalRef<jstring> j_mime = |
471 ConvertUTF8ToJavaString(env, ConvertInitDataType(init_data_type)); | 470 ConvertUTF8ToJavaString(env, ConvertInitDataType(init_data_type)); |
472 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); | 471 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); |
473 Java_MediaDrmBridge_createSession(env, j_media_drm_.obj(), j_init_data.obj(), | 472 Java_MediaDrmBridge_createSession(env, j_media_drm_.obj(), j_init_data.obj(), |
474 j_mime.obj(), promise_id); | 473 j_mime.obj(), promise_id); |
475 } | 474 } |
476 | 475 |
477 void MediaDrmBridge::LoadSession( | 476 void MediaDrmBridge::LoadSession( |
478 SessionType session_type, | 477 SessionType session_type, |
479 const std::string& session_id, | 478 const std::string& session_id, |
480 scoped_ptr<media::NewSessionCdmPromise> promise) { | 479 scoped_ptr<media::NewSessionCdmPromise> promise) { |
481 promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported."); | 480 promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported."); |
482 } | 481 } |
483 | 482 |
484 void MediaDrmBridge::UpdateSession( | 483 void MediaDrmBridge::UpdateSession( |
485 const std::string& session_id, | 484 const std::string& session_id, |
486 const uint8* response, | 485 const std::vector<uint8_t>& response, |
487 int response_length, | |
488 scoped_ptr<media::SimpleCdmPromise> promise) { | 486 scoped_ptr<media::SimpleCdmPromise> promise) { |
489 DVLOG(1) << __FUNCTION__; | 487 DVLOG(1) << __FUNCTION__; |
490 | 488 |
491 JNIEnv* env = AttachCurrentThread(); | 489 JNIEnv* env = AttachCurrentThread(); |
492 ScopedJavaLocalRef<jbyteArray> j_response = | 490 ScopedJavaLocalRef<jbyteArray> j_response = base::android::ToJavaByteArray( |
493 base::android::ToJavaByteArray(env, response, response_length); | 491 env, vector_as_array(&response), response.size()); |
494 ScopedJavaLocalRef<jbyteArray> j_session_id = base::android::ToJavaByteArray( | 492 ScopedJavaLocalRef<jbyteArray> j_session_id = base::android::ToJavaByteArray( |
495 env, reinterpret_cast<const uint8_t*>(session_id.data()), | 493 env, reinterpret_cast<const uint8_t*>(session_id.data()), |
496 session_id.size()); | 494 session_id.size()); |
497 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); | 495 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); |
498 Java_MediaDrmBridge_updateSession(env, j_media_drm_.obj(), j_session_id.obj(), | 496 Java_MediaDrmBridge_updateSession(env, j_media_drm_.obj(), j_session_id.obj(), |
499 j_response.obj(), promise_id); | 497 j_response.obj(), promise_id); |
500 } | 498 } |
501 | 499 |
502 void MediaDrmBridge::CloseSession(const std::string& session_id, | 500 void MediaDrmBridge::CloseSession(const std::string& session_id, |
503 scoped_ptr<media::SimpleCdmPromise> promise) { | 501 scoped_ptr<media::SimpleCdmPromise> promise) { |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 JNIEnv* env = AttachCurrentThread(); | 657 JNIEnv* env = AttachCurrentThread(); |
660 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); | 658 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); |
661 } | 659 } |
662 | 660 |
663 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( | 661 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( |
664 JNIEnv* env, jobject, bool success) { | 662 JNIEnv* env, jobject, bool success) { |
665 base::ResetAndReturn(&reset_credentials_cb_).Run(success); | 663 base::ResetAndReturn(&reset_credentials_cb_).Run(success); |
666 } | 664 } |
667 | 665 |
668 } // namespace media | 666 } // namespace media |
OLD | NEW |