diff options
author | gunsch <gunsch@chromium.org> | 2015-04-29 20:58:45 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-30 03:59:13 +0000 |
commit | 2288c539cc227ec262be28c4b684ff38527f7768 (patch) | |
tree | 12cf88619fe8fbc979a2f0aa1f0722ff2741a500 /media | |
parent | d92456f94d7d2563f3b1bd46e6b77d9c9eadd633 (diff) | |
download | chromium_src-2288c539cc227ec262be28c4b684ff38527f7768.zip chromium_src-2288c539cc227ec262be28c4b684ff38527f7768.tar.gz chromium_src-2288c539cc227ec262be28c4b684ff38527f7768.tar.bz2 |
Adds MediaClientAndroid to support embedder/MediaDrmBridge interaction.
This CL does a few things:
* Adds a MediaDrmBridgeDelegate interface to support per DRM-scheme logic for Android in MediaDrmBridge.
* Adds a MediaClientAndroid interface for embedders to provide MediaDrmBridgeDelegate implementations and key-system-UUID mappings
* Removes the Java-based key-system-UUID mapping path
* Embedders no longer call directly into MediaDrmBridge
R=qinmin@chromium.org,xhwang@chromium.org,boliu@chromium.org,jochen@chromium.org
BUG=462443
Review URL: https://codereview.chromium.org/962793005
Cr-Commit-Position: refs/heads/master@{#327650}
Diffstat (limited to 'media')
-rw-r--r-- | media/base/android/BUILD.gn | 4 | ||||
-rw-r--r-- | media/base/android/java/src/org/chromium/media/MediaDrmBridge.java | 71 | ||||
-rw-r--r-- | media/base/android/media_client_android.cc | 37 | ||||
-rw-r--r-- | media/base/android/media_client_android.h | 59 | ||||
-rw-r--r-- | media/base/android/media_drm_bridge.cc | 212 | ||||
-rw-r--r-- | media/base/android/media_drm_bridge_delegate.cc | 27 | ||||
-rw-r--r-- | media/base/android/media_drm_bridge_delegate.h | 46 | ||||
-rw-r--r-- | media/media.gyp | 4 |
8 files changed, 268 insertions, 192 deletions
diff --git a/media/base/android/BUILD.gn b/media/base/android/BUILD.gn index 6108389..c407b17 100644 --- a/media/base/android/BUILD.gn +++ b/media/base/android/BUILD.gn @@ -19,12 +19,16 @@ source_set("android") { "demuxer_android.h", "demuxer_stream_player_params.cc", "demuxer_stream_player_params.h", + "media_client_android.cc", + "media_client_android.h", "media_codec_bridge.cc", "media_codec_bridge.h", "media_decoder_job.cc", "media_decoder_job.h", "media_drm_bridge.cc", "media_drm_bridge.h", + "media_drm_bridge_delegate.cc", + "media_drm_bridge_delegate.h", "media_jni_registrar.cc", "media_jni_registrar.h", "media_player_android.cc", diff --git a/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java b/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java index 8f32ccb..9d49232 100644 --- a/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java +++ b/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java @@ -22,7 +22,6 @@ import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.util.ArrayDeque; import java.util.Arrays; import java.util.HashMap; @@ -107,11 +106,14 @@ public class MediaDrmBridge { private static class PendingCreateSessionData { private final byte[] mInitData; private final String mMimeType; + private final HashMap<String, String> mOptionalParameters; private final long mPromiseId; - private PendingCreateSessionData(byte[] initData, String mimeType, long promiseId) { + private PendingCreateSessionData(byte[] initData, String mimeType, + HashMap<String, String> optionalParameters, long promiseId) { mInitData = initData; mMimeType = mimeType; + mOptionalParameters = optionalParameters; mPromiseId = promiseId; } @@ -123,6 +125,10 @@ public class MediaDrmBridge { return mMimeType; } + private HashMap<String, String> optionalParameters() { + return mOptionalParameters; + } + private long promiseId() { return mPromiseId; } @@ -410,16 +416,20 @@ public class MediaDrmBridge { * @param sessionId ID of session on which we need to get the key request. * @param data Data needed to get the key request. * @param mime Mime type to get the key request. + * @param optionalParameters Optional parameters to pass to the DRM plugin. * * @return the key request. */ - private MediaDrm.KeyRequest getKeyRequest(byte[] sessionId, byte[] data, String mime) + private MediaDrm.KeyRequest getKeyRequest( + byte[] sessionId, byte[] data, String mime, HashMap<String, String> optionalParameters) throws android.media.NotProvisionedException { assert mMediaDrm != null; assert mMediaCrypto != null; assert !mProvisioningPending; - HashMap<String, String> optionalParameters = new HashMap<String, String>(); + if (optionalParameters == null) { + optionalParameters = new HashMap<String, String>(); + } MediaDrm.KeyRequest request = mMediaDrm.getKeyRequest( sessionId, data, mime, MediaDrm.KEY_TYPE_STREAMING, optionalParameters); String result = (request != null) ? "successed" : "failed"; @@ -433,12 +443,14 @@ public class MediaDrmBridge { * * @param initData Data needed to generate the key request. * @param mime Mime type. + * @param optionalParameters Optional parameters to pass to the DRM plugin. * @param promiseId Promise ID for the createSession() call. */ - private void savePendingCreateSessionData(byte[] initData, String mime, long promiseId) { + private void savePendingCreateSessionData(byte[] initData, String mime, + HashMap<String, String> optionalParameters, long promiseId) { Log.d(TAG, "savePendingCreateSessionData()"); mPendingCreateSessionDataQueue.offer( - new PendingCreateSessionData(initData, mime, promiseId)); + new PendingCreateSessionData(initData, mime, optionalParameters, promiseId)); } /** @@ -456,8 +468,9 @@ public class MediaDrmBridge { PendingCreateSessionData pendingData = mPendingCreateSessionDataQueue.poll(); byte[] initData = pendingData.initData(); String mime = pendingData.mimeType(); + HashMap<String, String> optionalParameters = pendingData.optionalParameters(); long promiseId = pendingData.promiseId(); - createSession(initData, mime, promiseId); + createSession(initData, mime, optionalParameters, promiseId); } } @@ -474,14 +487,35 @@ public class MediaDrmBridge { } /** + * createSession interface to be called from native using primitive types. + * @see createSession(byte[], String, HashMap<String, String>, long) + */ + @CalledByNative + private void createSessionFromNative( + byte[] initData, String mime, String[] optionalParamsArray, long promiseId) { + HashMap<String, String> optionalParameters = new HashMap<String, String>(); + if (optionalParamsArray != null) { + if (optionalParamsArray.length % 2 != 0) { + throw new IllegalArgumentException( + "Additional data array doesn't have equal keys/values"); + } + for (int i = 0; i < optionalParamsArray.length; i += 2) { + optionalParameters.put(optionalParamsArray[i], optionalParamsArray[i + 1]); + } + } + createSession(initData, mime, optionalParameters, promiseId); + } + + /** * Create a session, and generate a request with |initData| and |mime|. * * @param initData Data needed to generate the key request. * @param mime Mime type. + * @param optionalParameters Additional data to pass to getKeyRequest. * @param promiseId Promise ID for this call. */ - @CalledByNative - private void createSession(byte[] initData, String mime, long promiseId) { + private void createSession(byte[] initData, String mime, + HashMap<String, String> optionalParameters, long promiseId) { Log.d(TAG, "createSession()"); if (mMediaDrm == null) { Log.e(TAG, "createSession() called when MediaDrm is null."); @@ -490,7 +524,7 @@ public class MediaDrmBridge { if (mProvisioningPending) { assert mMediaCrypto == null; - savePendingCreateSessionData(initData, mime, promiseId); + savePendingCreateSessionData(initData, mime, optionalParameters, promiseId); return; } @@ -514,7 +548,7 @@ public class MediaDrmBridge { assert !sessionExists(sessionId); MediaDrm.KeyRequest request = null; - request = getKeyRequest(sessionId, initData, mime); + request = getKeyRequest(sessionId, initData, mime, optionalParameters); if (request == null) { mMediaDrm.closeSession(sessionId); onPromiseRejected(promiseId, "Generate request failed."); @@ -531,7 +565,7 @@ public class MediaDrmBridge { if (newSessionOpened) { mMediaDrm.closeSession(sessionId); } - savePendingCreateSessionData(initData, mime, promiseId); + savePendingCreateSessionData(initData, mime, optionalParameters, promiseId); startProvisioning(); } } @@ -832,7 +866,7 @@ public class MediaDrmBridge { String mime = mSessionIds.get(ByteBuffer.wrap(sessionId)); MediaDrm.KeyRequest request = null; try { - request = getKeyRequest(sessionId, data, mime); + request = getKeyRequest(sessionId, data, mime, null); } catch (android.media.NotProvisionedException e) { Log.e(TAG, "Device not provisioned", e); startProvisioning(); @@ -933,15 +967,6 @@ public class MediaDrmBridge { } } - public static void addKeySystemUuidMapping(String keySystem, UUID uuid) { - ByteBuffer uuidBuffer = ByteBuffer.allocateDirect(16); - // MSB (byte) should be positioned at the first element. - uuidBuffer.order(ByteOrder.BIG_ENDIAN); - uuidBuffer.putLong(uuid.getMostSignificantBits()); - uuidBuffer.putLong(uuid.getLeastSignificantBits()); - nativeAddKeySystemUuidMapping(keySystem, uuidBuffer); - } - private native void nativeOnMediaCryptoReady(long nativeMediaDrmBridge); private native void nativeOnPromiseResolved(long nativeMediaDrmBridge, long promiseId); @@ -960,6 +985,4 @@ public class MediaDrmBridge { private native void nativeOnResetDeviceCredentialsCompleted( long nativeMediaDrmBridge, boolean success); - - private static native void nativeAddKeySystemUuidMapping(String keySystem, ByteBuffer uuid); } diff --git a/media/base/android/media_client_android.cc b/media/base/android/media_client_android.cc new file mode 100644 index 0000000..ad4e11b --- /dev/null +++ b/media/base/android/media_client_android.cc @@ -0,0 +1,37 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/android/media_client_android.h" + +#include "base/logging.h" +#include "base/stl_util.h" + +namespace media { + +static MediaClientAndroid* g_media_client = nullptr; + +void SetMediaClientAndroid(MediaClientAndroid* media_client) { + DCHECK(!g_media_client); + g_media_client = media_client; +} + +MediaClientAndroid* GetMediaClientAndroid() { + return g_media_client; +} + +MediaClientAndroid::MediaClientAndroid() { +} + +MediaClientAndroid::~MediaClientAndroid() { +} + +void MediaClientAndroid::AddKeySystemUUIDMappings(KeySystemUuidMap* map) { +} + +media::MediaDrmBridgeDelegate* MediaClientAndroid::GetMediaDrmBridgeDelegate( + const std::vector<uint8_t>& scheme_uuid) { + return nullptr; +} + +} // namespace media diff --git a/media/base/android/media_client_android.h b/media/base/android/media_client_android.h new file mode 100644 index 0000000..0753b3b --- /dev/null +++ b/media/base/android/media_client_android.h @@ -0,0 +1,59 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_ANDROID_MEDIA_CLIENT_ANDROID_H_ +#define MEDIA_BASE_ANDROID_MEDIA_CLIENT_ANDROID_H_ + +#include <string> +#include <utility> +#include <vector> + +#include "base/containers/hash_tables.h" +#include "base/macros.h" +#include "media/base/media_export.h" + +namespace media { + +class MediaClientAndroid; +class MediaDrmBridgeDelegate; + +// Setter for MediaClientAndroid. This should be called early in embedder +// lifecycle, before any media playback could occur. +MEDIA_EXPORT void SetMediaClientAndroid(MediaClientAndroid* media_client); + +#if defined(MEDIA_IMPLEMENTATION) +// Getter for the client. Returns nullptr if no customized client is needed. +MediaClientAndroid* GetMediaClientAndroid(); +#endif + +using UUID = std::vector<uint8_t>; + +// A client interface for embedders (e.g. content/browser) to provide customized +// additions to Android's browser-side media handling. +class MEDIA_EXPORT MediaClientAndroid { + public: + typedef base::hash_map<std::string, UUID> KeySystemUuidMap; + + MediaClientAndroid(); + virtual ~MediaClientAndroid(); + + // Adds extra mappings from key-system name to Android UUID into |map|. + virtual void AddKeySystemUUIDMappings(KeySystemUuidMap* map); + + // Returns a MediaDrmBridgeDelegate that corresponds to |scheme_uuid|. + // MediaClientAndroid retains ownership. + virtual media::MediaDrmBridgeDelegate* GetMediaDrmBridgeDelegate( + const UUID& scheme_uuid); + + private: + friend class KeySystemManager; + + base::hash_map<std::string, UUID> key_system_uuid_map_; + + DISALLOW_COPY_AND_ASSIGN(MediaClientAndroid); +}; + +} // namespace media + +#endif // MEDIA_BASE_ANDROID_MEDIA_CLIENT_ANDROID_H_ diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc index 0aaeef4..79f7d42 100644 --- a/media/base/android/media_drm_bridge.cc +++ b/media/base/android/media_drm_bridge.cc @@ -15,12 +15,13 @@ #include "base/location.h" #include "base/logging.h" #include "base/message_loop/message_loop_proxy.h" -#include "base/numerics/safe_conversions.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/sys_byteorder.h" #include "base/sys_info.h" #include "jni/MediaDrmBridge_jni.h" +#include "media/base/android/media_client_android.h" +#include "media/base/android/media_drm_bridge_delegate.h" #include "media/base/cdm_key_information.h" #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. @@ -40,20 +41,6 @@ namespace { // here to report session expiration info. const char kDummyKeyId[] = "Dummy Key Id"; -uint32 ReadUint32(const uint8_t* data) { - uint32 value = 0; - for (int i = 0; i < 4; ++i) - value = (value << 8) | data[i]; - return value; -} - -uint64 ReadUint64(const uint8_t* data) { - uint64 value = 0; - for (int i = 0; i < 8; ++i) - value = (value << 8) | data[i]; - return value; -} - // Returns string session ID from jbyteArray (byte[] in Java). std::string GetSessionId(JNIEnv* env, jbyteArray j_session_id) { std::vector<uint8> session_id_vector; @@ -61,116 +48,10 @@ std::string GetSessionId(JNIEnv* env, jbyteArray j_session_id) { return std::string(session_id_vector.begin(), session_id_vector.end()); } -// The structure of an ISO CENC Protection System Specific Header (PSSH) box is -// as follows. (See ISO/IEC FDIS 23001-7:2011(E).) -// Note: ISO boxes use big-endian values. -// -// PSSH { -// uint32 Size -// uint32 Type -// uint64 LargeSize # Field is only present if value(Size) == 1. -// uint32 VersionAndFlags -// uint8[16] SystemId -// uint32 DataSize -// uint8[DataSize] Data -// } -const int kBoxHeaderSize = 8; // Box's header contains Size and Type. -const int kBoxLargeSizeSize = 8; -const int kPsshVersionFlagSize = 4; -const int kPsshSystemIdSize = 16; -const int kPsshDataSizeSize = 4; -const uint32 kTencType = 0x74656e63; -const uint32 kPsshType = 0x70737368; const uint8 kWidevineUuid[16] = { 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; -typedef std::vector<uint8> UUID; - -// Tries to find a PSSH box whose "SystemId" is |uuid| in |data|, parses the -// "Data" of the box and put it in |pssh_data|. Returns true if such a box is -// found and successfully parsed. Returns false otherwise. -// Notes: -// 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box -// will be set in |pssh_data|. -// 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped. -bool GetPsshData(const std::vector<uint8_t>& data, - const UUID& uuid, - std::vector<uint8>* pssh_data) { - int bytes_left = base::checked_cast<int>(data.size()); - const uint8_t* cur = &data[0]; - const uint8_t* data_end = cur + bytes_left; - - while (bytes_left > 0) { - const uint8* box_head = cur; - - if (bytes_left < kBoxHeaderSize) - return false; - - uint64_t box_size = ReadUint32(cur); - uint32 type = ReadUint32(cur + 4); - cur += kBoxHeaderSize; - bytes_left -= kBoxHeaderSize; - - if (box_size == 1) { // LargeSize is present. - if (bytes_left < kBoxLargeSizeSize) - return false; - - box_size = ReadUint64(cur); - cur += kBoxLargeSizeSize; - bytes_left -= kBoxLargeSizeSize; - } else if (box_size == 0) { - box_size = bytes_left + kBoxHeaderSize; - } - - const uint8* box_end = box_head + box_size; - if (data_end < box_end) - return false; - - if (type == kTencType) { - // Skip 'tenc' box. - cur = box_end; - bytes_left = data_end - cur; - continue; - } else if (type != kPsshType) { - return false; - } - - const int kPsshBoxMinimumSize = - kPsshVersionFlagSize + kPsshSystemIdSize + kPsshDataSizeSize; - if (box_end < cur + kPsshBoxMinimumSize) - return false; - - uint32 version_and_flags = ReadUint32(cur); - cur += kPsshVersionFlagSize; - bytes_left -= kPsshVersionFlagSize; - if (version_and_flags != 0) - return false; - - DCHECK_GE(bytes_left, kPsshSystemIdSize); - if (!std::equal(uuid.begin(), uuid.end(), cur)) { - cur = box_end; - bytes_left = data_end - cur; - continue; - } - - cur += kPsshSystemIdSize; - bytes_left -= kPsshSystemIdSize; - - uint32 data_size = ReadUint32(cur); - cur += kPsshDataSizeSize; - bytes_left -= kPsshDataSizeSize; - - if (box_end < cur + data_size) - return false; - - pssh_data->assign(cur, cur + data_size); - return true; - } - - return false; -} - // Convert |init_data_type| to a string supported by MediaDRM. // "audio"/"video" does not matter, so use "video". std::string ConvertInitDataType(media::EmeInitDataType init_data_type) { @@ -187,45 +68,37 @@ std::string ConvertInitDataType(media::EmeInitDataType init_data_type) { } } -class KeySystemUuidManager { +class KeySystemManager { public: - KeySystemUuidManager(); + KeySystemManager(); UUID GetUUID(const std::string& key_system); - void AddMapping(const std::string& key_system, const UUID& uuid); std::vector<std::string> GetPlatformKeySystemNames(); private: - typedef base::hash_map<std::string, UUID> KeySystemUuidMap; + using KeySystemUuidMap = MediaClientAndroid::KeySystemUuidMap; KeySystemUuidMap key_system_uuid_map_; - DISALLOW_COPY_AND_ASSIGN(KeySystemUuidManager); + DISALLOW_COPY_AND_ASSIGN(KeySystemManager); }; -KeySystemUuidManager::KeySystemUuidManager() { +KeySystemManager::KeySystemManager() { // Widevine is always supported in Android. key_system_uuid_map_[kWidevineKeySystem] = UUID(kWidevineUuid, kWidevineUuid + arraysize(kWidevineUuid)); + MediaClientAndroid* client = GetMediaClientAndroid(); + if (client) + client->AddKeySystemUUIDMappings(&key_system_uuid_map_); } -UUID KeySystemUuidManager::GetUUID(const std::string& key_system) { +UUID KeySystemManager::GetUUID(const std::string& key_system) { KeySystemUuidMap::iterator it = key_system_uuid_map_.find(key_system); if (it == key_system_uuid_map_.end()) return UUID(); return it->second; } -void KeySystemUuidManager::AddMapping(const std::string& key_system, - const UUID& uuid) { - KeySystemUuidMap::iterator it = key_system_uuid_map_.find(key_system); - DCHECK(it == key_system_uuid_map_.end()) - << "Shouldn't overwrite an existing key system."; - if (it != key_system_uuid_map_.end()) - return; - key_system_uuid_map_[key_system] = uuid; -} - -std::vector<std::string> KeySystemUuidManager::GetPlatformKeySystemNames() { +std::vector<std::string> KeySystemManager::GetPlatformKeySystemNames() { std::vector<std::string> key_systems; for (KeySystemUuidMap::iterator it = key_system_uuid_map_.begin(); it != key_system_uuid_map_.end(); ++it) { @@ -236,7 +109,7 @@ std::vector<std::string> KeySystemUuidManager::GetPlatformKeySystemNames() { return key_systems; } -base::LazyInstance<KeySystemUuidManager>::Leaky g_key_system_uuid_manager = +base::LazyInstance<KeySystemManager>::Leaky g_key_system_manager = LAZY_INSTANCE_INITIALIZER; // Checks whether |key_system| is supported with |container_mime_type|. Only @@ -249,7 +122,7 @@ bool IsKeySystemSupportedWithTypeImpl(const std::string& key_system, if (!MediaDrmBridge::IsAvailable()) return false; - UUID scheme_uuid = g_key_system_uuid_manager.Get().GetUUID(key_system); + UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system); if (scheme_uuid.empty()) return false; @@ -287,17 +160,6 @@ std::string GetSecurityLevelString( } // namespace -// Called by Java. -static void AddKeySystemUuidMapping(JNIEnv* env, - jclass clazz, - jstring j_key_system, - jobject j_buffer) { - std::string key_system = ConvertJavaStringToUTF8(env, j_key_system); - uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer)); - UUID uuid(buffer, buffer + 16); - g_key_system_uuid_manager.Get().AddMapping(key_system, uuid); -} - // static bool MediaDrmBridge::IsAvailable() { if (base::android::BuildInfo::GetInstance()->sdk_int() < 19) @@ -324,7 +186,7 @@ bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) { // static std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() { - return g_key_system_uuid_manager.Get().GetPlatformKeySystemNames(); + return g_key_system_manager.Get().GetPlatformKeySystemNames(); } // static @@ -385,7 +247,7 @@ scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create( if (!IsAvailable()) return media_drm_bridge.Pass(); - UUID scheme_uuid = g_key_system_uuid_manager.Get().GetUUID(key_system); + UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system); if (scheme_uuid.empty()) return media_drm_bridge.Pass(); @@ -449,19 +311,31 @@ void MediaDrmBridge::CreateSessionAndGenerateRequest( JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jbyteArray> j_init_data; - - // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as - // the init data when using MP4 container. - if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid) && - init_data_type == media::EmeInitDataType::CENC) { - std::vector<uint8> pssh_data; - if (!GetPsshData(init_data, scheme_uuid_, &pssh_data)) { - promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid PSSH data."); - return; + ScopedJavaLocalRef<jobjectArray> j_optional_parameters; + + MediaClientAndroid* client = GetMediaClientAndroid(); + if (client) { + MediaDrmBridgeDelegate* delegate = + client->GetMediaDrmBridgeDelegate(scheme_uuid_); + if (delegate) { + std::vector<uint8> init_data_from_delegate; + std::vector<std::string> optional_parameters_from_delegate; + if (!delegate->OnCreateSession(init_data_type, init_data, + &init_data_from_delegate, + &optional_parameters_from_delegate)) { + promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid init data."); + } + j_init_data = base::android::ToJavaByteArray( + env, vector_as_array(&init_data_from_delegate), + init_data_from_delegate.size()); + if (!optional_parameters_from_delegate.empty()) { + j_optional_parameters = base::android::ToJavaArrayOfStrings( + env, optional_parameters_from_delegate); + } } - j_init_data = base::android::ToJavaByteArray( - env, vector_as_array(&pssh_data), pssh_data.size()); - } else { + } + + if (j_init_data.is_null()) { j_init_data = base::android::ToJavaByteArray( env, vector_as_array(&init_data), init_data.size()); } @@ -469,8 +343,10 @@ void MediaDrmBridge::CreateSessionAndGenerateRequest( ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, ConvertInitDataType(init_data_type)); uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); - Java_MediaDrmBridge_createSession(env, j_media_drm_.obj(), j_init_data.obj(), - j_mime.obj(), promise_id); + Java_MediaDrmBridge_createSessionFromNative(env, j_media_drm_.obj(), + j_init_data.obj(), j_mime.obj(), + j_optional_parameters.obj(), + promise_id); } void MediaDrmBridge::LoadSession( diff --git a/media/base/android/media_drm_bridge_delegate.cc b/media/base/android/media_drm_bridge_delegate.cc new file mode 100644 index 0000000..5630d4a --- /dev/null +++ b/media/base/android/media_drm_bridge_delegate.cc @@ -0,0 +1,27 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/android/media_drm_bridge_delegate.h" + +#include "base/logging.h" + +namespace media { + +MediaDrmBridgeDelegate::MediaDrmBridgeDelegate() { +} + +MediaDrmBridgeDelegate::~MediaDrmBridgeDelegate() { +} + +bool MediaDrmBridgeDelegate::OnCreateSession( + const EmeInitDataType init_data_type, + const std::vector<uint8_t>& init_data, + std::vector<uint8_t>* init_data_out, + std::vector<std::string>* optional_parameters_out) { + DCHECK(init_data_out->empty()); + DCHECK(optional_parameters_out->empty()); + return true; +} + +} // namespace media diff --git a/media/base/android/media_drm_bridge_delegate.h b/media/base/android/media_drm_bridge_delegate.h new file mode 100644 index 0000000..7a18dac --- /dev/null +++ b/media/base/android/media_drm_bridge_delegate.h @@ -0,0 +1,46 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_ANDROID_MEDIA_DRM_BRIDGE_DELEGATE_H_ +#define MEDIA_BASE_ANDROID_MEDIA_DRM_BRIDGE_DELEGATE_H_ + +#include <string> +#include <vector> + +#include "base/macros.h" +#include "media/base/android/media_client_android.h" +#include "media/base/eme_constants.h" +#include "media/base/media_export.h" + +namespace media { + +// Allows embedders to modify the Android MediaDrm flow. Delegates are +// registered to a specific key system. +class MEDIA_EXPORT MediaDrmBridgeDelegate { + public: + MediaDrmBridgeDelegate(); + virtual ~MediaDrmBridgeDelegate(); + + // Returns the UUID of the DRM scheme that this delegate applies to. + virtual const UUID GetUUID() const = 0; + + // Invoked from CreateSession. + // If |init_data_out| is filled, it replaces |init_data| to send to the + // MediaDrm instance. + // If |optional_parameters_out| is filled, it is expected to be an + // even-length list of (key, value) pairs to send to the MediaDrm instance. + // Returns false if the request should be rejected. + virtual bool OnCreateSession( + const EmeInitDataType init_data_type, + const std::vector<uint8_t>& init_data, + std::vector<uint8_t>* init_data_out, + std::vector<std::string>* optional_parameters_out); + + private: + DISALLOW_COPY_AND_ASSIGN(MediaDrmBridgeDelegate); +}; + +} // namespace media + +#endif // MEDIA_BASE_ANDROID_MEDIA_DRM_BRIDGE_DELEGATE_H_ diff --git a/media/media.gyp b/media/media.gyp index e530e90..c228c83 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -1739,6 +1739,8 @@ 'base/android/demuxer_android.h', 'base/android/demuxer_stream_player_params.cc', 'base/android/demuxer_stream_player_params.h', + 'base/android/media_client_android.cc', + 'base/android/media_client_android.h', 'base/android/media_codec_bridge.cc', 'base/android/media_codec_bridge.h', 'base/android/media_common_android.h', @@ -1746,6 +1748,8 @@ 'base/android/media_decoder_job.h', 'base/android/media_drm_bridge.cc', 'base/android/media_drm_bridge.h', + 'base/android/media_drm_bridge_delegate.cc', + 'base/android/media_drm_bridge_delegate.h', 'base/android/media_jni_registrar.cc', 'base/android/media_jni_registrar.h', 'base/android/media_player_android.cc', |