blob: 161c182cd5e407036ccff42971c10d904b03926c [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 "dash_model.h"
#include <cstdio>
#include "adaptation_set.h"
#include "indent.h"
#include "period.h"
#include "webm_file.h"
using std::string;
using std::vector;
using webm_tools::WebMFile;
namespace webm_dash {
typedef vector<AdaptationSet*>::iterator AdaptationSetIterator;
typedef vector<AdaptationSet*>::const_iterator AdaptationSetConstIterator;
typedef vector<Period*>::iterator PeriodIterator;
typedef vector<Period*>::const_iterator PeriodConstIterator;
typedef vector<WebMFile*>::iterator WebMFileIterator;
typedef vector<WebMFile*>::const_iterator WebMFileConstIterator;
const char DashModel::webm_on_demand[] =
"urn:webm:dash:profile:webm-on-demand:2012";
const char DashModel::xml_schema_location[] =
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"";
const char DashModel::xml_namespace[] =
"xmlns=\"urn:mpeg:DASH:schema:MPD:2011\"";
const char DashModel::xml_namespace_location[] =
"xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011\"";
DashModel::DashModel()
: type_("static"),
duration_(0.0),
min_buffer_time_(1.0),
profile_(DashModel::webm_on_demand),
output_filename_("manifest.mpd") {
}
DashModel::~DashModel() {
for (AdaptationSetIterator iter = adaptation_sets_.begin();
iter != adaptation_sets_.end();
++iter) {
const AdaptationSet* const as = *iter;
delete as;
}
for (PeriodIterator period_iter = periods_.begin();
period_iter != periods_.end();
++period_iter) {
const Period* const period = *period_iter;
delete period;
}
for (WebMFileIterator webm_iter = webm_files_.begin();
webm_iter != webm_files_.end();
++webm_iter) {
const WebMFile* const webm = *webm_iter;
delete webm;
}
}
bool DashModel::Init() {
for (vector<string>::const_iterator file_iter = webm_filenames_.begin();
file_iter != webm_filenames_.end();
++file_iter) {
std::auto_ptr<WebMFile> webm(new (std::nothrow) WebMFile()); // NOLINT
if (!webm.get())
return false;
if (!webm->ParseFile(*file_iter))
return false;
if (profile_ == DashModel::webm_on_demand) {
if (!webm->OnlyOneStream()) {
return false;
}
}
webm_files_.push_back(webm.release());
}
AdaptationSetIterator as_iter;
for (as_iter = adaptation_sets_.begin();
as_iter != adaptation_sets_.end();
++as_iter) {
(*as_iter)->set_profile(profile_);
if ((*as_iter)->Init() == false)
return false;
}
// If no periods have been added on the command line add one by default.
if (periods_.empty())
AddPeriod();
Period* period = CurrentPeriod();
if (!period)
return false;
for (as_iter = adaptation_sets_.begin();
as_iter != adaptation_sets_.end();
++as_iter) {
period->AddAdaptationSetID((*as_iter)->id());
}
// Set the media group pointers
PeriodIterator period_iter;
for (period_iter = periods_.begin();
period_iter != periods_.end();
++period_iter) {
period = *period_iter;
for (int i = 0; i < period->AdaptationSetIDSize(); ++i) {
string id;
if (!period->AdaptationSetID(i, &id))
return false;
const AdaptationSet* const as = FindAdaptationSet(id);
if (!as)
return false;
period->AddAdaptationSet(as);
}
}
for (period_iter = periods_.begin();
period_iter != periods_.end();
++period_iter) {
if ((*period_iter)->Init() == false)
return false;
}
for (period_iter = periods_.begin();
period_iter != periods_.end();
++period_iter) {
if (duration_ < (*period_iter)->duration())
duration_ = (*period_iter)->duration();
}
return true;
}
void DashModel::AddAdaptationSet() {
char str[128];
snprintf(str, sizeof(str), "%d", static_cast<int>(adaptation_sets_.size()));
const string id = str;
adaptation_sets_.push_back(new AdaptationSet(id, *this));
}
void DashModel::AppendBaseUrl(const string& url) {
base_urls_.push_back(url);
}
void DashModel::AppendInputFile(const string& filename) {
webm_filenames_.push_back(filename);
}
void DashModel::AddPeriod() {
char str[128];
snprintf(str, sizeof(str), "%d", static_cast<int>(periods_.size()));
const string id = str;
periods_.push_back(new Period(id));
}
AdaptationSet* DashModel::CurrentAdaptationSet() const {
AdaptationSetConstIterator iter_curr(adaptation_sets_.end());
if (iter_curr == adaptation_sets_.begin())
return NULL;
--iter_curr;
return *iter_curr;
}
Period* DashModel::CurrentPeriod() const {
PeriodConstIterator iter_curr(periods_.end());
if (iter_curr == periods_.begin())
return NULL;
--iter_curr;
return *iter_curr;
}
const AdaptationSet* DashModel::FindAdaptationSet(const string& id) const {
for (AdaptationSetConstIterator iter = adaptation_sets_.begin();
iter != adaptation_sets_.end();
++iter) {
if ((*iter)->id() == id)
return *iter;
}
return NULL;
}
const WebMFile* DashModel::FindWebMFile(const string& filename) const {
for (WebMFileConstIterator iter = webm_files_.begin();
iter != webm_files_.end();
++iter) {
if ((*iter)->filename() == filename)
return *iter;
}
return NULL;
}
bool DashModel::OutputDashManifestFile() const {
if (output_filename_.empty())
return false;
FILE* const o = fopen(output_filename_.c_str(), "w");
if (!o)
return false;
fprintf(o, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
fprintf(o, "<MPD\n");
fprintf(o, " %s\n", xml_schema_location);
fprintf(o, " %s\n", xml_namespace);
fprintf(o, " %s\n", xml_namespace_location);
fprintf(o, " type=\"%s\"\n", type_.c_str());
fprintf(o, " mediaPresentationDuration=\"PT%gS\"\n", duration_);
fprintf(o, " minBufferTime=\"PT%gS\"\n", min_buffer_time_);
fprintf(o, " profiles=\"%s\"", profile_.c_str());
fprintf(o, ">\n");
for (vector<string>::const_iterator stri = base_urls_.begin();
stri != base_urls_.end();
++stri) {
fprintf(o, " <BaseURL>%s</BaseURL>\n", (*stri).c_str());
}
webm_tools::Indent indent(0);
for (PeriodConstIterator iter = periods_.begin();
iter != periods_.end();
++iter) {
(*iter)->OutputDashManifest(o, &indent);
}
fprintf(o, "</MPD>\n");
fclose(o);
return true;
}
} // namespace webm_dash