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.");
29 namespace edash_packager {
32 void DumpStreamInfo(
const std::vector<MediaStream*>& streams) {
33 printf(
"Found %zu stream(s).\n", streams.size());
34 for (
size_t i = 0; i < streams.size(); ++i)
35 printf(
"Stream [%zu] %s\n", i, streams[i]->info()->ToString().c_str());
38 scoped_ptr<RequestSigner> CreateSigner() {
39 scoped_ptr<RequestSigner> signer;
41 if (!FLAGS_aes_signing_key.empty()) {
43 FLAGS_signer, FLAGS_aes_signing_key, FLAGS_aes_signing_iv));
45 LOG(ERROR) <<
"Cannot create an AES signer object from '"
46 << FLAGS_aes_signing_key <<
"':'" << FLAGS_aes_signing_iv
48 return scoped_ptr<RequestSigner>();
50 }
else if (!FLAGS_rsa_signing_key_path.empty()) {
51 std::string rsa_private_key;
54 LOG(ERROR) <<
"Failed to read from '" << FLAGS_rsa_signing_key_path
56 return scoped_ptr<RequestSigner>();
60 LOG(ERROR) <<
"Cannot create a RSA signer object from '"
61 << FLAGS_rsa_signing_key_path <<
"'.";
62 return scoped_ptr<RequestSigner>();
68 scoped_ptr<KeySource> CreateEncryptionKeySource() {
69 scoped_ptr<KeySource> encryption_key_source;
70 if (FLAGS_enable_widevine_encryption) {
71 scoped_ptr<WidevineKeySource> widevine_key_source(
72 new WidevineKeySource(FLAGS_key_server_url));
73 if (!FLAGS_signer.empty()) {
74 scoped_ptr<RequestSigner> request_signer(CreateSigner());
76 return scoped_ptr<KeySource>();
77 widevine_key_source->set_signer(request_signer.Pass());
80 std::vector<uint8_t> content_id;
81 if (!base::HexStringToBytes(FLAGS_content_id, &content_id)) {
82 LOG(ERROR) <<
"Invalid content_id hex string specified.";
83 return scoped_ptr<KeySource>();
85 Status status = widevine_key_source->FetchKeys(content_id, FLAGS_policy);
87 LOG(ERROR) <<
"Widevine encryption key source failed to fetch keys: "
89 return scoped_ptr<KeySource>();
91 encryption_key_source = widevine_key_source.Pass();
92 }
else if (FLAGS_enable_fixed_key_encryption) {
94 FLAGS_key_id, FLAGS_key, FLAGS_pssh, FLAGS_iv);
96 return encryption_key_source.Pass();
99 scoped_ptr<KeySource> CreateDecryptionKeySource() {
100 scoped_ptr<KeySource> decryption_key_source;
101 if (FLAGS_enable_widevine_decryption) {
102 scoped_ptr<WidevineKeySource> widevine_key_source(
103 new WidevineKeySource(FLAGS_key_server_url));
104 if (!FLAGS_signer.empty()) {
105 scoped_ptr<RequestSigner> request_signer(CreateSigner());
107 return scoped_ptr<KeySource>();
108 widevine_key_source->set_signer(request_signer.Pass());
111 decryption_key_source = widevine_key_source.Pass();
112 }
else if (FLAGS_enable_fixed_key_decryption) {
113 decryption_key_source =
116 return decryption_key_source.Pass();
119 bool AssignFlagsFromProfile() {
120 bool single_segment = FLAGS_single_segment;
121 if (FLAGS_profile ==
"on-demand") {
122 single_segment =
true;
123 }
else if (FLAGS_profile ==
"live") {
124 single_segment =
false;
125 }
else if (FLAGS_profile !=
"") {
126 fprintf(stderr,
"ERROR: --profile '%s' is not supported.\n",
127 FLAGS_profile.c_str());
131 if (FLAGS_single_segment != single_segment) {
132 FLAGS_single_segment = single_segment;
133 fprintf(stdout,
"Profile %s: set --single_segment to %s.\n",
134 FLAGS_profile.c_str(), single_segment ?
"true" :
"false");
139 bool GetMuxerOptions(MuxerOptions* muxer_options) {
140 DCHECK(muxer_options);
142 muxer_options->single_segment = FLAGS_single_segment;
143 muxer_options->segment_duration = FLAGS_segment_duration;
144 muxer_options->fragment_duration = FLAGS_fragment_duration;
145 muxer_options->segment_sap_aligned = FLAGS_segment_sap_aligned;
146 muxer_options->fragment_sap_aligned = FLAGS_fragment_sap_aligned;
147 muxer_options->num_subsegments_per_sidx = FLAGS_num_subsegments_per_sidx;
148 muxer_options->temp_dir = FLAGS_temp_dir;
152 bool GetMpdOptions(MpdOptions* mpd_options) {
155 mpd_options->availability_time_offset = FLAGS_availability_time_offset;
156 mpd_options->minimum_update_period = FLAGS_minimum_update_period;
157 mpd_options->min_buffer_time = FLAGS_min_buffer_time;
158 mpd_options->time_shift_buffer_depth = FLAGS_time_shift_buffer_depth;
159 mpd_options->suggested_presentation_delay =
160 FLAGS_suggested_presentation_delay;
164 MediaStream* FindFirstStreamOfType(
const std::vector<MediaStream*>& streams,
165 StreamType stream_type) {
166 typedef std::vector<MediaStream*>::const_iterator StreamIterator;
167 for (StreamIterator it = streams.begin(); it != streams.end(); ++it) {
168 if ((*it)->info()->stream_type() == stream_type)
173 MediaStream* FindFirstVideoStream(
const std::vector<MediaStream*>& streams) {
174 return FindFirstStreamOfType(streams, kStreamVideo);
176 MediaStream* FindFirstAudioStream(
const std::vector<MediaStream*>& streams) {
177 return FindFirstStreamOfType(streams, kStreamAudio);
180 bool AddStreamToMuxer(
const std::vector<MediaStream*>& streams,
181 const std::string& stream_selector,
182 const std::string& language_override,
186 MediaStream* stream = NULL;
187 if (stream_selector ==
"video") {
188 stream = FindFirstVideoStream(streams);
189 }
else if (stream_selector ==
"audio") {
190 stream = FindFirstAudioStream(streams);
194 if (!base::StringToSizeT(stream_selector, &stream_id) ||
195 stream_id >= streams.size()) {
196 LOG(ERROR) <<
"Invalid argument --stream=" << stream_selector <<
"; "
197 <<
"should be 'audio', 'video', or a number within [0, "
198 << streams.size() - 1 <<
"].";
201 stream = streams[stream_id];
208 LOG(ERROR) <<
"No " << stream_selector <<
" stream found in the input.";
212 if (!language_override.empty()) {
213 stream->info()->set_language(language_override);
216 muxer->AddStream(stream);