7 #include "packager/app/packager_util.h"
9 #include <gflags/gflags.h>
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"
32 DEFINE_bool(mp4_use_decoding_timestamp_in_timeline,
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.");
44 FourCC GetProtectionScheme(
const std::string& protection_scheme) {
45 if (protection_scheme ==
"cenc") {
47 }
else if (protection_scheme ==
"cens") {
49 }
else if (protection_scheme ==
"cbc1") {
51 }
else if (protection_scheme ==
"cbcs") {
54 LOG(ERROR) <<
"Unknown protection scheme: " << protection_scheme;
61 std::unique_ptr<RequestSigner> CreateSigner() {
62 std::unique_ptr<RequestSigner> signer;
64 if (!FLAGS_aes_signing_key.empty()) {
66 FLAGS_signer, FLAGS_aes_signing_key, FLAGS_aes_signing_iv));
68 LOG(ERROR) <<
"Cannot create an AES signer object from '"
69 << FLAGS_aes_signing_key <<
"':'" << FLAGS_aes_signing_iv
71 return std::unique_ptr<RequestSigner>();
73 }
else if (!FLAGS_rsa_signing_key_path.empty()) {
74 std::string rsa_private_key;
77 LOG(ERROR) <<
"Failed to read from '" << FLAGS_rsa_signing_key_path
79 return std::unique_ptr<RequestSigner>();
83 LOG(ERROR) <<
"Cannot create a RSA signer object from '"
84 << FLAGS_rsa_signing_key_path <<
"'.";
85 return std::unique_ptr<RequestSigner>();
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());
100 return std::unique_ptr<KeySource>();
101 widevine_key_source->set_signer(std::move(request_signer));
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>();
109 Status status = widevine_key_source->FetchKeys(content_id, FLAGS_policy);
111 LOG(ERROR) <<
"Widevine encryption key source failed to fetch keys: "
112 << status.ToString();
113 return std::unique_ptr<KeySource>();
115 encryption_key_source = std::move(widevine_key_source);
116 }
else if (FLAGS_enable_fixed_key_encryption) {
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()) {
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));
135 playready_key_source.reset(
new PlayReadyKeySource(
136 FLAGS_playready_server_url));
138 if (!FLAGS_ca_file.empty()) {
139 playready_key_source->
SetCaFile(FLAGS_ca_file);
141 playready_key_source->FetchKeysWithProgramIdentifier(FLAGS_program_identifier);
142 encryption_key_source = std::move(playready_key_source);
144 LOG(ERROR) <<
"Error creating PlayReady key source.";
145 return std::unique_ptr<KeySource>();
148 return encryption_key_source;
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());
159 return std::unique_ptr<KeySource>();
160 widevine_key_source->set_signer(std::move(request_signer));
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[] =
"";
168 FLAGS_key_id, FLAGS_key, kNoPssh, kNoIv);
170 return decryption_key_source;
173 ChunkingOptions GetChunkingOptions() {
174 ChunkingOptions chunking_options;
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;
182 EncryptionOptions GetEncryptionOptions() {
183 EncryptionOptions encryption_options;
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;
196 MuxerOptions GetMuxerOptions() {
197 MuxerOptions muxer_options;
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.";
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;
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)
219 mpd_options.minimum_update_period = FLAGS_minimum_update_period;
220 mpd_options.min_buffer_time = FLAGS_min_buffer_time;
221 mpd_options.time_shift_buffer_depth = FLAGS_time_shift_buffer_depth;
222 mpd_options.suggested_presentation_delay = FLAGS_suggested_presentation_delay;
223 mpd_options.default_language = FLAGS_default_language;
227 Status ConnectHandlers(std::vector<std::shared_ptr<MediaHandler>>& handlers) {
228 size_t num_handlers = handlers.size();
230 for (
size_t i = 1; i < num_handlers; ++i) {
231 status.
Update(handlers[i - 1]->AddHandler(handlers[i]));