fix: Low Latency DASH: include the "availabilityTimeComplete=false" attribute (#1198)

# Low Latency DASH - `availabilityTimeComplete=false`

Low Latency DASH manifests generated by Packager were missing the
attribute `availabilityTimeComplete`. As per the [DASH
specs](https://dashif.org/docs/CR-Low-Latency-Live-r8.pdf):

**_the AdaptationSet@availabilityTimeCompleteshould be present and be
set to 'FALSE'_**

## The Issue
The missing attribute caused ULL streams from Shaka Packager to no
longer be compatible with DASH.js. Previous versions of DASH.js allowed
users to specify ULL mode when initializing the player. However, the
most recent releases of DASH.js automatically detect ULL by scanning the
manifest for ULL specific attributes. Although there are many attributes
only associated with ULL, [DASH.js only greps for
`availabilityTimeComplete` in its detection
logic](https://github.com/Dash-Industry-Forum/dash.js/blob/development/src/streaming/controllers/PlaybackController.js#L792-L805).
Because of the missing attribute in Packager and the limited ULL
verification criteria by DASH.js, Packager streams were not being
treated as low latency streams by DASH.js.

## Testing
### Unit Testing
`./mpd_unittest
--gtest_filter="SegmentTemplateTest.OneSegmentLowLatency"`
` ./mpd_unittest
--gtest_filter="LowLatencySegmentTest.LowLatencySegmentTemplate"`

### Manual Testing
- Created a low latency stream with Shaka Packager
- Observed the expected `availabilityTimeComplete=false` attribute in
the generated DASH manifest.
This commit is contained in:
Caitlin O'Callaghan 2023-07-05 23:33:51 +02:00 committed by GitHub
parent ef17cf81f2
commit d687ad1ed0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 8 additions and 2 deletions

View File

@ -559,8 +559,8 @@ TEST_F(SegmentTemplateTest, OneSegmentLowLatency) {
" width=\"720\" height=\"480\" frameRate=\"10/5\">\n"
" <SegmentTemplate timescale=\"1000\" "
" duration=\"5000\" availabilityTimeOffset=\"4.995\" "
" initialization=\"init.mp4\" media=\"$Time$.mp4\" "
" startNumber=\"1\"/>\n"
" availabilityTimeComplete=\"false\" initialization=\"init.mp4\" "
" media=\"$Time$.mp4\" startNumber=\"1\"/>\n"
"</Representation>\n";
EXPECT_THAT(representation_->GetXml(), XmlNodeEqual(kOutputTemplate));
}

View File

@ -483,6 +483,11 @@ bool RepresentationXmlNode::AddLiveOnlyInfo(
"availabilityTimeOffset", media_info.availability_time_offset()));
}
if (low_latency_dash_mode) {
RCHECK(segment_template.SetStringAttribute("availabilityTimeComplete",
"false"));
}
if (media_info.has_init_segment_url()) {
RCHECK(segment_template.SetStringAttribute("initialization",
media_info.init_segment_url()));

View File

@ -752,6 +752,7 @@ TEST_F(LowLatencySegmentTest, LowLatencySegmentTemplate) {
XmlNodeEqual("<Representation>"
" <SegmentTemplate timescale=\"90000\" duration=\"450000\" "
" availabilityTimeOffset=\"4.9750987314\" "
" availabilityTimeComplete=\"false\" "
" initialization=\"init.m4s\" "
" media=\"$Number$.m4s\" "
" startNumber=\"1\"/>"