-
Notifications
You must be signed in to change notification settings - Fork 425
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
fix: llhls syncing fixes #1125
Merged
Merged
fix: llhls syncing fixes #1125
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
3d39612
feat: Use ll-hls query directives and support skipping segments
brandonocasey 5e46a1e
Merge branch 'main' into feat/llhls-3
brandonocasey df957d4
Merge branch 'main' into feat/llhls-3
brandonocasey ff40332
unified manifest parse function
brandonocasey 53ec980
tests for llhls and query directives in playlist-loader
brandonocasey addf841
Merge branch 'main' into feat/llhls-3
brandonocasey 285a4ae
Merge branch 'main' into feat/llhls-3
brandonocasey a46f0a7
remove unused option
brandonocasey 9d1fc06
add duration to preload segment
brandonocasey 00a8e25
always add a part target duration when we have parts
brandonocasey 1ff48b0
query directive fixes
brandonocasey 3ff694a
small logging fix, bring map to skipped segments
brandonocasey d3fb477
pare down changes
brandonocasey 2854967
cover all scenarios
brandonocasey a842b84
fix logging and merging issues
brandonocasey 4f842e6
fix: use partIndex and segmentIndex for syncPoints/getMediaInfoForTime
brandonocasey 0205771
fix tests
brandonocasey 402de98
tests
brandonocasey 2c5080c
tests
brandonocasey 6899546
Update src/playlist.js
brandonocasey 00fd02c
code review
brandonocasey 842650c
add question mark
brandonocasey 4c19976
Update src/playlist.js
brandonocasey e079124
Update src/playlist.js
brandonocasey 112d029
Update src/sync-controller.js
brandonocasey d0679f6
Update src/sync-controller.js
brandonocasey b3141c1
Update test/playlist.test.js
brandonocasey 99dd646
Update test/playlist.test.js
brandonocasey ac9de31
code review
brandonocasey 6c32f9b
Merge branch 'main' into fix/llhls-fixes
brandonocasey 941bec9
Merge remote-tracking branch 'origin/main' into fix/llhls-fixes
brandonocasey 99ee6e6
revert main merge changes
brandonocasey 680d740
add comment for segment.start timing info
brandonocasey 65da7f2
Merge remote-tracking branch 'origin/main' into fix/llhls-fixes
brandonocasey 944df45
Update src/sync-controller.js
brandonocasey 18d06c5
Update src/sync-controller.js
brandonocasey File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,13 +18,13 @@ const {createTimeRange} = videojs; | |
* | ||
* @return {Array} The part/segment list. | ||
*/ | ||
const getPartsAndSegments = (playlist) => (playlist.segments || []).reduce((acc, segment, si) => { | ||
export const getPartsAndSegments = (playlist) => (playlist.segments || []).reduce((acc, segment, si) => { | ||
if (segment.parts) { | ||
segment.parts.forEach(function(part, pi) { | ||
acc.push({duration: part.duration, segmentIndex: si, partIndex: pi}); | ||
acc.push({duration: part.duration, segmentIndex: si, partIndex: pi, part, segment}); | ||
}); | ||
} else { | ||
acc.push({duration: segment.duration, segmentIndex: si, partIndex: null}); | ||
acc.push({duration: segment.duration, segmentIndex: si, partIndex: null, segment, part: null}); | ||
} | ||
return acc; | ||
}, []); | ||
|
@@ -261,12 +261,13 @@ export const duration = function(playlist, endSequence, expired) { | |
* playlist in which case, the targetDuration of the playlist is used | ||
* to approximate the durations of the segments | ||
* | ||
* @param {Object} playlist a media playlist object | ||
* @param {number} startIndex | ||
* @param {number} endIndex | ||
* @param {Array} options.durationList list to iterate over for durations. | ||
* @param {number} options.defaultDuration duration to use for elements before or after the durationList | ||
* @param {number} options.startIndex partsAndSegments index to start | ||
* @param {number} options.endIndex partsAndSegments index to end. | ||
* @return {number} the number of seconds between startIndex and endIndex | ||
*/ | ||
export const sumDurations = function(playlist, startIndex, endIndex) { | ||
export const sumDurations = function({defaultDuration, durationList, startIndex, endIndex}) { | ||
let durations = 0; | ||
|
||
if (startIndex > endIndex) { | ||
|
@@ -275,13 +276,13 @@ export const sumDurations = function(playlist, startIndex, endIndex) { | |
|
||
if (startIndex < 0) { | ||
for (let i = startIndex; i < Math.min(0, endIndex); i++) { | ||
durations += playlist.targetDuration; | ||
durations += defaultDuration; | ||
} | ||
startIndex = 0; | ||
} | ||
|
||
for (let i = startIndex; i < endIndex; i++) { | ||
durations += playlist.segments[i].duration; | ||
durations += durationList[i].duration; | ||
} | ||
|
||
return durations; | ||
|
@@ -367,38 +368,64 @@ export const seekable = function(playlist, expired, liveEdgePadding) { | |
* Determine the index and estimated starting time of the segment that | ||
* contains a specified playback position in a media playlist. | ||
* | ||
* @param {Object} playlist the media playlist to query | ||
* @param {number} currentTime The number of seconds since the earliest | ||
* @param {Object} options.playlist the media playlist to query | ||
* @param {number} options.currentTime The number of seconds since the earliest | ||
* possible position to determine the containing segment for | ||
* @param {number} startIndex | ||
* @param {number} startTime | ||
* @return {Object} | ||
* @param {number} options.startTime the time when the segment/part starts | ||
* @param {number} options.startingSegmentIndex the segment index to start looking at. | ||
* @param {number?} [options.startingPartIndex] the part index to look at within the segment. | ||
* | ||
* @return {Object} an object with partIndex, segmentIndex, and startTime. | ||
*/ | ||
export const getMediaInfoForTime = function( | ||
export const getMediaInfoForTime = function({ | ||
brandonocasey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
playlist, | ||
currentTime, | ||
startIndex, | ||
startingSegmentIndex, | ||
startingPartIndex, | ||
startTime | ||
) { | ||
}) { | ||
|
||
const partsAndSegments = getPartsAndSegments(playlist); | ||
let time = currentTime - startTime; | ||
const partsAndSegments = getPartsAndSegments(playlist); | ||
|
||
let startIndex = 0; | ||
|
||
for (let i = 0; i < partsAndSegments.length; i++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have to find the partAndSegment index for the specified segment/part |
||
const partAndSegment = partsAndSegments[i]; | ||
|
||
if (startingSegmentIndex !== partAndSegment.segmentIndex) { | ||
continue; | ||
} | ||
|
||
// skip this if part index does not match. | ||
if (typeof startingPartIndex === 'number' && typeof partAndSegment.partIndex === 'number' && startingPartIndex !== partAndSegment.partIndex) { | ||
continue; | ||
} | ||
|
||
startIndex = i; | ||
break; | ||
} | ||
|
||
if (time < 0) { | ||
// Walk backward from startIndex in the playlist, adding durations | ||
// until we find a segment that contains `time` and return it | ||
if (startIndex > 0) { | ||
for (let i = startIndex - 1; i >= 0; i--) { | ||
const segment = partsAndSegments[i]; | ||
const partAndSegment = partsAndSegments[i]; | ||
|
||
time += segment.duration; | ||
time += partAndSegment.duration; | ||
|
||
// TODO: consider not using TIME_FUDGE_FACTOR at all here | ||
if ((time + TIME_FUDGE_FACTOR) > 0) { | ||
return { | ||
mediaIndex: segment.segmentIndex, | ||
startTime: startTime - sumDurations(playlist, startIndex, segment.segmentIndex), | ||
partIndex: segment.partIndex | ||
partIndex: partAndSegment.partIndex, | ||
segmentIndex: partAndSegment.segmentIndex, | ||
startTime: startTime - sumDurations({ | ||
defaultDuration: playlist.targetDuration, | ||
durationList: partsAndSegments, | ||
startIndex, | ||
endIndex: i | ||
}) | ||
}; | ||
} | ||
} | ||
|
@@ -407,8 +434,8 @@ export const getMediaInfoForTime = function( | |
// We were unable to find a good segment within the playlist | ||
// so select the first segment | ||
return { | ||
mediaIndex: partsAndSegments[0] && partsAndSegments[0].segmentIndex || 0, | ||
partIndex: partsAndSegments[0] && partsAndSegments[0].partIndex || null, | ||
segmentIndex: partsAndSegments[0] && partsAndSegments[0].segmentIndex || 0, | ||
startTime: currentTime | ||
}; | ||
} | ||
|
@@ -421,7 +448,8 @@ export const getMediaInfoForTime = function( | |
time -= playlist.targetDuration; | ||
if (time < 0) { | ||
return { | ||
mediaIndex: partsAndSegments[0].segmentIndex, | ||
partIndex: partsAndSegments[0] && partsAndSegments[0].partIndex || null, | ||
segmentIndex: partsAndSegments[0] && partsAndSegments[0].segmentIndex || 0, | ||
startTime: currentTime | ||
}; | ||
} | ||
|
@@ -432,23 +460,28 @@ export const getMediaInfoForTime = function( | |
// Walk forward from startIndex in the playlist, subtracting durations | ||
// until we find a segment that contains `time` and return it | ||
for (let i = startIndex; i < partsAndSegments.length; i++) { | ||
const partSegment = partsAndSegments[i]; | ||
const partAndSegment = partsAndSegments[i]; | ||
|
||
time -= partSegment.duration; | ||
time -= partAndSegment.duration; | ||
|
||
// TODO: consider not using TIME_FUDGE_FACTOR at all here | ||
if ((time - TIME_FUDGE_FACTOR) < 0) { | ||
return { | ||
mediaIndex: partSegment.segmentIndex, | ||
startTime: startTime + sumDurations(playlist, startIndex, partSegment.segmentIndex), | ||
partIndex: partSegment.partIndex | ||
partIndex: partAndSegment.partIndex, | ||
segmentIndex: partAndSegment.segmentIndex, | ||
startTime: startTime + sumDurations({ | ||
defaultDuration: playlist.targetDuration, | ||
durationList: partsAndSegments, | ||
startIndex, | ||
endIndex: i | ||
}) | ||
}; | ||
} | ||
} | ||
|
||
// We are out of possible candidates so load the last one... | ||
return { | ||
mediaIndex: partsAndSegments[partsAndSegments.length - 1].segmentIndex, | ||
segmentIndex: partsAndSegments[partsAndSegments.length - 1].segmentIndex, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. renamed to segmentIndex as that is actually what this is. |
||
partIndex: partsAndSegments[partsAndSegments.length - 1].partIndex, | ||
startTime: currentTime | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changes to allow passing in a list and a default duration. This allows us to use
partsAndSegments
, justparts
, or justsegments