Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support multi-period live DASH with changing periods #152

Merged
merged 8 commits into from
Dec 17, 2021

Conversation

gesinger
Copy link
Contributor

In order to handle live DASH manifests where periods are changed, added, and removed,
merging is used to ensure that the new manifest is a continuation of the last parsed
manifest.

In order to handle live cases, the last MPD must be provided via the lastMpd option.

BREAKING CHANGE: period start time is now used as the timeline instead of period index

In order to handle live DASH manifests where periods are changed, added, and removed,
merging is used to ensure that the new manifest is a continuation of the last parsed
manifest.

In order to handle live cases, the last MPD must be provided via the `lastMpd` option.

BREAKING CHANGE: period start time is now used as the timeline instead of period index
@codecov
Copy link

codecov bot commented Oct 26, 2021

Codecov Report

Merging #152 (fbdd78e) into main (7814de7) will increase coverage by 1.12%.
The diff coverage is 96.80%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #152      +/-   ##
==========================================
+ Coverage   93.17%   94.30%   +1.12%     
==========================================
  Files          17       18       +1     
  Lines         674      772      +98     
  Branches      224      240      +16     
==========================================
+ Hits          628      728     +100     
+ Misses         46       44       -2     
Impacted Files Coverage Δ
src/inheritAttributes.js 97.33% <ø> (-0.04%) ⬇️
src/segment/segmentTemplate.js 100.00% <ø> (ø)
src/segment/timelineTimeParser.js 90.90% <50.00%> (-2.28%) ⬇️
src/segment/durationTimeParser.js 95.65% <66.66%> (-2.18%) ⬇️
src/toM3u8.js 98.73% <97.87%> (-0.49%) ⬇️
src/playlist-merge.js 98.03% <98.03%> (ø)
src/index.js 85.71% <100.00%> (ø)
src/segment/segmentBase.js 100.00% <100.00%> (ø)
src/utils/list.js 100.00% <100.00%> (ø)
src/parseAttributes.js 100.00% <0.00%> (+10.00%) ⬆️
... and 1 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7814de7...fbdd78e. Read the comment docs.

Copy link
Contributor

@brandonocasey brandonocasey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preliminary review, still need to do a deeper one in some places.

playlist.discontinuitySequence = findIndex(timelineStarts, ({ timeline }) => timeline === playlist.timeline);

if (!playlist.segments) {
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might as well add a test here

README.md Outdated Show resolved Hide resolved
src/index.js Outdated Show resolved Hide resolved
src/toM3u8.js Show resolved Hide resolved
Copy link
Member

@gkatsev gkatsev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick comments on the small files.

README.md Outdated Show resolved Hide resolved
src/utils/list.js Outdated Show resolved Hide resolved
src/playlist-merge.js Outdated Show resolved Hide resolved
src/playlist-merge.js Outdated Show resolved Hide resolved
src/playlist-merge.js Outdated Show resolved Hide resolved
src/toM3u8.js Outdated Show resolved Hide resolved
Copy link
Member

@gkatsev gkatsev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some fairly minor comments.

README.md Outdated
@@ -44,6 +44,17 @@ const manifest = await res.text();
var parsedManifest = mpdParser.parse(manifest, { manifestUri });
```

If dealing with a live stream, then on subsequent calls to parse, the last parsed manifest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If dealing with a live stream, then on subsequent calls to parse, the last parsed manifest
If dealing with a live stream, then on subsequent calls to parse, the previously parsed manifest


const SUPPORTED_MEDIA_TYPES = ['AUDIO', 'SUBTITLES'];
// allow one 60fps frame as leniency (arbitrarily chosen)
const TIME_FUDGE = 1 / 60;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delicious 🍫

Comment on lines 16 to 17
return union(timelineStarts, ({ timeline }) => timeline).sort((a, b) =>
(a.timeline > b.timeline) ? 1 : -1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Splitting on the .sort, I think, makes it a lot easier to understand that we call union and then sort on the response from union. At first, I thought that we were passing a method and the sort as a second argument to union.
The linter should be fine with this, I checked.

Suggested change
return union(timelineStarts, ({ timeline }) => timeline).sort((a, b) =>
(a.timeline > b.timeline) ? 1 : -1);
return union(timelineStarts, ({ timeline }) => timeline)
.sort((a, b) => (a.timeline > b.timeline) ? 1 : -1);

Comment on lines +64 to +66
playlist.segments.forEach((segment, index) => {
segment.number = playlist.mediaSequence + index;
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is part of the magic that makes thing whole thing work?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Along with the passed-in media sequence calculations in updateSequenceNumber below.

Multiperiod SIDX (in both live and VOD) and live SIDX where the SIDX
properties change on refresh, are not yet supported in mpd-parser. To
prevent exceptions, return early from merging logic on SIDX detection,
and add a TODO comment for the future.
Updates old start references to periodStart, as periodStart should not
be generated where the start attribute was missing.

Fixes durationTimeParser segment time values by using the number rather
than a 0 based index for calcuating time.

Add comments in durationTimeParser to make logic clearer.
gkatsev
gkatsev previously approved these changes Dec 6, 2021
@gkatsev gkatsev dismissed their stale review December 6, 2021 16:14

Still needs a rebase

gesinger added a commit to gesinger/http-streaming that referenced this pull request Dec 6, 2021
In order to support the new mpd-parser API, whenever a DASH manifest
refreshes, the prior parsed manifest object needs to be passed in as
`previousManifest`. This change adds support for that.

NOTE: this is to support an upcoming feature in mpd-parser:
videojs/mpd-parser#152
Copy link
Member

@gkatsev gkatsev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM, haven't tested it yet.

Copy link
Member

@gkatsev gkatsev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just ran a bunch of tests and it works great!

@gkatsev gkatsev merged commit fe886d0 into videojs:main Dec 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants