Shaka Packager SDK
packager_util.cc
1 // Copyright 2014 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include "packager/app/packager_util.h"
8 
9 #include "packager/base/logging.h"
10 #include "packager/base/strings/string_number_conversions.h"
11 #include "packager/base/strings/string_split.h"
12 #include "packager/file/file.h"
13 #include "packager/media/base/media_handler.h"
14 #include "packager/media/base/muxer_options.h"
15 #include "packager/media/base/playready_key_source.h"
16 #include "packager/media/base/raw_key_source.h"
17 #include "packager/media/base/request_signer.h"
18 #include "packager/media/base/widevine_key_source.h"
19 #include "packager/mpd/base/mpd_options.h"
20 #include "packager/status.h"
21 
22 namespace shaka {
23 namespace media {
24 namespace {
25 
26 std::unique_ptr<RequestSigner> CreateSigner(const WidevineSigner& signer) {
27  std::unique_ptr<RequestSigner> request_signer;
28  switch (signer.signing_key_type) {
29  case WidevineSigner::SigningKeyType::kAes:
30  request_signer.reset(AesRequestSigner::CreateSigner(
31  signer.signer_name, signer.aes.key, signer.aes.iv));
32  break;
33  case WidevineSigner::SigningKeyType::kRsa:
34  request_signer.reset(
35  RsaRequestSigner::CreateSigner(signer.signer_name, signer.rsa.key));
36  break;
37  case WidevineSigner::SigningKeyType::kNone:
38  break;
39  }
40  if (!request_signer)
41  LOG(ERROR) << "Failed to create the signer object.";
42  return request_signer;
43 }
44 
45 int GetProtectionSystemsFlag(
46  const std::vector<EncryptionParams::ProtectionSystem>& protection_systems) {
47  int protection_systems_flags = 0;
48  for (const auto protection_system : protection_systems) {
49  switch (protection_system) {
50  case EncryptionParams::ProtectionSystem::kCommonSystem:
51  protection_systems_flags |= COMMON_PROTECTION_SYSTEM_FLAG;
52  break;
53  case EncryptionParams::ProtectionSystem::kFairPlay:
54  protection_systems_flags |= FAIRPLAY_PROTECTION_SYSTEM_FLAG;
55  break;
56  case EncryptionParams::ProtectionSystem::kMarlin:
57  protection_systems_flags |= MARLIN_PROTECTION_SYSTEM_FLAG;
58  break;
59  case EncryptionParams::ProtectionSystem::kPlayReady:
60  protection_systems_flags |= PLAYREADY_PROTECTION_SYSTEM_FLAG;
61  break;
62  case EncryptionParams::ProtectionSystem::kWidevine:
63  protection_systems_flags |= WIDEVINE_PROTECTION_SYSTEM_FLAG;
64  break;
65  }
66  }
67  return protection_systems_flags;
68 }
69 
70 } // namespace
71 
72 std::unique_ptr<KeySource> CreateEncryptionKeySource(
73  FourCC protection_scheme,
74  const EncryptionParams& encryption_params) {
75  int protection_systems_flags =
76  GetProtectionSystemsFlag(encryption_params.protection_systems);
77 
78  std::unique_ptr<KeySource> encryption_key_source;
79  switch (encryption_params.key_provider) {
80  case KeyProvider::kWidevine: {
81  const WidevineEncryptionParams& widevine = encryption_params.widevine;
82  if (widevine.key_server_url.empty()) {
83  LOG(ERROR) << "'key_server_url' should not be empty.";
84  return nullptr;
85  }
86  if (widevine.content_id.empty()) {
87  LOG(ERROR) << "'content_id' should not be empty.";
88  return nullptr;
89  }
90  std::unique_ptr<WidevineKeySource> widevine_key_source(
91  new WidevineKeySource(widevine.key_server_url,
92  protection_systems_flags, protection_scheme));
93  if (!widevine.signer.signer_name.empty()) {
94  std::unique_ptr<RequestSigner> request_signer(
95  CreateSigner(widevine.signer));
96  if (!request_signer)
97  return nullptr;
98  widevine_key_source->set_signer(std::move(request_signer));
99  }
100  widevine_key_source->set_group_id(widevine.group_id);
101  widevine_key_source->set_enable_entitlement_license(
102  widevine.enable_entitlement_license);
103 
104  Status status =
105  widevine_key_source->FetchKeys(widevine.content_id, widevine.policy);
106  if (!status.ok()) {
107  LOG(ERROR) << "Widevine encryption key source failed to fetch keys: "
108  << status.ToString();
109  return nullptr;
110  }
111  encryption_key_source = std::move(widevine_key_source);
112  break;
113  }
114  case KeyProvider::kRawKey: {
115  encryption_key_source =
116  RawKeySource::Create(encryption_params.raw_key,
117  protection_systems_flags, protection_scheme);
118  break;
119  }
120  case KeyProvider::kPlayReady: {
121  const PlayReadyEncryptionParams& playready = encryption_params.playready;
122  if (!playready.key_server_url.empty() ||
123  !playready.program_identifier.empty()) {
124  if (playready.key_server_url.empty() ||
125  playready.program_identifier.empty()) {
126  LOG(ERROR) << "Either PlayReady key_server_url or program_identifier "
127  "is not set.";
128  return nullptr;
129  }
130  std::unique_ptr<PlayReadyKeySource> playready_key_source;
131  // private_key_password is allowed to be empty for unencrypted key.
132  if (!playready.client_cert_file.empty() ||
133  !playready.client_cert_private_key_file.empty()) {
134  if (playready.client_cert_file.empty() ||
135  playready.client_cert_private_key_file.empty()) {
136  LOG(ERROR) << "Either PlayReady client_cert_file or "
137  "client_cert_private_key_file is not set.";
138  return nullptr;
139  }
140  playready_key_source.reset(new PlayReadyKeySource(
141  playready.key_server_url, playready.client_cert_file,
142  playready.client_cert_private_key_file,
143  playready.client_cert_private_key_password,
144  protection_systems_flags, protection_scheme));
145  } else {
146  playready_key_source.reset(new PlayReadyKeySource(
147  playready.key_server_url, protection_systems_flags,
148  protection_scheme));
149  }
150  if (!playready.ca_file.empty()) {
151  playready_key_source->SetCaFile(playready.ca_file);
152  }
153  Status status = playready_key_source->FetchKeysWithProgramIdentifier(
154  playready.program_identifier);
155  if (!status.ok()) {
156  LOG(ERROR) << "PlayReady encryption key source failed to fetch keys: "
157  << status.ToString();
158  return nullptr;
159  }
160  encryption_key_source = std::move(playready_key_source);
161  } else {
162  LOG(ERROR) << "Error creating PlayReady key source.";
163  return nullptr;
164  }
165  break;
166  }
167  case KeyProvider::kNone:
168  break;
169  }
170  return encryption_key_source;
171 }
172 
173 std::unique_ptr<KeySource> CreateDecryptionKeySource(
174  const DecryptionParams& decryption_params) {
175  std::unique_ptr<KeySource> decryption_key_source;
176  switch (decryption_params.key_provider) {
177  case KeyProvider::kWidevine: {
178  const WidevineDecryptionParams& widevine = decryption_params.widevine;
179  if (widevine.key_server_url.empty()) {
180  LOG(ERROR) << "'key_server_url' should not be empty.";
181  return std::unique_ptr<KeySource>();
182  }
183  std::unique_ptr<WidevineKeySource> widevine_key_source(
184  new WidevineKeySource(
185  widevine.key_server_url,
186  WIDEVINE_PROTECTION_SYSTEM_FLAG /* value does not matter here */,
187  FOURCC_NULL /* value does not matter here */));
188  if (!widevine.signer.signer_name.empty()) {
189  std::unique_ptr<RequestSigner> request_signer(
190  CreateSigner(widevine.signer));
191  if (!request_signer)
192  return std::unique_ptr<KeySource>();
193  widevine_key_source->set_signer(std::move(request_signer));
194  }
195 
196  decryption_key_source = std::move(widevine_key_source);
197  break;
198  }
199  case KeyProvider::kRawKey: {
200  decryption_key_source = RawKeySource::Create(
201  decryption_params.raw_key,
202  COMMON_PROTECTION_SYSTEM_FLAG /* value does not matter here */,
203  FOURCC_NULL /* value does not matter here */);
204  break;
205  }
206  case KeyProvider::kNone:
207  case KeyProvider::kPlayReady:
208  break;
209  }
210  return decryption_key_source;
211 }
212 
213 MpdOptions GetMpdOptions(bool on_demand_profile, const MpdParams& mpd_params) {
214  MpdOptions mpd_options;
215  mpd_options.dash_profile =
216  on_demand_profile ? DashProfile::kOnDemand : DashProfile::kLive;
217  mpd_options.mpd_type =
218  (on_demand_profile || mpd_params.generate_static_live_mpd)
219  ? MpdType::kStatic
220  : MpdType::kDynamic;
221  mpd_options.mpd_params = mpd_params;
222  return mpd_options;
223 }
224 
225 } // namespace media
226 } // namespace shaka
static RsaRequestSigner * CreateSigner(const std::string &signer_name, const std::string &pkcs1_rsa_key)
std::string ToString() const
Definition: status.cc:83
static std::unique_ptr< RawKeySource > Create(const RawKeyParams &raw_key, int protection_system_flags, FourCC protection_scheme)
static AesRequestSigner * CreateSigner(const std::string &signer_name, const std::vector< uint8_t > &aes_key, const std::vector< uint8_t > &iv)
All the methods that are virtual are virtual for mocking.
void SetCaFile(const std::string &ca_file)
Sets the Certificate Authority file for validating self-signed certificates.