bigscreen-player
Advanced tools
Comparing version 2.1.0 to 2.2.0
{ | ||
"name": "bigscreen-player", | ||
"version": "2.1.0", | ||
"version": "2.2.0", | ||
"description": "Simplified media playback for bigscreen devices.", | ||
@@ -5,0 +5,0 @@ "main": "script/bigscreenplayer.js", |
@@ -27,3 +27,4 @@ require( | ||
'play', 'pause', 'isEnded', 'isPaused', 'setCurrentTime', 'getCurrentTime', 'getDuration', 'getSeekableRange', | ||
'getPlayerElement', 'isSubtitlesAvailable', 'isSubtitlesEnabled', 'setSubtitlesEnabled', 'tearDown']); | ||
'getPlayerElement', 'isSubtitlesAvailable', 'isSubtitlesEnabled', 'setSubtitlesEnabled', 'tearDown', | ||
'getWindowStartTime', 'getWindowEndTime']); | ||
@@ -48,2 +49,4 @@ var mockPlayerComponent = function (playbackElement, bigscreenPlayerData, windowType, enableSubtitles, callback, device) { | ||
}; | ||
mockPlayerComponentInstance.getWindowStartTime.and.returnValue(manifestData.time.windowStartTime); | ||
mockPlayerComponentInstance.getWindowEndTime.and.returnValue(manifestData.time.windowStartTime); | ||
} | ||
@@ -90,2 +93,7 @@ | ||
}; | ||
mockPlayerComponentInstance.getWindowStartTime.and.returnValue(options.windowStartTime); | ||
mockPlayerComponentInstance.getWindowEndTime.and.returnValue(options.windowEndTime); | ||
} else { | ||
mockPlayerComponentInstance.getWindowStartTime.and.returnValue(manifestData.time.windowStartTime); | ||
mockPlayerComponentInstance.getWindowEndTime.and.returnValue(manifestData.time.windowEndTime); | ||
} | ||
@@ -741,11 +749,2 @@ | ||
it('converts video time to epoch time when windowStartTime is supplied', function () { | ||
setupManifestData({ | ||
transferFormat: TransferFormats.DASH, | ||
time: { | ||
windowStartTime: 4200, | ||
windowEndTime: 150000000, | ||
correction: 0 | ||
} | ||
}); | ||
initialiseBigscreenPlayer({ | ||
@@ -755,2 +754,5 @@ windowType: WindowTypes.SLIDING | ||
mockPlayerComponentInstance.getWindowStartTime.and.returnValue(4200); | ||
mockPlayerComponentInstance.getWindowEndTime.and.returnValue(150000000); | ||
expect(bigscreenPlayer.convertVideoTimeSecondsToEpochMs(1000)).toBe(4200 + 1000000); | ||
@@ -762,2 +764,5 @@ }); | ||
mockPlayerComponentInstance.getWindowStartTime.and.returnValue(undefined); | ||
mockPlayerComponentInstance.getWindowEndTime.and.returnValue(undefined); | ||
expect(bigscreenPlayer.convertVideoTimeSecondsToEpochMs(1000)).toBeUndefined(); | ||
@@ -769,13 +774,2 @@ }); | ||
it('converts epoch time to video time when windowStartTime is available', function () { | ||
// windowStartTime - 16 January 2019 12:00:00 | ||
// windowEndTime - 16 January 2019 14:00:00 | ||
setupManifestData({ | ||
transferFormat: TransferFormats.DASH, | ||
time: { | ||
windowStartTime: 1547640000000, | ||
windowEndTime: 1547647200000, | ||
correction: 0 | ||
} | ||
}); | ||
initialiseBigscreenPlayer({ | ||
@@ -785,2 +779,7 @@ windowType: WindowTypes.SLIDING | ||
// windowStartTime - 16 January 2019 12:00:00 | ||
// windowEndTime - 16 January 2019 14:00:00 | ||
mockPlayerComponentInstance.getWindowStartTime.and.returnValue(1547640000000); | ||
mockPlayerComponentInstance.getWindowEndTime.and.returnValue(1547647200000); | ||
// Time to convert - 16 January 2019 13:00:00 - one hour (3600 seconds) | ||
@@ -793,2 +792,5 @@ expect(bigscreenPlayer.convertEpochMsToVideoTimeSeconds(1547643600000)).toBe(3600); | ||
mockPlayerComponentInstance.getWindowStartTime.and.returnValue(undefined); | ||
mockPlayerComponentInstance.getWindowEndTime.and.returnValue(undefined); | ||
expect(bigscreenPlayer.convertEpochMsToVideoTimeSeconds(1547643600000)).toBeUndefined(); | ||
@@ -795,0 +797,0 @@ }); |
@@ -28,2 +28,4 @@ require( | ||
var liveSupport; | ||
var manifestData; | ||
var forceManifestLoadError; | ||
@@ -48,4 +50,4 @@ // opts = streamType, playbackType, mediaType, subtitlesAvailable, subtitlesEnabled noStatsReporter, disableUi | ||
time: { | ||
windowStartTime: 724, | ||
windowEndTime: 4324, | ||
windowStartTime: 724000, | ||
windowEndTime: 4324000, | ||
correction: 0 | ||
@@ -69,2 +71,23 @@ } | ||
function setupManifestData (options) { | ||
manifestData = { | ||
transferFormat: options && options.transferFormat || 'dash', | ||
time: options && options.time || { | ||
windowStartTime: 724000, | ||
windowEndTime: 4324000, | ||
correction: 0 | ||
} | ||
}; | ||
} | ||
var manifestLoaderMock = { | ||
load: function (urls, serverDate, callbacks) { | ||
if (forceManifestLoadError) { | ||
callbacks.onError(); | ||
} else { | ||
callbacks.onSuccess(manifestData); | ||
} | ||
} | ||
}; | ||
beforeEach(function (done) { | ||
@@ -97,5 +120,9 @@ injector = new Squire(); | ||
'bigscreenplayer/playbackstrategy/mockstrategy': mockStrategyConstructor, | ||
'bigscreenplayer/plugins': mockPlugins | ||
'bigscreenplayer/plugins': mockPlugins, | ||
'bigscreenplayer/manifest/manifestloader': manifestLoaderMock | ||
}); | ||
spyOn(manifestLoaderMock, 'load'); | ||
manifestLoaderMock.load.and.callThrough(); | ||
injector.require(['bigscreenplayer/playercomponent'], function (PlayerComponent) { | ||
@@ -105,2 +132,4 @@ PlayerComponentWithMocks = PlayerComponent; | ||
}); | ||
forceManifestLoadError = false; | ||
}); | ||
@@ -840,2 +869,5 @@ | ||
var pluginData; | ||
var currentTime; | ||
var type; | ||
var currentTimeSpy; | ||
@@ -846,3 +878,3 @@ beforeEach(function () { | ||
seekable_range: '0 to 100', | ||
current_time: 94, | ||
current_time: 50, | ||
duration: 100 | ||
@@ -860,2 +892,11 @@ }; | ||
}; | ||
currentTime = 50; | ||
type = 'application/dash+xml'; | ||
spyOn(mockStrategy, 'load'); | ||
currentTimeSpy = spyOn(mockStrategy, 'getCurrentTime'); | ||
currentTimeSpy.and.returnValue(currentTime); | ||
spyOn(mockStrategy, 'getDuration').and.returnValue(100); | ||
spyOn(mockStrategy, 'getSeekableRange').and.returnValue({start: 0, end: 100}); | ||
}); | ||
@@ -868,8 +909,2 @@ | ||
it('should failover after buffering for 30 seconds on initial playback', function () { | ||
var currentTime = 10; | ||
var type = 'application/dash+xml'; | ||
spyOn(mockStrategy, 'load'); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(currentTime); | ||
setUpPlayerComponent({multiCdn: true}); | ||
@@ -882,2 +917,3 @@ | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(1); | ||
expect(corePlaybackData.media.urls).toContain(jasmine.objectContaining({cdn: 'cdn-a'})); | ||
@@ -889,11 +925,7 @@ jasmine.clock().tick(1); | ||
expect(mockStrategy.load).toHaveBeenCalledWith(corePlaybackData.media.urls, type, currentTime); | ||
expect(corePlaybackData.media.urls.length).toBe(2); | ||
expect(corePlaybackData.media.urls).not.toContain(jasmine.objectContaining({cdn: 'cdn-a'})); | ||
}); | ||
it('should failover after buffering for 20 seconds on normal playback', function () { | ||
var currentTime = 10; | ||
var type = 'application/dash+xml'; | ||
spyOn(mockStrategy, 'load'); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(currentTime); | ||
setUpPlayerComponent({multiCdn: true}); | ||
@@ -924,8 +956,2 @@ | ||
it('should failover after 5 seconds if we have not cleared an error from the device', function () { | ||
var currentTime = 10; | ||
var type = 'application/dash+xml'; | ||
spyOn(mockStrategy, 'load'); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(currentTime); | ||
setUpPlayerComponent({multiCdn: true}); | ||
@@ -939,2 +965,3 @@ | ||
expect(corePlaybackData.media.urls.length).toBe(3); | ||
expect(corePlaybackData.media.urls).toContain(jasmine.objectContaining({cdn: 'cdn-a'})); | ||
@@ -946,12 +973,7 @@ jasmine.clock().tick(1); | ||
expect(mockStrategy.load).toHaveBeenCalledWith(corePlaybackData.media.urls, type, currentTime); | ||
expect(corePlaybackData.media.urls.length).toBe(2); | ||
expect(corePlaybackData.media.urls).not.toContain(jasmine.objectContaining({cdn: 'cdn-a'})); | ||
}); | ||
it('should fire a fatal error on the plugins if there is only one cdn', function () { | ||
spyOn(mockStrategy, 'getDuration').and.returnValue(100); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(94); | ||
spyOn(mockStrategy, 'getSeekableRange').and.returnValue({start: 0, end: 100}); | ||
spyOn(mockStrategy, 'load'); | ||
setUpPlayerComponent(); | ||
@@ -969,6 +991,2 @@ | ||
it('should publish a media state update of fatal if there is only one cdn', function () { | ||
spyOn(mockStrategy, 'getDuration').and.returnValue(100); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(94); | ||
spyOn(mockStrategy, 'load'); | ||
setUpPlayerComponent(); | ||
@@ -985,23 +1003,3 @@ | ||
it('should publish a media state update of fatal when playing a hls simulcast', function () { | ||
spyOn(mockStrategy, 'getDuration').and.returnValue(100); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(94); | ||
spyOn(mockStrategy, 'load'); | ||
setUpPlayerComponent({multiCdn: true, transferFormat: TransferFormats.HLS, windowType: WindowTypes.SLIDING}); | ||
mockStrategy.mockingHooks.fireErrorEvent({errorProperties: {}}); | ||
jasmine.clock().tick(5000); | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(1); | ||
expect(mockStateUpdateCallback.calls.mostRecent().args[0].data.state).toEqual(MediaState.FATAL_ERROR); | ||
}); | ||
it('should publish a media state update of fatal when playing a hls webcast on a restartable device', function () { | ||
spyOn(mockStrategy, 'getDuration').and.returnValue(100); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(94); | ||
spyOn(mockStrategy, 'load'); | ||
it('should publish a media state update of fatal when failover is disabled', function () { | ||
liveSupport = LiveSupport.RESTARTABLE; | ||
@@ -1019,14 +1017,17 @@ setUpPlayerComponent({multiCdn: true, transferFormat: TransferFormats.HLS, windowType: WindowTypes.GROWING}); | ||
it('should failover on a seekable device when playing hls webcasts', function () { | ||
var currentTime = 10; | ||
var type = 'application/vnd.apple.mpegurl'; | ||
it('should failover for with updated failover time from manifest load', function () { | ||
type = 'application/vnd.apple.mpegurl'; | ||
spyOn(mockStrategy, 'load'); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(currentTime); | ||
setUpPlayerComponent({multiCdn: true, transferFormat: TransferFormats.HLS, windowType: WindowTypes.SLIDING, type: type}); | ||
setUpPlayerComponent({multiCdn: true, manifestType: 'm3u8', windowType: WindowTypes.GROWING, type: type}); | ||
setupManifestData({ | ||
transferFormat: TransferFormats.HLS, | ||
time: { | ||
windowStartTime: 744000, | ||
windowEndTime: 1000000 | ||
} | ||
}); | ||
// Set playback cause to normal | ||
mockStrategy.mockingHooks.fireEvent(MediaState.PLAYING); | ||
mockStrategy.mockingHooks.fireEvent(MediaState.WAITING); | ||
@@ -1037,3 +1038,2 @@ | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(1); | ||
expect(corePlaybackData.media.urls.length).toBe(3); | ||
@@ -1045,5 +1045,3 @@ expect(corePlaybackData.media.urls).toContain(jasmine.objectContaining({cdn: 'cdn-a'})); | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(2); | ||
expect(mockStrategy.load).toHaveBeenCalledWith(corePlaybackData.media.urls, type, currentTime); | ||
expect(mockStrategy.load).toHaveBeenCalledWith(corePlaybackData.media.urls, type, currentTime - 20); | ||
expect(corePlaybackData.media.urls.length).toBe(2); | ||
@@ -1053,45 +1051,48 @@ expect(corePlaybackData.media.urls).not.toContain(jasmine.objectContaining({cdn: 'cdn-a'})); | ||
it('should failover on a playable device when playing hls webcasts', function () { | ||
var currentTime = 10; | ||
var type = 'application/vnd.apple.mpegurl'; | ||
it('should failover for with updated failover time for multiple failovers', function () { | ||
type = 'application/vnd.apple.mpegurl'; | ||
spyOn(mockStrategy, 'load'); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(currentTime); | ||
setUpPlayerComponent({multiCdn: true, transferFormat: TransferFormats.HLS, windowType: WindowTypes.SLIDING, type: type}); | ||
liveSupport = LiveSupport.PLAYABLE; | ||
setUpPlayerComponent({multiCdn: true, manifestType: 'm3u8', windowType: WindowTypes.GROWING, liveSupport: LiveSupport.PLAYABLE, type: type}); | ||
// Set playback cause to normal | ||
mockStrategy.mockingHooks.fireEvent(MediaState.PLAYING); | ||
mockStrategy.mockingHooks.fireEvent(MediaState.WAITING); | ||
jasmine.clock().tick(19999); | ||
setupManifestData({ | ||
transferFormat: TransferFormats.HLS, | ||
time: { | ||
windowStartTime: 744000, | ||
windowEndTime: 1000000 | ||
} | ||
}); | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(1); | ||
jasmine.clock().tick(20000); | ||
expect(corePlaybackData.media.urls.length).toBe(3); | ||
expect(corePlaybackData.media.urls).toContain(jasmine.objectContaining({cdn: 'cdn-a'})); | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(2); | ||
expect(mockStrategy.load).toHaveBeenCalledWith(corePlaybackData.media.urls, type, currentTime - 20); | ||
jasmine.clock().tick(1); | ||
currentTimeSpy.and.returnValue(currentTime - 20); | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(2); | ||
mockStrategy.mockingHooks.fireEvent(MediaState.PLAYING); | ||
mockStrategy.mockingHooks.fireEvent(MediaState.WAITING); | ||
expect(mockStrategy.load).toHaveBeenCalledWith(corePlaybackData.media.urls, type, currentTime); | ||
setupManifestData({ | ||
transferFormat: TransferFormats.HLS, | ||
time: { | ||
windowStartTime: 764000, | ||
windowEndTime: 1000000 | ||
} | ||
}); | ||
expect(corePlaybackData.media.urls.length).toBe(2); | ||
expect(corePlaybackData.media.urls).not.toContain(jasmine.objectContaining({cdn: 'cdn-a'})); | ||
jasmine.clock().tick(20000); | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(3); | ||
expect(mockStrategy.load).toHaveBeenCalledWith(corePlaybackData.media.urls, type, currentTime - 40); | ||
}); | ||
it('should failover after buffering for 20 seconds on live dash playback', function () { | ||
var currentTime = 94; | ||
var type = 'application/dash+xml'; | ||
it('should failover on a without reloading the manifest', function () { | ||
type = 'application/vnd.apple.mpegurl'; | ||
spyOn(mockStrategy, 'getDuration').and.returnValue(100); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(currentTime); | ||
spyOn(mockStrategy, 'getSeekableRange').and.returnValue({start: 0, end: 100}); | ||
spyOn(mockStrategy, 'load'); | ||
setUpPlayerComponent({multiCdn: true, manifestType: 'm3u8', windowType: WindowTypes.GROWING, type: type}); | ||
setUpPlayerComponent({windowType: WindowTypes.SLIDING, multiCdn: true}); | ||
// Set playback cause to normal | ||
@@ -1107,18 +1108,16 @@ mockStrategy.mockingHooks.fireEvent(MediaState.PLAYING); | ||
expect(corePlaybackData.media.urls.length).toBe(3); | ||
expect(corePlaybackData.media.urls).toContain(jasmine.objectContaining({cdn: 'cdn-a'})); | ||
jasmine.clock().tick(1); | ||
expect(manifestLoaderMock.load).not.toHaveBeenCalled(); | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(2); | ||
expect(mockStrategy.load).toHaveBeenCalledWith(corePlaybackData.media.urls, type, currentTime); | ||
expect(corePlaybackData.media.urls.length).toBe(2); | ||
expect(corePlaybackData.media.urls).not.toContain(jasmine.objectContaining({cdn: 'cdn-a'})); | ||
}); | ||
it('should fire a fatal error on the plugins if we are in the last 5 seconds of playback', function () { | ||
errorProperties.current_time = 96; | ||
spyOn(mockStrategy, 'getDuration').and.returnValue(100); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(96); | ||
spyOn(mockStrategy, 'getSeekableRange').and.returnValue({start: 0, end: 100}); | ||
spyOn(mockStrategy, 'load'); | ||
it('should fire an error handled event on the plugins with the erroring CDN', function () { | ||
setUpPlayerComponent({multiCdn: true}); | ||
@@ -1130,34 +1129,2 @@ | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(1); | ||
expect(mockPluginsInterface.onFatalError).toHaveBeenCalledWith(jasmine.objectContaining(pluginData)); | ||
}); | ||
it('should publish a media state update of fatal if we are in the last 5 seconds of playback', function () { | ||
spyOn(mockStrategy, 'getDuration').and.returnValue(100); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(96); | ||
spyOn(mockStrategy, 'load'); | ||
setUpPlayerComponent({multiCdn: true}); | ||
mockStrategy.mockingHooks.fireErrorEvent({errorProperties: {}}); | ||
jasmine.clock().tick(5000); | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(1); | ||
expect(mockStateUpdateCallback.calls.mostRecent().args[0].data.state).toEqual(MediaState.FATAL_ERROR); | ||
}); | ||
it('should fire an error handled event on the plugins with the new CDN', function () { | ||
spyOn(mockStrategy, 'getDuration').and.returnValue(100); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(94); | ||
spyOn(mockStrategy, 'getSeekableRange').and.returnValue({start: 0, end: 100}); | ||
setUpPlayerComponent({multiCdn: true}); | ||
mockStrategy.mockingHooks.fireErrorEvent({errorProperties: {}}); | ||
jasmine.clock().tick(5000); | ||
var pluginData = { | ||
@@ -1176,2 +1143,19 @@ status: PluginEnums.STATUS.FAILOVER, | ||
it('should fire a fatal error if the manifest fails to reload', function () { | ||
forceManifestLoadError = true; | ||
setUpPlayerComponent({multiCdn: true, transferFormat: TransferFormats.HLS, windowType: WindowTypes.SLIDING}); | ||
// Set playback cause to normal | ||
mockStrategy.mockingHooks.fireEvent(MediaState.PLAYING); | ||
mockStrategy.mockingHooks.fireEvent(MediaState.WAITING); | ||
jasmine.clock().tick(20000); | ||
expect(mockStrategy.load).toHaveBeenCalledTimes(1); | ||
expect(mockPluginsInterface.onErrorHandled).not.toHaveBeenCalled(); | ||
expect(mockStateUpdateCallback.calls.mostRecent().args[0].data.state).toEqual(MediaState.FATAL_ERROR); | ||
}); | ||
it('should reset the strategy', function () { | ||
@@ -1223,3 +1207,3 @@ spyOn(mockStrategy, 'reset'); | ||
seekable_range: '0 to 100', | ||
current_time: 10, | ||
current_time: 50, | ||
duration: 100, | ||
@@ -1241,6 +1225,2 @@ dismissed_by: 'teardown' | ||
spyOn(mockStrategy, 'getSeekableRange').and.returnValue({start: 0, end: 100}); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(10); | ||
spyOn(mockStrategy, 'getDuration').and.returnValue(100); | ||
mockStrategy.mockingHooks.fireErrorEvent({errorProperties: {}}); | ||
@@ -1257,3 +1237,3 @@ | ||
seekable_range: '0 to 100', | ||
current_time: 10, | ||
current_time: 50, | ||
duration: 100, | ||
@@ -1275,6 +1255,2 @@ dismissed_by: 'teardown' | ||
spyOn(mockStrategy, 'getSeekableRange').and.returnValue({start: 0, end: 100}); | ||
spyOn(mockStrategy, 'getCurrentTime').and.returnValue(10); | ||
spyOn(mockStrategy, 'getDuration').and.returnValue(100); | ||
mockStrategy.mockingHooks.fireErrorEvent({errorProperties: {}}); | ||
@@ -1281,0 +1257,0 @@ |
@@ -13,5 +13,6 @@ define('bigscreenplayer/bigscreenplayer', | ||
'bigscreenplayer/manifest/manifestloader', | ||
'bigscreenplayer/utils/timeutils' | ||
'bigscreenplayer/utils/timeutils', | ||
'bigscreenplayer/utils/manifestutils' | ||
], | ||
function (MediaState, PlayerComponent, PauseTriggers, DynamicWindowUtils, WindowTypes, MockBigscreenPlayer, Plugins, Chronicle, DebugTool, ManifestLoader, SlidingWindowUtils) { | ||
function (MediaState, PlayerComponent, PauseTriggers, DynamicWindowUtils, WindowTypes, MockBigscreenPlayer, Plugins, Chronicle, DebugTool, ManifestLoader, SlidingWindowUtils, ManifestUtils) { | ||
'use strict'; | ||
@@ -23,4 +24,2 @@ function BigscreenPlayer () { | ||
var mediaKind; | ||
var windowStartTime; | ||
var windowEndTime; | ||
var initialPlaybackTimeEpoch; | ||
@@ -76,3 +75,3 @@ var serverDate; | ||
function deviceTimeToDate (time) { | ||
if (windowStartTime) { | ||
if (getWindowStartTime()) { | ||
return new Date(convertVideoTimeSecondsToEpochMs(time)); | ||
@@ -85,21 +84,7 @@ } else { | ||
function convertVideoTimeSecondsToEpochMs (seconds) { | ||
return windowStartTime ? windowStartTime + (seconds * 1000) : undefined; | ||
return getWindowStartTime() ? getWindowStartTime() + (seconds * 1000) : undefined; | ||
} | ||
// TODO: make this more reusable so Player Component can do this for HLS Live CDN failover | ||
function needToGetManifest () { | ||
var requiresSimulcastSeekingData = { | ||
restartable: true, | ||
seekable: true, | ||
playable: false, | ||
none: false | ||
}; | ||
return windowType !== WindowTypes.STATIC && requiresSimulcastSeekingData[getLiveSupport(device)]; | ||
} | ||
function bigscreenPlayerDataLoaded (playbackElement, bigscreenPlayerData, enableSubtitles, device, successCallback) { | ||
if (bigscreenPlayerData.time) { | ||
windowStartTime = bigscreenPlayerData.time.windowStartTime; | ||
windowEndTime = bigscreenPlayerData.time.windowEndTime; | ||
serverDate = bigscreenPlayerData.serverDate; | ||
@@ -109,3 +94,3 @@ | ||
// overwrite initialPlaybackTime with video time (it comes in as epoch time for a sliding/growing window) | ||
bigscreenPlayerData.initialPlaybackTime = SlidingWindowUtils.convertToSeekableVideoTime(bigscreenPlayerData.initialPlaybackTime, windowStartTime); | ||
bigscreenPlayerData.initialPlaybackTime = SlidingWindowUtils.convertToSeekableVideoTime(bigscreenPlayerData.initialPlaybackTime, bigscreenPlayerData.time.windowStartTime); | ||
} | ||
@@ -138,2 +123,10 @@ | ||
function getWindowStartTime () { | ||
return playerComponent && playerComponent.getWindowStartTime(); | ||
} | ||
function getWindowEndTime () { | ||
return playerComponent && playerComponent.getWindowEndTime(); | ||
} | ||
return { | ||
@@ -149,3 +142,3 @@ init: function (playbackElement, bigscreenPlayerData, newWindowType, enableSubtitles, newDevice, callbacks) { | ||
if (needToGetManifest() && !bigscreenPlayerData.time) { | ||
if (ManifestUtils.needToGetManifest(windowType, getLiveSupport(device)) && !bigscreenPlayerData.time) { | ||
ManifestLoader.load( | ||
@@ -181,4 +174,2 @@ bigscreenPlayerData.media.urls, | ||
mediaKind = undefined; | ||
windowStartTime = undefined; | ||
windowEndTime = undefined; | ||
pauseTrigger = undefined; | ||
@@ -239,4 +230,4 @@ windowType = undefined; | ||
return { | ||
windowStartTime: windowStartTime, | ||
windowEndTime: windowEndTime, | ||
windowStartTime: getWindowStartTime(), | ||
windowEndTime: getWindowEndTime(), | ||
initialPlaybackTime: initialPlaybackTimeEpoch, | ||
@@ -277,6 +268,6 @@ serverDate: serverDate | ||
canSeek: function () { | ||
return windowType === WindowTypes.STATIC || DynamicWindowUtils.canSeek(windowStartTime, windowEndTime, getLiveSupport(device), this.getSeekableRange()); | ||
return windowType === WindowTypes.STATIC || DynamicWindowUtils.canSeek(getWindowStartTime(), getWindowEndTime(), getLiveSupport(device), this.getSeekableRange()); | ||
}, | ||
canPause: function () { | ||
return windowType === WindowTypes.STATIC || DynamicWindowUtils.canPause(windowStartTime, windowEndTime, getLiveSupport(device)); | ||
return windowType === WindowTypes.STATIC || DynamicWindowUtils.canPause(getWindowStartTime(), getWindowEndTime(), getLiveSupport(device)); | ||
}, | ||
@@ -305,3 +296,3 @@ mock: function (opts) { | ||
convertEpochMsToVideoTimeSeconds: function (epochTime) { | ||
return windowStartTime ? Math.floor((epochTime - windowStartTime) / 1000) : undefined; | ||
return getWindowStartTime() ? Math.floor((epochTime - getWindowStartTime()) / 1000) : undefined; | ||
}, | ||
@@ -308,0 +299,0 @@ convertVideoTimeSecondsToEpochMs: convertVideoTimeSecondsToEpochMs |
@@ -38,2 +38,3 @@ define( | ||
headers: {}, | ||
timeout: 10000, | ||
onLoad: function () { | ||
@@ -66,2 +67,3 @@ try { | ||
headers: {}, | ||
timeout: 10000, | ||
onLoad: function (responseText) { | ||
@@ -97,2 +99,3 @@ var streamUrl; | ||
headers: {}, | ||
timeout: 10000, | ||
onLoad: function (responseText) { | ||
@@ -99,0 +102,0 @@ if (responseText) { |
@@ -8,10 +8,13 @@ define( | ||
'bigscreenplayer/utils/playbackutils', | ||
'bigscreenplayer/models/livesupport', | ||
'bigscreenplayer/plugindata', | ||
'bigscreenplayer/pluginenums', | ||
'bigscreenplayer/plugins', | ||
'bigscreenplayer/debugger/cdndebugoutput', | ||
'bigscreenplayer/models/transferformats' | ||
'bigscreenplayer/debugger/debugtool', | ||
'bigscreenplayer/models/transferformats', | ||
'bigscreenplayer/manifest/manifestloader', | ||
'bigscreenplayer/utils/manifestutils', | ||
'bigscreenplayer/mediaresilience', | ||
'bigscreenplayer/debugger/cdndebugoutput' | ||
], | ||
function (MediaState, CaptionsContainer, PlaybackStrategy, WindowTypes, PlaybackUtils, LiveSupport, PluginData, PluginEnums, Plugins, CdnDebugOutput, TransferFormats) { | ||
function (MediaState, CaptionsContainer, PlaybackStrategy, WindowTypes, PlaybackUtils, PluginData, PluginEnums, Plugins, DebugTool, TransferFormats, ManifestLoader, ManifestUtils, MediaResilience, CdnDebugOutput) { | ||
'use strict'; | ||
@@ -69,3 +72,3 @@ | ||
var disableAutoResume = windowType === WindowTypes.GROWING ? true : opts.disableAutoResume; | ||
playbackStrategy.pause({disableAutoResume: disableAutoResume}); | ||
playbackStrategy.pause({ disableAutoResume: disableAutoResume }); | ||
} | ||
@@ -78,2 +81,10 @@ } | ||
function getWindowStartTime () { | ||
return bigscreenPlayerData.time && bigscreenPlayerData.time.windowStartTime; | ||
} | ||
function getWindowEndTime () { | ||
return bigscreenPlayerData.time && bigscreenPlayerData.time.windowEndTime; | ||
} | ||
function getPlayerElement () { | ||
@@ -179,3 +190,3 @@ var element = null; | ||
function onTimeUpdate () { | ||
publishMediaStateUpdate(undefined, {timeUpdate: true}); | ||
publishMediaStateUpdate(undefined, { timeUpdate: true }); | ||
} | ||
@@ -222,27 +233,43 @@ | ||
function attemptCdnFailover (errorProperties, bufferingTimeoutError) { | ||
var hasNextCDN = mediaMetaData.urls.length > 1; | ||
var aboutToEndVod = getDuration() > 0 && (getDuration() - getCurrentTime()) <= 5; | ||
var canVodFailover = windowType === WindowTypes.STATIC && !aboutToEndVod; | ||
var canHlsLiveFailover = windowType === WindowTypes.GROWING && | ||
(getLiveSupport(device) === LiveSupport.SEEKABLE || getLiveSupport(device) === LiveSupport.PLAYABLE) && | ||
transferFormat === TransferFormats.HLS; | ||
var canDashLiveFailover = windowType !== WindowTypes.STATIC && transferFormat === TransferFormats.DASH; | ||
var shouldFailover = MediaResilience.shouldFailover(mediaMetaData.urls.length, getDuration(), getCurrentTime(), getLiveSupport(device), windowType, transferFormat); | ||
if (hasNextCDN && (canVodFailover || canHlsLiveFailover || canDashLiveFailover)) { | ||
cdnFailover(errorProperties, bufferingTimeoutError); | ||
if (shouldFailover) { | ||
var thenPause = playbackStrategy.isPaused(); | ||
tearDownMediaElement(); | ||
var failoverTime = getCurrentTime(); | ||
if (transferFormat === TransferFormats.HLS && ManifestUtils.needToGetManifest(windowType, getLiveSupport(device))) { | ||
manifestReloadFailover(failoverTime, thenPause, errorProperties, bufferingTimeoutError); | ||
} else { | ||
cdnFailover(failoverTime, thenPause, errorProperties, bufferingTimeoutError); | ||
} | ||
} else { | ||
var evt = new PluginData({status: PluginEnums.STATUS.FATAL, stateType: PluginEnums.TYPE.ERROR, properties: errorProperties, isBufferingTimeoutError: bufferingTimeoutError}); | ||
Plugins.interface.onFatalError(evt); | ||
publishMediaStateUpdate(MediaState.FATAL_ERROR, {isBufferingTimeoutError: bufferingTimeoutError}); | ||
bubbleFatalError(errorProperties, bufferingTimeoutError); | ||
} | ||
} | ||
function cdnFailover (errorProperties, bufferingTimeoutError) { | ||
var thenPause = playbackStrategy.isPaused(); | ||
tearDownMediaElement(); | ||
function manifestReloadFailover (failoverTime, thenPause, errorProperties, bufferingTimeoutError) { | ||
ManifestLoader.load( | ||
bigscreenPlayerData.media.urls, | ||
bigscreenPlayerData.serverDate, | ||
{ | ||
onSuccess: function (manifestData) { | ||
var windowOffset = manifestData.time.windowStartTime - getWindowStartTime(); | ||
bigscreenPlayerData.time = manifestData.time; | ||
failoverTime -= windowOffset / 1000; | ||
cdnFailover(failoverTime, thenPause, errorProperties, bufferingTimeoutError); | ||
}, | ||
onError: function () { | ||
bubbleFatalError(errorProperties, bufferingTimeoutError); | ||
} | ||
} | ||
); | ||
} | ||
function cdnFailover (failoverTime, thenPause, errorProperties, bufferingTimeoutError) { | ||
mediaMetaData.urls.shift(); | ||
var evt = new PluginData({status: PluginEnums.STATUS.FAILOVER, stateType: PluginEnums.TYPE.ERROR, properties: errorProperties, isBufferingTimeoutError: bufferingTimeoutError, cdn: mediaMetaData.urls[0].cdn}); | ||
var evt = new PluginData({ status: PluginEnums.STATUS.FAILOVER, stateType: PluginEnums.TYPE.ERROR, properties: errorProperties, isBufferingTimeoutError: bufferingTimeoutError, cdn: mediaMetaData.urls[0].cdn }); | ||
Plugins.interface.onErrorHandled(evt); | ||
cdnDebugOutput.update(); | ||
loadMedia(mediaMetaData.urls, mediaMetaData.type, getCurrentTime(), thenPause); | ||
loadMedia(mediaMetaData.urls, mediaMetaData.type, failoverTime, thenPause); | ||
} | ||
@@ -282,3 +309,3 @@ | ||
} | ||
var evt = new PluginData({status: PluginEnums.STATUS.DISMISSED, stateType: PluginEnums.TYPE.ERROR, properties: errorProperties}); | ||
var evt = new PluginData({ status: PluginEnums.STATUS.DISMISSED, stateType: PluginEnums.TYPE.ERROR, properties: errorProperties }); | ||
Plugins.interface.onErrorCleared(evt); | ||
@@ -288,3 +315,3 @@ } | ||
function bubbleErrorRaised (errorProperties, bufferingTimeoutError) { | ||
var evt = new PluginData({status: PluginEnums.STATUS.STARTED, stateType: PluginEnums.TYPE.ERROR, properties: errorProperties, isBufferingTimeoutError: bufferingTimeoutError}); | ||
var evt = new PluginData({ status: PluginEnums.STATUS.STARTED, stateType: PluginEnums.TYPE.ERROR, properties: errorProperties, isBufferingTimeoutError: bufferingTimeoutError }); | ||
Plugins.interface.onError(evt); | ||
@@ -294,3 +321,3 @@ } | ||
function bubbleBufferingRaised (playbackProperties) { | ||
var evt = new PluginData({status: PluginEnums.STATUS.STARTED, stateType: PluginEnums.TYPE.BUFFERING, properties: playbackProperties}); | ||
var evt = new PluginData({ status: PluginEnums.STATUS.STARTED, stateType: PluginEnums.TYPE.BUFFERING, properties: playbackProperties }); | ||
Plugins.interface.onBuffering(evt); | ||
@@ -308,6 +335,12 @@ } | ||
} | ||
var evt = new PluginData({status: PluginEnums.STATUS.DISMISSED, stateType: PluginEnums.TYPE.BUFFERING, properties: bufferingProperties, isInitialPlay: isInitialPlay}); | ||
var evt = new PluginData({ status: PluginEnums.STATUS.DISMISSED, stateType: PluginEnums.TYPE.BUFFERING, properties: bufferingProperties, isInitialPlay: isInitialPlay }); | ||
Plugins.interface.onBufferingCleared(evt); | ||
} | ||
function bubbleFatalError (errorProperties, bufferingTimeoutError) { | ||
var evt = new PluginData({ status: PluginEnums.STATUS.FATAL, stateType: PluginEnums.TYPE.ERROR, properties: errorProperties, isBufferingTimeoutError: bufferingTimeoutError }); | ||
Plugins.interface.onFatalError(evt); | ||
publishMediaStateUpdate(MediaState.FATAL_ERROR, { isBufferingTimeoutError: bufferingTimeoutError }); | ||
} | ||
function createPlaybackProperties () { | ||
@@ -338,3 +371,3 @@ var playbackProperties = {}; | ||
stateUpdateCallback({data: mediaData, timeUpdate: opts && opts.timeUpdate, isBufferingTimeoutError: (opts && opts.isBufferingTimeoutError || false)}); | ||
stateUpdateCallback({ data: mediaData, timeUpdate: opts && opts.timeUpdate, isBufferingTimeoutError: (opts && opts.isBufferingTimeoutError || false) }); | ||
} | ||
@@ -397,2 +430,4 @@ | ||
getDuration: getDuration, | ||
getWindowStartTime: getWindowStartTime, | ||
getWindowEndTime: getWindowEndTime, | ||
getSeekableRange: getSeekableRange, | ||
@@ -399,0 +434,0 @@ getPlayerElement: getPlayerElement, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
94
7328234
65748
22