shaka-player
Advanced tools
Comparing version 2.2.7 to 2.2.8
@@ -126,2 +126,7 @@ /** | ||
// Since videos go into a paused state at the end, Chrome and Edge both fire | ||
// the 'pause' event when a video ends. IE 11 only fires the 'ended' event. | ||
this.video_.addEventListener( | ||
'ended', this.onPlayStateChange_.bind(this)); | ||
this.seekBar_.addEventListener( | ||
@@ -192,5 +197,4 @@ 'mousedown', this.onSeekStart_.bind(this)); | ||
var screenOrientation = this.getScreenOrientation_(); | ||
if (screenOrientation) { | ||
screenOrientation.addEventListener( | ||
if (screen.orientation) { | ||
screen.orientation.addEventListener( | ||
'change', this.onScreenRotation_.bind(this)); | ||
@@ -208,9 +212,10 @@ } | ||
ShakaControls.prototype.onScreenRotation_ = function() { | ||
var orientation = this.getScreenOrientation_(); | ||
if (!this.video_ || this.video_.readyState == 0 || !orientation || | ||
if (!this.video_ || | ||
this.video_.readyState == 0 || | ||
this.castProxy_.isCasting()) return; | ||
if (orientation.type.indexOf('landscape') >= 0 && | ||
if (screen.orientation.type.indexOf('landscape') >= 0 && | ||
!document.fullscreenElement) { | ||
this.videoContainer_.requestFullscreen(); | ||
} else if (orientation.type.indexOf('portrait') >= 0 && | ||
} else if (screen.orientation.type.indexOf('portrait') >= 0 && | ||
document.fullscreenElement) { | ||
@@ -223,14 +228,2 @@ document.exitFullscreen(); | ||
/** | ||
* Get screen orientation. | ||
* Screen Orientation is implemented with a prefix for some browsers. | ||
* https://developer.mozilla.org/en-US/docs/Web/API/Screen/orientation | ||
* @return {?ScreenOrientation} | ||
* @private | ||
*/ | ||
ShakaControls.prototype.getScreenOrientation_ = function() { | ||
return screen.orientation || screen.mozOrientation || screen.msOrientation; | ||
}; | ||
/** | ||
* Initializes minimal player controls. Used on both sender (indirectly) and | ||
@@ -237,0 +230,0 @@ * receiver (directly). |
@@ -187,2 +187,6 @@ /** | ||
}); | ||
}).catch(function(error) { | ||
// Some part of the setup of the demo app threw an error. | ||
// Notify the user of this. | ||
shakaDemo.onError_(/** @type {!shaka.util.Error} */ (error)); | ||
}); | ||
@@ -622,3 +626,15 @@ } | ||
} else { | ||
shakaDemo.init(); | ||
/** | ||
* Poll for Shaka Player on window. On IE 11, the document is "ready", but | ||
* there are still deferred scripts being loaded. This does not occur on | ||
* Chrome or Edge, which set the document's state at the correct time. | ||
*/ | ||
var pollForShakaPlayer = function() { | ||
if (window.shaka) { | ||
shakaDemo.init(); | ||
} else { | ||
setTimeout(pollForShakaPlayer, 100); | ||
} | ||
}; | ||
pollForShakaPlayer(); | ||
} |
@@ -561,3 +561,4 @@ /** | ||
* smallGapLimit: number, | ||
* jumpLargeGaps: boolean | ||
* jumpLargeGaps: boolean, | ||
* durationBackoff: number | ||
* }} | ||
@@ -603,2 +604,8 @@ * | ||
* but the gap will not be jumped. | ||
* @property {number} durationBackoff | ||
* By default, we will not allow seeking to exactly the duration of a | ||
* presentation. This field is the number of seconds before duration we will | ||
* seek to when the user tries to seek to or start playback at the duration. | ||
* To disable this behavior, the config can be set to 0. We recommend using | ||
* the default value unless you have a good reason not to. | ||
* @exportDoc | ||
@@ -605,0 +612,0 @@ */ |
@@ -318,2 +318,7 @@ /** | ||
shaka.cast.CastReceiver.prototype.proxyEvent_ = function(targetName, event) { | ||
if (!this.player_) { | ||
// The receiver is destroyed, so it should ignore further events. | ||
return; | ||
} | ||
// Poll and send an update right before we send the event. Some events | ||
@@ -320,0 +325,0 @@ // indicate an attribute change, so that change should be visible when the |
@@ -390,6 +390,6 @@ /** | ||
var networkingEngine = this.playerInterface_.networkingEngine; | ||
var isCanceled = function() { | ||
var isCanceled = (function() { | ||
return !this.playerInterface_; | ||
}; | ||
return networkingEngine.request(requestType, request, isCanceled.bind(this)) | ||
}).bind(this); | ||
return networkingEngine.request(requestType, request, isCanceled) | ||
.then(function(response) { | ||
@@ -396,0 +396,0 @@ // Detect calls to stop(). |
@@ -1368,6 +1368,6 @@ /** | ||
var networkingEngine = this.playerInterface_.networkingEngine; | ||
var isCanceled = function() { | ||
var isCanceled = (function() { | ||
return !this.playerInterface_; | ||
}; | ||
return networkingEngine.request(requestType, request, isCanceled.bind(this)); | ||
}).bind(this); | ||
return networkingEngine.request(requestType, request, isCanceled); | ||
}; | ||
@@ -1374,0 +1374,0 @@ |
@@ -173,9 +173,16 @@ /** | ||
var async = this.activeSessions_.map(function(activeSession) { | ||
var async = []; | ||
// Wait for sessions to close when destroying. | ||
this.activeSessions_.forEach(function(activeSession) { | ||
// Ignore any errors when closing the sessions. One such error would be | ||
// an invalid state error triggered by closing a session which has not | ||
// generated any key requests. | ||
// Chrome sometimes returns |undefined|: https://crbug.com/690664 | ||
var p = activeSession.session.close() || Promise.resolve(); | ||
return p.catch(Functional.noop); | ||
var close = activeSession.session.close().catch(Functional.noop); | ||
// Due to a bug in Chrome, sometimes the Promise returned by close() | ||
// never resolves. See #1093 and https://crbug.com/690583 | ||
var closeTimeout = new Promise(function(resolve) { | ||
setTimeout(resolve, 1000); | ||
}); | ||
async.push(Promise.race([close, closeTimeout])); | ||
}); | ||
@@ -182,0 +189,0 @@ this.allSessionsLoaded_.reject(); |
@@ -69,3 +69,4 @@ /** | ||
*/ | ||
this.startTime_ = startTime; | ||
this.startTime_ = startTime == null ? null : | ||
this.clampSeekToDuration_(startTime); | ||
@@ -190,3 +191,8 @@ /** @private {?function()} */ | ||
/** @param {number} startTime */ | ||
/** | ||
* Adjust the start time. Used by Player to implement the | ||
* streaming.startAtSegmentBoundary configuration. | ||
* | ||
* @param {number} startTime | ||
*/ | ||
shaka.media.Playhead.prototype.setStartTime = function(startTime) { | ||
@@ -201,2 +207,27 @@ if (this.video_.readyState > 0) | ||
/** | ||
* Clamp seek times and playback start times so that we never seek to the | ||
* presentation duration. Seeking to or starting at duration does not work | ||
* consistently across browsers. | ||
* | ||
* TODO: Clean up and simplify Playhead. There are too many layers of, methods | ||
* for, and conditions on timestamp adjustment. | ||
* | ||
* @see https://github.com/google/shaka-player/issues/979 | ||
* @param {number} time | ||
* @return {number} The adjusted seek time. | ||
* @private | ||
*/ | ||
shaka.media.Playhead.prototype.clampSeekToDuration_ = function(time) { | ||
var timeline = this.manifest_.presentationTimeline; | ||
var duration = timeline.getDuration(); | ||
if (time >= duration) { | ||
goog.asserts.assert(this.config_.durationBackoff >= 0, | ||
'Duration backoff must be non-negative!'); | ||
return duration - this.config_.durationBackoff; | ||
} | ||
return time; | ||
}; | ||
/** | ||
* Gets the playhead's current (logical) position. | ||
@@ -251,3 +282,3 @@ * | ||
// TODO: re-evaluate after #999 (drift tolerance refactor) is resolved | ||
this.startTime_ = startTime; | ||
this.startTime_ = this.clampSeekToDuration_(startTime); | ||
@@ -591,2 +622,3 @@ return startTime; | ||
var end = timeline.getSegmentAvailabilityEnd(); | ||
var duration = timeline.getDuration(); | ||
@@ -610,2 +642,7 @@ // With live content, the beginning of the availability window is moving | ||
if (currentTime >= duration) { | ||
shaka.log.v1('Playhead past duration.'); | ||
return this.clampSeekToDuration_(currentTime); | ||
} | ||
if (currentTime > end) { | ||
@@ -612,0 +649,0 @@ shaka.log.v1('Playhead past end.'); |
@@ -339,3 +339,3 @@ /** | ||
var wrapper = function() { | ||
var wrapper = (function() { | ||
if (callback && typeof callback == 'function') { | ||
@@ -385,6 +385,6 @@ // Wrap around the callback. Exceptions thrown by the callback are | ||
} | ||
}; | ||
}).bind(this); | ||
// Enqueue a call to the wrapper. | ||
Promise.q_.push(wrapper.bind(this)); | ||
Promise.q_.push(wrapper); | ||
if (Promise.flushTimer_ == null) { | ||
@@ -391,0 +391,0 @@ Promise.flushTimer_ = Promise.setImmediate_(Promise.flush); |
@@ -119,2 +119,6 @@ /** | ||
// Skip style blocks. | ||
if (text[0] == 'STYLE') | ||
return null; | ||
var id = null; | ||
@@ -121,0 +125,0 @@ var index = text[0].indexOf('-->'); |
{ | ||
"name": "shaka-player", | ||
"description": "DASH/EME video player library", | ||
"version": "2.2.7", | ||
"version": "2.2.8", | ||
"homepage": "https://github.com/google/shaka-player", | ||
@@ -6,0 +6,0 @@ "author": "Google", |
@@ -192,3 +192,3 @@ /** | ||
var originalRequest = networkingEngine.request; | ||
var originalRequest = networkingEngine.request.bind(networkingEngine); | ||
var requestComplete; | ||
@@ -199,3 +199,3 @@ var requestSpy = jasmine.createSpy('request'); | ||
requestMade.resolve(); | ||
requestComplete = originalRequest.apply(this, arguments); | ||
requestComplete = originalRequest.apply(null, arguments); | ||
return requestComplete; | ||
@@ -202,0 +202,0 @@ }); |
@@ -80,3 +80,4 @@ /** | ||
smallGapLimit: 0.5, | ||
jumpLargeGaps: false | ||
jumpLargeGaps: false, | ||
durationBackoff: 1 | ||
}; | ||
@@ -242,14 +243,2 @@ | ||
beforeEach(function() { | ||
// expect(...).toEquals doesn't compare DOM nodes well, so create a custom | ||
// wrapper that will match it. | ||
var fakeElement = { | ||
asymmetricMatch: function(other) { | ||
// The |regionInfo.fakeElement| member should be copied by-reference. | ||
return other == this; | ||
}, | ||
jasmineToString: function() { | ||
return '<Event element>'; | ||
} | ||
}; | ||
regionInfo = { | ||
@@ -261,3 +250,6 @@ schemeIdUri: 'http://example.com', | ||
id: 'abc', | ||
eventElement: /** @type {?} */ (fakeElement) | ||
// This should be an actual object, but it doesn't matter what. | ||
// It will be checked with jasmine's toBe() to make sure it was copied | ||
// by reference. | ||
eventElement: /** @type {?} */({}) | ||
}; | ||
@@ -458,2 +450,4 @@ | ||
expect(event.detail).toEqual(info); | ||
// This should be a copy by reference, not just a value match. | ||
expect(event.detail.eventElement).toBe(info.eventElement); | ||
} | ||
@@ -460,0 +454,0 @@ |
@@ -140,6 +140,6 @@ /** | ||
timeline.getSegmentAvailabilityEnd.and.returnValue(60); | ||
timeline.getDuration.and.returnValue(60); | ||
// These tests should not cause these methods to be invoked. | ||
timeline.getSegmentAvailabilityDuration.and.throwError(new Error()); | ||
timeline.getDuration.and.throwError(new Error()); | ||
timeline.setDuration.and.throwError(new Error()); | ||
@@ -164,3 +164,4 @@ | ||
smallGapLimit: 0.5, | ||
jumpLargeGaps: false | ||
jumpLargeGaps: false, | ||
durationBackoff: 1 | ||
}; | ||
@@ -267,2 +268,18 @@ }); | ||
it('bumps startTime back from duration', function() { | ||
video.readyState = HTMLMediaElement.HAVE_METADATA; | ||
timeline.isLive.and.returnValue(false); | ||
timeline.getSegmentAvailabilityStart.and.returnValue(0); | ||
timeline.getSegmentAvailabilityEnd.and.returnValue(60); | ||
timeline.getSeekRangeEnd.and.returnValue(60); | ||
timeline.getDuration.and.returnValue(60); | ||
playhead = new shaka.media.Playhead( | ||
video, manifest, config, 60 /* startTime */, Util.spyFunc(onSeek), | ||
Util.spyFunc(onEvent)); | ||
expect(playhead.getTime()).toBe(59); // duration - durationBackoff | ||
expect(video.currentTime).toBe(59); // duration - durationBackoff | ||
}); | ||
it('respects a seek before metadata is loaded', function() { | ||
@@ -364,2 +381,3 @@ playhead = new shaka.media.Playhead( | ||
timeline.isLive.and.returnValue(true); | ||
timeline.getDuration.and.returnValue(Infinity); | ||
timeline.getSegmentAvailabilityStart.and.returnValue(5); | ||
@@ -506,2 +524,3 @@ timeline.getSegmentAvailabilityEnd.and.returnValue(60); | ||
timeline.getSegmentAvailabilityEnd.and.returnValue(60); | ||
timeline.getDuration.and.returnValue(60); | ||
timeline.getSegmentAvailabilityDuration.and.returnValue(null); | ||
@@ -524,4 +543,4 @@ | ||
video.on['seeking'](); | ||
expect(video.currentTime).toBe(60); | ||
expect(playhead.getTime()).toBe(60); | ||
expect(video.currentTime).toBe(59); // duration - durationBackoff | ||
expect(playhead.getTime()).toBe(59); // duration - durationBackoff | ||
expect(onSeek).not.toHaveBeenCalled(); | ||
@@ -548,2 +567,3 @@ video.on['seeking'](); | ||
timeline.isLive.and.returnValue(true); | ||
timeline.getDuration.and.returnValue(Infinity); | ||
timeline.getSegmentAvailabilityStart.and.returnValue(1000); | ||
@@ -582,2 +602,3 @@ timeline.getSegmentAvailabilityEnd.and.returnValue(1000); | ||
timeline.isLive.and.returnValue(true); | ||
timeline.getDuration.and.returnValue(Infinity); | ||
timeline.getSegmentAvailabilityStart.and.returnValue(5); | ||
@@ -618,2 +639,3 @@ timeline.getSegmentAvailabilityEnd.and.returnValue(60); | ||
timeline.getSegmentAvailabilityEnd.and.returnValue(60); | ||
timeline.getDuration.and.returnValue(60); | ||
timeline.getSegmentAvailabilityDuration.and.returnValue(30); | ||
@@ -653,2 +675,3 @@ | ||
timeline.getSegmentAvailabilityEnd.and.returnValue(60); | ||
timeline.getDuration.and.returnValue(60); | ||
@@ -655,0 +678,0 @@ config.smallGapLimit = 1; |
@@ -93,3 +93,4 @@ /** | ||
smallGapLimit: 0.5, | ||
jumpLargeGaps: false | ||
jumpLargeGaps: false, | ||
durationBackoff: 1 | ||
}; | ||
@@ -96,0 +97,0 @@ |
@@ -227,3 +227,3 @@ /** | ||
db.insert = function(storeName, value) { | ||
return this.createTransaction_(storeName, 'readwrite', function(store) { | ||
return db.createTransaction_(storeName, 'readwrite', function(store) { | ||
var request = store.put(value); | ||
@@ -230,0 +230,0 @@ request.onsuccess = function(event) { |
@@ -182,3 +182,11 @@ /** | ||
}) | ||
.catch(fail) | ||
.catch(function(error) { | ||
fail(error); | ||
// Make sure we clean up the extra DrmEngine even if the Promise | ||
// chain and test fail. | ||
if (drmEngine) { | ||
return drmEngine.destroy(); | ||
} | ||
}) | ||
.then(done); | ||
@@ -185,0 +193,0 @@ }); |
@@ -212,8 +212,10 @@ /** | ||
Promise.resolve(dummy) | ||
.then(function() { | ||
.then(/** @this {*} */ function() { | ||
expect(this).toBe(window); | ||
throw new Error(); | ||
}) | ||
.then(fail, function() { expect(this).toBe(window); }) | ||
.then(function() { | ||
.then(fail, /** @this {*} */ function() { | ||
expect(this).toBe(window); | ||
}) | ||
.then(/** @this {*} */ function() { | ||
'use strict'; | ||
@@ -223,3 +225,3 @@ expect(this).toBe(undefined); | ||
}) | ||
.then(fail, function() { | ||
.then(fail, /** @this {*} */ function() { | ||
'use strict'; | ||
@@ -226,0 +228,0 @@ expect(this).toBe(undefined); |
@@ -42,17 +42,3 @@ /** | ||
/** @type {boolean} */ | ||
var mockCue = false; | ||
beforeAll(function(done) { | ||
// Mock out VTTCue if not supported. These tests don't actually need | ||
// VTTCue to do anything, this simply verifies the value of its members. | ||
if (!window.VTTCue) { | ||
mockCue = true; | ||
window.VTTCue = function(start, end, text) { | ||
this.startTime = start; | ||
this.endTime = end; | ||
this.text = text; | ||
}; | ||
} | ||
Promise.all([ | ||
@@ -73,9 +59,2 @@ shaka.test.Util.fetch(vttInitSegmentUri), | ||
afterAll(function() { | ||
// Delete our mock. | ||
if (mockCue) { | ||
delete window.VTTCue; | ||
} | ||
}); | ||
it('parses init segment', function() { | ||
@@ -82,0 +61,0 @@ new shaka.text.Mp4VttParser().parseInit(vttInitSegment); |
@@ -41,7 +41,14 @@ /** | ||
window.VTTCue = function(start, end, text) { | ||
/** | ||
* @constructor | ||
* @param {number} start | ||
* @param {number} end | ||
* @param {string} text | ||
*/ | ||
function FakeVTTCue(start, end, text) { | ||
this.startTime = start; | ||
this.endTime = end; | ||
this.text = text; | ||
}; | ||
} | ||
window.VTTCue = /** @type {?} */(FakeVTTCue); | ||
}); | ||
@@ -233,31 +240,37 @@ | ||
it('uses a workaround for browsers not supporting align=center', | ||
function() { | ||
window.VTTCue = function(start, end, text) { | ||
var align = 'middle'; | ||
Object.defineProperty(this, 'align', { | ||
get: function() { return align; }, | ||
set: function(newValue) { | ||
if (newValue != 'center') align = newValue; | ||
} | ||
}); | ||
this.startTime = start; | ||
this.endTime = end; | ||
this.text = text; | ||
}; | ||
it('works around browsers not supporting align=center', function() { | ||
/** | ||
* @constructor | ||
* @param {number} start | ||
* @param {number} end | ||
* @param {string} text | ||
*/ | ||
function FakeVTTCueWithoutAlignCenter(start, end, text) { | ||
var align = 'middle'; | ||
Object.defineProperty(this, 'align', { | ||
get: function() { return align; }, | ||
set: function(newValue) { | ||
if (newValue != 'center') align = newValue; | ||
} | ||
}); | ||
this.startTime = start; | ||
this.endTime = end; | ||
this.text = text; | ||
} | ||
window.VTTCue = /** @type {?} */(FakeVTTCueWithoutAlignCenter); | ||
var cue1 = new shaka.text.Cue(20, 40, 'Test'); | ||
cue1.textAlign = Cue.textAlign.CENTER; | ||
var cue1 = new shaka.text.Cue(20, 40, 'Test'); | ||
cue1.textAlign = Cue.textAlign.CENTER; | ||
verifyHelper( | ||
[ | ||
{ | ||
start: 20, | ||
end: 40, | ||
text: 'Test', | ||
align: 'middle' | ||
} | ||
], | ||
[cue1]); | ||
}); | ||
verifyHelper( | ||
[ | ||
{ | ||
start: 20, | ||
end: 40, | ||
text: 'Test', | ||
align: 'middle' | ||
} | ||
], | ||
[cue1]); | ||
}); | ||
@@ -264,0 +277,0 @@ it('ignores cues with startTime >= endTime', function() { |
@@ -524,3 +524,18 @@ /** | ||
it('skips style blocks', function() { | ||
verifyHelper( | ||
[ | ||
{start: 20, end: 40, payload: 'Test'}, | ||
{start: 40, end: 50, payload: 'Test2'} | ||
], | ||
'WEBVTT\n\n' + | ||
'STYLE\n::cue(.cyan) { color: cyan; }\n\n' + | ||
'00:00:20.000 --> 00:00:40.000\n' + | ||
'Test\n\n' + | ||
'00:00:40.000 --> 00:00:50.000\n' + | ||
'Test2', | ||
{ periodStart: 0, segmentStart: 0, segmentEnd: 0 }); | ||
}); | ||
/** | ||
@@ -527,0 +542,0 @@ * @param {!Array} cues |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
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
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
17548109
88082