15 #include <absl/flags/flag.h>
16 #include <absl/flags/parse.h>
17 #include <absl/flags/usage.h>
18 #include <absl/flags/usage_config.h>
19 #include <absl/log/globals.h>
20 #include <absl/log/initialize.h>
21 #include <absl/log/log.h>
22 #include <absl/strings/numbers.h>
23 #include <absl/strings/str_format.h>
24 #include <absl/strings/str_split.h>
26 #include <packager/app/ad_cue_generator_flags.h>
27 #include <packager/app/crypto_flags.h>
28 #include <packager/app/hls_flags.h>
29 #include <packager/app/manifest_flags.h>
30 #include <packager/app/mpd_flags.h>
31 #include <packager/app/muxer_flags.h>
32 #include <packager/app/playready_key_encryption_flags.h>
33 #include <packager/app/protection_system_flags.h>
34 #include <packager/app/raw_key_encryption_flags.h>
35 #include <packager/app/retired_flags.h>
36 #include <packager/app/stream_descriptor.h>
37 #include <packager/app/widevine_encryption_flags.h>
38 #include <packager/file.h>
39 #include <packager/kv_pairs/kv_pairs.h>
40 #include <packager/tools/license_notice.h>
41 #include <packager/utils/string_trim_split.h>
43 ABSL_FLAG(
bool, dump_stream_info,
false,
"Dump demuxed stream info.");
44 ABSL_FLAG(
bool, licenses,
false,
"Dump licenses.");
45 ABSL_FLAG(
bool, quiet,
false,
"When enabled, LOG(INFO) output is suppressed.");
47 use_fake_clock_for_muxer,
49 "Set to true to use a fake clock for muxer. With this flag set, "
50 "creation time and modification time in outputs are set to 0. "
51 "Should only be used for testing.");
52 ABSL_FLAG(std::string,
53 test_packager_version,
55 "Packager version for testing. Should be used for testing only.");
59 "If enabled, only use one thread when generating content.");
62 ABSL_DECLARE_FLAG(
int, stderrthreshold);
68 "%s [flags] <stream_descriptor> ...\n\n"
69 " stream_descriptor consists of comma separated field_name/value pairs:\n"
70 " field_name=value,[field_name=value,]...\n"
71 " Supported field names are as follows (names in parenthesis are alias):\n"
72 " - input (in): Required input/source media file path or network stream\n"
74 " - stream_selector (stream): Required field with value 'audio',\n"
75 " 'video', 'text', or stream number (zero based).\n"
76 " - output (out,init_segment): Required output file (single file) or\n"
77 " initialization file path (multiple file).\n"
78 " - segment_template (segment): Optional value which specifies the\n"
79 " naming pattern for the segment files, and that the stream should be\n"
80 " split into multiple files. Its presence should be consistent across\n"
82 " - bandwidth (bw): Optional value which contains a user-specified\n"
83 " maximum bit rate for the stream, in bits/sec. If specified, this\n"
84 " value is propagated to (HLS) EXT-X-STREAM-INF:BANDWIDTH or (DASH)\n"
85 " Representation@bandwidth and the $Bandwidth$ template parameter for\n"
86 " segment names. If not specified, the bandwidth value is estimated\n"
87 " from content bitrate. Note that it only affects the generated\n"
88 " manifests/playlists; it has no effect on the media content itself.\n"
89 " - language (lang): Optional value which contains a user-specified\n"
90 " language tag. If specified, this value overrides any language\n"
91 " metadata in the input stream.\n"
92 " - output_format (format): Optional value which specifies the format\n"
93 " of the output files (MP4 or WebM). If not specified, it will be\n"
94 " derived from the file extension of the output file.\n"
95 " - input_format (format): Optional value which specifies the format\n"
96 " of the input files or streams. If not specified, it will be\n"
97 " autodetected, which in some cases (such as live UDP webvtt) may\n"
99 " - skip_encryption=0|1: Optional. Defaults to 0 if not specified. If\n"
100 " it is set to 1, no encryption of the stream will be made.\n"
101 " - drm_label: Optional value for custom DRM label, which defines the\n"
102 " encryption key applied to the stream. Typical values include AUDIO,\n"
103 " SD, HD, UHD1, UHD2. For raw key, it should be a label defined in\n"
104 " --keys. If not provided, the DRM label is derived from stream type\n"
105 " (video, audio), resolution, etc.\n"
106 " Note that it is case sensitive.\n"
107 " - trick_play_factor (tpf): Optional value which specifies the trick\n"
108 " play, a.k.a. trick mode, stream sampling rate among key frames.\n"
109 " If specified, the output is a trick play stream.\n"
110 " - hls_name: Used for HLS audio to set the NAME attribute for\n"
111 " EXT-X-MEDIA. Defaults to the base of the playlist name.\n"
112 " - hls_group_id: Used for HLS audio to set the GROUP-ID attribute for\n"
113 " EXT-X-MEDIA. Defaults to 'audio' if not specified.\n"
114 " - playlist_name: The HLS playlist file to create. Usually ends with\n"
115 " '.m3u8', and is relative to --hls_master_playlist_output. If\n"
116 " unspecified, defaults to something of the form 'stream_0.m3u8',\n"
117 " 'stream_1.m3u8', 'stream_2.m3u8', etc.\n"
118 " - iframe_playlist_name: The optional HLS I-Frames only playlist file\n"
119 " to create. Usually ends with '.m3u8', and is relative to\n"
120 " hls_master_playlist_output. Should only be set for video streams. If\n"
121 " unspecified, no I-Frames only playlist is created.\n"
122 " - hls_characteristics (charcs): Optional colon/semicolon separated\n"
123 " list of values for the CHARACTERISTICS attribute for EXT-X-MEDIA.\n"
124 " See CHARACTERISTICS attribute in http://bit.ly/2OOUkdB for details.\n"
125 " - dash_accessibilities (accessibilities): Optional semicolon separated\n"
126 " list of values for DASH Accessibility elements. The value should be\n"
127 " in the format: scheme_id_uri=value.\n"
128 " - dash_roles (roles): Optional semicolon separated list of values for\n"
129 " DASH Role elements. The value should be one of: caption, subtitle, \n"
130 " main, alternate, supplementary, commentary, dub, description, sign, \n"
131 " metadata, enhanced-audio- intelligibility, emergency, \n"
132 " forced-subtitle, easyreader, and karaoke. See DASH\n"
133 " (ISO/IEC 23009-1) specification for details.\n"
134 " - forced_subtitle: Optional boolean value (0|1). If set to 1 \n"
135 " indicates that this stream is a Forced Narrative subtitle that \n"
136 " should be displayed when subtitles are otherwise off, for example \n"
137 " used to caption short portions of the audio that might be in a \n"
138 " foreign language. For DASH this will set role to forced_subtitle, \n"
139 " for HLS it will set FORCED=YES and AUTOSELECT=YES. \n"
140 " Only valid for subtitles.\n";
143 const char kDrmLabelLabel[] =
"label";
144 const char kKeyIdLabel[] =
"key_id";
145 const char kKeyLabel[] =
"key";
146 const char kKeyIvLabel[] =
"iv";
150 kArgumentValidationFailed,
155 bool GetWidevineSigner(WidevineSigner* signer) {
156 signer->signer_name = absl::GetFlag(FLAGS_signer);
157 if (!absl::GetFlag(FLAGS_aes_signing_key).bytes.empty()) {
158 signer->signing_key_type = WidevineSigner::SigningKeyType::kAes;
159 signer->aes.key = absl::GetFlag(FLAGS_aes_signing_key).bytes;
160 signer->aes.iv = absl::GetFlag(FLAGS_aes_signing_iv).bytes;
161 }
else if (!absl::GetFlag(FLAGS_rsa_signing_key_path).empty()) {
162 signer->signing_key_type = WidevineSigner::SigningKeyType::kRsa;
163 if (!File::ReadFileToString(
164 absl::GetFlag(FLAGS_rsa_signing_key_path).c_str(),
166 LOG(ERROR) <<
"Failed to read from '"
167 << absl::GetFlag(FLAGS_rsa_signing_key_path) <<
"'.";
174 bool GetHlsPlaylistType(
const std::string& playlist_type,
175 HlsPlaylistType* playlist_type_enum) {
176 if (absl::AsciiStrToUpper(playlist_type) ==
"VOD") {
177 *playlist_type_enum = HlsPlaylistType::kVod;
178 }
else if (absl::AsciiStrToUpper(playlist_type) ==
"LIVE") {
179 *playlist_type_enum = HlsPlaylistType::kLive;
180 }
else if (absl::AsciiStrToUpper(playlist_type) ==
"EVENT") {
181 *playlist_type_enum = HlsPlaylistType::kEvent;
183 LOG(ERROR) <<
"Unrecognized playlist type " << playlist_type;
189 bool GetProtectionScheme(uint32_t* protection_scheme) {
190 if (absl::GetFlag(FLAGS_protection_scheme) ==
"cenc") {
191 *protection_scheme = EncryptionParams::kProtectionSchemeCenc;
194 if (absl::GetFlag(FLAGS_protection_scheme) ==
"cbc1") {
195 *protection_scheme = EncryptionParams::kProtectionSchemeCbc1;
198 if (absl::GetFlag(FLAGS_protection_scheme) ==
"cbcs") {
199 *protection_scheme = EncryptionParams::kProtectionSchemeCbcs;
202 if (absl::GetFlag(FLAGS_protection_scheme) ==
"cens") {
203 *protection_scheme = EncryptionParams::kProtectionSchemeCens;
206 LOG(ERROR) <<
"Unrecognized protection_scheme "
207 << absl::GetFlag(FLAGS_protection_scheme);
211 bool ParseKeys(
const std::string& keys, RawKeyParams* raw_key) {
212 std::vector<std::string> keys_data = SplitAndTrimSkipEmpty(keys,
',');
214 for (
const std::string& key_data : keys_data) {
215 std::vector<KVPair> string_pairs =
216 SplitStringIntoKeyValuePairs(key_data,
'=',
':');
218 std::map<std::string, std::string> value_map;
219 for (
const auto& string_pair : string_pairs)
220 value_map[string_pair.first] = string_pair.second;
221 const std::string drm_label = value_map[kDrmLabelLabel];
222 if (raw_key->key_map.find(drm_label) != raw_key->key_map.end()) {
223 LOG(ERROR) <<
"Seeing duplicated DRM label '" << drm_label <<
"'.";
226 auto& key_info = raw_key->key_map[drm_label];
227 if (value_map[kKeyIdLabel].empty() ||
228 !shaka::ValidHexStringToBytes(value_map[kKeyIdLabel],
230 LOG(ERROR) <<
"Empty key id or invalid hex string for key id: "
231 << value_map[kKeyIdLabel];
234 if (value_map[kKeyLabel].empty() ||
235 !shaka::ValidHexStringToBytes(value_map[kKeyLabel], &key_info.key)) {
236 LOG(ERROR) <<
"Empty key or invalid hex string for key: "
237 << value_map[kKeyLabel];
240 if (!value_map[kKeyIvLabel].empty()) {
241 if (!raw_key->iv.empty()) {
242 LOG(ERROR) <<
"IV already specified with --iv";
245 if (!shaka::ValidHexStringToBytes(value_map[kKeyIvLabel], &key_info.iv)) {
246 LOG(ERROR) <<
"Empty IV or invalid hex string for IV: "
247 << value_map[kKeyIvLabel];
255 bool GetRawKeyParams(RawKeyParams* raw_key) {
256 raw_key->iv = absl::GetFlag(FLAGS_iv).bytes;
257 raw_key->pssh = absl::GetFlag(FLAGS_pssh).bytes;
258 if (!absl::GetFlag(FLAGS_keys).empty()) {
259 if (!ParseKeys(absl::GetFlag(FLAGS_keys), raw_key)) {
260 LOG(ERROR) <<
"Failed to parse --keys " << absl::GetFlag(FLAGS_keys);
265 RawKeyParams::KeyInfo& key_info = raw_key->key_map[
""];
266 key_info.key_id = absl::GetFlag(FLAGS_key_id).bytes;
267 key_info.key = absl::GetFlag(FLAGS_key).bytes;
272 bool ParseAdCues(
const std::string& ad_cues, std::vector<Cuepoint>* cuepoints) {
274 size_t duration_count = 0;
275 std::vector<std::string> ad_cues_vec = SplitAndTrimSkipEmpty(ad_cues,
';');
277 for (
const std::string& ad_cue : ad_cues_vec) {
279 std::vector<std::string> split_ad_cue = SplitAndTrimSkipEmpty(ad_cue,
',');
281 if (split_ad_cue.size() > 2) {
282 LOG(ERROR) <<
"Failed to parse --ad_cues " << ad_cues
283 <<
" Each ad cue must contain no more than 2 components.";
285 if (!absl::SimpleAtod(split_ad_cue.front(),
286 &cuepoint.start_time_in_seconds)) {
287 LOG(ERROR) <<
"Failed to parse --ad_cues " << ad_cues
288 <<
" Start time component must be of type double.";
291 if (split_ad_cue.size() > 1) {
293 if (!absl::SimpleAtod(split_ad_cue[1], &cuepoint.duration_in_seconds)) {
294 LOG(ERROR) <<
"Failed to parse --ad_cues " << ad_cues
295 <<
" Duration component must be of type double.";
299 cuepoints->push_back(cuepoint);
302 if (duration_count > 0 && duration_count != cuepoints->size()) {
303 LOG(ERROR) <<
"Failed to parse --ad_cues " << ad_cues
304 <<
" Duration component is optional. However if it is supplied,"
305 <<
" it must be supplied consistently across all cuepoints.";
311 bool ParseProtectionSystems(
const std::string& protection_systems_str,
312 ProtectionSystem* protection_systems) {
313 *protection_systems = ProtectionSystem::kNone;
315 std::map<std::string, ProtectionSystem> mapping = {
316 {
"common", ProtectionSystem::kCommon},
317 {
"commonsystem", ProtectionSystem::kCommon},
318 {
"fairplay", ProtectionSystem::kFairPlay},
319 {
"marlin", ProtectionSystem::kMarlin},
320 {
"playready", ProtectionSystem::kPlayReady},
321 {
"widevine", ProtectionSystem::kWidevine},
324 std::vector<std::string> protection_systems_vec =
325 SplitAndTrimSkipEmpty(absl::AsciiStrToLower(protection_systems_str),
',');
327 for (
const std::string& protection_system : protection_systems_vec) {
328 auto iter = mapping.find(protection_system);
329 if (iter == mapping.end()) {
330 LOG(ERROR) <<
"Seeing unrecognized protection system: "
331 << protection_system;
334 *protection_systems |= iter->second;
339 std::optional<PackagingParams> GetPackagingParams() {
340 PackagingParams packaging_params;
342 packaging_params.temp_dir = absl::GetFlag(FLAGS_temp_dir);
343 packaging_params.single_threaded = absl::GetFlag(FLAGS_single_threaded);
345 AdCueGeneratorParams& ad_cue_generator_params =
346 packaging_params.ad_cue_generator_params;
347 if (!ParseAdCues(absl::GetFlag(FLAGS_ad_cues),
348 &ad_cue_generator_params.cue_points)) {
352 ChunkingParams& chunking_params = packaging_params.chunking_params;
353 chunking_params.segment_duration_in_seconds =
354 absl::GetFlag(FLAGS_segment_duration);
355 chunking_params.subsegment_duration_in_seconds =
356 absl::GetFlag(FLAGS_fragment_duration);
357 chunking_params.low_latency_dash_mode =
358 absl::GetFlag(FLAGS_low_latency_dash_mode);
359 chunking_params.segment_sap_aligned =
360 absl::GetFlag(FLAGS_segment_sap_aligned);
361 chunking_params.subsegment_sap_aligned =
362 absl::GetFlag(FLAGS_fragment_sap_aligned);
363 chunking_params.start_segment_number =
364 absl::GetFlag(FLAGS_start_segment_number);
366 int num_key_providers = 0;
367 EncryptionParams& encryption_params = packaging_params.encryption_params;
368 if (absl::GetFlag(FLAGS_enable_widevine_encryption)) {
369 encryption_params.key_provider = KeyProvider::kWidevine;
372 if (absl::GetFlag(FLAGS_enable_playready_encryption)) {
373 encryption_params.key_provider = KeyProvider::kPlayReady;
376 if (absl::GetFlag(FLAGS_enable_raw_key_encryption)) {
377 encryption_params.key_provider = KeyProvider::kRawKey;
380 if (num_key_providers > 1) {
381 LOG(ERROR) <<
"Only one of --enable_widevine_encryption, "
382 "--enable_playready_encryption, "
383 "--enable_raw_key_encryption can be enabled.";
387 if (!ParseProtectionSystems(absl::GetFlag(FLAGS_protection_systems),
388 &encryption_params.protection_systems)) {
392 if (encryption_params.key_provider != KeyProvider::kNone) {
393 encryption_params.clear_lead_in_seconds = absl::GetFlag(FLAGS_clear_lead);
394 if (!GetProtectionScheme(&encryption_params.protection_scheme))
396 encryption_params.crypt_byte_block = absl::GetFlag(FLAGS_crypt_byte_block);
397 encryption_params.skip_byte_block = absl::GetFlag(FLAGS_skip_byte_block);
399 encryption_params.crypto_period_duration_in_seconds =
400 absl::GetFlag(FLAGS_crypto_period_duration);
401 encryption_params.vp9_subsample_encryption =
402 absl::GetFlag(FLAGS_vp9_subsample_encryption);
403 encryption_params.stream_label_func = std::bind(
404 &Packager::DefaultStreamLabelFunction,
405 absl::GetFlag(FLAGS_max_sd_pixels), absl::GetFlag(FLAGS_max_hd_pixels),
406 absl::GetFlag(FLAGS_max_uhd1_pixels), std::placeholders::_1);
407 encryption_params.playready_extra_header_data =
408 absl::GetFlag(FLAGS_playready_extra_header_data);
410 switch (encryption_params.key_provider) {
411 case KeyProvider::kWidevine: {
412 WidevineEncryptionParams& widevine = encryption_params.widevine;
413 widevine.key_server_url = absl::GetFlag(FLAGS_key_server_url);
415 widevine.content_id = absl::GetFlag(FLAGS_content_id).bytes;
416 widevine.policy = absl::GetFlag(FLAGS_policy);
417 widevine.group_id = absl::GetFlag(FLAGS_group_id).bytes;
418 widevine.enable_entitlement_license =
419 absl::GetFlag(FLAGS_enable_entitlement_license);
420 if (!GetWidevineSigner(&widevine.signer))
424 case KeyProvider::kPlayReady: {
425 PlayReadyEncryptionParams& playready = encryption_params.playready;
426 playready.key_server_url = absl::GetFlag(FLAGS_playready_server_url);
427 playready.program_identifier = absl::GetFlag(FLAGS_program_identifier);
430 case KeyProvider::kRawKey: {
431 if (!GetRawKeyParams(&encryption_params.raw_key))
435 case KeyProvider::kNone:
439 num_key_providers = 0;
440 DecryptionParams& decryption_params = packaging_params.decryption_params;
441 if (absl::GetFlag(FLAGS_enable_widevine_decryption)) {
442 decryption_params.key_provider = KeyProvider::kWidevine;
445 if (absl::GetFlag(FLAGS_enable_raw_key_decryption)) {
446 decryption_params.key_provider = KeyProvider::kRawKey;
449 if (num_key_providers > 1) {
450 LOG(ERROR) <<
"Only one of --enable_widevine_decryption, "
451 "--enable_raw_key_decryption can be enabled.";
454 switch (decryption_params.key_provider) {
455 case KeyProvider::kWidevine: {
456 WidevineDecryptionParams& widevine = decryption_params.widevine;
457 widevine.key_server_url = absl::GetFlag(FLAGS_key_server_url);
458 if (!GetWidevineSigner(&widevine.signer))
462 case KeyProvider::kRawKey: {
463 if (!GetRawKeyParams(&decryption_params.raw_key))
467 case KeyProvider::kPlayReady:
468 case KeyProvider::kNone:
472 Mp4OutputParams& mp4_params = packaging_params.mp4_output_params;
473 mp4_params.generate_sidx_in_media_segments =
474 absl::GetFlag(FLAGS_generate_sidx_in_media_segments);
475 mp4_params.include_pssh_in_stream =
476 absl::GetFlag(FLAGS_mp4_include_pssh_in_stream);
477 mp4_params.low_latency_dash_mode = absl::GetFlag(FLAGS_low_latency_dash_mode);
479 packaging_params.transport_stream_timestamp_offset_ms =
480 absl::GetFlag(FLAGS_transport_stream_timestamp_offset_ms);
481 packaging_params.default_text_zero_bias_ms =
482 absl::GetFlag(FLAGS_default_text_zero_bias_ms);
484 packaging_params.output_media_info = absl::GetFlag(FLAGS_output_media_info);
486 MpdParams& mpd_params = packaging_params.mpd_params;
487 mpd_params.mpd_output = absl::GetFlag(FLAGS_mpd_output);
489 std::vector<std::string> base_urls =
490 SplitAndTrimSkipEmpty(absl::GetFlag(FLAGS_base_urls),
',');
492 mpd_params.base_urls = base_urls;
493 mpd_params.min_buffer_time = absl::GetFlag(FLAGS_min_buffer_time);
494 mpd_params.minimum_update_period = absl::GetFlag(FLAGS_minimum_update_period);
495 mpd_params.suggested_presentation_delay =
496 absl::GetFlag(FLAGS_suggested_presentation_delay);
497 mpd_params.time_shift_buffer_depth =
498 absl::GetFlag(FLAGS_time_shift_buffer_depth);
499 mpd_params.preserved_segments_outside_live_window =
500 absl::GetFlag(FLAGS_preserved_segments_outside_live_window);
501 mpd_params.use_segment_list = absl::GetFlag(FLAGS_dash_force_segment_list);
503 if (!absl::GetFlag(FLAGS_utc_timings).empty()) {
504 std::vector<KVPair> pairs = SplitStringIntoKeyValuePairs(
505 absl::GetFlag(FLAGS_utc_timings),
'=',
',');
507 LOG(ERROR) <<
"Invalid --utc_timings scheme_id_uri/value pairs.";
510 for (
const auto& string_pair : pairs) {
511 mpd_params.utc_timings.push_back({string_pair.first, string_pair.second});
515 mpd_params.default_language = absl::GetFlag(FLAGS_default_language);
516 mpd_params.default_text_language = absl::GetFlag(FLAGS_default_text_language);
517 mpd_params.generate_static_live_mpd =
518 absl::GetFlag(FLAGS_generate_static_live_mpd);
519 mpd_params.generate_dash_if_iop_compliant_mpd =
520 absl::GetFlag(FLAGS_generate_dash_if_iop_compliant_mpd);
521 mpd_params.allow_approximate_segment_timeline =
522 absl::GetFlag(FLAGS_allow_approximate_segment_timeline);
523 mpd_params.allow_codec_switching = absl::GetFlag(FLAGS_allow_codec_switching);
524 mpd_params.include_mspr_pro =
525 absl::GetFlag(FLAGS_include_mspr_pro_for_playready);
526 mpd_params.low_latency_dash_mode = absl::GetFlag(FLAGS_low_latency_dash_mode);
528 HlsParams& hls_params = packaging_params.hls_params;
529 if (!GetHlsPlaylistType(absl::GetFlag(FLAGS_hls_playlist_type),
530 &hls_params.playlist_type)) {
533 hls_params.master_playlist_output =
534 absl::GetFlag(FLAGS_hls_master_playlist_output);
535 hls_params.base_url = absl::GetFlag(FLAGS_hls_base_url);
536 hls_params.key_uri = absl::GetFlag(FLAGS_hls_key_uri);
537 hls_params.time_shift_buffer_depth =
538 absl::GetFlag(FLAGS_time_shift_buffer_depth);
539 hls_params.preserved_segments_outside_live_window =
540 absl::GetFlag(FLAGS_preserved_segments_outside_live_window);
541 hls_params.default_language = absl::GetFlag(FLAGS_default_language);
542 hls_params.default_text_language = absl::GetFlag(FLAGS_default_text_language);
543 hls_params.media_sequence_number =
544 absl::GetFlag(FLAGS_hls_media_sequence_number);
545 hls_params.start_time_offset = absl::GetFlag(FLAGS_hls_start_time_offset);
546 hls_params.create_session_keys = absl::GetFlag(FLAGS_create_session_keys);
548 TestParams& test_params = packaging_params.test_params;
549 test_params.dump_stream_info = absl::GetFlag(FLAGS_dump_stream_info);
550 test_params.inject_fake_clock = absl::GetFlag(FLAGS_use_fake_clock_for_muxer);
551 if (!absl::GetFlag(FLAGS_test_packager_version).empty())
552 test_params.injected_library_version =
553 absl::GetFlag(FLAGS_test_packager_version);
555 return packaging_params;
558 int PackagerMain(
int argc,
char** argv) {
559 absl::FlagsUsageConfig flag_config;
560 flag_config.version_string = []() -> std::string {
561 return "packager version " + shaka::Packager::GetLibraryVersion() +
"\n";
563 flag_config.contains_help_flags =
564 [](absl::string_view flag_file_name) ->
bool {
return true; };
565 absl::SetFlagsUsageConfig(flag_config);
567 auto usage = absl::StrFormat(kUsage, argv[0]);
568 absl::SetProgramUsageMessage(usage);
574 absl::SetFlag(&FLAGS_stderrthreshold, 0);
576 auto remaining_args = absl::ParseCommandLine(argc, argv);
577 if (absl::GetFlag(FLAGS_licenses)) {
578 for (
const char* line : kLicenseNotice)
579 std::cout << line << std::endl;
583 if (remaining_args.size() < 2) {
584 std::cerr <<
"Usage: " << absl::ProgramUsageMessage();
588 if (absl::GetFlag(FLAGS_quiet)) {
589 absl::SetMinLogLevel(absl::LogSeverityAtLeast::kWarning);
592 absl::InitializeLog();
596 !ValidateRetiredFlags()) {
597 return kArgumentValidationFailed;
600 std::optional<PackagingParams> packaging_params = GetPackagingParams();
601 if (!packaging_params)
602 return kArgumentValidationFailed;
604 std::vector<StreamDescriptor> stream_descriptors;
605 for (
size_t i = 1; i < remaining_args.size(); ++i) {
606 std::optional<StreamDescriptor> stream_descriptor =
608 if (!stream_descriptor)
609 return kArgumentValidationFailed;
610 stream_descriptors.push_back(stream_descriptor.value());
613 if (absl::GetFlag(FLAGS_force_cl_index)) {
615 for (
auto& descriptor : stream_descriptors) {
616 descriptor.index = index++;
622 packager.Initialize(packaging_params.value(), stream_descriptors);
624 LOG(ERROR) <<
"Failed to initialize packager: " << status.ToString();
625 return kArgumentValidationFailed;
627 status = packager.Run();
629 LOG(ERROR) <<
"Packaging Error: " << status.ToString();
630 return kPackagingFailed;
632 if (!absl::GetFlag(FLAGS_quiet))
633 printf(
"Packaging completed successfully.\n");
642 int wmain(
int argc,
wchar_t* argv[],
wchar_t* envp[]) {
643 std::unique_ptr<
char*[], std::function<void(
char**)>> utf8_argv(
644 new char*[argc], [argc](
char** utf8_args) {
652 std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
654 for (
int idx = 0; idx < argc; ++idx) {
655 std::string utf8_arg(converter.to_bytes(argv[idx]));
657 utf8_argv[idx] =
new char[utf8_arg.size()];
658 memcpy(utf8_argv[idx], &utf8_arg[0], utf8_arg.size());
665 std::setlocale(LC_ALL,
".UTF8");
667 return shaka::PackagerMain(argc, utf8_argv.get());
670 int main(
int argc,
char** argv) {
671 return shaka::PackagerMain(argc, argv);
All the methods that are virtual are virtual for mocking.
bool ValidatePRCryptoFlags()
std::optional< StreamDescriptor > ParseStreamDescriptor(const std::string &descriptor_string)
bool ValidateRawKeyCryptoFlags()
bool ValidateWidevineCryptoFlags()