shaka-player
Advanced tools
Comparing version 2.0.2 to 2.0.3
@@ -0,1 +1,27 @@ | ||
## 2.0.3 (2017-01-09) | ||
New features: | ||
- Treat HTTP 202 status codes as failures | ||
- https://github.com/google/shaka-player/issues/645 | ||
Bugfixes: | ||
- Fix race condition in StreamingEngine | ||
- Fix race in load/unload in Player | ||
- https://github.com/google/shaka-player/pull/613 | ||
- https://github.com/google/shaka-player/issues/612 | ||
- Update workarounds for Edge EME bugs | ||
- https://github.com/google/shaka-player/issues/634 | ||
- Add missing events and methods to cast proxy | ||
- Fix exclusion of standard features in custom builds | ||
- Be more permissive of text failures | ||
- Permit text parsing errors as well as streaming errors with the | ||
ignoreTextStreamFailures config option. | ||
- Do not fail StreamingEngine startup because of text streams, | ||
regardless of config. | ||
- https://github.com/google/shaka-player/issues/635 | ||
- Fix selectTrack() call with no text tracks | ||
- https://github.com/google/shaka-player/issues/640 | ||
- Fix buffering state for live streams (stop at live edge) | ||
- https://github.com/google/shaka-player/issues/636 | ||
## 2.0.2 (2016-12-15) | ||
@@ -2,0 +28,0 @@ |
@@ -116,118 +116,2 @@ /** | ||
customLaunchers: { | ||
// These entries are specific to Shaka team's internal test lab: | ||
// OS X El Capitan {{{ | ||
WebDriver_Safari9: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4445}, | ||
browserName: 'safari', | ||
pseudoActivityInterval: 20000 | ||
}, | ||
// }}} | ||
// macOS Sierra {{{ | ||
WebDriver_Safari10: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4444}, | ||
browserName: 'safari', | ||
pseudoActivityInterval: 20000 | ||
}, | ||
WebDriver_ChromeMac: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4444}, | ||
browserName: 'chrome', | ||
pseudoActivityInterval: 20000, | ||
chromeOptions: { | ||
// Instruct chromedriver not to disable component updater. The | ||
// component updater must run in order for the Widevine CDM to be | ||
// available when using a new user-data-dir. | ||
// TODO: remove once http://crbug.com/613581 is fixed. | ||
excludeSwitches: ['disable-component-update'] | ||
} | ||
}, | ||
WebDriver_FirefoxMac: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4444}, | ||
browserName: 'firefox', | ||
pseudoActivityInterval: 20000 | ||
}, | ||
WebDriver_OperaMac: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4444}, | ||
browserName: 'operablink', | ||
pseudoActivityInterval: 20000 | ||
}, | ||
// }}} | ||
// Windows 10 {{{ | ||
WebDriver_IE11: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4446}, | ||
browserName: 'internet explorer', | ||
pseudoActivityInterval: 20000, | ||
ignoreZoomSetting: true, | ||
ignoreProtectedModeSettings: true | ||
}, | ||
WebDriver_Edge: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4446}, | ||
browserName: 'MicrosoftEdge', | ||
pseudoActivityInterval: 20000 | ||
}, | ||
WebDriver_ChromeWin: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4446}, | ||
browserName: 'chrome', | ||
pseudoActivityInterval: 20000, | ||
chromeOptions: { | ||
// Instruct chromedriver not to disable component updater. The | ||
// component updater must run in order for the Widevine CDM to be | ||
// available when using a new user-data-dir. | ||
// TODO: remove once http://crbug.com/613581 is fixed. | ||
excludeSwitches: ['disable-component-update'] | ||
} | ||
}, | ||
WebDriver_FirefoxWin: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4446}, | ||
browserName: 'firefox', | ||
pseudoActivityInterval: 20000 | ||
}, | ||
// }}} | ||
// Linux {{{ | ||
WebDriver_ChromeLinux: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4447}, | ||
browserName: 'chrome', | ||
pseudoActivityInterval: 20000 | ||
}, | ||
WebDriver_FirefoxLinux: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4447}, | ||
browserName: 'firefox', | ||
pseudoActivityInterval: 20000 | ||
}, | ||
// }}} | ||
// Android 6.0.1 {{{ | ||
// Note: this is tethered to the Linux machine. | ||
WebDriver_ChromeAndroid: { | ||
base: 'WebDriver', | ||
config: {hostname: 'localhost', port: 4447}, | ||
browserName: 'chrome', | ||
pseudoActivityInterval: 20000, | ||
chromeOptions: {'androidPackage': 'com.android.chrome'} | ||
}, | ||
// }}} | ||
}, | ||
coverageReporter: { | ||
@@ -234,0 +118,0 @@ includeAllSources: true, |
@@ -95,3 +95,6 @@ /** | ||
'buffering', | ||
'emsg', | ||
'error', | ||
'loading', | ||
'unloading', | ||
'texttrackvisibility', | ||
@@ -107,10 +110,14 @@ 'trackschanged' | ||
shaka.cast.CastUtils.PlayerGetterMethods = [ | ||
'drmInfo', | ||
'getConfiguration', | ||
'getManifestUri', | ||
'getPlaybackRate', | ||
'getPlayheadTimeAsDate', | ||
'getTracks', | ||
'getStats', | ||
'isBuffering', | ||
'isInProgress', | ||
'isLive', | ||
'isTextTrackVisible', | ||
'keySystem', | ||
'seekRange' | ||
@@ -145,9 +152,9 @@ ]; | ||
shaka.cast.CastUtils.PlayerVoidMethods = [ | ||
'addTextTrack', | ||
'cancelTrickPlay', | ||
'configure', | ||
'resetConfiguration', | ||
'trickPlay', | ||
'cancelTrickPlay', | ||
'selectTrack', | ||
'setTextTrackVisibility', | ||
'addTextTrack' | ||
'trickPlay' | ||
]; | ||
@@ -154,0 +161,0 @@ |
@@ -787,2 +787,3 @@ /** | ||
var trickModeFor = null; | ||
var unrecognizedEssentialProperty = false; | ||
essentialProperties.forEach(function(prop) { | ||
@@ -792,2 +793,4 @@ var schemeId = prop.getAttribute('schemeIdUri'); | ||
trickModeFor = prop.getAttribute('value'); | ||
} else { | ||
unrecognizedEssentialProperty = true; | ||
} | ||
@@ -800,2 +803,12 @@ }); | ||
// According to DASH spec (2014) section 5.8.4.8, "the successful processing | ||
// of the descriptor is essential to properly use the information in the | ||
// parent element". According to DASH IOP v3.3, section 3.3.4, "if the scheme | ||
// or the value" for EssentialProperty is not recognized, "the DASH client | ||
// shall ignore the parent element." | ||
if (unrecognizedEssentialProperty) { | ||
// Stop parsing this AdaptationSet and let the caller filter out the nulls. | ||
return null; | ||
} | ||
var contentProtectionElems = XmlUtils.findChildren(elem, 'ContentProtection'); | ||
@@ -802,0 +815,0 @@ var contentProtection = shaka.dash.ContentProtection.parseFromAdaptationSet( |
@@ -378,5 +378,2 @@ /** | ||
// TODO: Remove once Edge has released a fix for https://goo.gl/vr2Vle | ||
var isEdge = navigator.userAgent.indexOf('Edge/') >= 0; | ||
manifest.periods.forEach(function(period) { | ||
@@ -440,10 +437,2 @@ period.streamSets.forEach(function(streamSet) { | ||
// Edge 13 fails this negotiation with NotSupportedError if more than | ||
// one entry is given, even if each entry individually would be | ||
// supported. Bug filed: https://goo.gl/vr2Vle | ||
// TODO: Remove once Edge has released a fix. | ||
if (isEdge && drmInfo.keySystem == 'com.microsoft.playready' && | ||
capabilities.length) { | ||
return; | ||
} | ||
capabilities.push({ | ||
@@ -521,2 +510,5 @@ robustness: robustness, | ||
// TODO: Remove once Edge has released a fix for https://goo.gl/qMeV7v | ||
var isEdge = navigator.userAgent.indexOf('Edge/') >= 0; | ||
// Store the capabilities of the key system. | ||
@@ -528,9 +520,12 @@ var realConfig = mediaKeySystemAccess.getConfiguration(); | ||
this.supportedTypes_ = caps.map(function(c) { return c.contentType; }); | ||
if (this.supportedTypes_.length == 0) { | ||
// Edge 13 does not report capabilities. To work around this, set the | ||
// supported types to null, which Player will use as a signal that the | ||
// information is not available. | ||
// See: https://goo.gl/0cSuT2 | ||
if (isEdge) { | ||
// Edge 14 does not report correct capabilities. It will only report the | ||
// first MIME type even if the others are supported. To work around this, | ||
// set the supported types to null, which Player will use as a signal that | ||
// the information is not available. | ||
// See: https://goo.gl/qMeV7v | ||
this.supportedTypes_ = null; | ||
} | ||
goog.asserts.assert(!this.supportedTypes_ || this.supportedTypes_.length, | ||
'We should get at least one supported MIME type'); | ||
@@ -537,0 +532,0 @@ var originalConfig = configsByKeySystem[mediaKeySystemAccess.keySystem]; |
@@ -231,3 +231,8 @@ /** | ||
var duration = this.video_.duration - fudgeFactor; | ||
var duration; | ||
if (this.timeline_.isLive()) { | ||
duration = this.timeline_.getSegmentAvailabilityEnd() - fudgeFactor; | ||
} else { | ||
duration = this.video_.duration - fudgeFactor; | ||
} | ||
@@ -234,0 +239,0 @@ var atEnd = (bufferEnd >= duration) || (this.video_.ended); |
@@ -1145,3 +1145,9 @@ /** | ||
shaka.log.error(logPrefix, 'failed fetch and append: code=' + error.code); | ||
this.onError_(error); | ||
if (mediaState.type == 'text' && this.config_.ignoreTextStreamFailures) { | ||
shaka.log.warning(logPrefix, | ||
'Text stream failed to parse. Proceeding without it.'); | ||
delete this.mediaStates_['text']; | ||
} else { | ||
this.onError_(error); | ||
} | ||
} | ||
@@ -1164,3 +1170,4 @@ }.bind(this)); | ||
error.code == shaka.util.Error.Code.BAD_HTTP_STATUS) { | ||
shaka.log.warning(logPrefix, 'Text stream failed. Proceeding without it.'); | ||
shaka.log.warning(logPrefix, | ||
'Text stream failed to download. Proceeding without it.'); | ||
delete this.mediaStates_['text']; | ||
@@ -1409,3 +1416,4 @@ } else { | ||
// Startup completes once we have buffered at least one segment from each | ||
// MediaState. | ||
// MediaState, not counting text. | ||
if (ms.type == 'text') return true; | ||
return !ms.waitingToClearBuffer && | ||
@@ -1654,3 +1662,3 @@ !ms.clearingBuffer && | ||
p.then(function() { | ||
if (flush) { | ||
if (!this.destroyed_ && flush) { | ||
return this.mediaSourceEngine_.flush(mediaState.type); | ||
@@ -1657,0 +1665,0 @@ } |
@@ -47,4 +47,5 @@ /** | ||
goog.asserts.assert(target, 'XHR onload has no target!'); | ||
if (target.status >= 200 && target.status <= 299) { | ||
// All 2xx HTTP codes are success cases. | ||
if (target.status >= 200 && target.status <= 299 && | ||
target.status != 202) { | ||
// Most 2xx HTTP codes are success cases. | ||
var headers = target.getAllResponseHeaders().split('\r\n').reduce( | ||
@@ -51,0 +52,0 @@ function(all, part) { |
@@ -284,3 +284,5 @@ /** | ||
return p.then(function(response) { | ||
this.requests_.splice(this.requests_.indexOf(p), 1); | ||
if (this.requests_.indexOf(p) >= 0) { | ||
this.requests_.splice(this.requests_.indexOf(p), 1); | ||
} | ||
var endTimeMs = Date.now(); | ||
@@ -294,3 +296,5 @@ if (this.onSegmentDownloaded_ && | ||
}.bind(this)).catch(function(e) { | ||
this.requests_.splice(this.requests_.indexOf(p), 1); | ||
if (this.requests_.indexOf(p) >= 0) { | ||
this.requests_.splice(this.requests_.indexOf(p), 1); | ||
} | ||
return Promise.reject(e); | ||
@@ -297,0 +301,0 @@ }.bind(this)); |
@@ -126,2 +126,5 @@ /** | ||
/** @private {Promise} */ | ||
this.unloadChain_ = null; | ||
/** | ||
@@ -181,2 +184,6 @@ * @private {!Object.<string, { | ||
var p = Promise.all([ | ||
// We need to destroy the current fields as well as waiting for an | ||
// existing unload to complete. It is fine to call destroyStreaming_ if | ||
// there is an unload since it resets the fields immediately. | ||
this.unloadChain_, | ||
this.destroyStreaming_(), | ||
@@ -202,3 +209,3 @@ this.eventManager_ ? this.eventManager_.destroy() : null, | ||
*/ | ||
goog.define('GIT_VERSION', 'v2.0.2-debug'); | ||
goog.define('GIT_VERSION', 'v2.0.3-debug'); | ||
@@ -604,3 +611,8 @@ | ||
// Need to apply the restrictions to every period. | ||
this.manifest_.periods.forEach(this.filterPeriod_.bind(this)); | ||
try { | ||
// this.filterPeriod_() may throw. | ||
this.manifest_.periods.forEach(this.filterPeriod_.bind(this)); | ||
} catch (error) { | ||
this.onError_(error); | ||
} | ||
@@ -770,14 +782,20 @@ // May need to choose new streams. | ||
var p = Promise.resolve(); | ||
if (this.loadChain_) { | ||
// A load is in progress. Cancel it, then reset the streaming system. | ||
// A load is in progress, cancel it. | ||
var interrupt = new shaka.util.Error( | ||
shaka.util.Error.Category.PLAYER, | ||
shaka.util.Error.Code.LOAD_INTERRUPTED); | ||
return this.loadChain_.cancel(interrupt) | ||
.then(this.resetStreaming_.bind(this)); | ||
} else { | ||
// No loads or unloads are in progress. | ||
// Just reset the streaming system if needed. | ||
return this.resetStreaming_(); | ||
p = this.loadChain_.cancel(interrupt); | ||
} | ||
return p.then(function() { | ||
// If there is an existing unload operation, use that. | ||
if (!this.unloadChain_) { | ||
this.unloadChain_ = this.resetStreaming_().then(function() { | ||
this.unloadChain_ = null; | ||
}.bind(this)); | ||
} | ||
return this.unloadChain_; | ||
}.bind(this)); | ||
}; | ||
@@ -888,3 +906,3 @@ | ||
if (track.type != 'text') { | ||
// Save current text stream to insure that it doesn't get overriden | ||
// Save current text stream to insure that it doesn't get overridden | ||
// by a default one inside shaka.Player.configure() | ||
@@ -898,3 +916,5 @@ var activeStreams = this.streamingEngine_.getActiveStreams(); | ||
streamsToSwitch['text'] = currentTextStream; | ||
if (currentTextStream) { | ||
streamsToSwitch['text'] = currentTextStream; | ||
} | ||
} | ||
@@ -1301,9 +1321,9 @@ | ||
if (!hasPlayableStreamSets) { | ||
this.onError_(new shaka.util.Error( | ||
throw new shaka.util.Error( | ||
shaka.util.Error.Category.MANIFEST, | ||
shaka.util.Error.Code.UNPLAYABLE_PERIOD)); | ||
shaka.util.Error.Code.UNPLAYABLE_PERIOD); | ||
} else if (allStreamsRestricted) { | ||
this.onError_(new shaka.util.Error( | ||
throw new shaka.util.Error( | ||
shaka.util.Error.Category.MANIFEST, | ||
shaka.util.Error.Code.RESTRICTIONS_CANNOT_BE_MET)); | ||
shaka.util.Error.Code.RESTRICTIONS_CANNOT_BE_MET); | ||
} | ||
@@ -1310,0 +1330,0 @@ }; |
{ | ||
"name": "shaka-player", | ||
"description": "DASH/EME video player library", | ||
"version": "2.0.2", | ||
"version": "2.0.3", | ||
"homepage": "https://github.com/google/shaka-player", | ||
@@ -6,0 +6,0 @@ "author": "Google", |
@@ -662,16 +662,21 @@ /** | ||
var player = { | ||
configure: jasmine.createSpy('configure'), | ||
destroy: jasmine.createSpy('destroy'), | ||
drmInfo: jasmine.createSpy('drmInfo'), | ||
getConfiguration: jasmine.createSpy('getConfiguration'), | ||
getManifestUri: jasmine.createSpy('getManifestUri'), | ||
getPlaybackRate: jasmine.createSpy('getPlaybackRate'), | ||
getPlayheadTimeAsDate: jasmine.createSpy('getPlayheadTimeAsDate'), | ||
getTracks: jasmine.createSpy('getTracks'), | ||
getStats: jasmine.createSpy('getStats'), | ||
isBuffering: jasmine.createSpy('isBuffering'), | ||
isInProgress: jasmine.createSpy('isInProgress'), | ||
isLive: jasmine.createSpy('isLive'), | ||
isTextTrackVisible: jasmine.createSpy('isTextTrackVisible'), | ||
keySystem: jasmine.createSpy('keySystem'), | ||
load: jasmine.createSpy('load'), | ||
seekRange: jasmine.createSpy('seekRange'), | ||
configure: jasmine.createSpy('configure'), | ||
setMaxHardwareResolution: jasmine.createSpy('setMaxHardwareResolution'), | ||
setTextTrackVisibility: jasmine.createSpy('setTextTrackVisibility'), | ||
setMaxHardwareResolution: jasmine.createSpy('setMaxHardwareResolution'), | ||
load: jasmine.createSpy('load'), | ||
destroy: jasmine.createSpy('destroy'), | ||
addEventListener: function(eventName, listener) { | ||
@@ -678,0 +683,0 @@ player.listeners[eventName] = listener; |
@@ -939,2 +939,31 @@ /** | ||
it('skips unrecognized EssentialProperty elements', function(done) { | ||
var manifestText = [ | ||
'<MPD minBufferTime="PT75S">', | ||
' <Period id="1" duration="PT30S">', | ||
' <AdaptationSet id="1" mimeType="video/mp4">', | ||
' <Representation bandwidth="1">', | ||
' <SegmentTemplate media="1.mp4" duration="1" />', | ||
' </Representation>', | ||
' </AdaptationSet>', | ||
' <AdaptationSet id="2" mimeType="video/mp4">', | ||
' <EssentialProperty schemeIdUri="http://foo.bar/" />', | ||
' <Representation bandwidth="1">', | ||
' <SegmentTemplate media="2.mp4" duration="1" />', | ||
' </Representation>', | ||
' </AdaptationSet>', | ||
' </Period>', | ||
'</MPD>' | ||
].join('\n'); | ||
fakeNetEngine.setResponseMapAsText({'dummy://foo': manifestText}); | ||
parser.start('dummy://foo', fakeNetEngine, filterPeriod, fail, onEventSpy) | ||
.then(function(manifest) { | ||
expect(manifest.periods.length).toBe(1); | ||
// The bogus EssentialProperty did not result in a StreamSet. | ||
expect(manifest.periods[0].streamSets.length).toBe(1); | ||
}).catch(fail).then(done); | ||
}); | ||
it('sets contentType to text for embedded text mime types', function(done) { | ||
@@ -941,0 +970,0 @@ // One MIME type for embedded TTML, one for embedded WebVTT. |
@@ -188,5 +188,11 @@ /** | ||
expect(drmEngine.initialized()).toBe(true); | ||
expect(drmEngine.getSupportedTypes()).toEqual([ | ||
'audio/webm', 'video/mp4; codecs="fake"' | ||
]); | ||
var supportedTypes = drmEngine.getSupportedTypes(); | ||
// This is conditional because Edge 14 has a bug that prevents us from | ||
// getting the types at all. TODO: Remove the condition once Edge has | ||
// released a fix for https://goo.gl/qMeV7v | ||
if (supportedTypes) { | ||
expect(supportedTypes).toEqual([ | ||
'audio/webm', 'video/mp4; codecs="fake"' | ||
]); | ||
} | ||
}).catch(fail).then(done); | ||
@@ -193,0 +199,0 @@ }); |
@@ -30,2 +30,6 @@ /** | ||
}); | ||
jasmine.Ajax.stubRequest('https://foo.bar/202').andReturn({ | ||
'response': new ArrayBuffer(0), | ||
'status': 202 | ||
}); | ||
jasmine.Ajax.stubRequest('https://foo.bar/204').andReturn({ | ||
@@ -77,2 +81,6 @@ 'response': new ArrayBuffer(10), | ||
it('fails with 202 status', function(done) { | ||
testFails('https://foo.bar/202', done); | ||
}); | ||
it('succeeds with 204 status', function(done) { | ||
@@ -79,0 +87,0 @@ testSucceeds('https://foo.bar/204', done); |
@@ -126,2 +126,33 @@ /** | ||
it('won\'t start loading until unloading is done', function(done) { | ||
// There was a bug when calling unload before calling load would cause | ||
// the load to continue before the (first) unload was complete. | ||
// https://github.com/google/shaka-player/issues/612 | ||
player.load('', 0, factory1).then(function() { | ||
// Delay the promise to destroy the parser. | ||
var p = new shaka.util.PublicPromise(); | ||
parser1.stop.and.returnValue(p); | ||
var unloadDone = false; | ||
spyOn(player, 'createMediaSourceEngine'); | ||
shaka.test.Util.delay(0.5).then(function() { | ||
// Should not start loading yet. | ||
expect(player.createMediaSourceEngine).not.toHaveBeenCalled(); | ||
// Unblock the unload chain. | ||
unloadDone = true; | ||
p.resolve(); | ||
}); | ||
// Explicitly unload the player first. When load calls unload, it | ||
// should wait until the parser is destroyed. | ||
player.unload(); | ||
player.load('', 0, factory2).then(function() { | ||
expect(unloadDone).toBe(true); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('handles repeated load/unload', function(done) { | ||
@@ -128,0 +159,0 @@ player.load('', 0, factory1).then(function() { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
15725697
477
63840
0