From bad769e1fcc073b9e90d44b7ee2ec2e3087a735d Mon Sep 17 00:00:00 2001 From: Matthew Neil Date: Thu, 5 Oct 2017 15:24:45 -0400 Subject: [PATCH] use 3*targetDuration for safe live point instead of 3 segments --- src/playlist.js | 32 ++++++++++-- test/playlist.test.js | 85 +++++++++++++++++++++++++++++++- test/videojs-contrib-hls.test.js | 1 + 3 files changed, 113 insertions(+), 5 deletions(-) diff --git a/src/playlist.js b/src/playlist.js index 5d69bfd3b..86b4500ca 100644 --- a/src/playlist.js +++ b/src/playlist.js @@ -219,6 +219,33 @@ export const sumDurations = function(playlist, startIndex, endIndex) { return durations; }; +/** + * Determines the media index of the segment corresponding to the safe edge of the live + * window which is 3 times target duration. + * + * @param {Object} playlist + * a media playlist object; + * @return {Number} + * The media index of the segment + * @function safeLiveIndex + */ +export const safeLiveIndex = function(playlist) { + const safeDistance = playlist.targetDuration * Playlist.UNSAFE_LIVE_SEGMENTS; + + let i = playlist.segments.length; + let distanceFromEnd = 0; + + while (i--) { + distanceFromEnd += playlist.segments[i].duration; + + if (distanceFromEnd >= safeDistance) { + break; + } + } + + return Math.max(0, i); +}; + /** * Calculates the playlist end time * @@ -246,9 +273,7 @@ export const playlistEnd = function(playlist, expired, useSafeLiveEnd) { expired = expired || 0; - let endSequence = useSafeLiveEnd ? - Math.max(0, playlist.segments.length - Playlist.UNSAFE_LIVE_SEGMENTS) : - Math.max(0, playlist.segments.length); + let endSequence = useSafeLiveEnd ? safeLiveIndex(playlist) : playlist.segments.length; return intervalDuration(playlist, playlist.mediaSequence + endSequence, @@ -485,6 +510,7 @@ export const estimateSegmentRequestTime = function(segmentDuration, Playlist.duration = duration; Playlist.seekable = seekable; +Playlist.safeLiveIndex = safeLiveIndex; Playlist.getMediaInfoForTime = getMediaInfoForTime; Playlist.isEnabled = isEnabled; Playlist.isBlacklisted = isBlacklisted; diff --git a/test/playlist.test.js b/test/playlist.test.js index 30d57d950..aee2ed547 100644 --- a/test/playlist.test.js +++ b/test/playlist.test.js @@ -385,11 +385,92 @@ function(assert) { assert.equal(seekable.start(0), 0, 'starts at the earliest available segment'); assert.equal(seekable.end(0), - 9 - (2 + 2 + 1), - 'allows seeking no further than three segments from the end'); + 9 - (2 + 2 + 1 + 2), + 'allows seeking no further than three times target duration from the end'); assert.equal(playlistEnd, 9, 'playlist end at the last segment'); }); +QUnit.test('safeLiveIndex returns the correct media index for the safe live point', +function(assert) { + const playlist = { + targetDuration: 6, + mediaSequence: 10, + syncInfo: { + time: 0, + mediaSequence: 10 + }, + segments: [ + { + duration: 6 + }, + { + duration: 6 + }, + { + duration: 6 + }, + { + duration: 6 + }, + { + duration: 6 + }, + { + duration: 6 + } + ] + }; + + let expected = 3; + let actual = Playlist.safeLiveIndex(playlist); + + assert.equal(actual, expected, 'correct media index for standard durations'); + + playlist.segments = [ + { + duration: 6 + }, + { + duration: 4 + }, + { + duration: 5 + }, + { + duration: 6 + }, + { + duration: 3 + }, + { + duration: 4 + }, + { + duration: 3 + } + ]; + + expected = 2; + actual = Playlist.safeLiveIndex(playlist); + assert.equal(actual, expected, 'correct media index for variable segment durations'); + + playlist.segments = [ + { + duration: 6 + }, + { + duration: 6 + }, + { + duration: 3 + } + ]; + expected = 0; + actual = Playlist.safeLiveIndex(playlist); + assert.equal(actual, expected, + 'returns media index 0 when playlist has no safe live point'); +}); + QUnit.test( 'seekable end and playlist end account for non-zero starting VOD media sequence', function(assert) { diff --git a/test/videojs-contrib-hls.test.js b/test/videojs-contrib-hls.test.js index 2124ee81f..ee2eedac9 100644 --- a/test/videojs-contrib-hls.test.js +++ b/test/videojs-contrib-hls.test.js @@ -421,6 +421,7 @@ QUnit.test('translates seekable by the starting time for live playlists', functi this.requests.shift().respond(200, null, '#EXTM3U\n' + '#EXT-X-MEDIA-SEQUENCE:15\n' + + '#EXT-X-TARGETDURATION:10\n' + '#EXTINF:10,\n' + '0.ts\n' + '#EXTINF:10,\n' +