7 #include "packager/app/packager_util.h"
9 #include <gflags/gflags.h>
12 #include "packager/app/fixed_key_encryption_flags.h"
13 #include "packager/app/mpd_flags.h"
14 #include "packager/app/muxer_flags.h"
15 #include "packager/app/widevine_encryption_flags.h"
16 #include "packager/base/logging.h"
17 #include "packager/base/strings/string_number_conversions.h"
18 #include "packager/media/base/media_stream.h"
19 #include "packager/media/base/muxer.h"
20 #include "packager/media/base/muxer_options.h"
21 #include "packager/media/base/request_signer.h"
22 #include "packager/media/base/stream_info.h"
23 #include "packager/media/base/widevine_key_source.h"
24 #include "packager/media/file/file.h"
25 #include "packager/mpd/base/mpd_builder.h"
27 DEFINE_bool(dump_stream_info,
false,
"Dump demuxed stream info.");
28 DEFINE_bool(override_version_string,
30 "Override packager version string in the generated outputs with "
31 "--test_version_string if it is set to true. Should be used for "
33 DEFINE_string(test_version_string,
35 "Packager version string for testing. Ignored if "
36 "--override_version_string is false. Should be used for testing "
39 namespace edash_packager {
42 void DumpStreamInfo(
const std::vector<MediaStream*>& streams) {
43 printf(
"Found %zu stream(s).\n", streams.size());
44 for (
size_t i = 0; i < streams.size(); ++i)
45 printf(
"Stream [%zu] %s\n", i, streams[i]->info()->ToString().c_str());
48 scoped_ptr<RequestSigner> CreateSigner() {
49 scoped_ptr<RequestSigner> signer;
51 if (!FLAGS_aes_signing_key.empty()) {
53 FLAGS_signer, FLAGS_aes_signing_key, FLAGS_aes_signing_iv));
55 LOG(ERROR) <<
"Cannot create an AES signer object from '"
56 << FLAGS_aes_signing_key <<
"':'" << FLAGS_aes_signing_iv
58 return scoped_ptr<RequestSigner>();
60 }
else if (!FLAGS_rsa_signing_key_path.empty()) {
61 std::string rsa_private_key;
64 LOG(ERROR) <<
"Failed to read from '" << FLAGS_rsa_signing_key_path
66 return scoped_ptr<RequestSigner>();
70 LOG(ERROR) <<
"Cannot create a RSA signer object from '"
71 << FLAGS_rsa_signing_key_path <<
"'.";
72 return scoped_ptr<RequestSigner>();
78 scoped_ptr<KeySource> CreateEncryptionKeySource() {
79 scoped_ptr<KeySource> encryption_key_source;
80 if (FLAGS_enable_widevine_encryption) {
81 scoped_ptr<WidevineKeySource> widevine_key_source(
82 new WidevineKeySource(FLAGS_key_server_url));
83 if (!FLAGS_signer.empty()) {
84 scoped_ptr<RequestSigner> request_signer(CreateSigner());
86 return scoped_ptr<KeySource>();
87 widevine_key_source->set_signer(request_signer.Pass());
90 std::vector<uint8_t> content_id;
91 if (!base::HexStringToBytes(FLAGS_content_id, &content_id)) {
92 LOG(ERROR) <<
"Invalid content_id hex string specified.";
93 return scoped_ptr<KeySource>();
95 Status status = widevine_key_source->FetchKeys(content_id, FLAGS_policy);
97 LOG(ERROR) <<
"Widevine encryption key source failed to fetch keys: "
99 return scoped_ptr<KeySource>();
101 encryption_key_source = widevine_key_source.Pass();
102 }
else if (FLAGS_enable_fixed_key_encryption) {
104 FLAGS_key_id, FLAGS_key, FLAGS_pssh, FLAGS_iv);
106 return encryption_key_source.Pass();
109 scoped_ptr<KeySource> CreateDecryptionKeySource() {
110 scoped_ptr<KeySource> decryption_key_source;
111 if (FLAGS_enable_widevine_decryption) {
112 scoped_ptr<WidevineKeySource> widevine_key_source(
113 new WidevineKeySource(FLAGS_key_server_url));
114 if (!FLAGS_signer.empty()) {
115 scoped_ptr<RequestSigner> request_signer(CreateSigner());
117 return scoped_ptr<KeySource>();
118 widevine_key_source->set_signer(request_signer.Pass());
121 decryption_key_source = widevine_key_source.Pass();
122 }
else if (FLAGS_enable_fixed_key_decryption) {
123 decryption_key_source =
126 return decryption_key_source.Pass();
129 bool AssignFlagsFromProfile() {
130 bool single_segment = FLAGS_single_segment;
131 if (FLAGS_profile ==
"on-demand") {
132 single_segment =
true;
133 }
else if (FLAGS_profile ==
"live") {
134 single_segment =
false;
135 }
else if (FLAGS_profile !=
"") {
136 fprintf(stderr,
"ERROR: --profile '%s' is not supported.\n",
137 FLAGS_profile.c_str());
141 if (FLAGS_single_segment != single_segment) {
142 FLAGS_single_segment = single_segment;
143 fprintf(stdout,
"Profile %s: set --single_segment to %s.\n",
144 FLAGS_profile.c_str(), single_segment ?
"true" :
"false");
149 bool GetMuxerOptions(MuxerOptions* muxer_options) {
150 DCHECK(muxer_options);
152 muxer_options->single_segment = FLAGS_single_segment;
153 muxer_options->segment_duration = FLAGS_segment_duration;
154 muxer_options->fragment_duration = FLAGS_fragment_duration;
155 muxer_options->segment_sap_aligned = FLAGS_segment_sap_aligned;
156 muxer_options->fragment_sap_aligned = FLAGS_fragment_sap_aligned;
157 muxer_options->num_subsegments_per_sidx = FLAGS_num_subsegments_per_sidx;
158 muxer_options->temp_dir = FLAGS_temp_dir;
159 if (FLAGS_override_version_string)
160 muxer_options->packager_version_string = FLAGS_test_version_string;
164 bool GetMpdOptions(MpdOptions* mpd_options) {
167 mpd_options->availability_time_offset = FLAGS_availability_time_offset;
168 mpd_options->minimum_update_period = FLAGS_minimum_update_period;
169 mpd_options->min_buffer_time = FLAGS_min_buffer_time;
170 mpd_options->time_shift_buffer_depth = FLAGS_time_shift_buffer_depth;
171 mpd_options->suggested_presentation_delay =
172 FLAGS_suggested_presentation_delay;
173 if (FLAGS_override_version_string)
174 mpd_options->packager_version_string = FLAGS_test_version_string;
178 MediaStream* FindFirstStreamOfType(
const std::vector<MediaStream*>& streams,
179 StreamType stream_type) {
180 typedef std::vector<MediaStream*>::const_iterator StreamIterator;
181 for (StreamIterator it = streams.begin(); it != streams.end(); ++it) {
182 if ((*it)->info()->stream_type() == stream_type)
187 MediaStream* FindFirstVideoStream(
const std::vector<MediaStream*>& streams) {
188 return FindFirstStreamOfType(streams, kStreamVideo);
190 MediaStream* FindFirstAudioStream(
const std::vector<MediaStream*>& streams) {
191 return FindFirstStreamOfType(streams, kStreamAudio);
194 bool AddStreamToMuxer(
const std::vector<MediaStream*>& streams,
195 const std::string& stream_selector,
196 const std::string& language_override,
200 MediaStream* stream = NULL;
201 if (stream_selector ==
"video") {
202 stream = FindFirstVideoStream(streams);
203 }
else if (stream_selector ==
"audio") {
204 stream = FindFirstAudioStream(streams);
208 if (!base::StringToSizeT(stream_selector, &stream_id) ||
209 stream_id >= streams.size()) {
210 LOG(ERROR) <<
"Invalid argument --stream=" << stream_selector <<
"; "
211 <<
"should be 'audio', 'video', or a number within [0, "
212 << streams.size() - 1 <<
"].";
215 stream = streams[stream_id];
222 LOG(ERROR) <<
"No " << stream_selector <<
" stream found in the input.";
226 if (!language_override.empty()) {
227 stream->info()->set_language(language_override);
230 muxer->AddStream(stream);