dc135fdf by David LaPalomento

Merge pull request #184 from bc-bbay/master

Setting start position on a live stream
2 parents 9e932b3b 2fcc16f3
......@@ -89,6 +89,18 @@ videojs.Hls.prototype.src = function(src) {
});
};
videojs.Hls.setMediaIndexForLive = function(selectedPlaylist) {
var tailIterator = selectedPlaylist.segments.length,
tailDuration = 0;
while (tailDuration < 30 && tailIterator > 0) {
tailDuration += selectedPlaylist.segments[tailIterator - 1].duration;
tailIterator--;
}
return tailIterator;
};
videojs.Hls.prototype.handleSourceOpen = function() {
// construct the video data buffer and set the appropriate MIME type
var
......@@ -142,6 +154,11 @@ videojs.Hls.prototype.handleSourceOpen = function() {
segmentDlTime = Infinity;
}
// start live playlists 30 seconds before the current time
if (this.duration() === Infinity && this.mediaIndex === 0 && selectedPlaylist.segments) {
this.mediaIndex = videojs.Hls.setMediaIndexForLive(selectedPlaylist);
}
// this threshold is to account for having a high latency on the manifest
// request which is a somewhat small file.
threshold = 10;
......@@ -781,14 +798,15 @@ videojs.Hls.getPlaylistTotalDuration = function(playlist) {
* playlist
*/
videojs.Hls.translateMediaIndex = function(mediaIndex, original, update) {
var
i,
originalSegment;
var i,
originalSegment,
translatedMediaIndex;
// no segments have been loaded from the original playlist
if (mediaIndex === 0) {
return 0;
}
if (!(update && update.segments)) {
// let the media index be zero when there are no segments defined
return 0;
......@@ -803,8 +821,15 @@ videojs.Hls.translateMediaIndex = function(mediaIndex, original, update) {
}
}
translatedMediaIndex = (mediaIndex + (original.mediaSequence - update.mediaSequence));
if (translatedMediaIndex >= update.segments.length || translatedMediaIndex < 0) {
// recalculate the live point if the streams are too far out of sync
return videojs.Hls.setMediaIndexForLive(update) + 1;
}
// sync on media sequence
return (original.mediaSequence + mediaIndex) - update.mediaSequence;
return translatedMediaIndex;
};
/**
......
{
"allowCache": true,
"mediaSequence": 0,
"segments": [
{
"duration": 10,
"uri": "001.ts"
},
{
"duration": 19,
"uri": "002.ts"
},
{
"duration": 10,
"uri": "003.ts"
},
{
"duration": 11,
"uri": "004.ts"
},
{
"duration": 10,
"uri": "005.ts"
},
{
"duration": 10,
"uri": "006.ts"
},
{
"duration": 10,
"uri": "007.ts"
},
{
"duration": 10,
"uri": "008.ts"
},
{
"duration": 16,
"uri": "009.ts"
}
],
"targetDuration": 19
}
\ No newline at end of file
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:19
#EXTINF:10,0
001.ts
#EXTINF:19,0
002.ts
#EXTINF:10,0
003.ts
#EXTINF:11,0
004.ts
#EXTINF:10,0
005.ts
#EXTINF:10,0
006.ts
#EXTINF:10,0
007.ts
#EXTINF:10,0
008.ts
#EXTINF:16,0
009.ts
\ No newline at end of file
......@@ -1054,6 +1054,20 @@ test('updates the media index when a playlist reloads', function() {
strictEqual(player.hls.mediaIndex, 2, 'mediaIndex is updated after the reload');
});
test('live playlist starts 30s before live', function() {
player.src({
src: 'http://example.com/manifest/liveStart30sBefore.m3u8',
type: 'application/vnd.apple.mpegurl'
});
openMediaSource(player);
standardXHRResponse(requests[0]);
player.hls.playlists.trigger('loadedmetadata');
strictEqual(player.hls.mediaIndex, 6, 'mediaIndex is updated after the reload');
});
test('mediaIndex is zero before the first segment loads', function() {
window.manifests['first-seg-load'] =
'#EXTM3U\n' +
......