14 #include <absl/flags/parse.h>
15 #include <absl/flags/usage.h>
16 #include <absl/flags/usage_config.h>
17 #include <absl/log/check.h>
18 #include <absl/log/initialize.h>
19 #include <absl/log/log.h>
20 #include <absl/strings/str_format.h>
21 #include <absl/strings/str_split.h>
23 #include <packager/app/mpd_generator_flags.h>
24 #include <packager/mpd/util/mpd_writer.h>
25 #include <packager/tools/license_notice.h>
26 #include <packager/version/version.h>
28 ABSL_FLAG(
bool, licenses,
false,
"Dump licenses.");
29 ABSL_FLAG(std::string,
30 test_packager_version,
32 "Packager version for testing. Should be used for testing only.");
35 ABSL_DECLARE_FLAG(
int, stderrthreshold);
40 "MPD generation driver program.\n"
41 "This program accepts MediaInfo files in human readable text "
42 "format and outputs an MPD.\n"
43 "The main use case for this is to output MPD for VOD.\n"
45 " Each MediaInfo can only have one of VideoInfo, AudioInfo, or TextInfo.\n"
46 " There will be at most 3 AdaptationSets in the MPD, i.e. 1 video, 1 "
47 "audio, and 1 text.\n"
49 "%s --input=\"video1.media_info,video2.media_info,audio1.media_info\" "
50 "--output=\"video_audio.mpd\"";
56 kFailedToWriteMpdToFileError
59 ExitStatus CheckRequiredFlags() {
60 if (absl::GetFlag(FLAGS_input).empty()) {
61 LOG(ERROR) <<
"--input is required.";
62 return kEmptyInputError;
65 if (absl::GetFlag(FLAGS_output).empty()) {
66 LOG(ERROR) <<
"--output is required.";
67 return kEmptyOutputError;
73 ExitStatus RunMpdGenerator() {
74 DCHECK_EQ(CheckRequiredFlags(), kSuccess);
75 std::vector<std::string> base_urls;
76 typedef std::vector<std::string>::const_iterator Iterator;
78 std::vector<std::string> input_files =
79 absl::StrSplit(absl::GetFlag(FLAGS_input),
",", absl::AllowEmpty());
81 if (!absl::GetFlag(FLAGS_base_urls).empty()) {
83 absl::StrSplit(absl::GetFlag(FLAGS_base_urls),
",", absl::AllowEmpty());
87 for (Iterator it = base_urls.begin(); it != base_urls.end(); ++it)
88 mpd_writer.AddBaseUrl(*it);
90 for (
const std::string& file : input_files) {
91 if (!mpd_writer.AddFile(file)) {
92 LOG(WARNING) <<
"MpdWriter failed to read " << file <<
", skipping.";
96 if (!mpd_writer.WriteMpdToFile(absl::GetFlag(FLAGS_output).c_str())) {
97 LOG(ERROR) <<
"Failed to write MPD to " << absl::GetFlag(FLAGS_output);
98 return kFailedToWriteMpdToFileError;
104 int MpdMain(
int argc,
char** argv) {
105 absl::FlagsUsageConfig flag_config;
106 flag_config.version_string = []() -> std::string {
107 return "mpd_generator version " + GetPackagerVersion() +
"\n";
109 flag_config.contains_help_flags =
110 [](absl::string_view flag_file_name) ->
bool {
return true; };
111 absl::SetFlagsUsageConfig(flag_config);
113 auto usage = absl::StrFormat(kUsage, argv[0]);
114 absl::SetProgramUsageMessage(usage);
120 absl::SetFlag(&FLAGS_stderrthreshold, 0);
122 absl::ParseCommandLine(argc, argv);
124 if (absl::GetFlag(FLAGS_licenses)) {
125 for (
const char* line : kLicenseNotice)
126 std::cout << line << std::endl;
130 ExitStatus status = CheckRequiredFlags();
131 if (status != kSuccess) {
132 std::cerr <<
"Usage " << absl::ProgramUsageMessage();
136 absl::InitializeLog();
138 if (!absl::GetFlag(FLAGS_test_packager_version).empty())
139 SetPackagerVersionForTesting(absl::GetFlag(FLAGS_test_packager_version));
141 return RunMpdGenerator();
149 int wmain(
int argc,
wchar_t* argv[],
wchar_t* envp[]) {
150 std::unique_ptr<
char* [], std::function<void(
char**)>> utf8_argv(
151 new char*[argc], [argc](
char** utf8_args) {
159 std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
161 for (
int idx = 0; idx < argc; ++idx) {
162 std::string utf8_arg(converter.to_bytes(argv[idx]));
164 utf8_argv[idx] =
new char[utf8_arg.size()];
165 memcpy(utf8_argv[idx], &utf8_arg[0], utf8_arg.size());
172 std::setlocale(LC_ALL,
".UTF8");
174 return shaka::MpdMain(argc, utf8_argv.get());
177 int main(
int argc,
char** argv) {
178 return shaka::MpdMain(argc, argv);
All the methods that are virtual are virtual for mocking.