2014-02-14 23:21:05 +00:00
|
|
|
// Copyright 2014 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file or at
|
|
|
|
// https://developers.google.com/open-source/licenses/bsd
|
2014-01-15 22:44:11 +00:00
|
|
|
|
2014-10-15 21:56:12 +00:00
|
|
|
#include "packager/app/packager_util.h"
|
|
|
|
|
2014-10-01 22:10:21 +00:00
|
|
|
#include "packager/base/logging.h"
|
|
|
|
#include "packager/base/strings/string_number_conversions.h"
|
2017-05-22 20:31:41 +00:00
|
|
|
#include "packager/base/strings/string_split.h"
|
2017-07-10 18:26:22 +00:00
|
|
|
#include "packager/file/file.h"
|
2017-03-21 23:14:46 +00:00
|
|
|
#include "packager/media/base/media_handler.h"
|
2014-10-01 22:10:21 +00:00
|
|
|
#include "packager/media/base/muxer_options.h"
|
2017-01-05 17:32:17 +00:00
|
|
|
#include "packager/media/base/playready_key_source.h"
|
2017-10-17 23:03:08 +00:00
|
|
|
#include "packager/media/base/raw_key_source.h"
|
2014-10-01 22:10:21 +00:00
|
|
|
#include "packager/media/base/request_signer.h"
|
|
|
|
#include "packager/media/base/widevine_key_source.h"
|
2017-02-24 01:17:47 +00:00
|
|
|
#include "packager/media/chunking/chunking_handler.h"
|
2017-03-11 02:49:55 +00:00
|
|
|
#include "packager/media/crypto/encryption_handler.h"
|
2017-02-21 18:36:50 +00:00
|
|
|
#include "packager/mpd/base/mpd_options.h"
|
2017-06-29 22:23:53 +00:00
|
|
|
#include "packager/status.h"
|
2014-01-15 22:44:11 +00:00
|
|
|
|
2016-05-20 21:19:33 +00:00
|
|
|
namespace shaka {
|
2014-01-15 22:44:11 +00:00
|
|
|
namespace media {
|
2017-03-11 02:49:55 +00:00
|
|
|
namespace {
|
|
|
|
|
2017-05-22 20:31:41 +00:00
|
|
|
std::unique_ptr<RequestSigner> CreateSigner(const WidevineSigner& signer) {
|
|
|
|
std::unique_ptr<RequestSigner> request_signer;
|
|
|
|
switch (signer.signing_key_type) {
|
|
|
|
case WidevineSigner::SigningKeyType::kAes:
|
|
|
|
request_signer.reset(AesRequestSigner::CreateSigner(
|
|
|
|
signer.signer_name, signer.aes.key, signer.aes.iv));
|
|
|
|
break;
|
|
|
|
case WidevineSigner::SigningKeyType::kRsa:
|
|
|
|
request_signer.reset(
|
|
|
|
RsaRequestSigner::CreateSigner(signer.signer_name, signer.rsa.key));
|
|
|
|
break;
|
|
|
|
case WidevineSigner::SigningKeyType::kNone:
|
|
|
|
break;
|
2014-08-20 23:51:15 +00:00
|
|
|
}
|
2017-05-22 20:31:41 +00:00
|
|
|
if (!request_signer)
|
|
|
|
LOG(ERROR) << "Failed to create the signer object.";
|
|
|
|
return request_signer;
|
2014-08-20 23:51:15 +00:00
|
|
|
}
|
2014-01-15 22:44:11 +00:00
|
|
|
|
2018-08-06 23:12:19 +00:00
|
|
|
int GetProtectionSystemsFlag(
|
|
|
|
const std::vector<EncryptionParams::ProtectionSystem>& protection_systems) {
|
|
|
|
int protection_systems_flags = 0;
|
|
|
|
for (const auto protection_system : protection_systems) {
|
|
|
|
switch (protection_system) {
|
|
|
|
case EncryptionParams::ProtectionSystem::kCommonSystem:
|
|
|
|
protection_systems_flags |= COMMON_PROTECTION_SYSTEM_FLAG;
|
|
|
|
break;
|
2018-08-07 23:01:43 +00:00
|
|
|
case EncryptionParams::ProtectionSystem::kFairPlay:
|
|
|
|
protection_systems_flags |= FAIRPLAY_PROTECTION_SYSTEM_FLAG;
|
|
|
|
break;
|
2018-08-06 23:12:19 +00:00
|
|
|
case EncryptionParams::ProtectionSystem::kPlayReady:
|
|
|
|
protection_systems_flags |= PLAYREADY_PROTECTION_SYSTEM_FLAG;
|
|
|
|
break;
|
|
|
|
case EncryptionParams::ProtectionSystem::kWidevine:
|
|
|
|
protection_systems_flags |= WIDEVINE_PROTECTION_SYSTEM_FLAG;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return protection_systems_flags;
|
|
|
|
}
|
|
|
|
|
2017-07-27 18:49:50 +00:00
|
|
|
} // namespace
|
|
|
|
|
2017-05-22 20:31:41 +00:00
|
|
|
std::unique_ptr<KeySource> CreateEncryptionKeySource(
|
|
|
|
FourCC protection_scheme,
|
|
|
|
const EncryptionParams& encryption_params) {
|
2018-08-06 23:12:19 +00:00
|
|
|
int protection_systems_flags =
|
|
|
|
GetProtectionSystemsFlag(encryption_params.additional_protection_systems);
|
2017-09-12 19:22:39 +00:00
|
|
|
|
2016-08-17 17:41:40 +00:00
|
|
|
std::unique_ptr<KeySource> encryption_key_source;
|
2017-05-22 20:31:41 +00:00
|
|
|
switch (encryption_params.key_provider) {
|
|
|
|
case KeyProvider::kWidevine: {
|
|
|
|
const WidevineEncryptionParams& widevine = encryption_params.widevine;
|
|
|
|
if (widevine.key_server_url.empty()) {
|
|
|
|
LOG(ERROR) << "'key_server_url' should not be empty.";
|
2017-10-11 21:34:04 +00:00
|
|
|
return nullptr;
|
2017-05-22 20:31:41 +00:00
|
|
|
}
|
|
|
|
if (widevine.content_id.empty()) {
|
|
|
|
LOG(ERROR) << "'content_id' should not be empty.";
|
2017-10-11 21:34:04 +00:00
|
|
|
return nullptr;
|
2017-05-22 20:31:41 +00:00
|
|
|
}
|
|
|
|
std::unique_ptr<WidevineKeySource> widevine_key_source(
|
|
|
|
new WidevineKeySource(widevine.key_server_url,
|
2018-08-07 21:43:42 +00:00
|
|
|
protection_systems_flags, protection_scheme));
|
2017-05-22 20:31:41 +00:00
|
|
|
if (!widevine.signer.signer_name.empty()) {
|
|
|
|
std::unique_ptr<RequestSigner> request_signer(
|
|
|
|
CreateSigner(widevine.signer));
|
|
|
|
if (!request_signer)
|
2017-10-11 21:34:04 +00:00
|
|
|
return nullptr;
|
2017-05-22 20:31:41 +00:00
|
|
|
widevine_key_source->set_signer(std::move(request_signer));
|
|
|
|
}
|
2017-07-18 21:30:02 +00:00
|
|
|
widevine_key_source->set_group_id(widevine.group_id);
|
2018-05-11 00:19:28 +00:00
|
|
|
widevine_key_source->set_enable_entitlement_license(
|
|
|
|
widevine.enable_entitlement_license);
|
2014-10-15 00:47:25 +00:00
|
|
|
|
2017-05-22 20:31:41 +00:00
|
|
|
Status status =
|
|
|
|
widevine_key_source->FetchKeys(widevine.content_id, widevine.policy);
|
|
|
|
if (!status.ok()) {
|
|
|
|
LOG(ERROR) << "Widevine encryption key source failed to fetch keys: "
|
|
|
|
<< status.ToString();
|
2017-10-11 21:34:04 +00:00
|
|
|
return nullptr;
|
2017-05-22 20:31:41 +00:00
|
|
|
}
|
|
|
|
encryption_key_source = std::move(widevine_key_source);
|
|
|
|
break;
|
2014-08-20 23:51:15 +00:00
|
|
|
}
|
2017-05-22 20:31:41 +00:00
|
|
|
case KeyProvider::kRawKey: {
|
2018-08-07 21:43:42 +00:00
|
|
|
encryption_key_source =
|
|
|
|
RawKeySource::Create(encryption_params.raw_key,
|
|
|
|
protection_systems_flags, protection_scheme);
|
2017-05-22 20:31:41 +00:00
|
|
|
break;
|
2014-05-08 23:34:45 +00:00
|
|
|
}
|
2018-04-20 18:06:36 +00:00
|
|
|
case KeyProvider::kPlayReady: {
|
|
|
|
const PlayReadyEncryptionParams& playready = encryption_params.playready;
|
2018-04-20 17:46:14 +00:00
|
|
|
if (!playready.key_server_url.empty() ||
|
|
|
|
!playready.program_identifier.empty()) {
|
2017-10-11 21:34:04 +00:00
|
|
|
if (playready.key_server_url.empty() ||
|
|
|
|
playready.program_identifier.empty()) {
|
2018-08-06 23:12:19 +00:00
|
|
|
LOG(ERROR) << "Either PlayReady key_server_url or program_identifier "
|
2017-10-11 21:34:04 +00:00
|
|
|
"is not set.";
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-05-22 20:31:41 +00:00
|
|
|
std::unique_ptr<PlayReadyKeySource> playready_key_source;
|
2017-10-11 21:34:04 +00:00
|
|
|
// private_key_password is allowed to be empty for unencrypted key.
|
|
|
|
if (!playready.client_cert_file.empty() ||
|
|
|
|
!playready.client_cert_private_key_file.empty()) {
|
|
|
|
if (playready.client_cert_file.empty() ||
|
|
|
|
playready.client_cert_private_key_file.empty()) {
|
2018-08-06 23:12:19 +00:00
|
|
|
LOG(ERROR) << "Either PlayReady client_cert_file or "
|
2017-10-11 21:34:04 +00:00
|
|
|
"client_cert_private_key_file is not set.";
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-05-22 20:31:41 +00:00
|
|
|
playready_key_source.reset(new PlayReadyKeySource(
|
|
|
|
playready.key_server_url, playready.client_cert_file,
|
|
|
|
playready.client_cert_private_key_file,
|
2018-04-20 17:46:14 +00:00
|
|
|
playready.client_cert_private_key_password,
|
2018-08-07 21:43:42 +00:00
|
|
|
protection_systems_flags, protection_scheme));
|
2017-05-22 20:31:41 +00:00
|
|
|
} else {
|
2018-04-20 17:46:14 +00:00
|
|
|
playready_key_source.reset(new PlayReadyKeySource(
|
2018-08-07 21:43:42 +00:00
|
|
|
playready.key_server_url, protection_systems_flags,
|
|
|
|
protection_scheme));
|
2017-05-22 20:31:41 +00:00
|
|
|
}
|
|
|
|
if (!playready.ca_file.empty()) {
|
|
|
|
playready_key_source->SetCaFile(playready.ca_file);
|
|
|
|
}
|
2018-08-10 01:31:44 +00:00
|
|
|
Status status = playready_key_source->FetchKeysWithProgramIdentifier(
|
2017-05-22 20:31:41 +00:00
|
|
|
playready.program_identifier);
|
2018-08-10 01:31:44 +00:00
|
|
|
if (!status.ok()) {
|
|
|
|
LOG(ERROR) << "PlayReady encryption key source failed to fetch keys: "
|
|
|
|
<< status.ToString();
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-05-22 20:31:41 +00:00
|
|
|
encryption_key_source = std::move(playready_key_source);
|
2017-01-05 17:32:17 +00:00
|
|
|
} else {
|
2017-05-22 20:31:41 +00:00
|
|
|
LOG(ERROR) << "Error creating PlayReady key source.";
|
2017-10-11 21:34:04 +00:00
|
|
|
return nullptr;
|
2017-01-05 17:32:17 +00:00
|
|
|
}
|
2017-05-22 20:31:41 +00:00
|
|
|
break;
|
2017-01-05 17:32:17 +00:00
|
|
|
}
|
2017-05-22 20:31:41 +00:00
|
|
|
case KeyProvider::kNone:
|
|
|
|
break;
|
2014-01-15 22:44:11 +00:00
|
|
|
}
|
2016-08-17 17:41:40 +00:00
|
|
|
return encryption_key_source;
|
2014-01-15 22:44:11 +00:00
|
|
|
}
|
|
|
|
|
2017-05-22 20:31:41 +00:00
|
|
|
std::unique_ptr<KeySource> CreateDecryptionKeySource(
|
|
|
|
const DecryptionParams& decryption_params) {
|
2016-08-17 17:41:40 +00:00
|
|
|
std::unique_ptr<KeySource> decryption_key_source;
|
2017-05-22 20:31:41 +00:00
|
|
|
switch (decryption_params.key_provider) {
|
|
|
|
case KeyProvider::kWidevine: {
|
|
|
|
const WidevineDecryptionParams& widevine = decryption_params.widevine;
|
|
|
|
if (widevine.key_server_url.empty()) {
|
|
|
|
LOG(ERROR) << "'key_server_url' should not be empty.";
|
2016-08-17 17:41:40 +00:00
|
|
|
return std::unique_ptr<KeySource>();
|
2017-05-22 20:31:41 +00:00
|
|
|
}
|
2018-08-07 21:43:42 +00:00
|
|
|
std::unique_ptr<WidevineKeySource> widevine_key_source(
|
|
|
|
new WidevineKeySource(
|
|
|
|
widevine.key_server_url,
|
|
|
|
WIDEVINE_PROTECTION_SYSTEM_FLAG /* value does not matter here */,
|
|
|
|
FOURCC_NULL /* value does not matter here */));
|
2017-05-22 20:31:41 +00:00
|
|
|
if (!widevine.signer.signer_name.empty()) {
|
|
|
|
std::unique_ptr<RequestSigner> request_signer(
|
|
|
|
CreateSigner(widevine.signer));
|
|
|
|
if (!request_signer)
|
|
|
|
return std::unique_ptr<KeySource>();
|
|
|
|
widevine_key_source->set_signer(std::move(request_signer));
|
|
|
|
}
|
2014-10-15 00:47:25 +00:00
|
|
|
|
2017-05-22 20:31:41 +00:00
|
|
|
decryption_key_source = std::move(widevine_key_source);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case KeyProvider::kRawKey: {
|
2018-01-17 18:53:58 +00:00
|
|
|
decryption_key_source = RawKeySource::Create(
|
|
|
|
decryption_params.raw_key,
|
2018-08-07 21:43:42 +00:00
|
|
|
COMMON_PROTECTION_SYSTEM_FLAG /* value does not matter here */,
|
|
|
|
FOURCC_NULL /* value does not matter here */);
|
2017-05-22 20:31:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case KeyProvider::kNone:
|
2018-04-20 18:06:36 +00:00
|
|
|
case KeyProvider::kPlayReady:
|
2017-05-22 20:31:41 +00:00
|
|
|
break;
|
2014-08-20 23:51:15 +00:00
|
|
|
}
|
2016-08-17 17:41:40 +00:00
|
|
|
return decryption_key_source;
|
2014-08-20 23:51:15 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 19:18:50 +00:00
|
|
|
MpdOptions GetMpdOptions(bool on_demand_profile,
|
|
|
|
const MpdParams& mpd_params,
|
|
|
|
double target_segment_duration) {
|
2017-02-24 01:17:47 +00:00
|
|
|
MpdOptions mpd_options;
|
|
|
|
mpd_options.dash_profile =
|
2017-01-07 02:40:37 +00:00
|
|
|
on_demand_profile ? DashProfile::kOnDemand : DashProfile::kLive;
|
2017-05-22 20:31:41 +00:00
|
|
|
mpd_options.mpd_type =
|
|
|
|
(on_demand_profile || mpd_params.generate_static_live_mpd)
|
|
|
|
? MpdType::kStatic
|
|
|
|
: MpdType::kDynamic;
|
2017-07-27 18:49:50 +00:00
|
|
|
mpd_options.mpd_params = mpd_params;
|
2017-09-25 19:18:50 +00:00
|
|
|
mpd_options.target_segment_duration = target_segment_duration;
|
2017-02-24 01:17:47 +00:00
|
|
|
return mpd_options;
|
2014-06-26 01:33:09 +00:00
|
|
|
}
|
|
|
|
|
2014-01-15 22:44:11 +00:00
|
|
|
} // namespace media
|
2016-05-20 21:19:33 +00:00
|
|
|
} // namespace shaka
|