-
Notifications
You must be signed in to change notification settings - Fork 516
/
Copy pathmpd_generator.cc
180 lines (147 loc) · 5.45 KB
/
mpd_generator.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright 2014 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include <iostream>
#if defined(OS_WIN)
#include <codecvt>
#include <functional>
#endif // defined(OS_WIN)
#include <absl/flags/parse.h>
#include <absl/flags/usage.h>
#include <absl/flags/usage_config.h>
#include <absl/log/check.h>
#include <absl/log/initialize.h>
#include <absl/log/log.h>
#include <absl/strings/str_format.h>
#include <absl/strings/str_split.h>
#include <packager/app/mpd_generator_flags.h>
#include <packager/mpd/util/mpd_writer.h>
#include <packager/tools/license_notice.h>
#include <packager/version/version.h>
ABSL_FLAG(bool, licenses, false, "Dump licenses.");
ABSL_FLAG(std::string,
test_packager_version,
"",
"Packager version for testing. Should be used for testing only.");
// From absl/log:
ABSL_DECLARE_FLAG(int, stderrthreshold);
namespace shaka {
namespace {
const char kUsage[] =
"MPD generation driver program.\n"
"This program accepts MediaInfo files in human readable text "
"format and outputs an MPD.\n"
"The main use case for this is to output MPD for VOD.\n"
"Limitations:\n"
" Each MediaInfo can only have one of VideoInfo, AudioInfo, or TextInfo.\n"
" There will be at most 3 AdaptationSets in the MPD, i.e. 1 video, 1 "
"audio, and 1 text.\n"
"Sample Usage:\n"
"%s --input=\"video1.media_info,video2.media_info,audio1.media_info\" "
"--output=\"video_audio.mpd\"";
enum ExitStatus {
kSuccess = 0,
kEmptyInputError,
kEmptyOutputError,
kFailedToWriteMpdToFileError
};
ExitStatus CheckRequiredFlags() {
if (absl::GetFlag(FLAGS_input).empty()) {
LOG(ERROR) << "--input is required.";
return kEmptyInputError;
}
if (absl::GetFlag(FLAGS_output).empty()) {
LOG(ERROR) << "--output is required.";
return kEmptyOutputError;
}
return kSuccess;
}
ExitStatus RunMpdGenerator() {
DCHECK_EQ(CheckRequiredFlags(), kSuccess);
std::vector<std::string> base_urls;
typedef std::vector<std::string>::const_iterator Iterator;
std::vector<std::string> input_files =
absl::StrSplit(absl::GetFlag(FLAGS_input), ",", absl::AllowEmpty());
if (!absl::GetFlag(FLAGS_base_urls).empty()) {
base_urls =
absl::StrSplit(absl::GetFlag(FLAGS_base_urls), ",", absl::AllowEmpty());
}
MpdWriter mpd_writer;
for (Iterator it = base_urls.begin(); it != base_urls.end(); ++it)
mpd_writer.AddBaseUrl(*it);
for (const std::string& file : input_files) {
if (!mpd_writer.AddFile(file)) {
LOG(WARNING) << "MpdWriter failed to read " << file << ", skipping.";
}
}
if (!mpd_writer.WriteMpdToFile(absl::GetFlag(FLAGS_output).c_str())) {
LOG(ERROR) << "Failed to write MPD to " << absl::GetFlag(FLAGS_output);
return kFailedToWriteMpdToFileError;
}
return kSuccess;
}
int MpdMain(int argc, char** argv) {
absl::FlagsUsageConfig flag_config;
flag_config.version_string = []() -> std::string {
return "mpd_generator version " + GetPackagerVersion() + "\n";
};
flag_config.contains_help_flags =
[](absl::string_view flag_file_name) -> bool { return true; };
absl::SetFlagsUsageConfig(flag_config);
auto usage = absl::StrFormat(kUsage, argv[0]);
absl::SetProgramUsageMessage(usage);
// Before parsing the command line, change the default value of some flags
// provided by libraries.
// Always log to stderr. Log levels are still controlled by --minloglevel.
absl::SetFlag(&FLAGS_stderrthreshold, 0);
absl::ParseCommandLine(argc, argv);
if (absl::GetFlag(FLAGS_licenses)) {
for (const char* line : kLicenseNotice)
std::cout << line << std::endl;
return kSuccess;
}
ExitStatus status = CheckRequiredFlags();
if (status != kSuccess) {
std::cerr << "Usage " << absl::ProgramUsageMessage();
return status;
}
absl::InitializeLog();
if (!absl::GetFlag(FLAGS_test_packager_version).empty())
SetPackagerVersionForTesting(absl::GetFlag(FLAGS_test_packager_version));
return RunMpdGenerator();
}
} // namespace
} // namespace shaka
#if defined(OS_WIN)
// Windows wmain, which converts wide character arguments to UTF-8.
int wmain(int argc, wchar_t* argv[], wchar_t* envp[]) {
std::unique_ptr<char* [], std::function<void(char**)>> utf8_argv(
new char*[argc], [argc](char** utf8_args) {
// TODO(tinskip): This leaks, but if this code is enabled, it crashes.
// Figure out why. I suspect gflags does something funny with the
// argument array.
// for (int idx = 0; idx < argc; ++idx)
// delete[] utf8_args[idx];
delete[] utf8_args;
});
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
for (int idx = 0; idx < argc; ++idx) {
std::string utf8_arg(converter.to_bytes(argv[idx]));
utf8_arg += '\0';
utf8_argv[idx] = new char[utf8_arg.size()];
memcpy(utf8_argv[idx], &utf8_arg[0], utf8_arg.size());
}
// Because we just converted wide character args into UTF8, and because
// std::filesystem::u8path is used to interpret all std::string paths as
// UTF8, we should set the locale to UTF8 as well, for the transition point
// to C library functions like fopen to work correctly with non-ASCII paths.
std::setlocale(LC_ALL, ".UTF8");
return shaka::MpdMain(argc, utf8_argv.get());
}
#else
int main(int argc, char** argv) {
return shaka::MpdMain(argc, argv);
}
#endif // !defined(OS_WIN)