[DASH] Support signalling of last segment number (#713)

Per https://dashif.org/docs/DASH-IF-IOP-v4.3.pdf 4.4.3.6 Signalling the last segment number in Period, there are three ways to signal the last segment number:

  a. Use the lmsg signalling as defined in clause 4.4.3.5.
  b. Use the Segment Timeline with @r value greater or equal to 0.
  c. Add a Supplemental Descriptor with @schemeIdUri set to http://dashif.org/guidelines/last-segment-number with the @value set to the last segment number.

We do not support (a). This change adds support for (c) when Segment Timeline (b) is not used, i.e. when Representation has constant duration (could be approximate).

Under flag --dash_add_last_segment_number_when_needed (disabled by default).
This commit is contained in:
sr90 2020-02-24 23:12:53 -08:00 committed by GitHub
parent ce932f68a2
commit 1ca873f453
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 0 deletions

View File

@ -24,6 +24,12 @@ DEFINE_bool(segment_template_constant_duration,
"Generates SegmentTemplate@duration if all segments except the " "Generates SegmentTemplate@duration if all segments except the "
"last one has the same duration if this flag is set to true."); "last one has the same duration if this flag is set to true.");
DEFINE_bool(dash_add_last_segment_number_when_needed,
false,
"Adds a Supplemental Descriptor with @schemeIdUri "
"set to http://dashif.org/guidelines/last-segment-number with "
"the @value set to the last segment number.");
namespace shaka { namespace shaka {
using xml::XmlNode; using xml::XmlNode;
@ -429,6 +435,15 @@ bool RepresentationXmlNode::AddLiveOnlyInfo(
if (IsTimelineConstantDuration(segment_infos, start_number)) { if (IsTimelineConstantDuration(segment_infos, start_number)) {
segment_template.SetIntegerAttribute("duration", segment_template.SetIntegerAttribute("duration",
segment_infos.front().duration); segment_infos.front().duration);
if (FLAGS_dash_add_last_segment_number_when_needed) {
uint32_t last_segment_number = start_number - 1;
for (const auto& segment_info_element : segment_infos)
last_segment_number += segment_info_element.repeat + 1;
AddSupplementalProperty(
"http://dashif.org/guidelines/last-segment-number",
std::to_string(last_segment_number));
}
} else { } else {
XmlNode segment_timeline("SegmentTimeline"); XmlNode segment_timeline("SegmentTimeline");
if (!PopulateSegmentTimeline(segment_infos, &segment_timeline) || if (!PopulateSegmentTimeline(segment_infos, &segment_timeline) ||

View File

@ -18,6 +18,7 @@
#include "packager/mpd/test/xml_compare.h" #include "packager/mpd/test/xml_compare.h"
DECLARE_bool(segment_template_constant_duration); DECLARE_bool(segment_template_constant_duration);
DECLARE_bool(dash_add_last_segment_number_when_needed);
using ::testing::ElementsAre; using ::testing::ElementsAre;
@ -397,5 +398,31 @@ TEST_F(LiveSegmentTimelineTest, TwoSegmentInfoWithGap) {
"</Representation>")); "</Representation>"));
} }
TEST_F(LiveSegmentTimelineTest, LastSegmentNumberSupplementalProperty) {
const uint32_t kStartNumber = 1;
const uint64_t kStartTime = 0;
const uint64_t kDuration = 100;
const uint64_t kRepeat = 9;
std::list<SegmentInfo> segment_infos = {
{kStartTime, kDuration, kRepeat},
};
RepresentationXmlNode representation;
FLAGS_dash_add_last_segment_number_when_needed = true;
ASSERT_TRUE(
representation.AddLiveOnlyInfo(media_info_, segment_infos, kStartNumber));
EXPECT_THAT(
representation.GetRawPtr(),
XmlNodeEqual("<Representation>"
"<SupplementalProperty schemeIdUri=\"http://dashif.org/"
"guidelines/last-segment-number\" value=\"10\"/>"
" <SegmentTemplate media=\"$Number$.m4s\" "
" startNumber=\"1\" duration=\"100\"/>"
"</Representation>"));
FLAGS_dash_add_last_segment_number_when_needed = false;
}
} // namespace xml } // namespace xml
} // namespace shaka } // namespace shaka