Hooked MPD flags up to MpdOptions.
Added calculation of availabilityStartTime MPD attribute. Change-Id: I00876005c71f28ea83fb5d9ba0ad1f19f1d08e69
This commit is contained in:
parent
6651ae1c3d
commit
79d3c4f4ec
|
@ -29,3 +29,25 @@ DEFINE_string(base_urls,
|
|||
"",
|
||||
"Comma separated BaseURLs for the MPD. The values will be added "
|
||||
"as <BaseURL> element(s) immediately under the <MPD> element.");
|
||||
DEFINE_double(min_buffer_time,
|
||||
2.0,
|
||||
"Specifies, in seconds, a common duration used in the definition "
|
||||
"of the MPD Representation data rate.");
|
||||
DEFINE_double(availability_time_offset,
|
||||
10.0,
|
||||
"Offset with respect to the wall clock time for MPD "
|
||||
"availabilityStartTime and availabilityEndTime values, in "
|
||||
" seconds. This value is used for live profile only.");
|
||||
DEFINE_double(minimum_update_period,
|
||||
5.0,
|
||||
"Indicates to the player how often to refresh the media "
|
||||
"presentation description in seconds. This value is used for "
|
||||
"live profile only.");
|
||||
DEFINE_double(time_shift_buffer_depth,
|
||||
1800.0,
|
||||
"Guaranteed duration of the time shifting buffer for dynamic "
|
||||
"media presentations, in seconds.");
|
||||
DEFINE_double(suggested_presentation_delay,
|
||||
0.0,
|
||||
"Specifies a delay, in seconds, to be added to the media "
|
||||
"presentation time. This value is used for live profile only.");
|
||||
|
|
|
@ -15,5 +15,10 @@ DECLARE_bool(output_media_info);
|
|||
DECLARE_string(mpd_output);
|
||||
DECLARE_string(scheme_id_uri);
|
||||
DECLARE_string(base_urls);
|
||||
DECLARE_double(availability_time_offset);
|
||||
DECLARE_double(minimum_update_period);
|
||||
DECLARE_double(min_buffer_time);
|
||||
DECLARE_double(time_shift_buffer_depth);
|
||||
DECLARE_double(suggested_presentation_delay);
|
||||
|
||||
#endif // APP_MPD_FLAGS_H_
|
||||
|
|
|
@ -234,6 +234,10 @@ bool RunPackager(const StreamDescriptorList& stream_descriptors) {
|
|||
if (!GetMuxerOptions(&muxer_options))
|
||||
return false;
|
||||
|
||||
MpdOptions mpd_options;
|
||||
if (!GetMpdOptions(&mpd_options))
|
||||
return false;
|
||||
|
||||
// Create encryption key source if needed.
|
||||
scoped_ptr<EncryptionKeySource> encryption_key_source;
|
||||
if (FLAGS_enable_widevine_encryption || FLAGS_enable_fixed_key_encryption) {
|
||||
|
@ -248,8 +252,7 @@ bool RunPackager(const StreamDescriptorList& stream_descriptors) {
|
|||
FLAGS_single_segment ? kOnDemandProfile : kLiveProfile;
|
||||
std::vector<std::string> base_urls;
|
||||
base::SplitString(FLAGS_base_urls, ',', &base_urls);
|
||||
// TODO(rkuroiwa,kqyang): Get mpd options from command line.
|
||||
mpd_notifier.reset(new SimpleMpdNotifier(profile, MpdOptions(), base_urls,
|
||||
mpd_notifier.reset(new SimpleMpdNotifier(profile, mpd_options, base_urls,
|
||||
FLAGS_mpd_output));
|
||||
if (!mpd_notifier->Init()) {
|
||||
LOG(ERROR) << "MpdNotifier failed to initialize.";
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <iostream>
|
||||
|
||||
#include "app/fixed_key_encryption_flags.h"
|
||||
#include "app/mpd_flags.h"
|
||||
#include "app/muxer_flags.h"
|
||||
#include "app/widevine_encryption_flags.h"
|
||||
#include "base/logging.h"
|
||||
|
@ -19,9 +20,12 @@
|
|||
#include "media/base/stream_info.h"
|
||||
#include "media/base/widevine_encryption_key_source.h"
|
||||
#include "media/file/file.h"
|
||||
#include "mpd/base/mpd_builder.h"
|
||||
|
||||
DEFINE_bool(dump_stream_info, false, "Dump demuxed stream info.");
|
||||
|
||||
using dash_packager::MpdOptions;
|
||||
|
||||
namespace media {
|
||||
|
||||
void DumpStreamInfo(const std::vector<MediaStream*>& streams) {
|
||||
|
@ -128,6 +132,18 @@ bool GetMuxerOptions(MuxerOptions* muxer_options) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GetMpdOptions(MpdOptions* mpd_options) {
|
||||
DCHECK(mpd_options);
|
||||
|
||||
mpd_options->availability_time_offset = FLAGS_availability_time_offset;
|
||||
mpd_options->minimum_update_period = FLAGS_minimum_update_period;
|
||||
mpd_options->min_buffer_time = FLAGS_min_buffer_time;
|
||||
mpd_options->time_shift_buffer_depth = FLAGS_time_shift_buffer_depth;
|
||||
mpd_options->suggested_presentation_delay =
|
||||
FLAGS_suggested_presentation_delay;
|
||||
return true;
|
||||
}
|
||||
|
||||
MediaStream* FindFirstStreamOfType(const std::vector<MediaStream*>& streams,
|
||||
StreamType stream_type) {
|
||||
typedef std::vector<MediaStream*>::const_iterator StreamIterator;
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
|
||||
DECLARE_bool(dump_stream_info);
|
||||
|
||||
namespace dash_packager {
|
||||
struct MpdOptions;
|
||||
}
|
||||
|
||||
namespace media {
|
||||
|
||||
class EncryptionKeySource;
|
||||
|
@ -39,6 +43,9 @@ bool AssignFlagsFromProfile();
|
|||
/// Fill MuxerOptions members using provided command line options.
|
||||
bool GetMuxerOptions(MuxerOptions* muxer_options);
|
||||
|
||||
/// Fill MpdOptions members using provided command line options.
|
||||
bool GetMpdOptions(dash_packager::MpdOptions* mpd_options);
|
||||
|
||||
/// Select and add a stream from a provided set to a muxer.
|
||||
/// @param streams contains the set of MediaStreams from which to select.
|
||||
/// @param stream_selector is a string containing one of the following values:
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#ifndef MEDIA_BASE_MUXER_OPTIONS_H_
|
||||
#define MEDIA_BASE_MUXER_OPTIONS_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
@ -65,7 +67,8 @@ struct MuxerOptions {
|
|||
/// Specify temporary directory for intermediate files.
|
||||
std::string temp_dir;
|
||||
|
||||
/// User-specified bandwidth for the stream. zero means "unspecified".
|
||||
/// User-specified bit rate for the media stream. If zero, the muxer will
|
||||
/// attempt to estimate.
|
||||
uint32 bandwidth;
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "mpd/base/mpd_builder.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
|
@ -90,18 +91,19 @@ bool Positive(double d) {
|
|||
}
|
||||
|
||||
// Return current time in XML DateTime format.
|
||||
std::string XmlDateTimeNow() {
|
||||
base::Time now = base::Time::Now();
|
||||
base::Time::Exploded now_exploded;
|
||||
now.UTCExplode(&now_exploded);
|
||||
std::string XmlDateTimeNowWithOffset(int32 offset_seconds) {
|
||||
base::Time time = base::Time::Now();
|
||||
time += base::TimeDelta::FromSeconds(offset_seconds);
|
||||
base::Time::Exploded time_exploded;
|
||||
time.UTCExplode(&time_exploded);
|
||||
|
||||
return base::StringPrintf("%4d-%02d-%02dT%02d:%02d:%02d",
|
||||
now_exploded.year,
|
||||
now_exploded.month,
|
||||
now_exploded.day_of_month,
|
||||
now_exploded.hour,
|
||||
now_exploded.minute,
|
||||
now_exploded.second);
|
||||
time_exploded.year,
|
||||
time_exploded.month,
|
||||
time_exploded.day_of_month,
|
||||
time_exploded.hour,
|
||||
time_exploded.minute,
|
||||
time_exploded.second);
|
||||
}
|
||||
|
||||
void SetIfPositive(const char* attr_name, double value, XmlNode* mpd) {
|
||||
|
@ -157,13 +159,12 @@ int SearchTimedOutRepeatIndex(uint64 timeshift_limit,
|
|||
} // namespace
|
||||
|
||||
MpdOptions::MpdOptions()
|
||||
: minimum_update_period(),
|
||||
min_buffer_time(),
|
||||
time_shift_buffer_depth(),
|
||||
suggested_presentation_delay(),
|
||||
max_segment_duration(),
|
||||
max_subsegment_duration(),
|
||||
number_of_blocks_for_bandwidth_estimation() {}
|
||||
: availability_time_offset(0),
|
||||
minimum_update_period(0),
|
||||
// TODO(tinskip): Set min_buffer_time in unit tests rather than here.
|
||||
min_buffer_time(2.0),
|
||||
time_shift_buffer_depth(0),
|
||||
suggested_presentation_delay(0) {}
|
||||
|
||||
MpdOptions::~MpdOptions() {}
|
||||
|
||||
|
@ -222,9 +223,6 @@ xmlDocPtr MpdBuilder::GenerateMpd() {
|
|||
static const char kXmlVersion[] = "1.0";
|
||||
xml::ScopedXmlPtr<xmlDoc>::type doc(xmlNewDoc(BAD_CAST kXmlVersion));
|
||||
XmlNode mpd("MPD");
|
||||
AddMpdNameSpaceInfo(&mpd);
|
||||
|
||||
SetMpdOptionsValues(&mpd);
|
||||
|
||||
// Iterate thru AdaptationSets and add them to one big Period element.
|
||||
XmlNode period("Period");
|
||||
|
@ -254,6 +252,8 @@ xmlDocPtr MpdBuilder::GenerateMpd() {
|
|||
if (!mpd.AddChild(period.PassScopedPtr()))
|
||||
return NULL;
|
||||
|
||||
AddMpdNameSpaceInfo(&mpd);
|
||||
AddCommonMpdInfo(&mpd);
|
||||
switch (type_) {
|
||||
case kStatic:
|
||||
AddStaticMpdInfo(&mpd);
|
||||
|
@ -271,6 +271,17 @@ xmlDocPtr MpdBuilder::GenerateMpd() {
|
|||
return doc.release();
|
||||
}
|
||||
|
||||
void MpdBuilder::AddCommonMpdInfo(XmlNode* mpd_node) {
|
||||
if (Positive(mpd_options_.min_buffer_time)) {
|
||||
mpd_node->SetStringAttribute(
|
||||
"minBufferTime",
|
||||
SecondsToXmlDuration(mpd_options_.min_buffer_time));
|
||||
} else {
|
||||
LOG(ERROR) << "minBufferTime value not specified.";
|
||||
// TODO(tinskip): Propagate error.
|
||||
}
|
||||
}
|
||||
|
||||
void MpdBuilder::AddStaticMpdInfo(XmlNode* mpd_node) {
|
||||
DCHECK(mpd_node);
|
||||
DCHECK_EQ(MpdBuilder::kStatic, type_);
|
||||
|
@ -294,6 +305,38 @@ void MpdBuilder::AddDynamicMpdInfo(XmlNode* mpd_node) {
|
|||
"urn:mpeg:dash:profile:isoff-live:2011";
|
||||
mpd_node->SetStringAttribute("type", kDynamicMpdType);
|
||||
mpd_node->SetStringAttribute("profiles", kDynamicMpdProfile);
|
||||
|
||||
// 'availabilityStartTime' is required for dynamic profile. Calculate if
|
||||
// not already calculated.
|
||||
if (availability_start_time_.empty()) {
|
||||
double earliest_presentation_time;
|
||||
if (GetEarliestTimestamp(&earliest_presentation_time)) {
|
||||
availability_start_time_ =
|
||||
XmlDateTimeNowWithOffset(mpd_options_.availability_time_offset
|
||||
- std::ceil(earliest_presentation_time));
|
||||
} else {
|
||||
LOG(ERROR) << "Could not determine the earliest segment presentation "
|
||||
"time for availabilityStartTime calculation.";
|
||||
// TODO(tinskip). Propagate an error.
|
||||
}
|
||||
}
|
||||
if (!availability_start_time_.empty())
|
||||
mpd_node->SetStringAttribute("availabilityStartTime", availability_start_time_);
|
||||
|
||||
if (Positive(mpd_options_.minimum_update_period)) {
|
||||
mpd_node->SetStringAttribute(
|
||||
"minimumUpdatePeriod",
|
||||
SecondsToXmlDuration(mpd_options_.minimum_update_period));
|
||||
} else {
|
||||
LOG(WARNING) << "The profile is dynamic but no minimumUpdatePeriod "
|
||||
"specified.";
|
||||
}
|
||||
|
||||
SetIfPositive(
|
||||
"timeShiftBufferDepth", mpd_options_.time_shift_buffer_depth, mpd_node);
|
||||
SetIfPositive("suggestedPresentationDelay",
|
||||
mpd_options_.suggested_presentation_delay,
|
||||
mpd_node);
|
||||
}
|
||||
|
||||
float MpdBuilder::GetStaticMpdDuration(XmlNode* mpd_node) {
|
||||
|
@ -328,62 +371,25 @@ float MpdBuilder::GetStaticMpdDuration(XmlNode* mpd_node) {
|
|||
return max_duration;
|
||||
}
|
||||
|
||||
void MpdBuilder::SetMpdOptionsValues(XmlNode* mpd) {
|
||||
if (type_ == kStatic) {
|
||||
if (!mpd_options_.availability_start_time.empty()) {
|
||||
mpd->SetStringAttribute("availabilityStartTime",
|
||||
mpd_options_.availability_start_time);
|
||||
bool MpdBuilder::GetEarliestTimestamp(double* timestamp_seconds) {
|
||||
DCHECK(timestamp_seconds);
|
||||
|
||||
double earliest_timestamp(-1);
|
||||
for (std::list<AdaptationSet*>::const_iterator iter =
|
||||
adaptation_sets_.begin();
|
||||
iter != adaptation_sets_.end();
|
||||
++iter) {
|
||||
double timestamp;
|
||||
if ((*iter)->GetEarliestTimestamp(×tamp) &&
|
||||
((earliest_timestamp < 0) || (timestamp < earliest_timestamp))) {
|
||||
earliest_timestamp = timestamp;
|
||||
}
|
||||
LOG_IF(WARNING, Positive(mpd_options_.minimum_update_period))
|
||||
<< "minimumUpdatePeriod should not be present in 'static' profile. "
|
||||
"Ignoring.";
|
||||
LOG_IF(WARNING, Positive(mpd_options_.time_shift_buffer_depth))
|
||||
<< "timeShiftBufferDepth will not be used for 'static' profile. "
|
||||
"Ignoring.";
|
||||
LOG_IF(WARNING, Positive(mpd_options_.suggested_presentation_delay))
|
||||
<< "suggestedPresentationDelay will not be used for 'static' profile. "
|
||||
"Ignoring.";
|
||||
} else if (type_ == kDynamic) {
|
||||
// 'availabilityStartTime' is required for dynamic profile, so use current
|
||||
// time if not specified.
|
||||
const std::string avail_start =
|
||||
!mpd_options_.availability_start_time.empty()
|
||||
? mpd_options_.availability_start_time
|
||||
: XmlDateTimeNow();
|
||||
mpd->SetStringAttribute("availabilityStartTime", avail_start);
|
||||
|
||||
if (Positive(mpd_options_.minimum_update_period)) {
|
||||
mpd->SetStringAttribute(
|
||||
"minimumUpdatePeriod",
|
||||
SecondsToXmlDuration(mpd_options_.minimum_update_period));
|
||||
} else {
|
||||
// TODO(rkuroiwa): Set minimumUpdatePeriod to some default value.
|
||||
LOG(WARNING) << "The profile is dynamic but no minimumUpdatePeriod "
|
||||
"specified. Setting minimumUpdatePeriod to 0.";
|
||||
}
|
||||
|
||||
SetIfPositive(
|
||||
"timeShiftBufferDepth", mpd_options_.time_shift_buffer_depth, mpd);
|
||||
SetIfPositive("suggestedPresentationDelay",
|
||||
mpd_options_.suggested_presentation_delay,
|
||||
mpd);
|
||||
}
|
||||
if (earliest_timestamp < 0)
|
||||
return false;
|
||||
|
||||
const double kDefaultMinBufferTime = 2.0;
|
||||
const double min_buffer_time = Positive(mpd_options_.min_buffer_time)
|
||||
? mpd_options_.min_buffer_time
|
||||
: kDefaultMinBufferTime;
|
||||
mpd->SetStringAttribute("minBufferTime",
|
||||
SecondsToXmlDuration(min_buffer_time));
|
||||
|
||||
if (!mpd_options_.availability_end_time.empty()) {
|
||||
mpd->SetStringAttribute("availabilityEndTime",
|
||||
mpd_options_.availability_end_time);
|
||||
}
|
||||
|
||||
SetIfPositive("maxSegmentDuration", mpd_options_.max_segment_duration, mpd);
|
||||
SetIfPositive(
|
||||
"maxSubsegmentDuration", mpd_options_.max_subsegment_duration, mpd);
|
||||
*timestamp_seconds = earliest_timestamp;
|
||||
return true;
|
||||
}
|
||||
|
||||
AdaptationSet::AdaptationSet(uint32 adaptation_set_id,
|
||||
|
@ -441,6 +447,29 @@ xml::ScopedXmlPtr<xmlNode>::type AdaptationSet::GetXml() {
|
|||
return adaptation_set.PassScopedPtr();
|
||||
}
|
||||
|
||||
bool AdaptationSet::GetEarliestTimestamp(double* timestamp_seconds) {
|
||||
DCHECK(timestamp_seconds);
|
||||
|
||||
base::AutoLock scoped_lock(lock_);
|
||||
double earliest_timestamp(-1);
|
||||
for (std::list<Representation*>::const_iterator iter =
|
||||
representations_.begin();
|
||||
iter != representations_.end();
|
||||
++iter) {
|
||||
double timestamp;
|
||||
if ((*iter)->GetEarliestTimestamp(×tamp) &&
|
||||
((earliest_timestamp < 0) || (timestamp < earliest_timestamp))) {
|
||||
earliest_timestamp = timestamp;
|
||||
}
|
||||
}
|
||||
if (earliest_timestamp < 0)
|
||||
return false;
|
||||
|
||||
*timestamp_seconds = earliest_timestamp;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Representation::Representation(const MediaInfo& media_info,
|
||||
const MpdOptions& mpd_options,
|
||||
uint32 id)
|
||||
|
@ -715,4 +744,17 @@ std::string Representation::GetAudioMimeType() const {
|
|||
return GetMimeType("audio", media_info_.container_type());
|
||||
}
|
||||
|
||||
bool Representation::GetEarliestTimestamp(double* timestamp_seconds) {
|
||||
DCHECK(timestamp_seconds);
|
||||
|
||||
base::AutoLock scoped_lock(lock_);
|
||||
if (segment_infos_.empty())
|
||||
return false;
|
||||
|
||||
*timestamp_seconds =
|
||||
static_cast<double>(segment_infos_.begin()->start_time) /
|
||||
GetTimeScale(media_info_);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dash_packager
|
||||
|
|
|
@ -41,18 +41,11 @@ struct MpdOptions {
|
|||
MpdOptions();
|
||||
~MpdOptions();
|
||||
|
||||
std::string availability_start_time;
|
||||
std::string availability_end_time;
|
||||
double availability_time_offset;
|
||||
double minimum_update_period;
|
||||
double min_buffer_time;
|
||||
double time_shift_buffer_depth;
|
||||
double suggested_presentation_delay;
|
||||
double max_segment_duration;
|
||||
double max_subsegment_duration;
|
||||
|
||||
/// Value passed to BandwidthEstimator's contructor. See BandwidthEstimator
|
||||
/// for more.
|
||||
int number_of_blocks_for_bandwidth_estimation;
|
||||
};
|
||||
|
||||
/// This class generates DASH MPDs (Media Presentation Descriptions).
|
||||
|
@ -86,8 +79,8 @@ class MpdBuilder {
|
|||
MpdType type() { return type_; }
|
||||
|
||||
private:
|
||||
// DynamicMpdBuilderTest uses SetMpdOptionsValues to set availabilityStartTime
|
||||
// so that the test doesn't need to depend on current time.
|
||||
// DynamicMpdBuilderTest needs to set availabilityStartTime so that the test
|
||||
// doesn't need to depend on current time.
|
||||
friend class DynamicMpdBuilderTest;
|
||||
|
||||
bool ToStringImpl(std::string* output);
|
||||
|
@ -97,6 +90,10 @@ class MpdBuilder {
|
|||
// On failure, this returns NULL.
|
||||
xmlDocPtr GenerateMpd();
|
||||
|
||||
// Set MPD attributes common to all profiles. Uses non-zero |mpd_options_| to
|
||||
// set attributes for the MPD.
|
||||
void AddCommonMpdInfo(xml::XmlNode* mpd_node);
|
||||
|
||||
// Adds 'static' MPD attributes and elements to |mpd_node|. This assumes that
|
||||
// the first child element is a Period element.
|
||||
void AddStaticMpdInfo(xml::XmlNode* mpd_node);
|
||||
|
@ -106,10 +103,13 @@ class MpdBuilder {
|
|||
|
||||
float GetStaticMpdDuration(xml::XmlNode* mpd_node);
|
||||
|
||||
// Use |mpd_options_| to set attributes for MPD. Only values that are set will be
|
||||
// used, i.e. if a string field is not empty and numeric field is not 0.
|
||||
// Required fields will be set with some reasonable values.
|
||||
void SetMpdOptionsValues(xml::XmlNode* mpd_node);
|
||||
// Set MPD attributes for dynamic profile MPD. Uses non-zero |mpd_options_| as
|
||||
// well as various calculations to set attributes for the MPD.
|
||||
void SetDynamicMpdAttributes(xml::XmlNode* mpd_node);
|
||||
|
||||
// Gets the earliest, normalized segment timestamp. Returns true if
|
||||
// successful, false otherwise.
|
||||
bool GetEarliestTimestamp(double* timestamp_seconds);
|
||||
|
||||
MpdType type_;
|
||||
MpdOptions mpd_options_;
|
||||
|
@ -117,6 +117,7 @@ class MpdBuilder {
|
|||
::STLElementDeleter<std::list<AdaptationSet*> > adaptation_sets_deleter_;
|
||||
|
||||
std::list<std::string> base_urls_;
|
||||
std::string availability_start_time_;
|
||||
|
||||
base::Lock lock_;
|
||||
base::AtomicSequenceNumber adaptation_set_counter_;
|
||||
|
@ -167,6 +168,10 @@ class AdaptationSet {
|
|||
const MpdOptions& mpd_options_,
|
||||
base::AtomicSequenceNumber* representation_counter);
|
||||
|
||||
// Gets the earliest, normalized segment timestamp. Returns true if
|
||||
// successful, false otherwise.
|
||||
bool GetEarliestTimestamp(double* timestamp_seconds);
|
||||
|
||||
std::list<ContentProtectionElement> content_protection_elements_;
|
||||
std::list<Representation*> representations_;
|
||||
::STLElementDeleter<std::list<Representation*> > representations_deleter_;
|
||||
|
@ -248,6 +253,10 @@ class Representation {
|
|||
std::string GetVideoMimeType() const;
|
||||
std::string GetAudioMimeType() const;
|
||||
|
||||
// Gets the earliest, normalized segment timestamp. Returns true if
|
||||
// successful, false otherwise.
|
||||
bool GetEarliestTimestamp(double* timestamp_seconds);
|
||||
|
||||
MediaInfo media_info_;
|
||||
std::list<ContentProtectionElement> content_protection_elements_;
|
||||
std::list<SegmentInfo> segment_infos_;
|
||||
|
@ -258,7 +267,7 @@ class Representation {
|
|||
std::string mime_type_;
|
||||
std::string codecs_;
|
||||
BandwidthEstimator bandwidth_estimator_;
|
||||
const MpdOptions& mpd_options_;;
|
||||
const MpdOptions& mpd_options_;
|
||||
|
||||
// startNumber attribute for SegmentTemplate.
|
||||
// Starts from 1.
|
||||
|
|
|
@ -99,7 +99,7 @@ class DynamicMpdBuilderTest : public MpdBuilderTest<MpdBuilder::kDynamic> {
|
|||
// Anchors availabilityStartTime so that the test result doesn't depend on the
|
||||
// current time.
|
||||
virtual void SetUp() {
|
||||
mpd_.mpd_options_.availability_start_time = "2011-12-25T12:30:00";
|
||||
mpd_.availability_start_time_ = "2011-12-25T12:30:00";
|
||||
}
|
||||
|
||||
MpdOptions* mutable_mpd_options() { return &mpd_.mpd_options_; }
|
||||
|
@ -370,9 +370,9 @@ TEST_F(DynamicMpdBuilderTest, CheckMpdAttributes) {
|
|||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||
"xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
|
||||
"xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 "
|
||||
"DASH-MPD.xsd\" availabilityStartTime=\"2011-12-25T12:30:00\" "
|
||||
"minBufferTime=\"PT2S\" type=\"dynamic\" "
|
||||
"profiles=\"urn:mpeg:dash:profile:isoff-live:2011\">\n"
|
||||
"DASH-MPD.xsd\" minBufferTime=\"PT2S\" type=\"dynamic\" "
|
||||
"profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
|
||||
"availabilityStartTime=\"2011-12-25T12:30:00\">\n"
|
||||
" <Period start=\"PT0S\"/>\n"
|
||||
"</MPD>\n";
|
||||
|
||||
|
|
Loading…
Reference in New Issue