Skip to content

Commit

Permalink
Update video duration if there's a gap at end.
Browse files Browse the repository at this point in the history
If the media segments don't reach to the end of the presentation (as
given in the manifest), then we may get stuck buffering forever.  Now
StreamingEngine will update the duration so PlayheadObserver won't
enter a buffering state.

b/37722271

Change-Id: Idf95fcccc04a024307601f0741b5da4474f76d03
  • Loading branch information
TheModMaker committed May 6, 2017
1 parent 07c40ab commit 40aaa3d
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
8 changes: 7 additions & 1 deletion lib/media/streaming_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,13 @@ shaka.media.StreamingEngine.prototype.onUpdate_ = function(mediaState) {
// Check if we've buffered to the end of the presentation.
if (mediaStates.every(function(ms) { return ms.endOfStream; })) {
shaka.log.v1(logPrefix, 'calling endOfStream()...');
this.playerInterface_.mediaSourceEngine.endOfStream();
this.playerInterface_.mediaSourceEngine.endOfStream().then(function() {
// If the media segments don't reach the end, then we need to update the
// timeline duration to match the final media duration to avoid buffering
// forever at the end.
var duration = this.playerInterface_.mediaSourceEngine.getDuration();
this.manifest_.presentationTimeline.setDuration(duration);
}.bind(this));
}
};

Expand Down
35 changes: 33 additions & 2 deletions test/media/streaming_engine_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,33 @@ describe('StreamingEngine', function() {
});
});

it('updates the timeline duration to match media duration', function() {
setupVod();
mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
createStreamingEngine();

playhead.getTime.and.returnValue(0);
onStartupComplete.and.callFake(setupFakeGetTime.bind(null, 0));
onChooseStreams.and.callFake(defaultOnChooseStreams);

// TODO(modmaker): Don't just silence the compiler error.
var endOfStream = /** @type {?} */ (mediaSourceEngine.endOfStream);
endOfStream.and.callFake(function() {
// Simulate the media ending before the expected (manifest) duration.
expect(mediaSourceEngine.setDuration).toHaveBeenCalledWith(40);
expect(mediaSourceEngine.setDuration).toHaveBeenCalledTimes(1);
mediaSourceEngine.getDuration.and.returnValue(35);
return Promise.resolve();
});

// Here we go!
streamingEngine.init();

runTest();
expect(mediaSourceEngine.endOfStream).toHaveBeenCalled();
expect(timeline.setDuration).toHaveBeenCalledWith(35);
});

describe('handles seeks (VOD)', function() {
var onTick;
var stub = function() {};
Expand Down Expand Up @@ -882,6 +909,7 @@ describe('StreamingEngine', function() {
expect(playhead.getTime()).toBe(26);
playheadTime -= 20;
streamingEngine.seeked();
return Promise.resolve();
});

// Init the first Period.
Expand Down Expand Up @@ -1046,11 +1074,12 @@ describe('StreamingEngine', function() {
return defaultOnChooseStreams(period);
});

mediaSourceEngine.endOfStream.and.stub();
mediaSourceEngine.endOfStream.and.callThrough();

// Switch to the first Period.
return defaultOnChooseStreams(period);
});
return Promise.resolve();
});

// Here we go!
Expand Down Expand Up @@ -1157,6 +1186,7 @@ describe('StreamingEngine', function() {
// call seeked().
expect(playhead.getTime()).toBe(26);
playheadTime -= 10;
return Promise.resolve();
});

// Here we go!
Expand Down Expand Up @@ -1260,7 +1290,8 @@ describe('StreamingEngine', function() {
playheadTime -= 20;
streamingEngine.seeked();

mediaSourceEngine.endOfStream.and.stub();
mediaSourceEngine.endOfStream.and.callThrough();
return Promise.resolve();
});

return defaultOnChooseStreams(period);
Expand Down

0 comments on commit 40aaa3d

Please sign in to comment.