diff --git a/app/mpd_generator.cc b/app/mpd_generator.cc new file mode 100644 index 0000000000..a633306139 --- /dev/null +++ b/app/mpd_generator.cc @@ -0,0 +1,86 @@ +#include "app/mpd_generator_flags.h" +#include "base/logging.h" +#include "base/strings/string_split.h" +#include "base/strings/stringprintf.h" +#include "mpd/util/mpd_writer.h" + +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.txt,video2.txt,audio1.txt\" " + "--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 base_urls; + std::vector input_files; + typedef std::vector::const_iterator Iterator; + + base::SplitString(FLAGS_input, ',', &input_files); + + + if (!FLAGS_base_urls.empty()) { + base::SplitString(FLAGS_base_urls, ',', &base_urls); + } + + dash_packager::MpdWriter mpd_writer; + 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) { + if (!mpd_writer.AddFile(it->c_str())) { + 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; +} + +} // namespace + +int main(int argc, char** argv) { + google::SetUsageMessage(base::StringPrintf(kUsage, argv[0])); + google::ParseCommandLineFlags(&argc, &argv, true); + + ExitStatus status = CheckRequiredFlags(); + if (status != kSuccess) { + google::ShowUsageWithFlags(argv[0]); + return status; + } + + return RunMpdGenerator(); +} diff --git a/app/mpd_generator_flags.h b/app/mpd_generator_flags.h new file mode 100644 index 0000000000..329462e1be --- /dev/null +++ b/app/mpd_generator_flags.h @@ -0,0 +1,14 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. + +#ifndef APP_MPD_GENERATOR_FLAGS_H_ +#define APP_MPD_GENERATOR_FLAGS_H_ + +#include + +DEFINE_string(input, "", "Comma separated list of MediaInfo input files."); +DEFINE_string(output, "", "MPD output file name."); +DEFINE_string(base_urls, + "", + "Comma separated BaseURLs for the MPD. The values will be added " + "as element(s) immediately under the element."); +#endif // APP_MPD_GENERATOR_FLAGS_H_ diff --git a/mpd/mpd.gyp b/mpd/mpd.gyp index 41a80d1f81..f65156bc85 100644 --- a/mpd/mpd.gyp +++ b/mpd/mpd.gyp @@ -75,6 +75,7 @@ 'util/mpd_writer.h', ], 'dependencies': [ + '../packager.gyp:file', 'mpd_builder', ], }, diff --git a/packager.gyp b/packager.gyp index 9956781ad4..b9d0cc1146 100644 --- a/packager.gyp +++ b/packager.gyp @@ -302,5 +302,18 @@ 'third_party/gflags/gflags.gyp:gflags', ], }, + { + 'target_name': 'mpd_generator', + 'type': 'executable', + 'sources': [ + 'app/mpd_generator.cc', + 'app/mpd_generator_flags.h', + ], + 'dependencies': [ + 'base/base.gyp:base', + 'mpd/mpd.gyp:mpd_util', + 'third_party/gflags/gflags.gyp:gflags', + ], + }, ], }