DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
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 <gflags/gflags.h>
10 #include <iostream>
11 
12 #include "packager/app/crypto_flags.h"
13 #include "packager/app/fixed_key_encryption_flags.h"
14 #include "packager/app/mpd_flags.h"
15 #include "packager/app/muxer_flags.h"
16 #include "packager/app/playready_key_encryption_flags.h"
17 #include "packager/app/widevine_encryption_flags.h"
18 #include "packager/base/logging.h"
19 #include "packager/base/strings/string_number_conversions.h"
20 #include "packager/media/base/fixed_key_source.h"
21 #include "packager/media/base/media_handler.h"
22 #include "packager/media/base/muxer_options.h"
23 #include "packager/media/base/playready_key_source.h"
24 #include "packager/media/base/request_signer.h"
25 #include "packager/media/base/status.h"
26 #include "packager/media/base/widevine_key_source.h"
27 #include "packager/media/chunking/chunking_handler.h"
28 #include "packager/media/crypto/encryption_handler.h"
29 #include "packager/media/file/file.h"
30 #include "packager/mpd/base/mpd_options.h"
31 
32 DEFINE_bool(mp4_use_decoding_timestamp_in_timeline,
33  false,
34  "If set, decoding timestamp instead of presentation timestamp will "
35  "be used when generating media timeline, e.g. timestamps in sidx "
36  "and mpd. This is to workaround a Chromium bug that decoding "
37  "timestamp is used in buffered range, https://crbug.com/398130.");
38 DEFINE_bool(dump_stream_info, false, "Dump demuxed stream info.");
39 
40 namespace shaka {
41 namespace media {
42 namespace {
43 
44 FourCC GetProtectionScheme(const std::string& protection_scheme) {
45  if (protection_scheme == "cenc") {
46  return FOURCC_cenc;
47  } else if (protection_scheme == "cens") {
48  return FOURCC_cens;
49  } else if (protection_scheme == "cbc1") {
50  return FOURCC_cbc1;
51  } else if (protection_scheme == "cbcs") {
52  return FOURCC_cbcs;
53  } else {
54  LOG(ERROR) << "Unknown protection scheme: " << protection_scheme;
55  return FOURCC_NULL;
56  }
57 }
58 
59 } // namespace
60 
61 std::unique_ptr<RequestSigner> CreateSigner() {
62  std::unique_ptr<RequestSigner> signer;
63 
64  if (!FLAGS_aes_signing_key.empty()) {
65  signer.reset(AesRequestSigner::CreateSigner(
66  FLAGS_signer, FLAGS_aes_signing_key, FLAGS_aes_signing_iv));
67  if (!signer) {
68  LOG(ERROR) << "Cannot create an AES signer object from '"
69  << FLAGS_aes_signing_key << "':'" << FLAGS_aes_signing_iv
70  << "'.";
71  return std::unique_ptr<RequestSigner>();
72  }
73  } else if (!FLAGS_rsa_signing_key_path.empty()) {
74  std::string rsa_private_key;
75  if (!File::ReadFileToString(FLAGS_rsa_signing_key_path.c_str(),
76  &rsa_private_key)) {
77  LOG(ERROR) << "Failed to read from '" << FLAGS_rsa_signing_key_path
78  << "'.";
79  return std::unique_ptr<RequestSigner>();
80  }
81  signer.reset(RsaRequestSigner::CreateSigner(FLAGS_signer, rsa_private_key));
82  if (!signer) {
83  LOG(ERROR) << "Cannot create a RSA signer object from '"
84  << FLAGS_rsa_signing_key_path << "'.";
85  return std::unique_ptr<RequestSigner>();
86  }
87  }
88  return signer;
89 }
90 
91 std::unique_ptr<KeySource> CreateEncryptionKeySource(FourCC protection_scheme) {
92  std::unique_ptr<KeySource> encryption_key_source;
93  if (FLAGS_enable_widevine_encryption) {
94  std::unique_ptr<WidevineKeySource> widevine_key_source(
95  new WidevineKeySource(FLAGS_key_server_url, FLAGS_include_common_pssh));
96  widevine_key_source->set_protection_scheme(protection_scheme);
97  if (!FLAGS_signer.empty()) {
98  std::unique_ptr<RequestSigner> request_signer(CreateSigner());
99  if (!request_signer)
100  return std::unique_ptr<KeySource>();
101  widevine_key_source->set_signer(std::move(request_signer));
102  }
103 
104  std::vector<uint8_t> content_id;
105  if (!base::HexStringToBytes(FLAGS_content_id, &content_id)) {
106  LOG(ERROR) << "Invalid content_id hex string specified.";
107  return std::unique_ptr<KeySource>();
108  }
109  Status status = widevine_key_source->FetchKeys(content_id, FLAGS_policy);
110  if (!status.ok()) {
111  LOG(ERROR) << "Widevine encryption key source failed to fetch keys: "
112  << status.ToString();
113  return std::unique_ptr<KeySource>();
114  }
115  encryption_key_source = std::move(widevine_key_source);
116  } else if (FLAGS_enable_fixed_key_encryption) {
117  encryption_key_source = FixedKeySource::CreateFromHexStrings(
118  FLAGS_key_id, FLAGS_key, FLAGS_pssh, FLAGS_iv);
119  } else if (FLAGS_enable_playready_encryption) {
120  if (!FLAGS_playready_key_id.empty() && !FLAGS_playready_key.empty()) {
121  encryption_key_source = PlayReadyKeySource::CreateFromKeyAndKeyId(
122  FLAGS_playready_key_id, FLAGS_playready_key);
123  } else if (!FLAGS_playready_server_url.empty() &&
124  !FLAGS_program_identifier.empty()) {
125  std::unique_ptr<PlayReadyKeySource> playready_key_source;
126  if (!FLAGS_client_cert_file.empty() &&
127  !FLAGS_client_cert_private_key_file.empty() &&
128  !FLAGS_client_cert_private_key_password.empty()) {
129  playready_key_source.reset(new PlayReadyKeySource(
130  FLAGS_playready_server_url,
131  FLAGS_client_cert_file,
132  FLAGS_client_cert_private_key_file,
133  FLAGS_client_cert_private_key_password));
134  } else {
135  playready_key_source.reset(new PlayReadyKeySource(
136  FLAGS_playready_server_url));
137  }
138  if (!FLAGS_ca_file.empty()) {
139  playready_key_source->SetCaFile(FLAGS_ca_file);
140  }
141  playready_key_source->FetchKeysWithProgramIdentifier(FLAGS_program_identifier);
142  encryption_key_source = std::move(playready_key_source);
143  } else {
144  LOG(ERROR) << "Error creating PlayReady key source.";
145  return std::unique_ptr<KeySource>();
146  }
147  }
148  return encryption_key_source;
149 }
150 
151 std::unique_ptr<KeySource> CreateDecryptionKeySource() {
152  std::unique_ptr<KeySource> decryption_key_source;
153  if (FLAGS_enable_widevine_decryption) {
154  std::unique_ptr<WidevineKeySource> widevine_key_source(
155  new WidevineKeySource(FLAGS_key_server_url, FLAGS_include_common_pssh));
156  if (!FLAGS_signer.empty()) {
157  std::unique_ptr<RequestSigner> request_signer(CreateSigner());
158  if (!request_signer)
159  return std::unique_ptr<KeySource>();
160  widevine_key_source->set_signer(std::move(request_signer));
161  }
162 
163  decryption_key_source = std::move(widevine_key_source);
164  } else if (FLAGS_enable_fixed_key_decryption) {
165  const char kNoPssh[] = "";
166  const char kNoIv[] = "";
167  decryption_key_source = FixedKeySource::CreateFromHexStrings(
168  FLAGS_key_id, FLAGS_key, kNoPssh, kNoIv);
169  }
170  return decryption_key_source;
171 }
172 
173 ChunkingOptions GetChunkingOptions() {
174  ChunkingOptions chunking_options;
175  chunking_options.segment_duration_in_seconds = FLAGS_segment_duration;
176  chunking_options.subsegment_duration_in_seconds = FLAGS_fragment_duration;
177  chunking_options.segment_sap_aligned = FLAGS_segment_sap_aligned;
178  chunking_options.subsegment_sap_aligned = FLAGS_fragment_sap_aligned;
179  return chunking_options;
180 }
181 
182 EncryptionOptions GetEncryptionOptions() {
183  EncryptionOptions encryption_options;
184  encryption_options.clear_lead_in_seconds = FLAGS_clear_lead;
185  encryption_options.protection_scheme =
186  GetProtectionScheme(FLAGS_protection_scheme);
187  encryption_options.max_sd_pixels = FLAGS_max_sd_pixels;
188  encryption_options.max_hd_pixels = FLAGS_max_hd_pixels;
189  encryption_options.max_uhd1_pixels = FLAGS_max_uhd1_pixels;
190  encryption_options.crypto_period_duration_in_seconds =
191  FLAGS_crypto_period_duration;
192  encryption_options.vp9_subsample_encryption = FLAGS_vp9_subsample_encryption;
193  return encryption_options;
194 }
195 
196 MuxerOptions GetMuxerOptions() {
197  MuxerOptions muxer_options;
198  muxer_options.num_subsegments_per_sidx = FLAGS_num_subsegments_per_sidx;
199  muxer_options.mp4_include_pssh_in_stream = FLAGS_mp4_include_pssh_in_stream;
200  if (FLAGS_mp4_use_decoding_timestamp_in_timeline) {
201  LOG(WARNING) << "Flag --mp4_use_decoding_timestamp_in_timeline is set. "
202  "Note that it is a temporary hack to workaround Chromium "
203  "bug https://crbug.com/398130. The flag may be removed "
204  "when the Chromium bug is fixed.";
205  }
206  muxer_options.mp4_use_decoding_timestamp_in_timeline =
207  FLAGS_mp4_use_decoding_timestamp_in_timeline;
208  muxer_options.temp_dir = FLAGS_temp_dir;
209  return muxer_options;
210 }
211 
212 MpdOptions GetMpdOptions(bool on_demand_profile) {
213  MpdOptions mpd_options;
214  mpd_options.dash_profile =
215  on_demand_profile ? DashProfile::kOnDemand : DashProfile::kLive;
216  mpd_options.mpd_type = (on_demand_profile || FLAGS_generate_static_mpd)
217  ? MpdType::kStatic
218  : MpdType::kDynamic;
219  mpd_options.availability_time_offset = FLAGS_availability_time_offset;
220  mpd_options.minimum_update_period = FLAGS_minimum_update_period;
221  mpd_options.min_buffer_time = FLAGS_min_buffer_time;
222  mpd_options.time_shift_buffer_depth = FLAGS_time_shift_buffer_depth;
223  mpd_options.suggested_presentation_delay = FLAGS_suggested_presentation_delay;
224  mpd_options.default_language = FLAGS_default_language;
225  return mpd_options;
226 }
227 
228 Status ConnectHandlers(std::vector<std::shared_ptr<MediaHandler>>& handlers) {
229  size_t num_handlers = handlers.size();
230  Status status;
231  for (size_t i = 1; i < num_handlers; ++i) {
232  status.Update(handlers[i - 1]->AddHandler(handlers[i]));
233  }
234  return status;
235 }
236 
237 } // namespace media
238 } // namespace shaka
static RsaRequestSigner * CreateSigner(const std::string &signer_name, const std::string &pkcs1_rsa_key)
static AesRequestSigner * CreateSigner(const std::string &signer_name, const std::string &aes_key_hex, const std::string &iv_hex)
void Update(const Status &new_status)
Definition: status.h:130
static std::unique_ptr< FixedKeySource > CreateFromHexStrings(const std::string &key_id_hex, const std::string &key_hex, const std::string &pssh_boxes_hex, const std::string &iv_hex)
void SetCaFile(const std::string &ca_file)
Sets the Certificate Authority file for validating self-signed certificates.
double clear_lead_in_seconds
Clear lead duration in seconds.
double segment_duration_in_seconds
Segment duration in seconds.
static bool ReadFileToString(const char *file_name, std::string *contents)
Definition: file.cc:185
static std::unique_ptr< PlayReadyKeySource > CreateFromKeyAndKeyId(const std::string &key_id_hex, const std::string &key_hex)