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 /components | |
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 'components')
-rw-r--r-- | components/OWNERS | 4 | ||||
-rw-r--r-- | components/cdm.gypi | 2 | ||||
-rw-r--r-- | components/cdm/browser/BUILD.gn | 2 | ||||
-rw-r--r-- | components/cdm/browser/widevine_drm_delegate_android.cc | 163 | ||||
-rw-r--r-- | components/cdm/browser/widevine_drm_delegate_android.h | 32 |
5 files changed, 203 insertions, 0 deletions
diff --git a/components/OWNERS b/components/OWNERS index 9180998..86bc6db 100644 --- a/components/OWNERS +++ b/components/OWNERS @@ -25,6 +25,10 @@ per-file browsing_data.gypi=mkwst@chromium.org per-file browsing_data.gypi=bauerb@chromium.org per-file browsing_data.gypi=michaeln@chromium.org +per-file cdm.gypi=ddorwin@chromium.org +per-file cdm.gypi=scherkus@chromium.org +per-file cdm.gypi=xhwang@chromium.org + per-file cloud_devices*=gene@chromium.org per-file cloud_devices*=vitalybuka@chromium.org diff --git a/components/cdm.gypi b/components/cdm.gypi index d6f640a..853ff35 100644 --- a/components/cdm.gypi +++ b/components/cdm.gypi @@ -64,6 +64,8 @@ 'sources': [ 'cdm/browser/cdm_message_filter_android.cc', 'cdm/browser/cdm_message_filter_android.h', + 'cdm/browser/widevine_drm_delegate_android.cc', + 'cdm/browser/widevine_drm_delegate_android.h', ], }, ], diff --git a/components/cdm/browser/BUILD.gn b/components/cdm/browser/BUILD.gn index e18b670..cea393b 100644 --- a/components/cdm/browser/BUILD.gn +++ b/components/cdm/browser/BUILD.gn @@ -6,6 +6,8 @@ source_set("browser") { sources = [ "cdm_message_filter_android.cc", "cdm_message_filter_android.h", + "widevine_drm_delegate_android.cc", + "widevine_drm_delegate_android.h", ] deps = [ diff --git a/components/cdm/browser/widevine_drm_delegate_android.cc b/components/cdm/browser/widevine_drm_delegate_android.cc new file mode 100644 index 0000000..64b90bf --- /dev/null +++ b/components/cdm/browser/widevine_drm_delegate_android.cc @@ -0,0 +1,163 @@ +// 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 "components/cdm/browser/widevine_drm_delegate_android.h" + +#include "base/logging.h" +#include "base/numerics/safe_conversions.h" + +namespace cdm { + +namespace { + +uint32_t ReadUint32(const uint8_t* data) { + uint32_t value = 0; + for (int i = 0; i < 4; ++i) + value = (value << 8) | data[i]; + return value; +} + +uint64_t ReadUint64(const uint8_t* data) { + uint64_t value = 0; + for (int i = 0; i < 8; ++i) + value = (value << 8) | data[i]; + return value; +} + +// 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_t Size +// uint32_t Type +// uint64_t LargeSize # Field is only present if value(Size) == 1. +// uint32_t VersionAndFlags +// uint8_t[16] SystemId +// uint32_t DataSize +// uint8_t[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_t kTencType = 0x74656e63; +const uint32_t kPsshType = 0x70737368; + +const uint8_t kWidevineUuid[16] = { + 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, + 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED }; + +// Tries to find a PSSH box with the Widevine UUID, 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, + std::vector<uint8_t>* 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_t* box_head = cur; + + if (bytes_left < kBoxHeaderSize) + return false; + + uint64_t box_size = ReadUint32(cur); + uint32_t 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_t* 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_t 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(kWidevineUuid, + kWidevineUuid + sizeof(kWidevineUuid), cur)) { + cur = box_end; + bytes_left = data_end - cur; + continue; + } + + cur += kPsshSystemIdSize; + bytes_left -= kPsshSystemIdSize; + + uint32_t 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; +} + +} + +WidevineDrmDelegateAndroid::WidevineDrmDelegateAndroid() { +} + +WidevineDrmDelegateAndroid::~WidevineDrmDelegateAndroid() { +} + +const std::vector<uint8_t> WidevineDrmDelegateAndroid::GetUUID() const { + return std::vector<uint8_t>(kWidevineUuid, + kWidevineUuid + arraysize(kWidevineUuid)); +} + +bool WidevineDrmDelegateAndroid::OnCreateSession( + const media::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 */) { + if (init_data_type != media::EmeInitDataType::CENC) + return true; + + // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as + // the init data when using MP4 container. + return GetPsshData(init_data, init_data_out); +} + +} // namespace cdm diff --git a/components/cdm/browser/widevine_drm_delegate_android.h b/components/cdm/browser/widevine_drm_delegate_android.h new file mode 100644 index 0000000..09a54ae --- /dev/null +++ b/components/cdm/browser/widevine_drm_delegate_android.h @@ -0,0 +1,32 @@ +// 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 COMPONENTS_CDM_BROWSER_WIDEVINE_DRM_DELEGATE_ANDROID_H_ +#define COMPONENTS_CDM_BROWSER_WIDEVINE_DRM_DELEGATE_ANDROID_H_ + +#include "base/macros.h" +#include "media/base/android/media_drm_bridge_delegate.h" + +namespace cdm { + +class WidevineDrmDelegateAndroid : public media::MediaDrmBridgeDelegate { + public: + WidevineDrmDelegateAndroid(); + ~WidevineDrmDelegateAndroid() override; + + // media::MediaDrmBridgeDelegate implementation: + const std::vector<uint8_t> GetUUID() const override; + bool OnCreateSession( + const media::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) override; + + private: + DISALLOW_COPY_AND_ASSIGN(WidevineDrmDelegateAndroid); +}; + +} // namespace cdm + +#endif // COMPONENTS_CDM_BROWSER_WIDEVINE_DRM_DELEGATE_ANDROID_H_ |