11#include <absl/flags/declare.h>
12#include <absl/flags/flag.h>
13#include <absl/strings/string_view.h>
20#include <absl/flags/parse.h>
21#include <absl/flags/usage.h>
22#include <absl/flags/usage_config.h>
23#include <absl/log/check.h>
24#include <absl/log/initialize.h>
25#include <absl/log/log.h>
26#include <absl/strings/str_format.h>
27#include <absl/strings/str_split.h>
29#include <packager/app/mpd_generator_flags.h>
30#include <packager/mpd/util/mpd_writer.h>
31#include <packager/tools/license_notice.h>
32#include <packager/version/version.h>
34ABSL_FLAG(
bool, licenses,
false,
"Dump licenses.");
36 test_packager_version,
38 "Packager version for testing. Should be used for testing only.");
41ABSL_DECLARE_FLAG(
int, stderrthreshold);
46 "MPD generation driver program.\n"
47 "This program accepts MediaInfo files in human readable text "
48 "format and outputs an MPD.\n"
49 "The main use case for this is to output MPD for VOD.\n"
51 " Each MediaInfo can only have one of VideoInfo, AudioInfo, or TextInfo.\n"
52 " There will be at most 3 AdaptationSets in the MPD, i.e. 1 video, 1 "
53 "audio, and 1 text.\n"
55 "%s --input=\"video1.media_info,video2.media_info,audio1.media_info\" "
56 "--output=\"video_audio.mpd\"";
62 kFailedToWriteMpdToFileError
65ExitStatus CheckRequiredFlags() {
66 if (absl::GetFlag(FLAGS_input).empty()) {
67 LOG(ERROR) <<
"--input is required.";
68 return kEmptyInputError;
71 if (absl::GetFlag(FLAGS_output).empty()) {
72 LOG(ERROR) <<
"--output is required.";
73 return kEmptyOutputError;
79ExitStatus RunMpdGenerator() {
80 DCHECK_EQ(CheckRequiredFlags(), kSuccess);
81 std::vector<std::string> base_urls;
82 typedef std::vector<std::string>::const_iterator Iterator;
84 std::vector<std::string> input_files =
85 absl::StrSplit(absl::GetFlag(FLAGS_input),
",", absl::AllowEmpty());
87 if (!absl::GetFlag(FLAGS_base_urls).empty()) {
89 absl::StrSplit(absl::GetFlag(FLAGS_base_urls),
",", absl::AllowEmpty());
93 for (Iterator it = base_urls.begin(); it != base_urls.end(); ++it)
94 mpd_writer.AddBaseUrl(*it);
96 for (
const std::string& file : input_files) {
97 if (!mpd_writer.AddFile(file)) {
98 LOG(WARNING) <<
"MpdWriter failed to read " << file <<
", skipping.";
102 if (!mpd_writer.WriteMpdToFile(absl::GetFlag(FLAGS_output).c_str())) {
103 LOG(ERROR) <<
"Failed to write MPD to " << absl::GetFlag(FLAGS_output);
104 return kFailedToWriteMpdToFileError;
110int MpdMain(
int argc,
char** argv) {
111 absl::FlagsUsageConfig flag_config;
112 flag_config.version_string = []() -> std::string {
113 return "mpd_generator version " + GetPackagerVersion() +
"\n";
115 flag_config.contains_help_flags =
116 [](absl::string_view flag_file_name) ->
bool {
return true; };
117 absl::SetFlagsUsageConfig(flag_config);
119 auto usage = absl::StrFormat(kUsage, argv[0]);
120 absl::SetProgramUsageMessage(usage);
126 absl::SetFlag(&FLAGS_stderrthreshold, 0);
128 absl::ParseCommandLine(argc, argv);
130 if (absl::GetFlag(FLAGS_licenses)) {
131 for (
const char* line : kLicenseNotice)
132 std::cout << line << std::endl;
136 ExitStatus status = CheckRequiredFlags();
137 if (status != kSuccess) {
138 std::cerr <<
"Usage " << absl::ProgramUsageMessage();
142 absl::InitializeLog();
144 if (!absl::GetFlag(FLAGS_test_packager_version).empty())
145 SetPackagerVersionForTesting(absl::GetFlag(FLAGS_test_packager_version));
147 return RunMpdGenerator();
155int wmain(
int argc,
wchar_t* argv[],
wchar_t* envp[]) {
156 std::unique_ptr<
char*[], std::function<void(
char**)>> utf8_argv(
157 new char*[argc], [argc](
char** utf8_args) {
165 std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
167 for (
int idx = 0; idx < argc; ++idx) {
168 std::string utf8_arg(converter.to_bytes(argv[idx]));
170 utf8_argv[idx] =
new char[utf8_arg.size()];
171 memcpy(utf8_argv[idx], &utf8_arg[0], utf8_arg.size());
178 std::setlocale(LC_ALL,
".UTF8");
180 return shaka::MpdMain(argc, utf8_argv.get());
183int main(
int argc,
char** argv) {
184 return shaka::MpdMain(argc, argv);
All the methods that are virtual are virtual for mocking.