| /* |
| * 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 |