From 74f559c2c8d23115ad7e3c4f9335230edd155546 Mon Sep 17 00:00:00 2001 From: kjellander Date: Wed, 10 Jun 2015 00:22:31 -0700 Subject: Revert of Combine 'pssh' parsing routines. (patchset #8 id:140001 of https://codereview.chromium.org/1149023002/) Reason for revert: Breaks compile on 'Google Chrome Win' bot: https://build.chromium.org/p/chromium.chrome/builders/Google%20Chrome%20Win/builds/1066 Original issue's description: > Combine CENC 'pssh' box parsing routines. > > Also update the routines to ignore 'pssh' boxes with version 2 or > later. > > BUG=460359, 460360 > TEST=new unittests pass > > Committed: https://crrev.com/b666d7874efac44b359a95329f0cb890e97671df > Cr-Commit-Position: refs/heads/master@{#333556} > > Committed: https://crrev.com/7a84443597e92a03f90806712f8629df40bf408e > Cr-Commit-Position: refs/heads/master@{#333611} TBR=sandersd@chromium.org,ddorwin@chromium.org,xhwang@chromium.org,jrummell@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=460359, 460360 Review URL: https://codereview.chromium.org/1165313003 Cr-Commit-Position: refs/heads/master@{#333694} --- components/cdm/browser/DEPS | 2 +- .../cdm/browser/widevine_drm_delegate_android.cc | 140 ++++++++++++++++++++- 2 files changed, 138 insertions(+), 4 deletions(-) (limited to 'components/cdm') diff --git a/components/cdm/browser/DEPS b/components/cdm/browser/DEPS index 1891599..d0fb59f 100644 --- a/components/cdm/browser/DEPS +++ b/components/cdm/browser/DEPS @@ -1,4 +1,4 @@ include_rules = [ "+content/public/browser", - "+media/cdm", + "+media/base/android", ] diff --git a/components/cdm/browser/widevine_drm_delegate_android.cc b/components/cdm/browser/widevine_drm_delegate_android.cc index 8acf800..1c2b6e4 100644 --- a/components/cdm/browser/widevine_drm_delegate_android.cc +++ b/components/cdm/browser/widevine_drm_delegate_android.cc @@ -4,17 +4,151 @@ #include "components/cdm/browser/widevine_drm_delegate_android.h" -#include "media/cdm/cenc_utils.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 Size +// uint32 Type +// uint64 LargeSize # Field is only present if value(Size) == 1. +// uint8 Version +// uint24 Flags +// uint8[16] SystemId +// if (version > 0) { +// uint32 KID_count; +// uint8[16][KID_Count] KID; +// } +// 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 uint32_t k24BitMask = 0x00ffffff; +const int kPsshSystemIdSize = 16; +const int kPsshKidCountSize = 4; +const int kPsshKidSize = 16; +const int kPsshDataSizeSize = 4; +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 }; -} // namespace +// 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 boxes are allowed in |data|. +bool GetPsshData(const std::vector& data, + std::vector* pssh_data) { + int bytes_left = base::checked_cast(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 != kPsshType) + return false; + + const int kPsshBoxMinimumSize = + kPsshVersionFlagSize + kPsshSystemIdSize + kPsshDataSizeSize; + if (box_end < cur + kPsshBoxMinimumSize) + return false; + + uint8_t version = cur[0]; + uint32_t flags = ReadUint32(cur) & k24BitMask; + cur += kPsshVersionFlagSize; + bytes_left -= kPsshVersionFlagSize; + if (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; + + // If KeyIDs specified, skip them. + if (version > 0) { + DCHECK_GE(bytes_left, kPsshKidCountSize); + uint32_t kid_count = ReadUint32(cur); + cur += kPsshKidCountSize + kid_count * kPsshKidSize; + bytes_left -= kPsshKidCountSize + kid_count * kPsshKidSize; + // Must be bytes left in this box for data_size. + if (box_end < cur + kPsshDataSizeSize) + return false; + } + + DCHECK_GE(bytes_left, kPsshDataSizeSize); + 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() { } @@ -37,7 +171,7 @@ bool WidevineDrmDelegateAndroid::OnCreateSession( // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as // the init data when using MP4 container. - return media::GetPsshData(init_data, GetUUID(), init_data_out); + return GetPsshData(init_data, init_data_out); } } // namespace cdm -- cgit v1.1