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/fixed_key_source.h"
19 #include "packager/media/base/media_stream.h"
20 #include "packager/media/base/muxer.h"
21 #include "packager/media/base/muxer_options.h"
22 #include "packager/media/base/request_signer.h"
23 #include "packager/media/base/stream_info.h"
24 #include "packager/media/base/widevine_key_source.h"
25 #include "packager/media/file/file.h"
26 #include "packager/mpd/base/mpd_builder.h"
28 DEFINE_bool(dump_stream_info,
false,
"Dump demuxed stream info.");
29 DEFINE_bool(override_version_string,
31 "Override packager version string in the generated outputs with "
32 "--test_version_string if it is set to true. Should be used for "
34 DEFINE_string(test_version_string,
36 "Packager version string for testing. Ignored if "
37 "--override_version_string is false. Should be used for testing "
40 namespace edash_packager {
43 void DumpStreamInfo(
const std::vector<MediaStream*>& streams) {
44 printf(
"Found %zu stream(s).\n", streams.size());
45 for (
size_t i = 0; i < streams.size(); ++i)
46 printf(
"Stream [%zu] %s\n", i, streams[i]->info()->ToString().c_str());
49 scoped_ptr<RequestSigner> CreateSigner() {
50 scoped_ptr<RequestSigner> signer;
52 if (!FLAGS_aes_signing_key.empty()) {
54 FLAGS_signer, FLAGS_aes_signing_key, FLAGS_aes_signing_iv));
56 LOG(ERROR) <<
"Cannot create an AES signer object from '"
57 << FLAGS_aes_signing_key <<
"':'" << FLAGS_aes_signing_iv
59 return scoped_ptr<RequestSigner>();
61 }
else if (!FLAGS_rsa_signing_key_path.empty()) {
62 std::string rsa_private_key;
65 LOG(ERROR) <<
"Failed to read from '" << FLAGS_rsa_signing_key_path
67 return scoped_ptr<RequestSigner>();
71 LOG(ERROR) <<
"Cannot create a RSA signer object from '"
72 << FLAGS_rsa_signing_key_path <<
"'.";
73 return scoped_ptr<RequestSigner>();
79 scoped_ptr<KeySource> CreateEncryptionKeySource() {
80 scoped_ptr<KeySource> encryption_key_source;
81 if (FLAGS_enable_widevine_encryption) {
82 scoped_ptr<WidevineKeySource> widevine_key_source(
83 new WidevineKeySource(FLAGS_key_server_url, FLAGS_include_common_pssh));
84 if (!FLAGS_signer.empty()) {
85 scoped_ptr<RequestSigner> request_signer(CreateSigner());
87 return scoped_ptr<KeySource>();
88 widevine_key_source->set_signer(request_signer.Pass());
91 std::vector<uint8_t> content_id;
92 if (!base::HexStringToBytes(FLAGS_content_id, &content_id)) {
93 LOG(ERROR) <<
"Invalid content_id hex string specified.";
94 return scoped_ptr<KeySource>();
96 Status status = widevine_key_source->FetchKeys(content_id, FLAGS_policy);
98 LOG(ERROR) <<
"Widevine encryption key source failed to fetch keys: "
100 return scoped_ptr<KeySource>();
102 encryption_key_source = widevine_key_source.Pass();
103 }
else if (FLAGS_enable_fixed_key_encryption) {
105 FLAGS_key_id, FLAGS_key, FLAGS_pssh, FLAGS_iv);
107 return encryption_key_source.Pass();
110 scoped_ptr<KeySource> CreateDecryptionKeySource() {
111 scoped_ptr<KeySource> decryption_key_source;
112 if (FLAGS_enable_widevine_decryption) {
113 scoped_ptr<WidevineKeySource> widevine_key_source(
114 new WidevineKeySource(FLAGS_key_server_url, FLAGS_include_common_pssh));
115 if (!FLAGS_signer.empty()) {
116 scoped_ptr<RequestSigner> request_signer(CreateSigner());
118 return scoped_ptr<KeySource>();
119 widevine_key_source->set_signer(request_signer.Pass());
122 decryption_key_source = widevine_key_source.Pass();
123 }
else if (FLAGS_enable_fixed_key_decryption) {
124 const char kNoPssh[] =
"";
125 const char kNoIv[] =
"";
127 FLAGS_key_id, FLAGS_key, kNoPssh, kNoIv);
129 return decryption_key_source.Pass();
132 bool AssignFlagsFromProfile() {
133 bool single_segment = FLAGS_single_segment;
134 if (FLAGS_profile ==
"on-demand") {
135 single_segment =
true;
136 }
else if (FLAGS_profile ==
"live") {
137 single_segment =
false;
138 }
else if (FLAGS_profile !=
"") {
139 fprintf(stderr,
"ERROR: --profile '%s' is not supported.\n",
140 FLAGS_profile.c_str());
144 if (FLAGS_single_segment != single_segment) {
145 FLAGS_single_segment = single_segment;
146 fprintf(stdout,
"Profile %s: set --single_segment to %s.\n",
147 FLAGS_profile.c_str(), single_segment ?
"true" :
"false");
152 bool GetMuxerOptions(MuxerOptions* muxer_options) {
153 DCHECK(muxer_options);
155 muxer_options->single_segment = FLAGS_single_segment;
156 muxer_options->segment_duration = FLAGS_segment_duration;
157 muxer_options->fragment_duration = FLAGS_fragment_duration;
158 muxer_options->segment_sap_aligned = FLAGS_segment_sap_aligned;
159 muxer_options->fragment_sap_aligned = FLAGS_fragment_sap_aligned;
160 muxer_options->num_subsegments_per_sidx = FLAGS_num_subsegments_per_sidx;
161 muxer_options->temp_dir = FLAGS_temp_dir;
162 if (FLAGS_override_version_string)
163 muxer_options->packager_version_string = FLAGS_test_version_string;
167 bool GetMpdOptions(MpdOptions* mpd_options) {
170 mpd_options->availability_time_offset = FLAGS_availability_time_offset;
171 mpd_options->minimum_update_period = FLAGS_minimum_update_period;
172 mpd_options->min_buffer_time = FLAGS_min_buffer_time;
173 mpd_options->time_shift_buffer_depth = FLAGS_time_shift_buffer_depth;
174 mpd_options->suggested_presentation_delay =
175 FLAGS_suggested_presentation_delay;
176 if (FLAGS_override_version_string)
177 mpd_options->packager_version_string = FLAGS_test_version_string;
181 MediaStream* FindFirstStreamOfType(
const std::vector<MediaStream*>& streams,
182 StreamType stream_type) {
183 typedef std::vector<MediaStream*>::const_iterator StreamIterator;
184 for (StreamIterator it = streams.begin(); it != streams.end(); ++it) {
185 if ((*it)->info()->stream_type() == stream_type)
190 MediaStream* FindFirstVideoStream(
const std::vector<MediaStream*>& streams) {
191 return FindFirstStreamOfType(streams, kStreamVideo);
193 MediaStream* FindFirstAudioStream(
const std::vector<MediaStream*>& streams) {
194 return FindFirstStreamOfType(streams, kStreamAudio);
197 bool AddStreamToMuxer(
const std::vector<MediaStream*>& streams,
198 const std::string& stream_selector,
199 const std::string& language_override,
203 MediaStream* stream = NULL;
204 if (stream_selector ==
"video") {
205 stream = FindFirstVideoStream(streams);
206 }
else if (stream_selector ==
"audio") {
207 stream = FindFirstAudioStream(streams);
211 if (!base::StringToSizeT(stream_selector, &stream_id) ||
212 stream_id >= streams.size()) {
213 LOG(ERROR) <<
"Invalid argument --stream=" << stream_selector <<
"; "
214 <<
"should be 'audio', 'video', or a number within [0, "
215 << streams.size() - 1 <<
"].";
218 stream = streams[stream_id];
225 LOG(ERROR) <<
"No " << stream_selector <<
" stream found in the input.";
229 if (!language_override.empty()) {
230 stream->info()->set_language(language_override);
233 muxer->AddStream(stream);