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.");
33 void DumpStreamInfo(
const std::vector<MediaStream*>& streams) {
34 printf(
"Found %zu stream(s).\n", streams.size());
35 for (
size_t i = 0; i < streams.size(); ++i)
36 printf(
"Stream [%zu] %s\n", i, streams[i]->info()->ToString().c_str());
39 scoped_ptr<RequestSigner> CreateSigner() {
40 scoped_ptr<RequestSigner> signer;
42 if (!FLAGS_aes_signing_key.empty()) {
44 FLAGS_signer, FLAGS_aes_signing_key, FLAGS_aes_signing_iv));
46 LOG(ERROR) <<
"Cannot create an AES signer object from '"
47 << FLAGS_aes_signing_key <<
"':'" << FLAGS_aes_signing_iv
49 return scoped_ptr<RequestSigner>();
51 }
else if (!FLAGS_rsa_signing_key_path.empty()) {
52 std::string rsa_private_key;
55 LOG(ERROR) <<
"Failed to read from '" << FLAGS_rsa_signing_key_path
57 return scoped_ptr<RequestSigner>();
61 LOG(ERROR) <<
"Cannot create a RSA signer object from '"
62 << FLAGS_rsa_signing_key_path <<
"'.";
63 return scoped_ptr<RequestSigner>();
69 scoped_ptr<KeySource> CreateEncryptionKeySource() {
70 scoped_ptr<KeySource> encryption_key_source;
71 if (FLAGS_enable_widevine_encryption) {
72 scoped_ptr<WidevineKeySource> widevine_key_source(
73 new WidevineKeySource(FLAGS_key_server_url, FLAGS_include_common_pssh));
74 if (!FLAGS_signer.empty()) {
75 scoped_ptr<RequestSigner> request_signer(CreateSigner());
77 return scoped_ptr<KeySource>();
78 widevine_key_source->set_signer(request_signer.Pass());
81 std::vector<uint8_t> content_id;
82 if (!base::HexStringToBytes(FLAGS_content_id, &content_id)) {
83 LOG(ERROR) <<
"Invalid content_id hex string specified.";
84 return scoped_ptr<KeySource>();
86 Status status = widevine_key_source->FetchKeys(content_id, FLAGS_policy);
88 LOG(ERROR) <<
"Widevine encryption key source failed to fetch keys: "
90 return scoped_ptr<KeySource>();
92 encryption_key_source = widevine_key_source.Pass();
93 }
else if (FLAGS_enable_fixed_key_encryption) {
95 FLAGS_key_id, FLAGS_key, FLAGS_pssh, FLAGS_iv);
97 return encryption_key_source.Pass();
100 scoped_ptr<KeySource> CreateDecryptionKeySource() {
101 scoped_ptr<KeySource> decryption_key_source;
102 if (FLAGS_enable_widevine_decryption) {
103 scoped_ptr<WidevineKeySource> widevine_key_source(
104 new WidevineKeySource(FLAGS_key_server_url, FLAGS_include_common_pssh));
105 if (!FLAGS_signer.empty()) {
106 scoped_ptr<RequestSigner> request_signer(CreateSigner());
108 return scoped_ptr<KeySource>();
109 widevine_key_source->set_signer(request_signer.Pass());
112 decryption_key_source = widevine_key_source.Pass();
113 }
else if (FLAGS_enable_fixed_key_decryption) {
114 const char kNoPssh[] =
"";
115 const char kNoIv[] =
"";
117 FLAGS_key_id, FLAGS_key, kNoPssh, kNoIv);
119 return decryption_key_source.Pass();
122 bool AssignFlagsFromProfile() {
123 bool single_segment = FLAGS_single_segment;
124 if (FLAGS_profile ==
"on-demand") {
125 single_segment =
true;
126 }
else if (FLAGS_profile ==
"live") {
127 single_segment =
false;
128 }
else if (FLAGS_profile !=
"") {
129 fprintf(stderr,
"ERROR: --profile '%s' is not supported.\n",
130 FLAGS_profile.c_str());
134 if (FLAGS_single_segment != single_segment) {
135 FLAGS_single_segment = single_segment;
136 fprintf(stdout,
"Profile %s: set --single_segment to %s.\n",
137 FLAGS_profile.c_str(), single_segment ?
"true" :
"false");
142 bool GetMuxerOptions(MuxerOptions* muxer_options) {
143 DCHECK(muxer_options);
145 muxer_options->single_segment = FLAGS_single_segment;
146 muxer_options->segment_duration = FLAGS_segment_duration;
147 muxer_options->fragment_duration = FLAGS_fragment_duration;
148 muxer_options->segment_sap_aligned = FLAGS_segment_sap_aligned;
149 muxer_options->fragment_sap_aligned = FLAGS_fragment_sap_aligned;
150 muxer_options->num_subsegments_per_sidx = FLAGS_num_subsegments_per_sidx;
151 muxer_options->temp_dir = FLAGS_temp_dir;
155 bool GetMpdOptions(MpdOptions* mpd_options) {
158 mpd_options->availability_time_offset = FLAGS_availability_time_offset;
159 mpd_options->minimum_update_period = FLAGS_minimum_update_period;
160 mpd_options->min_buffer_time = FLAGS_min_buffer_time;
161 mpd_options->time_shift_buffer_depth = FLAGS_time_shift_buffer_depth;
162 mpd_options->suggested_presentation_delay =
163 FLAGS_suggested_presentation_delay;
167 MediaStream* FindFirstStreamOfType(
const std::vector<MediaStream*>& streams,
168 StreamType stream_type) {
169 typedef std::vector<MediaStream*>::const_iterator StreamIterator;
170 for (StreamIterator it = streams.begin(); it != streams.end(); ++it) {
171 if ((*it)->info()->stream_type() == stream_type)
176 MediaStream* FindFirstVideoStream(
const std::vector<MediaStream*>& streams) {
177 return FindFirstStreamOfType(streams, kStreamVideo);
179 MediaStream* FindFirstAudioStream(
const std::vector<MediaStream*>& streams) {
180 return FindFirstStreamOfType(streams, kStreamAudio);
183 bool AddStreamToMuxer(
const std::vector<MediaStream*>& streams,
184 const std::string& stream_selector,
185 const std::string& language_override,
189 MediaStream* stream = NULL;
190 if (stream_selector ==
"video") {
191 stream = FindFirstVideoStream(streams);
192 }
else if (stream_selector ==
"audio") {
193 stream = FindFirstAudioStream(streams);
197 if (!base::StringToSizeT(stream_selector, &stream_id) ||
198 stream_id >= streams.size()) {
199 LOG(ERROR) <<
"Invalid argument --stream=" << stream_selector <<
"; "
200 <<
"should be 'audio', 'video', or a number within [0, "
201 << streams.size() - 1 <<
"].";
204 stream = streams[stream_id];
211 LOG(ERROR) <<
"No " << stream_selector <<
" stream found in the input.";
215 if (!language_override.empty()) {
216 stream->info()->set_language(language_override);
219 muxer->AddStream(stream);