blob: f382d651ad650d88386a4242059e50e61bfb930a [file] [log] [blame]
/*
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include "adaptation_set.h"
#include "dash_model.h"
#include "period.h"
#include "representation.h"
using std::string;
using webm_dash::DashModel;
using webm_dash::AdaptationSet;
using webm_dash::Period;
using webm_dash::Representation;
static const char VERSION_STRING[] = "1.0.3.0";
static void Usage() {
printf("Usage: webm_dash_manifest [-o output_file] [-p options] ");
printf("<-as [as options] <-r [r options]>... >...\n");
printf("\n");
printf("Main options:\n");
printf("-h | -? show help\n");
printf("-v show version\n");
printf("-url <string> [...] Base URL list\n");
printf("-profile <string> Set profile.\n");
printf("\n");
printf("Period (-p) options:\n");
printf("-duration <double> duration in seconds\n");
printf("-id <string> id of the Period\n");
printf("-start <double> start time in seconds\n");
printf("\n");
printf("AdaptationSet (-as) options:\n");
printf("-id <string> id of the AdaptationSet\n");
printf("-lang <string> lang of the AdaptationSet\n");
printf("\n");
printf("Representation (-r) options:\n");
printf("-id <string> id of the Media\n");
printf("-file <string> Input file\n");
printf("\n");
}
static bool ParseOption(const string& option, string* name, string* value) {
if (!name || !value)
return false;
const size_t equal_sign = option.find_first_of('=');
if (equal_sign == string::npos)
return false;
*name = option.substr(0, equal_sign);
*value = option.substr(equal_sign + 1, string::npos);
return true;
}
static void ParseAdaptationSetOptions(const string& option_list,
AdaptationSet* as) {
size_t start = 0;
size_t end = option_list.find_first_of(',');
for (;;) {
const string option = option_list.substr(start, end - start);
string name;
string value;
if (ParseOption(option, &name, &value)) {
if (name == "id") {
as->set_id(value);
} else if (name == "lang") {
as->set_lang(value);
}
}
if (end == string::npos)
break;
start = end + 1;
end = option_list.find_first_of(',', start);
}
}
static double StringToDouble(const std::string& s) {
return strtod(s.c_str(), NULL);
}
static void ParsePeriodOptions(const string& option_list, Period* period) {
size_t start = 0;
size_t end = option_list.find_first_of(',');
for (;;) {
const string option = option_list.substr(start, end - start);
string name;
string value;
if (ParseOption(option, &name, &value)) {
if (name == "id") {
period->set_id(value);
} else if (name == "duration") {
period->set_duration(StringToDouble(value));
} else if (name == "start") {
period->set_start(StringToDouble(value));
}
}
if (end == string::npos)
break;
start = end + 1;
end = option_list.find_first_of(',', start);
}
}
static void ParseRepresentationOptions(const string& option_list,
DashModel* model,
Representation* r) {
size_t start = 0;
size_t end = option_list.find_first_of(',');
for (;;) {
const string option = option_list.substr(start, end - start);
string name;
string value;
if (ParseOption(option, &name, &value)) {
if (name == "id") {
r->set_id(value);
} else if (name == "file") {
model->AppendInputFile(value);
r->set_webm_filename(value);
}
}
if (end == string::npos)
break;
start = end + 1;
end = option_list.find_first_of(',', start);
}
}
static bool ParseMainCommandLine(int argc,
char* argv[],
DashModel* model) {
if (argc < 2) {
Usage();
return false;
}
if (!model) {
fprintf(stderr, "model parameter is NULL.\n");
return EXIT_FAILURE;
}
const int argc_check = argc - 1;
for (int i = 1; i < argc; ++i) {
if (!strcmp("-p", argv[i]) && i < argc_check) {
model->AddPeriod();
Period* const p = model->CurrentPeriod();
const string option_list(argv[++i]);
ParsePeriodOptions(option_list, p);
} else if (!strcmp("-as", argv[i]) && i < argc_check) {
model->AddAdaptationSet();
AdaptationSet* const as = model->CurrentAdaptationSet();
const string option_list(argv[++i]);
ParseAdaptationSetOptions(option_list, as);
} else if (!strcmp("-r", argv[i]) && i < argc_check) {
AdaptationSet* const as = model->CurrentAdaptationSet();
if (as) {
as->AddRepresentation();
Representation* const rep = as->CurrentRepresentation();
const string option_list(argv[++i]);
ParseRepresentationOptions(option_list, model, rep);
}
} else if (!strcmp("-o", argv[i]) && i < argc_check) {
model->set_output_filename(argv[++i]);
} else if (!strcmp("-v", argv[i])) {
printf("version: %s\n", VERSION_STRING);
} else if ( (!strcmp("-h", argv[i])) || (!strcmp("-?", argv[i])) ) {
Usage();
return false;
} else if (!strcmp("-url", argv[i]) && i < argc_check) {
model->AppendBaseUrl(argv[++i]);
} else if (!strcmp("-profile", argv[i]) && i < argc_check) {
model->set_profile(argv[++i]);
}
}
return true;
}
int main(int argc, char* argv[]) {
DashModel model;
if (!ParseMainCommandLine(argc, argv, &model)) {
return EXIT_FAILURE;
}
if (!model.Init()) {
fprintf(stderr, "Manifest Model Init() Failed.\n");
return EXIT_FAILURE;
}
if (!model.OutputDashManifestFile()) {
fprintf(stderr, "OutputDashManifestFile() Failed.\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}