Files
shaka-player/spec/config_integration.js
T
Jacob Trimble f346ece22c Improve live end-of-stream behavior.
* Supports live streams of a fixed length.
* Live streams that stop now correctly end the video.
* Only uses local MPD when @availabilityStartTime is in the future.
* Added configuration option liveStreamEndTimeout.

A live stream is considered "ended" when the play-head moves past
the last segment for liveStreamEndTimeout amount of time.  This allows
the MPD to be updated with new segments.

Closes #139
Closes #140
Closes #145
Issue #172

Change-Id: I0675203931f35ca3e0dee60a87c54ba74cbdbaea
2015-10-13 18:00:01 +00:00

443 lines
14 KiB
JavaScript

/**
* @license
* Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
goog.require('shaka.player.Defaults');
goog.require('shaka.player.Restrictions');
goog.require('shaka.util.EventManager');
describe('Configuration', function() {
var video;
var player;
var eventManager;
var estimator;
beforeAll(integration.setUp);
afterAll(integration.tearDown);
beforeEach(function() {
// Create a video tag. This will be visible so that long tests do not
// create the illusion of the test-runner being hung.
video = createVideo();
document.body.appendChild(video);
player = createPlayer(video);
eventManager = new shaka.util.EventManager();
});
afterEach(function(done) {
eventManager.destroy();
eventManager = null;
player.destroy().then(function() {
player = null;
done();
});
// Remove the video tag from the DOM.
document.body.removeChild(video);
});
describe('configuring the preferredLanguage', function() {
it('changes the default tracks', function(done) {
var originalAudioId;
var originalTextId;
player.load(newSource(manifests.languagesManifest)).then(function() {
video.play();
return waitForMovement(video, eventManager);
}).then(function() {
var activeAudioTrack = getActiveAudioTrack(player);
expect(activeAudioTrack.lang).toBe('en');
originalAudioId = activeAudioTrack.id;
var activeTextTrack = getActiveTextTrack(player);
expect(activeTextTrack.lang).toBe('en');
originalTextId = activeTextTrack.id;
player.configure({'preferredLanguage': 'fr'});
return player.load(newSource(manifests.languagesManifest));
}).then(function() {
video.play();
return waitForMovement(video, eventManager);
}).then(function() {
var activeAudioTrack = getActiveAudioTrack(player);
expect(activeAudioTrack.lang).toBe('fr');
expect(activeAudioTrack.id).not.toBe(originalAudioId);
var activeTextTrack = getActiveTextTrack(player);
expect(activeTextTrack.lang).toBe('fr');
expect(activeTextTrack.id).not.toBe(originalTextId);
done();
}).catch(function(error) {
fail(error);
done();
});
});
it('enables text tracks when no matching audio is found', function(done) {
player.configure({'preferredLanguage': 'el'});
player.load(newSource(manifests.languagesManifest)).then(function() {
video.play();
return waitForMovement(video, eventManager);
}).then(function() {
var activeAudioTrack = getActiveAudioTrack(player);
expect(activeAudioTrack.lang).toBe('en');
var activeTextTrack = getActiveTextTrack(player);
expect(activeTextTrack.lang).toBe('el');
expect(activeTextTrack.enabled).toBe(true);
done();
}).catch(function(error) {
fail(error);
done();
});
});
it('disables text tracks when matching audio is found', function(done) {
player.configure({'preferredLanguage': 'fr'});
player.load(newSource(manifests.languagesManifest)).then(function() {
video.play();
return waitForMovement(video, eventManager);
}).then(function() {
var activeAudioTrack = getActiveAudioTrack(player);
expect(activeAudioTrack.lang).toBe('fr');
var activeTextTrack = getActiveTextTrack(player);
expect(activeTextTrack.lang).toBe('fr');
expect(activeTextTrack.enabled).toBe(false);
done();
}).catch(function(error) {
fail(error);
done();
});
});
it('respects the \'main\' attribute', function(done) {
// There are no Thai audio AdaptationSets in the MPD, but the English
// audio AdaptationSet is marked as main, so even though it is not the
// first AdaptationSet, it should be preferred.
player.configure({'preferredLanguage': 'th'});
player.load(newSource(manifests.languagesManifest)).then(function() {
video.play();
return waitForMovement(video, eventManager);
}).then(function() {
var activeAudioTrack = getActiveAudioTrack(player);
expect(activeAudioTrack.lang).toBe('en');
done();
}).catch(function(error) {
fail(error);
done();
});
});
});
describe('configuring restrictions', function() {
it('ignores video tracks above the maximum height', function(done) {
player.load(newSource(manifests.encryptedManifest)).then(function() {
var hdVideoTrack = getVideoTrackByHeight(player, 720);
var sdVideoTrack = getVideoTrackByHeight(player, 480);
expect(hdVideoTrack).not.toBe(null);
expect(sdVideoTrack).not.toBe(null);
var restrictions = player.getConfiguration()['restrictions'];
restrictions.maxHeight = 480;
player.configure({'restrictions': restrictions});
hdVideoTrack = getVideoTrackByHeight(player, 720);
sdVideoTrack = getVideoTrackByHeight(player, 480);
expect(hdVideoTrack).toBe(null);
expect(sdVideoTrack).not.toBe(null);
done();
}).catch(function(error) {
fail(error);
done();
});
});
it('ignores video tracks above the maximum width', function(done) {
player.load(newSource(manifests.encryptedManifest)).then(function() {
var hdVideoTrack = getVideoTrackByHeight(player, 720);
var sdVideoTrack = getVideoTrackByHeight(player, 480);
expect(hdVideoTrack).not.toBe(null);
expect(sdVideoTrack).not.toBe(null);
var restrictions = player.getConfiguration()['restrictions'];
restrictions.maxWidth = 854;
player.configure({'restrictions': restrictions});
hdVideoTrack = getVideoTrackByHeight(player, 720);
sdVideoTrack = getVideoTrackByHeight(player, 480);
expect(hdVideoTrack).toBe(null);
expect(sdVideoTrack).not.toBe(null);
done();
}).catch(function(error) {
fail(error);
done();
});
});
it('takes effect before the source is loaded', function(done) {
var restrictions = player.getConfiguration()['restrictions'];
restrictions.maxHeight = 480;
player.configure({'restrictions': restrictions});
player.load(newSource(manifests.encryptedManifest)).then(function() {
var hdVideoTrack = getVideoTrackByHeight(player, 720);
var sdVideoTrack = getVideoTrackByHeight(player, 480);
expect(hdVideoTrack).toBe(null);
expect(sdVideoTrack).not.toBe(null);
var restrictions = player.getConfiguration()['restrictions'];
restrictions.maxHeight = null;
player.configure({'restrictions': restrictions});
hdVideoTrack = getVideoTrackByHeight(player, 720);
sdVideoTrack = getVideoTrackByHeight(player, 480);
expect(hdVideoTrack).not.toBe(null);
expect(sdVideoTrack).not.toBe(null);
done();
}).catch(function(error) {
fail(error);
done();
});
});
it('fires error if all tracks restricted while playing', function(done) {
player.removeEventListener('error', convertErrorToTestFailure, false);
var onError = jasmine.createSpy('onError');
player.addEventListener('error', onError, false);
player.load(newSource(manifests.plainManifest)).then(function() {
waitForMovement(video, eventManager);
}).then(function() {
var restrictions = player.getConfiguration()['restrictions'];
restrictions.maxBandwidth = 10000;
player.configure({'restrictions': restrictions});
expect(onError.calls.any()).toBe(true);
expect(player.getVideoTracks().length).toBe(0);
done();
}).catch(function(error) {
fail(error);
done();
});
});
it('fires error if all tracks restricted before playing', function(done) {
player.removeEventListener('error', convertErrorToTestFailure, false);
var onError = jasmine.createSpy('onError');
player.addEventListener('error', onError, false);
var restrictions = player.getConfiguration()['restrictions'];
restrictions.maxBandwidth = 10000;
player.configure({'restrictions': restrictions});
player.load(newSource(manifests.encryptedManifest)).then(function() {
fail();
}).catch(function(error) {
expect(onError.calls.any()).toBe(true);
done();
});
});
});
describe('configure and getConfiguration', function() {
it('rejects an invalid enableAdaptation', function() {
var exception;
try {
player.configure({'enableAdaptation': 2});
fail();
} catch (e) {
exception = e;
}
expect(exception instanceof TypeError).toBe(true);
});
it('gets/sets stream buffer size', function() {
var original = player.getConfiguration()['streamBufferSize'];
expect(original).not.toBe(5);
expect(original).toBe(shaka.player.Defaults.STREAM_BUFFER_SIZE);
expect(player.getConfiguration()['streamBufferSize']).toBe(original);
player.configure({'streamBufferSize': 5});
expect(player.getConfiguration()['streamBufferSize']).toBe(5);
player.configure({'streamBufferSize': original});
expect(player.getConfiguration()['streamBufferSize']).toBe(original);
});
it('rejects an invalid streamBufferSize', function() {
var exception;
try {
player.configure({'streamBufferSize': 'three seconds'});
fail();
} catch (e) {
exception = e;
}
expect(exception instanceof TypeError).toBe(true);
try {
player.configure({'streamBufferSize': -1});
fail();
} catch (e) {
exception = e;
}
expect(exception instanceof RangeError).toBe(true);
});
it('gets/sets LicenseRequest timeout', function() {
var original = player.getConfiguration()['licenseRequestTimeout'];
expect(original).not.toBe(5);
expect(original).toBe(shaka.player.Defaults.LICENSE_REQUEST_TIMEOUT);
expect(player.getConfiguration()['licenseRequestTimeout']).toBe(original);
player.configure({'licenseRequestTimeout': 5});
expect(player.getConfiguration()['licenseRequestTimeout']).toBe(5);
player.configure({'licenseRequestTimeout': original});
expect(player.getConfiguration()['licenseRequestTimeout']).toBe(original);
});
it('rejects an invalid LicenseRequest timeout', function() {
var exception;
try {
player.configure({'licenseRequestTimeout': 'five seconds'});
fail();
} catch (e) {
exception = e;
}
expect(exception instanceof TypeError).toBe(true);
try {
player.configure({'licenseRequestTimeout': NaN});
fail();
} catch (e) {
exception = e;
}
expect(exception instanceof RangeError).toBe(true);
});
it('gets/sets MpdRequest timeout', function() {
var original = player.getConfiguration()['mpdRequestTimeout'];
expect(original).not.toBe(5);
expect(original).toBe(shaka.player.Defaults.MPD_REQUEST_TIMEOUT);
expect(player.getConfiguration()['mpdRequestTimeout']).toBe(original);
player.configure({'mpdRequestTimeout': 5});
expect(player.getConfiguration()['mpdRequestTimeout']).toBe(5);
player.configure({'mpdRequestTimeout': original});
expect(player.getConfiguration()['mpdRequestTimeout']).toBe(original);
});
it('rejects an invalid MpdRequest timeout', function() {
var exception;
try {
player.configure({'mpdRequestTimeout': 'seven seconds'});
fail();
} catch (e) {
exception = e;
}
expect(exception instanceof TypeError).toBe(true);
try {
player.configure({'mpdRequestTimeout': Number.NEGATIVE_INFINITY});
fail();
} catch (e) {
exception = e;
}
expect(exception instanceof RangeError).toBe(true);
});
it('gets/sets SegmentRequest timeout', function() {
var original = player.getConfiguration()['segmentRequestTimeout'];
expect(original).not.toBe(5);
expect(original).toBe(shaka.player.Defaults.SEGMENT_REQUEST_TIMEOUT);
expect(player.getConfiguration()['segmentRequestTimeout']).toBe(original);
player.configure({'segmentRequestTimeout': 5});
expect(player.getConfiguration()['segmentRequestTimeout']).toBe(5);
player.configure({'segmentRequestTimeout': original});
expect(player.getConfiguration()['segmentRequestTimeout']).toBe(original);
});
it('rejects an invalid SegmentRequest timeout', function() {
var exception;
try {
player.configure({'segmentRequestTimeout': 'eleven seconds'});
fail();
} catch (e) {
exception = e;
}
expect(exception instanceof TypeError).toBe(true);
try {
player.configure({'segmentRequestTimeout': Number.POSITIVE_INFINITY});
fail();
} catch (e) {
exception = e;
}
expect(exception instanceof RangeError).toBe(true);
});
it('rejects an invalid preferredLanguage', function() {
var exception;
try {
player.configure({'preferredLanguage': 13});
fail();
} catch (e) {
exception = e;
}
expect(exception instanceof TypeError).toBe(true);
});
it('gets/sets multiple options at once', function() {
var restrictions = new shaka.player.Restrictions();
restrictions.maxWidth = 1280;
var originalConfig = player.getConfiguration();
var config = {
'enableAdaptation': true,
'streamBufferSize': 17,
'liveStreamEndTimeout': 20,
'licenseRequestTimeout': 19,
'mpdRequestTimeout': 23,
'segmentRequestTimeout': 29,
'preferredLanguage': 'fr',
'restrictions': restrictions
};
player.configure(config);
expect(JSON.stringify(player.getConfiguration()))
.toBe(JSON.stringify(config));
player.configure(originalConfig);
});
});
});