2014-02-14 23:21:05 +00:00
|
|
|
// Copyright 2014 Google Inc. 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
|
|
|
|
|
2014-10-01 22:10:21 +00:00
|
|
|
#include "packager/app/mpd_generator_flags.h"
|
2015-10-27 18:52:50 +00:00
|
|
|
#include "packager/app/vlog_flags.h"
|
2015-12-30 01:09:12 +00:00
|
|
|
#include "packager/base/at_exit.h"
|
2015-10-27 18:52:50 +00:00
|
|
|
#include "packager/base/command_line.h"
|
2014-10-01 22:10:21 +00:00
|
|
|
#include "packager/base/logging.h"
|
|
|
|
#include "packager/base/strings/string_split.h"
|
|
|
|
#include "packager/base/strings/stringprintf.h"
|
|
|
|
#include "packager/mpd/util/mpd_writer.h"
|
2015-12-21 23:10:17 +00:00
|
|
|
#include "packager/version/version.h"
|
2014-01-29 21:40:13 +00:00
|
|
|
|
2016-08-14 22:28:21 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
#include <codecvt>
|
|
|
|
#include <functional>
|
|
|
|
#include <locale>
|
|
|
|
#endif // defined(OS_WIN)
|
|
|
|
|
2016-05-20 21:19:33 +00:00
|
|
|
namespace shaka {
|
2014-01-29 21:40:13 +00:00
|
|
|
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"
|
2014-02-13 00:35:05 +00:00
|
|
|
"%s --input=\"video1.media_info,video2.media_info,audio1.media_info\" "
|
2014-01-29 21:40:13 +00:00
|
|
|
"--output=\"video_audio.mpd\"";
|
|
|
|
|
|
|
|
enum ExitStatus {
|
|
|
|
kSuccess = 0,
|
|
|
|
kEmptyInputError,
|
|
|
|
kEmptyOutputError,
|
|
|
|
kFailedToWriteMpdToFileError
|
|
|
|
};
|
|
|
|
|
|
|
|
ExitStatus CheckRequiredFlags() {
|
|
|
|
if (FLAGS_input.empty()) {
|
|
|
|
LOG(ERROR) << "--input is required.";
|
|
|
|
return kEmptyInputError;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (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;
|
|
|
|
|
2016-08-17 21:42:23 +00:00
|
|
|
std::vector<std::string> input_files = base::SplitString(
|
|
|
|
FLAGS_input, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
|
2014-01-29 21:40:13 +00:00
|
|
|
|
|
|
|
if (!FLAGS_base_urls.empty()) {
|
2016-08-17 21:42:23 +00:00
|
|
|
base_urls = base::SplitString(FLAGS_base_urls, ",", base::KEEP_WHITESPACE,
|
|
|
|
base::SPLIT_WANT_ALL);
|
2014-01-29 21:40:13 +00:00
|
|
|
}
|
|
|
|
|
2016-05-19 21:38:15 +00:00
|
|
|
MpdWriter mpd_writer;
|
2014-01-29 21:40:13 +00:00
|
|
|
for (Iterator it = base_urls.begin(); it != base_urls.end(); ++it)
|
|
|
|
mpd_writer.AddBaseUrl(*it);
|
|
|
|
|
|
|
|
for (Iterator it = input_files.begin(); it != input_files.end(); ++it) {
|
2014-12-16 01:32:19 +00:00
|
|
|
if (!mpd_writer.AddFile(it->c_str(), FLAGS_output)) {
|
2014-01-29 21:40:13 +00:00
|
|
|
LOG(WARNING) << "MpdWriter failed to read " << *it << ", skipping.";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mpd_writer.WriteMpdToFile(FLAGS_output.c_str())) {
|
|
|
|
LOG(ERROR) << "Failed to write MPD to " << FLAGS_output;
|
|
|
|
return kFailedToWriteMpdToFileError;
|
|
|
|
}
|
|
|
|
|
|
|
|
return kSuccess;
|
|
|
|
}
|
|
|
|
|
2014-10-03 05:17:54 +00:00
|
|
|
int MpdMain(int argc, char** argv) {
|
2015-12-30 01:09:12 +00:00
|
|
|
base::AtExitManager exit;
|
2015-10-27 18:52:50 +00:00
|
|
|
// Needed to enable VLOG/DVLOG through --vmodule or --v.
|
|
|
|
base::CommandLine::Init(argc, argv);
|
|
|
|
CHECK(logging::InitLogging(logging::LoggingSettings()));
|
|
|
|
|
2014-01-29 21:40:13 +00:00
|
|
|
google::SetUsageMessage(base::StringPrintf(kUsage, argv[0]));
|
|
|
|
google::ParseCommandLineFlags(&argc, &argv, true);
|
|
|
|
|
|
|
|
ExitStatus status = CheckRequiredFlags();
|
|
|
|
if (status != kSuccess) {
|
2016-07-07 19:34:07 +00:00
|
|
|
const std::string version_string = base::StringPrintf(
|
|
|
|
"mpd_generator version %s", GetPackagerVersion().c_str());
|
2015-12-21 23:10:17 +00:00
|
|
|
google::ShowUsageWithFlags(version_string.c_str());
|
2014-01-29 21:40:13 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RunMpdGenerator();
|
|
|
|
}
|
2014-10-03 05:17:54 +00:00
|
|
|
|
|
|
|
} // namespace
|
2016-05-20 21:19:33 +00:00
|
|
|
} // namespace shaka
|
2014-10-03 05:17:54 +00:00
|
|
|
|
2016-08-14 22:28:21 +00:00
|
|
|
#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());
|
|
|
|
}
|
|
|
|
return shaka::MpdMain(argc, utf8_argv.get());
|
|
|
|
}
|
|
|
|
#else
|
2014-10-03 05:17:54 +00:00
|
|
|
int main(int argc, char** argv) {
|
2016-05-20 21:19:33 +00:00
|
|
|
return shaka::MpdMain(argc, argv);
|
2014-10-03 05:17:54 +00:00
|
|
|
}
|
2016-08-14 22:28:21 +00:00
|
|
|
#endif // !defined(OS_WIN)
|