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: suggestedPresentationDelay #698

Merged
merged 18 commits into from
Feb 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 51 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"aes-decrypter": "3.0.0",
"global": "^4.3.0",
"m3u8-parser": "4.4.0",
"mpd-parser": "0.8.1",
"mpd-parser": "0.10.0",
"mux.js": "5.4.0",
"url-toolkit": "^2.1.3",
"video.js": "^6.8.0 || ^7.0.0"
Expand Down
6 changes: 4 additions & 2 deletions src/master-playlist-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,9 @@ export class MasterPlaylistController extends videojs.EventTarget {
return;
}

mainSeekable = Hls.Playlist.seekable(media, expired);
const suggestedPresentationDelay = this.masterPlaylistLoader_.master.suggestedPresentationDelay

mainSeekable = Hls.Playlist.seekable(media, expired, suggestedPresentationDelay);

if (mainSeekable.length === 0) {
return;
Expand All @@ -951,7 +953,7 @@ export class MasterPlaylistController extends videojs.EventTarget {
return;
}

audioSeekable = Hls.Playlist.seekable(media, expired);
audioSeekable = Hls.Playlist.seekable(media, expired, suggestedPresentationDelay);

if (audioSeekable.length === 0) {
return;
Expand Down
39 changes: 31 additions & 8 deletions src/playlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,21 +216,36 @@ export const sumDurations = function(playlist, startIndex, endIndex) {
* window which is the duration of the last segment plus 2 target durations from the end
* of the playlist.
*
* A liveEdgePadding can be provided which will be used instead of calculating the safe live edge.
* This corresponds to suggestedPresentationDelay in DASH manifests.
*
* @param {Object} playlist
* a media playlist object
* @param {Number} [liveEdgePadding]
* A number in seconds indicating how far from the end we want to be.
* If provided, this value is used instead of calculating the safe live index from the target durations.
* Corresponds to suggestedPresentationDelay in DASH manifests.
* @return {Number}
* The media index of the segment at the safe live point. 0 if there is no "safe"
* point.
* @function safeLiveIndex
*/
export const safeLiveIndex = function(playlist) {
export const safeLiveIndex = function(playlist, liveEdgePadding) {
if (!playlist.segments.length) {
return 0;
}

let i = playlist.segments.length - 1;
let distanceFromEnd = playlist.segments[i].duration || playlist.targetDuration;
const safeDistance = distanceFromEnd + playlist.targetDuration * 2;
let i = playlist.segments.length;
let lastSegmentDuration = playlist.segments[i - 1].duration || playlist.targetDuration;
const safeDistance = typeof liveEdgePadding === 'number' ?
liveEdgePadding :
lastSegmentDuration + playlist.targetDuration * 2;

if (safeDistance === 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want this to account for any distance less than last segment duration?

Copy link
Member Author

Choose a reason for hiding this comment

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

no, I think we should only special-case 0 exactly. Any other value should be ran through the loop below to find the appropriate return value.

return i;
}

let distanceFromEnd = 0;

while (i--) {
distanceFromEnd += playlist.segments[i].duration;
Expand All @@ -253,10 +268,16 @@ export const safeLiveIndex = function(playlist) {
* playlist end calculation should consider the safe live end
* (truncate the playlist end by three segments). This is normally
* used for calculating the end of the playlist's seekable range.
* This takes into account the value of liveEdgePadding.
* Setting liveEdgePadding to 0 is equivalent to setting this to false.
* @param {Number} liveEdgePadding a number indicating how far from the end of the playlist we should be in seconds.
* If this is provided, it is used in the safe live end calculation.
* Setting useSafeLiveEnd=false or liveEdgePadding=0 are equivalent.
* Corresponds to suggestedPresentationDelay in DASH manifests.
* @returns {Number} the end time of playlist
* @function playlistEnd
*/
export const playlistEnd = function(playlist, expired, useSafeLiveEnd) {
export const playlistEnd = function(playlist, expired, useSafeLiveEnd, liveEdgePadding) {
if (!playlist || !playlist.segments) {
return null;
}
Expand All @@ -270,7 +291,7 @@ export const playlistEnd = function(playlist, expired, useSafeLiveEnd) {

expired = expired || 0;

const endSequence = useSafeLiveEnd ? safeLiveIndex(playlist) : playlist.segments.length;
const endSequence = useSafeLiveEnd ? safeLiveIndex(playlist, liveEdgePadding) : playlist.segments.length;

return intervalDuration(playlist,
playlist.mediaSequence + endSequence,
Expand All @@ -289,13 +310,15 @@ export const playlistEnd = function(playlist, expired, useSafeLiveEnd) {
* dropped off the front of the playlist in a live scenario
* @param {Number=} expired the amount of time that has
* dropped off the front of the playlist in a live scenario
* @param {Number} liveEdgePadding how far from the end of the playlist we should be in seconds.
* Corresponds to suggestedPresentationDelay in DASH manifests.
* @return {TimeRanges} the periods of time that are valid targets
* for seeking
*/
export const seekable = function(playlist, expired) {
export const seekable = function(playlist, expired, liveEdgePadding) {
let useSafeLiveEnd = true;
let seekableStart = expired || 0;
let seekableEnd = playlistEnd(playlist, expired, useSafeLiveEnd);
let seekableEnd = playlistEnd(playlist, expired, useSafeLiveEnd, liveEdgePadding);

if (seekableEnd === null) {
return createTimeRange();
Expand Down
2 changes: 2 additions & 0 deletions test/master-playlist-controller.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1839,6 +1839,7 @@ function(assert) {
let mainTimeRanges = [];
let audioTimeRanges = [];

this.masterPlaylistController.masterPlaylistLoader_.master = {};
this.masterPlaylistController.masterPlaylistLoader_.media = () => mainMedia;
this.masterPlaylistController.syncController_.getExpiredTime = () => 0;

Expand Down Expand Up @@ -1973,6 +1974,7 @@ function(assert) {
Playlist.seekable = () => {
return videojs.createTimeRanges(mainTimeRanges);
};
this.masterPlaylistController.masterPlaylistLoader_.master = {};
this.masterPlaylistController.masterPlaylistLoader_.media = () => media;
this.masterPlaylistController.syncController_.getExpiredTime = () => 0;

Expand Down
Loading