Prefer Period@duration for static MPD with >1 periods
It is easier to insert Ad Periods with Period@duration compared to Period@start. Change-Id: Ib52e81612562bf60b0e0513a09d9a31c42b09604
This commit is contained in:
parent
48cb55c8d4
commit
221ac81772
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>-->
|
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>-->
|
||||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" 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" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
|
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" 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" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
|
||||||
<Period id="0">
|
<Period id="0" duration="PT2.06873S">
|
||||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||||
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
|
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
</Representation>
|
</Representation>
|
||||||
</AdaptationSet>
|
</AdaptationSet>
|
||||||
</Period>
|
</Period>
|
||||||
<Period id="1" start="PT2.06873S">
|
<Period id="1" duration="PT0.694441S">
|
||||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||||
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
|
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>-->
|
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>-->
|
||||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" 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" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-live:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
|
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" 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" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-live:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
|
||||||
<Period id="0">
|
<Period id="0" duration="PT2.06873S">
|
||||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9">
|
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9">
|
||||||
<Representation id="0" bandwidth="875099" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
<Representation id="0" bandwidth="875099" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||||
<SegmentTemplate timescale="30000" initialization="output_video-init.mp4" media="output_video-$Number$.m4s" startNumber="1">
|
<SegmentTemplate timescale="30000" initialization="output_video-init.mp4" media="output_video-$Number$.m4s" startNumber="1">
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
</Representation>
|
</Representation>
|
||||||
</AdaptationSet>
|
</AdaptationSet>
|
||||||
</Period>
|
</Period>
|
||||||
<Period id="1" start="PT2.06873S">
|
<Period id="1" duration="PT0.694444S">
|
||||||
<AdaptationSet id="1" contentType="audio" segmentAlignment="true">
|
<AdaptationSet id="1" contentType="audio" segmentAlignment="true">
|
||||||
<Representation id="1" bandwidth="108486" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
|
<Representation id="1" bandwidth="108486" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
|
||||||
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
|
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "packager/mpd/base/mpd_builder.h"
|
#include "packager/mpd/base/mpd_builder.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "packager/base/files/file_path.h"
|
#include "packager/base/files/file_path.h"
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
|
@ -170,6 +172,21 @@ xmlDocPtr MpdBuilder::GenerateMpd() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prefer Period@duration to Period@start for static MPD with more than one
|
||||||
|
// periods.
|
||||||
|
if (mpd_options_.mpd_type == MpdType::kStatic && periods_.size() > 1) {
|
||||||
|
// The duration of every period is determined by its start_time and next
|
||||||
|
// period start_time. The code below traverses |periods_| backwards.
|
||||||
|
double next_period_start_time = GetStaticMpdDuration();
|
||||||
|
std::for_each(
|
||||||
|
periods_.rbegin(), periods_.rend(),
|
||||||
|
[&next_period_start_time](const std::unique_ptr<Period>& period) {
|
||||||
|
period->set_duration_seconds(next_period_start_time -
|
||||||
|
period->start_time_in_seconds());
|
||||||
|
next_period_start_time = period->start_time_in_seconds();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& period : periods_) {
|
for (const auto& period : periods_) {
|
||||||
xml::scoped_xml_ptr<xmlNode> period_node(period->GetXml());
|
xml::scoped_xml_ptr<xmlNode> period_node(period->GetXml());
|
||||||
if (!period_node || !mpd.AddChild(std::move(period_node)))
|
if (!period_node || !mpd.AddChild(std::move(period_node)))
|
||||||
|
@ -242,9 +259,8 @@ void MpdBuilder::AddStaticMpdInfo(XmlNode* mpd_node) {
|
||||||
|
|
||||||
static const char kStaticMpdType[] = "static";
|
static const char kStaticMpdType[] = "static";
|
||||||
mpd_node->SetStringAttribute("type", kStaticMpdType);
|
mpd_node->SetStringAttribute("type", kStaticMpdType);
|
||||||
mpd_node->SetStringAttribute(
|
mpd_node->SetStringAttribute("mediaPresentationDuration",
|
||||||
"mediaPresentationDuration",
|
SecondsToXmlDuration(GetStaticMpdDuration()));
|
||||||
SecondsToXmlDuration(GetStaticMpdDuration(mpd_node)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MpdBuilder::AddDynamicMpdInfo(XmlNode* mpd_node) {
|
void MpdBuilder::AddDynamicMpdInfo(XmlNode* mpd_node) {
|
||||||
|
@ -290,8 +306,7 @@ void MpdBuilder::AddDynamicMpdInfo(XmlNode* mpd_node) {
|
||||||
mpd_options_.mpd_params.suggested_presentation_delay, mpd_node);
|
mpd_options_.mpd_params.suggested_presentation_delay, mpd_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
float MpdBuilder::GetStaticMpdDuration(XmlNode* mpd_node) {
|
float MpdBuilder::GetStaticMpdDuration() {
|
||||||
DCHECK(mpd_node);
|
|
||||||
DCHECK_EQ(MpdType::kStatic, mpd_options_.mpd_type);
|
DCHECK_EQ(MpdType::kStatic, mpd_options_.mpd_type);
|
||||||
|
|
||||||
if (periods_.empty()) {
|
if (periods_.empty()) {
|
||||||
|
|
|
@ -100,7 +100,7 @@ class MpdBuilder {
|
||||||
// Same as AddStaticMpdInfo() but for 'dynamic' MPDs.
|
// Same as AddStaticMpdInfo() but for 'dynamic' MPDs.
|
||||||
void AddDynamicMpdInfo(xml::XmlNode* mpd_node);
|
void AddDynamicMpdInfo(xml::XmlNode* mpd_node);
|
||||||
|
|
||||||
float GetStaticMpdDuration(xml::XmlNode* mpd_node);
|
float GetStaticMpdDuration();
|
||||||
|
|
||||||
// Set MPD attributes for dynamic profile MPD. Uses non-zero |mpd_options_| as
|
// Set MPD attributes for dynamic profile MPD. Uses non-zero |mpd_options_| as
|
||||||
// well as various calculations to set attributes for the MPD.
|
// well as various calculations to set attributes for the MPD.
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
// license that can be found in the LICENSE file or at
|
// license that can be found in the LICENSE file or at
|
||||||
// https://developers.google.com/open-source/licenses/bsd
|
// https://developers.google.com/open-source/licenses/bsd
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "packager/mpd/base/adaptation_set.h"
|
#include "packager/mpd/base/adaptation_set.h"
|
||||||
|
@ -12,6 +13,8 @@
|
||||||
#include "packager/mpd/test/mpd_builder_test_helper.h"
|
#include "packager/mpd/test/mpd_builder_test_helper.h"
|
||||||
#include "packager/version/version.h"
|
#include "packager/version/version.h"
|
||||||
|
|
||||||
|
using ::testing::HasSubstr;
|
||||||
|
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -150,7 +153,7 @@ TEST_F(OnDemandMpdBuilderTest, MediaInfoMissingBandwidth) {
|
||||||
ASSERT_FALSE(mpd_.ToString(&mpd_doc));
|
ASSERT_FALSE(mpd_.ToString(&mpd_doc));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(LiveMpdBuilderTest, MultiplePeriodTest) {
|
TEST_F(OnDemandMpdBuilderTest, MultiplePeriodTest) {
|
||||||
const double kPeriodStartTimeSeconds = 1.0;
|
const double kPeriodStartTimeSeconds = 1.0;
|
||||||
Period* period = mpd_.GetOrCreatePeriod(kPeriodStartTimeSeconds);
|
Period* period = mpd_.GetOrCreatePeriod(kPeriodStartTimeSeconds);
|
||||||
ASSERT_TRUE(period);
|
ASSERT_TRUE(period);
|
||||||
|
@ -170,6 +173,40 @@ TEST_F(LiveMpdBuilderTest, MultiplePeriodTest) {
|
||||||
ASSERT_EQ(kPeriodStartTimeSeconds3, period3->start_time_in_seconds());
|
ASSERT_EQ(kPeriodStartTimeSeconds3, period3->start_time_in_seconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(OnDemandMpdBuilderTest, MultiplePeriodCheckXmlTest) {
|
||||||
|
const double kPeriodStartTimeSeconds = 0.0;
|
||||||
|
const double kPeriodStartTimeSeconds2 = 3.1;
|
||||||
|
const double kPeriodStartTimeSeconds3 = 8.0;
|
||||||
|
mpd_.GetOrCreatePeriod(kPeriodStartTimeSeconds);
|
||||||
|
mpd_.GetOrCreatePeriod(kPeriodStartTimeSeconds2);
|
||||||
|
mpd_.GetOrCreatePeriod(kPeriodStartTimeSeconds3);
|
||||||
|
|
||||||
|
std::string mpd_doc;
|
||||||
|
ASSERT_TRUE(mpd_.ToString(&mpd_doc));
|
||||||
|
EXPECT_THAT(mpd_doc,
|
||||||
|
HasSubstr(" <Period id=\"0\" duration=\"PT3.1S\"/>\n"
|
||||||
|
" <Period id=\"1\" duration=\"PT4.9S\"/>\n"
|
||||||
|
// There are no Representations so MPD duration is 0,
|
||||||
|
// which results in a negative duration for the last
|
||||||
|
// period. This would not happen in practice.
|
||||||
|
" <Period id=\"2\" duration=\"PT-8S\"/>\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LiveMpdBuilderTest, MultiplePeriodCheckXmlTest) {
|
||||||
|
const double kPeriodStartTimeSeconds = 0.0;
|
||||||
|
const double kPeriodStartTimeSeconds2 = 3.1;
|
||||||
|
const double kPeriodStartTimeSeconds3 = 8.0;
|
||||||
|
mpd_.GetOrCreatePeriod(kPeriodStartTimeSeconds);
|
||||||
|
mpd_.GetOrCreatePeriod(kPeriodStartTimeSeconds2);
|
||||||
|
mpd_.GetOrCreatePeriod(kPeriodStartTimeSeconds3);
|
||||||
|
|
||||||
|
std::string mpd_doc;
|
||||||
|
ASSERT_TRUE(mpd_.ToString(&mpd_doc));
|
||||||
|
EXPECT_THAT(mpd_doc, HasSubstr(" <Period id=\"0\" start=\"PT0S\"/>\n"
|
||||||
|
" <Period id=\"1\" start=\"PT3.1S\"/>\n"
|
||||||
|
" <Period id=\"2\" start=\"PT8S\"/>\n"));
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether the attributes are set correctly for dynamic <MPD> element.
|
// Check whether the attributes are set correctly for dynamic <MPD> element.
|
||||||
// This test must use ASSERT_EQ for comparison because XmlEqual() cannot
|
// This test must use ASSERT_EQ for comparison because XmlEqual() cannot
|
||||||
// handle namespaces correctly yet.
|
// handle namespaces correctly yet.
|
||||||
|
|
|
@ -94,7 +94,7 @@ AdaptationSet* Period::GetOrCreateAdaptationSet(
|
||||||
return adaptation_set_ptr;
|
return adaptation_set_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
xml::scoped_xml_ptr<xmlNode> Period::GetXml() {
|
xml::scoped_xml_ptr<xmlNode> Period::GetXml() const {
|
||||||
xml::XmlNode period("Period");
|
xml::XmlNode period("Period");
|
||||||
|
|
||||||
// Required for 'dynamic' MPDs.
|
// Required for 'dynamic' MPDs.
|
||||||
|
@ -106,7 +106,10 @@ xml::scoped_xml_ptr<xmlNode> Period::GetXml() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpd_options_.mpd_type == MpdType::kDynamic ||
|
if (duration_seconds_ != 0) {
|
||||||
|
period.SetStringAttribute("duration",
|
||||||
|
SecondsToXmlDuration(duration_seconds_));
|
||||||
|
} else if (mpd_options_.mpd_type == MpdType::kDynamic ||
|
||||||
start_time_in_seconds_ != 0) {
|
start_time_in_seconds_ != 0) {
|
||||||
period.SetStringAttribute("start",
|
period.SetStringAttribute("start",
|
||||||
SecondsToXmlDuration(start_time_in_seconds_));
|
SecondsToXmlDuration(start_time_in_seconds_));
|
||||||
|
|
|
@ -48,7 +48,7 @@ class Period {
|
||||||
/// Generates <Period> xml element with its child AdaptationSet elements.
|
/// Generates <Period> xml element with its child AdaptationSet elements.
|
||||||
/// @return On success returns a non-NULL scoped_xml_ptr. Otherwise returns a
|
/// @return On success returns a non-NULL scoped_xml_ptr. Otherwise returns a
|
||||||
/// NULL scoped_xml_ptr.
|
/// NULL scoped_xml_ptr.
|
||||||
xml::scoped_xml_ptr<xmlNode> GetXml();
|
xml::scoped_xml_ptr<xmlNode> GetXml() const;
|
||||||
|
|
||||||
/// @return The list of AdaptationSets in this Period.
|
/// @return The list of AdaptationSets in this Period.
|
||||||
const std::list<AdaptationSet*> GetAdaptationSets() const;
|
const std::list<AdaptationSet*> GetAdaptationSets() const;
|
||||||
|
@ -56,6 +56,11 @@ class Period {
|
||||||
/// @return The start time of this Period.
|
/// @return The start time of this Period.
|
||||||
double start_time_in_seconds() const { return start_time_in_seconds_; }
|
double start_time_in_seconds() const { return start_time_in_seconds_; }
|
||||||
|
|
||||||
|
/// Set period duration.
|
||||||
|
void set_duration_seconds(double duration_seconds) {
|
||||||
|
duration_seconds_ = duration_seconds;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// @param period_id is an ID number for this Period.
|
/// @param period_id is an ID number for this Period.
|
||||||
/// @param start_time_in_seconds is the start time for this Period.
|
/// @param start_time_in_seconds is the start time for this Period.
|
||||||
|
@ -102,6 +107,7 @@ class Period {
|
||||||
|
|
||||||
const uint32_t id_;
|
const uint32_t id_;
|
||||||
const double start_time_in_seconds_;
|
const double start_time_in_seconds_;
|
||||||
|
double duration_seconds_ = 0;
|
||||||
const MpdOptions& mpd_options_;
|
const MpdOptions& mpd_options_;
|
||||||
base::AtomicSequenceNumber* const adaptation_set_counter_;
|
base::AtomicSequenceNumber* const adaptation_set_counter_;
|
||||||
base::AtomicSequenceNumber* const representation_counter_;
|
base::AtomicSequenceNumber* const representation_counter_;
|
||||||
|
|
|
@ -177,6 +177,38 @@ TEST_P(PeriodTest, DynamicMpdGetXml) {
|
||||||
EXPECT_THAT(testable_period_.GetXml().get(), XmlNodeEqual(kExpectedXml));
|
EXPECT_THAT(testable_period_.GetXml().get(), XmlNodeEqual(kExpectedXml));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(PeriodTest, SetDurationAndGetXml) {
|
||||||
|
const char kVideoMediaInfo[] =
|
||||||
|
"video_info {\n"
|
||||||
|
" codec: 'avc1'\n"
|
||||||
|
" width: 1280\n"
|
||||||
|
" height: 720\n"
|
||||||
|
" time_scale: 10\n"
|
||||||
|
" frame_duration: 10\n"
|
||||||
|
" pixel_width: 1\n"
|
||||||
|
" pixel_height: 1\n"
|
||||||
|
"}\n"
|
||||||
|
"container_type: 1\n";
|
||||||
|
|
||||||
|
EXPECT_CALL(testable_period_, NewAdaptationSet(_, _, _, _))
|
||||||
|
.WillOnce(Return(ByMove(std::move(default_adaptation_set_))));
|
||||||
|
|
||||||
|
ASSERT_EQ(default_adaptation_set_ptr_,
|
||||||
|
testable_period_.GetOrCreateAdaptationSet(
|
||||||
|
ConvertToMediaInfo(kVideoMediaInfo),
|
||||||
|
content_protection_in_adaptation_set_));
|
||||||
|
|
||||||
|
testable_period_.set_duration_seconds(100.234);
|
||||||
|
|
||||||
|
const char kExpectedXml[] =
|
||||||
|
"<Period id=\"9\" duration=\"PT100.234S\">"
|
||||||
|
// ContentType and Representation elements are populated after
|
||||||
|
// Representation::Init() is called.
|
||||||
|
" <AdaptationSet id=\"0\" contentType=\"\"/>"
|
||||||
|
"</Period>";
|
||||||
|
EXPECT_THAT(testable_period_.GetXml().get(), XmlNodeEqual(kExpectedXml));
|
||||||
|
}
|
||||||
|
|
||||||
// Verify ForceSetSegmentAlignment is called.
|
// Verify ForceSetSegmentAlignment is called.
|
||||||
TEST_P(PeriodTest, Text) {
|
TEST_P(PeriodTest, Text) {
|
||||||
const char kTextMediaInfo[] =
|
const char kTextMediaInfo[] =
|
||||||
|
|
|
@ -315,7 +315,7 @@ float Representation::GetDurationSeconds() const {
|
||||||
return media_info_.media_duration_seconds();
|
return media_info_.media_duration_seconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Representation::HasRequiredMediaInfoFields() {
|
bool Representation::HasRequiredMediaInfoFields() const {
|
||||||
if (HasVODOnlyFields(media_info_) && HasLiveOnlyFields(media_info_)) {
|
if (HasVODOnlyFields(media_info_) && HasLiveOnlyFields(media_info_)) {
|
||||||
LOG(ERROR) << "MediaInfo cannot have both VOD and Live fields.";
|
LOG(ERROR) << "MediaInfo cannot have both VOD and Live fields.";
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -172,7 +172,7 @@ class Representation {
|
||||||
|
|
||||||
// Returns true if |media_info_| has required fields to generate a valid
|
// Returns true if |media_info_| has required fields to generate a valid
|
||||||
// Representation. Otherwise returns false.
|
// Representation. Otherwise returns false.
|
||||||
bool HasRequiredMediaInfoFields();
|
bool HasRequiredMediaInfoFields() const;
|
||||||
|
|
||||||
// Return false if the segment should be considered a new segment. True if the
|
// Return false if the segment should be considered a new segment. True if the
|
||||||
// segment is contiguous.
|
// segment is contiguous.
|
||||||
|
|
Loading…
Reference in New Issue