blob: 3888c1fec8cf7ed6c8e086a66a0b4afd1e3beb9c [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 "representation.h"
#include "mkvparser/mkvreader.h"
#include "dash_model.h"
#include "indent.h"
#include "webm_constants.h"
#include "webm_file.h"
using std::string;
using webm_tools::Indent;
using webm_tools::int64;
using webm_tools::kNanosecondsPerSecond;
using webm_tools::WebMFile;
namespace webm_dash {
Representation::Representation(const string& id, const DashModel& dash)
: dash_model_(dash),
id_(id),
output_audio_sample_rate_(true),
output_header_(true),
output_index_(true),
output_video_height_(true),
output_video_width_(true),
webm_file_(NULL),
webm_filename_() {
}
Representation::~Representation() {
}
bool Representation::SetWebMFile() {
if (webm_filename_.empty()) {
fprintf(stderr, "WebM filename is empty.\n");
return false;
}
webm_file_ = dash_model_.FindWebMFile(webm_filename_);
if (!webm_file_) {
fprintf(stderr, "Could not find WebM file:%s\n", webm_filename_.c_str());
return false;
}
return true;
}
bool Representation::BitstreamSwitching(
const Representation& representation) const {
const WebMFile* const webm = representation.webm_file();
if (!webm) {
fprintf(stderr, "WebM file is NULL.\n");
return false;
}
if (!webm_file_) {
fprintf(stderr, "WebM file is NULL.\n");
return false;
}
return webm_file_->CheckBitstreamSwitching(*webm);
}
bool Representation::CheckCuesAlignment(
const Representation& representation) const {
const WebMFile* const webm = representation.webm_file();
if (!webm) {
fprintf(stderr, "WebM file is NULL.\n");
return false;
}
if (!webm_file_) {
fprintf(stderr, "WebM file is NULL.\n");
return false;
}
return webm_file_->CheckCuesAlignment(*webm);
}
int Representation::GetAudioSampleRate() const {
return webm_file_->AudioSampleRate();
}
double Representation::GetVideoFramerate() const {
return webm_file_->VideoFramerate();
}
int Representation::GetVideoHeight() const {
return webm_file_->VideoHeight();
}
int Representation::GetVideoWidth() const {
return webm_file_->VideoWidth();
}
bool Representation::OutputDashManifest(FILE* o, Indent* indent) const {
indent->Adjust(webm_tools::kIncreaseIndent);
fprintf(o, "%s<Representation id=\"%s\"", indent->indent_str().c_str(),
id_.c_str());
const int64 prebuffer_ns =
static_cast<int64>(dash_model_.min_buffer_time() *
kNanosecondsPerSecond);
fprintf(o, " bandwidth=\"%lld\"",
webm_file_->PeakBitsPerSecondOverFile(prebuffer_ns));
// Video
if (output_video_width_) {
const int width = webm_file_->VideoWidth();
if (width > 0) {
fprintf(o, " width=\"%d\"", width);
}
}
if (output_video_height_) {
const int height = webm_file_->VideoHeight();
if (height > 0) {
fprintf(o, " height=\"%d\"", height);
}
}
// TODO(fgalligan): webm_file_->CalculateVideoFrameRate can take a relatively
// long time as it must go through every block in the file. For now only
// output the framerate if the FrameRate element is set in the file. This
// will most likely need to change later.
const double rate = webm_file_->VideoFramerate();
if (rate > 0.0) {
fprintf(o, " framerate=\"%g\"", rate);
}
if (output_audio_sample_rate_) {
const int sample_rate = webm_file_->AudioSampleRate();
if (sample_rate > 0) {
fprintf(o, " audioSamplingRate=\"%d\"", sample_rate);
}
}
fprintf(o, ">\n");
indent->Adjust(webm_tools::kIncreaseIndent);
fprintf(o, "%s<BaseURL>%s</BaseURL>\n", indent->indent_str().c_str(),
webm_file_->filename().c_str());
indent->Adjust(webm_tools::kDecreaseIndent);
const bool b = OutputSegmentBase(o, indent);
if (!b)
return false;
fprintf(o, "%s</Representation>\n", indent->indent_str().c_str());
indent->Adjust(webm_tools::kDecreaseIndent);
return true;
}
bool Representation::SubsegmentStartsWithSAP() const {
if (!webm_file_) {
fprintf(stderr, "WebM file is NULL.\n");
return false;
}
return webm_file_->CuesFirstInCluster(WebMFile::kUnknown);
}
bool Representation::OutputSegmentBase(FILE* o, Indent* indent) const {
if (!output_header_ && !output_index_)
return true;
if (!webm_file_)
return true;
indent->Adjust(webm_tools::kIncreaseIndent);
fprintf(o, "%s<SegmentBase", indent->indent_str().c_str());
if (output_index_) {
if (!webm_file_->CheckForCues())
return false;
// Output the entire Cues element.
const mkvparser::Cues* const cues = webm_file_->GetCues();
const int64 start = cues->m_element_start;
const int64 end = start + cues->m_element_size;
// Range is based off RFC 2616. All byte positions are inclusive.
fprintf(o, " indexRange=\"%lld-%lld\"", start, end - 1);
}
if (output_header_) {
fprintf(o, ">\n");
int64 start;
int64 end;
webm_file_->GetHeaderRange(&start, &end);
indent->Adjust(webm_tools::kIncreaseIndent);
fprintf(o, "%s<Initialization", indent->indent_str().c_str());
// Range is based off RFC 2616. All byte positions are inclusive.
fprintf(o, " range=\"%lld-%lld\" />\n", start, end - 1);
indent->Adjust(webm_tools::kDecreaseIndent);
fprintf(o, "%s</SegmentBase>\n", indent->indent_str().c_str());
} else {
fprintf(o, " />\n");
}
indent->Adjust(webm_tools::kDecreaseIndent);
return true;
}
} // namespace webm_dash