Skip to content
This repository has been archived by the owner on Jan 12, 2019. It is now read-only.

Commit

Permalink
Merge pull request #473 from videojs/firefox-live
Browse files Browse the repository at this point in the history
Firefox live
  • Loading branch information
dmlap committed Dec 15, 2015
2 parents 7462bdc + 2286959 commit e3c5271
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 38 deletions.
4 changes: 4 additions & 0 deletions src/playlist-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,10 @@
return;
}

if (update.uri !== outdated.uri) {
return;
}

// try using precise timing from first segment of the updated
// playlist
if (update.segments.length) {
Expand Down
81 changes: 43 additions & 38 deletions src/videojs-hls.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ videojs.HlsHandler.prototype.src = function(src) {
}
this.playlists = new videojs.Hls.PlaylistLoader(this.source_.src, this.options_.withCredentials);

this.tech_.on('canplay', this.setupFirstPlay.bind(this));

this.playlists.on('loadedmetadata', function() {
oldMediaPlaylist = this.playlists.media();

Expand Down Expand Up @@ -422,7 +424,11 @@ videojs.HlsHandler.prototype.setupFirstPlay = function() {
this.sourceBuffer &&

// 4) the active media playlist is available
media) {
media &&

// 5) the video element or flash player is in a readyState of
// at least HAVE_FUTURE_DATA
this.tech_.readyState >= 3) {

// seek to the latest media position for live videos
seekable = this.seekable();
Expand Down Expand Up @@ -819,11 +825,14 @@ videojs.HlsHandler.prototype.fillBuffer = function(mediaIndex) {
var
tech = this.tech_,
currentTime = tech.currentTime(),
hasBufferedContent = (this.tech_.buffered().length !== 0),
currentBuffered = this.findBufferedRange_(),
outsideBufferedRanges = !(currentBuffered && currentBuffered.length),
currentBufferedEnd = 0,
bufferedTime = 0,
segment,
segmentInfo;
segmentInfo,
segmentTimestampOffset;

// if preload is set to "none", do not download segments until playback is requested
if (this.loadingState_ !== 'segments') {
Expand Down Expand Up @@ -906,9 +915,35 @@ videojs.HlsHandler.prototype.fillBuffer = function(mediaIndex) {
// the state of the buffer before a segment is appended will be
// stored here so that the actual segment duration can be
// determined after it has been appended
buffered: null
buffered: null,
// The target timestampOffset for this segment when we append it
// to the source buffer
timestampOffset: null
};

if (mediaIndex > 0) {
segmentTimestampOffset = videojs.Hls.Playlist.duration(segmentInfo.playlist,
segmentInfo.playlist.mediaSequence + mediaIndex) + this.playlists.expired_;
}

if (this.tech_.seeking() && outsideBufferedRanges) {
// If there are discontinuities in the playlist, we can't be sure of anything
// related to time so we reset the timestamp offset and start appending data
// anew on every seek
if (segmentInfo.playlist.discontinuityStarts.length) {
segmentInfo.timestampOffset = segmentTimestampOffset;
}
} else if (segment.discontinuity && currentBuffered.length) {
// If we aren't seeking and are crossing a discontinuity, we should set
// timestampOffset for new segments to be appended the end of the current
// buffered time-range
segmentInfo.timestampOffset = currentBuffered.end(0);
} else if (!hasBufferedContent && this.tech_.currentTime() > 0.05) {
// If we are trying to play at a position that is not zero but we aren't
// currently seeking according to the video element
segmentInfo.timestampOffset = segmentTimestampOffset;
}

this.loadSegment(segmentInfo);
};

Expand Down Expand Up @@ -1068,7 +1103,7 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) {

};

videojs.HlsHandler.prototype.drainBuffer = function(event) {
videojs.HlsHandler.prototype.drainBuffer = function() {
var
segmentInfo,
mediaIndex,
Expand All @@ -1077,11 +1112,7 @@ videojs.HlsHandler.prototype.drainBuffer = function(event) {
bytes,
segment,
decrypter,
segIv,
segmentTimestampOffset = 0,
hasBufferedContent = (this.tech_.buffered().length !== 0),
currentBuffered = this.findBufferedRange_(),
outsideBufferedRanges = !(currentBuffered && currentBuffered.length);
segIv;

// if the buffer is empty or the source buffer hasn't been created
// yet, do nothing
Expand Down Expand Up @@ -1109,7 +1140,6 @@ videojs.HlsHandler.prototype.drainBuffer = function(event) {
segment = playlist.segments[mediaIndex];

if (segment.key && !bytes) {

// this is an encrypted segment
// if the key download failed, we want to skip this segment
// but if the key hasn't downloaded yet, we want to try again later
Expand Down Expand Up @@ -1144,37 +1174,12 @@ videojs.HlsHandler.prototype.drainBuffer = function(event) {
}
}

event = event || {};

if (segmentInfo.mediaIndex > 0) {
segmentTimestampOffset = videojs.Hls.Playlist.duration(segmentInfo.playlist,
playlist.mediaSequence + segmentInfo.mediaIndex);
}
this.pendingSegment_.buffered = this.tech_.buffered();

// If we have seeked into a non-buffered time-range, remove all buffered
// time-ranges because they could have been incorrectly placed originally
if (this.tech_.seeking() && outsideBufferedRanges) {
// If there are discontinuities in the playlist, we can't be sure of anything
// related to time so we reset the timestamp offset and start appending data
// anew on every seek
if (segmentInfo.playlist.discontinuityStarts.length) {
// Now that the forward buffer is clear, we have to set timestamp offset to
// the start of the buffered region
this.sourceBuffer.timestampOffset = segmentTimestampOffset;
}
} else if (segment.discontinuity && currentBuffered.length) {
// If we aren't seeking and are crossing a discontinuity, we should set
// timestampOffset for new segments to be appended the end of the current
// buffered time-range
this.sourceBuffer.timestampOffset = currentBuffered.end(0);
} else if (!hasBufferedContent && this.tech_.currentTime() > 0.05) {
// If we are trying to play at a position that is not zero but we aren't
// currently seeking according to the video element
this.sourceBuffer.timestampOffset = segmentTimestampOffset;
if (segmentInfo.timestampOffset !== null) {
this.sourceBuffer.timestampOffset = segmentInfo.timestampOffset;
}

this.pendingSegment_.buffered = this.tech_.buffered();

// the segment is asynchronously added to the current buffered data
this.sourceBuffer.appendBuffer(bytes);
};
Expand Down
7 changes: 7 additions & 0 deletions test/videojs-hls_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ test('autoplay seeks to the live point after playlist load', function() {
type: 'application/vnd.apple.mpegurl'
});
openMediaSource(player);
player.tech_.readyState = 3;
player.tech_.trigger('play');
standardXHRResponse(requests.shift());
clock.tick(1);

Expand All @@ -355,6 +357,8 @@ test('autoplay seeks to the live point after media source open', function() {
clock.tick(1);
standardXHRResponse(requests.shift());
openMediaSource(player);
player.tech_.readyState = 3;
player.tech_.trigger('play');
clock.tick(1);

notEqual(currentTime, 0, 'seeked on autoplay');
Expand Down Expand Up @@ -406,6 +410,7 @@ test('calls `remove` on sourceBuffer to when loading a live segment', function()
player.tech_.hls.playlists.trigger('loadedmetadata');
player.tech_.trigger('canplay');
player.tech_.paused = function() { return false; };
player.tech_.readyState = 3;
player.tech_.trigger('play');

clock.tick(1);
Expand Down Expand Up @@ -1683,6 +1688,7 @@ test('live playlist starts three target durations before live', function() {
equal(requests.length, 0, 'no outstanding segment request');

player.tech_.paused = function() { return false; };
player.tech_.readyState = 3;
player.tech_.trigger('play');
clock.tick(1);
mediaPlaylist = player.tech_.hls.playlists.media();
Expand All @@ -1703,6 +1709,7 @@ test('live playlist starts with correct currentTime value', function() {
player.tech_.hls.playlists.trigger('loadedmetadata');

player.tech_.paused = function() { return false; };
player.tech_.readyState = 3;
player.tech_.trigger('play');
clock.tick(1);

Expand Down

0 comments on commit e3c5271

Please sign in to comment.