Corrections to support HLS

am: cbde9109b6

* commit 'cbde9109b61beac47e93394f3e03b8fb52e8df97':
  Corrections to support HLS
This commit is contained in:
Rahul Frias
2016-03-11 18:15:55 +00:00
committed by android-build-merger
4 changed files with 73 additions and 30 deletions

View File

@@ -36,9 +36,9 @@ class InitializationData {
bool ExtractHlsAttributes(const std::string& attribute_list, bool ExtractHlsAttributes(const std::string& attribute_list,
CdmHlsMethod* method, std::vector<uint8_t>* iv, CdmHlsMethod* method, std::vector<uint8_t>* iv,
std::string* uri); std::string* uri);
static bool ConstructWidevineInitData(const std::string& uri, static bool ConstructWidevineInitData(CdmHlsMethod method,
CdmInitData* output); const std::string& uri,
CdmInitData* output);
static bool ExtractQuotedAttribute(const std::string& attribute_list, static bool ExtractQuotedAttribute(const std::string& attribute_list,
const std::string& key, const std::string& key,
std::string* value); std::string* value);

View File

@@ -20,6 +20,7 @@ const char kDoubleQuote = '\"';
const char kLeftBracket = '['; const char kLeftBracket = '[';
const char kRightBracket = ']'; const char kRightBracket = ']';
const std::string kBase64String = "base64,"; const std::string kBase64String = "base64,";
const uint32_t kFourCcCbc1 = 0x63626331;
const uint32_t kFourCcCbcs = 0x63626373; const uint32_t kFourCcCbcs = 0x63626373;
// json init data key values // json init data key values
@@ -63,7 +64,7 @@ InitializationData::InitializationData(const std::string& type,
} else if (is_hls()) { } else if (is_hls()) {
std::string uri; std::string uri;
if (ExtractHlsAttributes(data, &hls_method_, &hls_iv_, &uri)) { if (ExtractHlsAttributes(data, &hls_method_, &hls_iv_, &uri)) {
ConstructWidevineInitData(uri, &data_); ConstructWidevineInitData(hls_method_, uri, &data_);
} }
} }
} }
@@ -332,11 +333,16 @@ bool InitializationData::ExtractHlsAttributes(const std::string& attribute_list,
// ] // ]
// } // }
bool InitializationData::ConstructWidevineInitData( bool InitializationData::ConstructWidevineInitData(
const std::string& uri, CdmInitData* init_data_proto) { CdmHlsMethod method, const std::string& uri, CdmInitData* init_data_proto) {
if (!init_data_proto) { if (!init_data_proto) {
LOGV("InitializationData::ConstructWidevineInitData: Invalid parameter"); LOGV("InitializationData::ConstructWidevineInitData: Invalid parameter");
return false; return false;
} }
if (method != kHlsMethodAes128 && method != kHlsMethodSampleAes) {
LOGV("InitializationData::ConstructWidevineInitData: Invalid method"
" parameter");
return false;
}
size_t pos = uri.find(kBase64String); size_t pos = uri.find(kBase64String);
if (pos == std::string::npos) { if (pos == std::string::npos) {
@@ -419,8 +425,12 @@ bool InitializationData::ConstructWidevineInitData(
break; break;
case kContentIdState: case kContentIdState:
if (tokens[i].type == JSMN_STRING) { if (tokens[i].type == JSMN_STRING) {
content_id.assign(json_string, tokens[i].start, std::string base64_content_id(json_string, tokens[i].start,
tokens[i].end - tokens[i].start); tokens[i].end - tokens[i].start);
std::vector<uint8_t> content_id_data =
Base64Decode(base64_content_id);
content_id.assign(reinterpret_cast<const char*>(&content_id_data[0]),
content_id_data.size());
} }
state = kParseState; state = kParseState;
break; break;
@@ -465,7 +475,10 @@ bool InitializationData::ConstructWidevineInitData(
} }
cenc_header.set_provider(provider); cenc_header.set_provider(provider);
cenc_header.set_content_id(content_id); cenc_header.set_content_id(content_id);
cenc_header.set_protection_scheme(htonl(kFourCcCbcs)); if (method == kHlsMethodAes128)
cenc_header.set_protection_scheme(htonl(kFourCcCbc1));
else
cenc_header.set_protection_scheme(htonl(kFourCcCbcs));
cenc_header.SerializeToString(init_data_proto); cenc_header.SerializeToString(init_data_proto);
return true; return true;
} }

View File

@@ -246,7 +246,7 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
LicenseRequest_ContentIdentification* content_id = LicenseRequest_ContentIdentification* content_id =
license_request.mutable_content_id(); license_request.mutable_content_id();
if (init_data.is_cenc()) { if (init_data.is_cenc() || init_data.is_hls()) {
LicenseRequest_ContentIdentification_CENC* cenc_content_id = LicenseRequest_ContentIdentification_CENC* cenc_content_id =
content_id->mutable_cenc_id(); content_id->mutable_cenc_id();

View File

@@ -1,5 +1,6 @@
// Copyright 2015 Google Inc. All Rights Reserved. // Copyright 2015 Google Inc. All Rights Reserved.
#include <arpa/inet.h>
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
@@ -35,6 +36,9 @@ const std::string kJsonProvider = "provider";
const std::string kJsonContentId = "content_id"; const std::string kJsonContentId = "content_id";
const std::string kJsonKeyIds = "key_ids"; const std::string kJsonKeyIds = "key_ids";
const uint32_t kFourCcCbc1 = 0x63626331;
const uint32_t kFourCcCbcs = 0x63626373;
const std::string kWidevinePssh = a2bs_hex( const std::string kWidevinePssh = a2bs_hex(
// Widevine PSSH box // Widevine PSSH box
"00000042" // atom size "00000042" // atom size
@@ -346,15 +350,18 @@ std::string InsertHlsAttributeInList(const std::string key,
} }
struct HlsInitDataVariant { struct HlsInitDataVariant {
HlsInitDataVariant(const std::string& provider, const std::string& content_id, HlsInitDataVariant(CdmHlsMethod method, const std::string& provider,
const std::string& key_id, bool success) const std::string& content_id, const std::string& key_id,
: provider_(provider), content_id_(content_id), success_(success) { bool success)
: method_(method), provider_(provider), content_id_(content_id),
success_(success) {
if (key_id.size() > 0) key_ids_.push_back(key_id); if (key_id.size() > 0) key_ids_.push_back(key_id);
} }
HlsInitDataVariant& AddKeyId(const std::string& key_id) { HlsInitDataVariant& AddKeyId(const std::string& key_id) {
key_ids_.push_back(key_id); key_ids_.push_back(key_id);
return *this; return *this;
} }
const CdmHlsMethod method_;
const std::string provider_; const std::string provider_;
const std::string content_id_; const std::string content_id_;
std::vector<std::string> key_ids_; std::vector<std::string> key_ids_;
@@ -588,8 +595,9 @@ TEST_P(HlsConstructionTest, InitData) {
std::string uri = std::string uri =
GenerateHlsUriData(param.provider_, param.content_id_, param.key_ids_); GenerateHlsUriData(param.provider_, param.content_id_, param.key_ids_);
std::string value; std::string value;
EXPECT_EQ(param.success_, InitializationData::ConstructWidevineInitData(
param.method_, uri, &value));
if (param.success_) { if (param.success_) {
EXPECT_TRUE(InitializationData::ConstructWidevineInitData(uri, &value));
WidevineCencHeader cenc_header; WidevineCencHeader cenc_header;
EXPECT_TRUE(cenc_header.ParseFromString(value)); EXPECT_TRUE(cenc_header.ParseFromString(value));
EXPECT_EQ(video_widevine_server::sdk::WidevineCencHeader_Algorithm_AESCTR, EXPECT_EQ(video_widevine_server::sdk::WidevineCencHeader_Algorithm_AESCTR,
@@ -606,28 +614,50 @@ TEST_P(HlsConstructionTest, InitData) {
EXPECT_TRUE(key_id_found); EXPECT_TRUE(key_id_found);
} }
EXPECT_EQ(param.provider_, cenc_header.provider()); EXPECT_EQ(param.provider_, cenc_header.provider());
EXPECT_EQ(param.content_id_, cenc_header.content_id()); std::vector<uint8_t> param_content_id_vec(Base64Decode(param.content_id_));
} else { EXPECT_EQ(
EXPECT_FALSE(InitializationData::ConstructWidevineInitData(uri, &value)); std::string(param_content_id_vec.begin(), param_content_id_vec.end()),
cenc_header.content_id());
uint32_t protection_scheme = 0;
switch (param.method_) {
case kHlsMethodAes128: protection_scheme = kFourCcCbc1; break;
case kHlsMethodSampleAes: protection_scheme = kFourCcCbcs; break;
default: break;
}
EXPECT_EQ(protection_scheme, ntohl(cenc_header.protection_scheme()));
} }
} }
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
HlsTest, HlsConstructionTest, HlsTest, HlsConstructionTest,
::testing::Values( ::testing::Values(
HlsInitDataVariant("", kHlsTestContentId, kHlsTestKeyId1, false), HlsInitDataVariant(kHlsMethodAes128, "", kHlsTestContentId,
HlsInitDataVariant(kHlsTestProvider, "", kHlsTestKeyId1, false), kHlsTestKeyId1, false),
HlsInitDataVariant(kHlsTestProvider, kHlsTestContentId, "", false), HlsInitDataVariant(kHlsMethodAes128, kHlsTestProvider,
HlsInitDataVariant(kHlsTestProvider, kHlsTestContentId, "", kHlsTestKeyId1, false),
kHlsTestInvalidKeyId, false), HlsInitDataVariant(kHlsMethodAes128, kHlsTestProvider,
HlsInitDataVariant(kHlsTestProvider, kHlsTestContentId, kHlsTestKeyId1, kHlsTestContentId, "", false),
true), HlsInitDataVariant(kHlsMethodAes128, kHlsTestProvider,
HlsInitDataVariant(kHlsTestProvider, kHlsTestContentId, kHlsTestKeyId1, kHlsTestContentId, kHlsTestInvalidKeyId, false),
true) HlsInitDataVariant(kHlsMethodNone, kHlsTestProvider, kHlsTestContentId,
kHlsTestKeyId1, false),
HlsInitDataVariant(kHlsMethodAes128, kHlsTestProvider,
kHlsTestContentId, kHlsTestKeyId1, true),
HlsInitDataVariant(kHlsMethodSampleAes, kHlsTestProvider,
kHlsTestContentId, kHlsTestKeyId1, true),
HlsInitDataVariant(kHlsMethodAes128, kHlsTestProvider,
kHlsTestContentId, kHlsTestKeyId1, true)
.AddKeyId(kHlsTestKeyId2) .AddKeyId(kHlsTestKeyId2)
.AddKeyId(kHlsTestKeyId3), .AddKeyId(kHlsTestKeyId3),
HlsInitDataVariant(kHlsTestProvider, kHlsTestContentId, HlsInitDataVariant(kHlsMethodSampleAes, kHlsTestProvider,
kHlsTestInvalidKeyId, true) kHlsTestContentId, kHlsTestKeyId1, true)
.AddKeyId(kHlsTestKeyId2)
.AddKeyId(kHlsTestKeyId3),
HlsInitDataVariant(kHlsMethodAes128, kHlsTestProvider,
kHlsTestContentId, kHlsTestInvalidKeyId, true)
.AddKeyId(kHlsTestKeyId1),
HlsInitDataVariant(kHlsMethodSampleAes, kHlsTestProvider,
kHlsTestContentId, kHlsTestInvalidKeyId, true)
.AddKeyId(kHlsTestKeyId1))); .AddKeyId(kHlsTestKeyId1)));
TEST_F(HlsInitDataConstructionTest, InvalidUriDataFormat) { TEST_F(HlsInitDataConstructionTest, InvalidUriDataFormat) {
@@ -639,7 +669,7 @@ TEST_F(HlsInitDataConstructionTest, InvalidUriDataFormat) {
reinterpret_cast<const uint8_t*>(json.data() + json.size())); reinterpret_cast<const uint8_t*>(json.data() + json.size()));
std::string value; std::string value;
EXPECT_FALSE(InitializationData::ConstructWidevineInitData( EXPECT_FALSE(InitializationData::ConstructWidevineInitData(
Base64Encode(json_init_data), &value)); kHlsMethodAes128, Base64Encode(json_init_data), &value));
} }
TEST_F(HlsInitDataConstructionTest, InvalidUriBase64Encode) { TEST_F(HlsInitDataConstructionTest, InvalidUriBase64Encode) {
@@ -648,7 +678,7 @@ TEST_F(HlsInitDataConstructionTest, InvalidUriBase64Encode) {
VectorOfStrings(kHlsTestKeyId1).Generate()); VectorOfStrings(kHlsTestKeyId1).Generate());
std::string value; std::string value;
EXPECT_FALSE(InitializationData::ConstructWidevineInitData( EXPECT_FALSE(InitializationData::ConstructWidevineInitData(
kHlsTestUriDataFormat + json, &value)); kHlsMethodSampleAes, kHlsTestUriDataFormat + json, &value));
} }
TEST_P(HlsParseTest, Parse) { TEST_P(HlsParseTest, Parse) {
@@ -700,7 +730,7 @@ INSTANTIATE_TEST_CASE_P(
HlsAttributeVariant(kHlsAttributeListMethodAes128, HLS_METHOD_ATTRIBUTE, HlsAttributeVariant(kHlsAttributeListMethodAes128, HLS_METHOD_ATTRIBUTE,
HLS_METHOD_AES_128, true), HLS_METHOD_AES_128, true),
HlsAttributeVariant(kHlsAttributeListMethodNone, HLS_METHOD_ATTRIBUTE, HlsAttributeVariant(kHlsAttributeListMethodNone, HLS_METHOD_ATTRIBUTE,
HLS_METHOD_NONE, true), HLS_METHOD_NONE, false),
HlsAttributeVariant(kHlsAttributeListKeyFormatVersionMultiple, HlsAttributeVariant(kHlsAttributeListKeyFormatVersionMultiple,
HLS_KEYFORMAT_VERSIONS_ATTRIBUTE, HLS_KEYFORMAT_VERSIONS_ATTRIBUTE,
HLS_KEYFORMAT_VERSION_VALUE_1, true), HLS_KEYFORMAT_VERSION_VALUE_1, true),