Skip to content

Commit

Permalink
stream-controller: don't switch to ENDED state in case fragPrevious i…
Browse files Browse the repository at this point in the history
…s last playlist frag but currentTime is not buffered, or if stream not buffered till the end

also don't allow seeking more than maxSeekHole on loadedmetadata

related to #1193
related to #1119
  • Loading branch information
mangui committed Jun 8, 2017
1 parent 3797787 commit 2069b72
Showing 1 changed file with 20 additions and 16 deletions.
36 changes: 20 additions & 16 deletions src/controller/stream-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,11 @@ class StreamController extends EventHandler {
return;
}

// we just got done loading the final fragment, check if we need to finalize media stream
// we just got done loading the final fragment, and currentPos is buffered, and there is no other buffered range after ...
// rationale is that in case there are any buffered rangesafter, it means that there are unbuffered portion in between
// so we should not switch to ENDED in that case, to be able to buffer themx
let fragPrevious = this.fragPrevious;
if (!levelDetails.live && fragPrevious && fragPrevious.sn === levelDetails.endSN) {
if (!levelDetails.live && fragPrevious && fragPrevious.sn === levelDetails.endSN && bufferLen && !bufferInfo.nextStart) {
// fragPrevious is last fragment. retrieve level duration using last frag start offset + duration
// real duration might be lower than initial duration if there are drifts between real frag duration and playlist signaling
const duration = Math.min(media.duration,fragPrevious.start + fragPrevious.duration);
Expand All @@ -252,14 +254,14 @@ class StreamController extends EventHandler {
// tolerate up to one frag duration to cope with these cases.
// also cope with almost zero last frag duration (max last frag duration with 200ms) refer to https://github.com/video-dev/hls.js/pull/657
if (duration - Math.max(bufferInfo.end,fragPrevious.start) <= Math.max(0.2,fragPrevious.duration)) {
// Finalize the media stream
let data = {};
if (this.altAudio) {
data.type = 'video';
}
this.hls.trigger(Event.BUFFER_EOS,data);
this.state = State.ENDED;
return;
// Finalize the media stream
let data = {};
if (this.altAudio) {
data.type = 'video';
}
this.hls.trigger(Event.BUFFER_EOS,data);
this.state = State.ENDED;
return;
}
}

Expand Down Expand Up @@ -1387,7 +1389,8 @@ class StreamController extends EventHandler {
}

_checkBuffer() {
var media = this.media;
var media = this.media,
config = this.config;
// if ready state different from HAVE_NOTHING (numeric value 0), we are allowed to seek
if(media && media.readyState) {
let currentTime = media.currentTime,
Expand All @@ -1399,13 +1402,15 @@ _checkBuffer() {
// only adjust currentTime if different from startPosition or if startPosition not buffered
// at that stage, there should be only one buffered range, as we reach that code after first fragment has been buffered
let startPosition = media.seeking ? currentTime : this.startPosition,
startPositionBuffered = BufferHelper.isBuffered(mediaBuffer,startPosition);
startPositionBuffered = BufferHelper.isBuffered(mediaBuffer,startPosition),
firstbufferedPosition = buffered.start(0);
// if currentTime not matching with expected startPosition or startPosition not buffered
if (currentTime !== startPosition || !startPositionBuffered) {
if (currentTime !== startPosition ||
(!startPositionBuffered && (Math.abs(startPosition-firstbufferedPosition) < config.maxSeekHole))) {
logger.log(`target start position:${startPosition}`);
// if startPosition not buffered, let's seek to buffered.start(0)
if(!startPositionBuffered) {
startPosition = buffered.start(0);
startPosition = firstbufferedPosition;
logger.log(`target start position not buffered, seek to buffered.start(0) ${startPosition}`);
}
logger.log(`adjust currentTime from ${currentTime} to ${startPosition}`);
Expand All @@ -1419,8 +1424,7 @@ _checkBuffer() {
media.ended || // not playing when media is ended
media.buffered.length === 0), // not playing if nothing buffered
jumpThreshold = 0.5, // tolerance needed as some browsers stalls playback before reaching buffered range end
playheadMoving = currentTime !== this.lastCurrentTime,
config = this.config;
playheadMoving = currentTime !== this.lastCurrentTime;

if (playheadMoving) {
// played moving, but was previously stalled => now not stuck anymore
Expand Down

0 comments on commit 2069b72

Please sign in to comment.