From 93a2bfdb197ba552122784db430e816bec1f2130 Mon Sep 17 00:00:00 2001 From: mister-ben Date: Wed, 15 Mar 2023 09:10:25 +0100 Subject: [PATCH] feat: Remove remnants of IE and old Edge (#1343) Co-authored-by: Pat O'Neill --- src/playlist-controller.js | 23 +- src/segment-loader.js | 2 +- src/source-updater.js | 8 +- src/videojs-http-streaming.js | 8 +- test/loader-common.js | 12 +- test/playback.test.js | 43 +- test/playlist-controller.test.js | 126 +---- test/playlist-loader.test.js | 791 ++++++++++++++-------------- test/playlist.test.js | 85 ++- test/sanity.test.js | 6 +- test/source-updater.test.js | 88 ++-- test/videojs-http-streaming.test.js | 90 +--- 12 files changed, 522 insertions(+), 760 deletions(-) diff --git a/src/playlist-controller.js b/src/playlist-controller.js index e91131d0f..79f0da771 100644 --- a/src/playlist-controller.js +++ b/src/playlist-controller.js @@ -933,18 +933,12 @@ export class PlaylistController extends videojs.EventTarget { // Delete all buffered data to allow an immediate quality switch, then seek to give // the browser a kick to remove any cached frames from the previous rendtion (.04 seconds - // ahead is roughly the minimum that will accomplish this across a variety of content + // ahead was roughly the minimum that will accomplish this across a variety of content // in IE and Edge, but seeking in place is sufficient on all other browsers) // Edge/IE bug: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/14600375/ // Chrome bug: https://bugs.chromium.org/p/chromium/issues/detail?id=651904 this.mainSegmentLoader_.resetEverything(() => { - // Since this is not a typical seek, we avoid the seekTo method which can cause segments - // from the previously enabled rendition to load before the new playlist has finished loading - if (videojs.browser.IE_VERSION || videojs.browser.IS_EDGE) { - this.tech_.setCurrentTime(this.tech_.currentTime() + 0.04); - } else { - this.tech_.setCurrentTime(this.tech_.currentTime()); - } + this.tech_.setCurrentTime(this.tech_.currentTime()); }); // don't need to reset audio as it is reset when media changes @@ -1003,19 +997,6 @@ export class PlaylistController extends videojs.EventTarget { return false; } - if (videojs.browser.IE_VERSION && - this.tech_.readyState() === 0) { - // IE11 throws an InvalidStateError if you try to set currentTime while the - // readyState is 0, so it must be delayed until the tech fires loadedmetadata. - this.tech_.one('loadedmetadata', () => { - this.trigger('firstplay'); - this.tech_.setCurrentTime(seekable.end(0)); - this.hasPlayed_ = true; - }); - - return false; - } - // trigger firstplay to inform the source handler to ignore the next seek event this.trigger('firstplay'); // seek to the live point diff --git a/src/segment-loader.js b/src/segment-loader.js index 049d4a672..5428a8347 100644 --- a/src/segment-loader.js +++ b/src/segment-loader.js @@ -576,7 +576,7 @@ export default class SegmentLoader extends videojs.EventTarget { // TODO possibly move gopBuffer and timeMapping info to a separate controller this.gopBuffer_ = []; this.timeMapping_ = 0; - this.safeAppend_ = videojs.browser.IE_VERSION >= 11; + this.safeAppend_ = false; this.appendInitSegment_ = { audio: true, video: true diff --git a/src/source-updater.js b/src/source-updater.js index 5b4f541b7..a7f3f11da 100644 --- a/src/source-updater.js +++ b/src/source-updater.js @@ -468,11 +468,9 @@ export default class SourceUpdater extends videojs.EventTarget { * if removeSourceBuffer can be called. */ canRemoveSourceBuffer() { - // IE reports that it supports removeSourceBuffer, but often throws - // errors when attempting to use the function. So we report that it - // does not support removeSourceBuffer. As of Firefox 83 removeSourceBuffer - // throws errors, so we report that it does not support this as well. - return !videojs.browser.IE_VERSION && !videojs.browser.IS_FIREFOX && window.MediaSource && + // As of Firefox 83 removeSourceBuffer + // throws errors, so we report that it does not support this. + return !videojs.browser.IS_FIREFOX && window.MediaSource && window.MediaSource.prototype && typeof window.MediaSource.prototype.removeSourceBuffer === 'function'; } diff --git a/src/videojs-http-streaming.js b/src/videojs-http-streaming.js index 08561a45d..9486f96e1 100644 --- a/src/videojs-http-streaming.js +++ b/src/videojs-http-streaming.js @@ -287,8 +287,8 @@ export const waitForKeySessionCreation = ({ const keySessionCreatedPromises = []; // Since PSSH values are interpreted as initData, EME will dedupe any duplicates. The - // only place where it should not be deduped is for ms-prefixed APIs, but the early - // return for IE11 above, and the existence of modern EME APIs in addition to + // only place where it should not be deduped is for ms-prefixed APIs, but + // the existence of modern EME APIs in addition to // ms-prefixed APIs on Edge should prevent this from being a concern. // initializeMediaKeys also won't use the webkit-prefixed APIs. keySystemsOptionsArr.forEach((keySystemsOptions) => { @@ -1058,9 +1058,7 @@ class VhsHandler extends Component { this.handleWaitingForKey_ = this.handleWaitingForKey_.bind(this); this.player_.tech_.on('waitingforkey', this.handleWaitingForKey_); - // In IE11 this is too early to initialize media keys, and IE11 does not support - // promises. - if (videojs.browser.IE_VERSION === 11 || !didSetupEmeOptions) { + if (!didSetupEmeOptions) { // If EME options were not set up, we've done all we could to initialize EME. this.playlistController_.sourceUpdater_.initializedEme(); return; diff --git a/test/loader-common.js b/test/loader-common.js index 6681c6094..0016b114d 100644 --- a/test/loader-common.js +++ b/test/loader-common.js @@ -1,5 +1,4 @@ import QUnit from 'qunit'; -import videojs from 'video.js'; import xhrFactory from '../src/xhr'; import Config from '../src/config'; import document from 'global/document'; @@ -941,16 +940,7 @@ export const LoaderCommonFactory = ({ // only main/fmp4 segment loaders use async appends and parts/partIndex if (usesAsyncAppends) { - let testFn = 'test'; - - if (videojs.browser.IE_VERSION) { - testFn = 'skip'; - } - - // this test has a race condition on ie 11 that causes it to fail some of the time. - // Since IE 11 isn't really a priority and it only fails some of the time we decided to - // skip this on IE 11. - QUnit[testFn]('playlist change before any appends does not error', function(assert) { + QUnit.test('playlist change before any appends does not error', function(assert) { return this.setupMediaSource(loader.mediaSource_, loader.sourceUpdater_).then(() => { loader.playlist(playlistWithDuration(50, { uri: 'bar-720.m3u8', diff --git a/test/playback.test.js b/test/playback.test.js index 25d658278..07a7215eb 100644 --- a/test/playback.test.js +++ b/test/playback.test.js @@ -34,13 +34,6 @@ const playFor = function(player, time, cb) { checkPlayerTime(); }; -let testFn = 'test'; - -// TODO: get these tests working, right now we just one the one basic test -if (videojs.browser.IE_VERSION || videojs.browser.IS_EDGE) { - testFn = 'skip'; -} - QUnit.module('Playback', { beforeEach(assert) { assert.timeout(50000); @@ -117,7 +110,7 @@ QUnit.test('Advanced Bip Bop', function(assert) { }); }); -QUnit[testFn]('replay', function(assert) { +QUnit.test('replay', function(assert) { const done = assert.async(); assert.expect(2); @@ -145,7 +138,7 @@ QUnit[testFn]('replay', function(assert) { }); }); -QUnit[testFn]('playlist with fmp4 segments', function(assert) { +QUnit.test('playlist with fmp4 segments', function(assert) { const done = assert.async(); assert.expect(2); @@ -164,7 +157,7 @@ QUnit[testFn]('playlist with fmp4 segments', function(assert) { }); }); -QUnit[testFn]('playlist with fmp4 and ts segments', function(assert) { +QUnit.test('playlist with fmp4 and ts segments', function(assert) { const done = assert.async(); assert.expect(2); @@ -183,7 +176,7 @@ QUnit[testFn]('playlist with fmp4 and ts segments', function(assert) { }); }); -QUnit[testFn]('Advanced Bip Bop preload=none', function(assert) { +QUnit.test('Advanced Bip Bop preload=none', function(assert) { const done = assert.async(); assert.expect(2); @@ -204,7 +197,7 @@ QUnit[testFn]('Advanced Bip Bop preload=none', function(assert) { }); }); -QUnit[testFn]('Big Buck Bunny', function(assert) { +QUnit.test('Big Buck Bunny', function(assert) { const done = assert.async(); assert.expect(2); @@ -223,7 +216,7 @@ QUnit[testFn]('Big Buck Bunny', function(assert) { }); }); -QUnit[testFn]('Live DASH', function(assert) { +QUnit.test('Live DASH', function(assert) { const done = assert.async(); const player = this.player; @@ -257,7 +250,7 @@ QUnit[testFn]('Live DASH', function(assert) { player.play(); }); -QUnit[testFn]('Multiperiod dash works and can end', function(assert) { +QUnit.test('Multiperiod dash works and can end', function(assert) { const done = assert.async(); assert.expect(2); @@ -287,7 +280,7 @@ QUnit[testFn]('Multiperiod dash works and can end', function(assert) { // firefox has lower performance or more aggressive throttling than chrome // which causes a variety of issues. if (!videojs.browser.IS_FIREFOX) { - QUnit[testFn]('Big Buck Bunny audio only, groups & renditions same uri', function(assert) { + QUnit.test('Big Buck Bunny audio only, groups & renditions same uri', function(assert) { const done = assert.async(); assert.expect(2); @@ -306,7 +299,7 @@ if (!videojs.browser.IS_FIREFOX) { }); }); - QUnit[testFn]('Big Buck Bunny Demuxed av, audio only rendition same as group', function(assert) { + QUnit.test('Big Buck Bunny Demuxed av, audio only rendition same as group', function(assert) { const done = assert.async(); assert.expect(2); @@ -325,7 +318,7 @@ if (!videojs.browser.IS_FIREFOX) { }); }); - QUnit[testFn]('DASH sidx', function(assert) { + QUnit.test('DASH sidx', function(assert) { const done = assert.async(); const player = this.player; @@ -349,7 +342,7 @@ if (!videojs.browser.IS_FIREFOX) { }); }); - QUnit[testFn]('DASH sidx with alt audio should end', function(assert) { + QUnit.test('DASH sidx with alt audio should end', function(assert) { const done = assert.async(); const player = this.player; @@ -376,7 +369,7 @@ if (!videojs.browser.IS_FIREFOX) { }); }); - QUnit[testFn]('DRM Dash', function(assert) { + QUnit.test('DRM Dash', function(assert) { const done = assert.async(); const player = this.player; @@ -419,7 +412,7 @@ if (!videojs.browser.IS_FIREFOX) { // TODO: why does this make the next test // throw an "The operation was aborted." on firefox - QUnit[testFn]('loops', function(assert) { + QUnit.test('loops', function(assert) { const done = assert.async(); const player = this.player; @@ -444,7 +437,7 @@ if (!videojs.browser.IS_FIREFOX) { }); } -QUnit[testFn]('zero-length id3 segment', function(assert) { +QUnit.test('zero-length id3 segment', function(assert) { const done = assert.async(); const player = this.player; @@ -465,7 +458,7 @@ QUnit[testFn]('zero-length id3 segment', function(assert) { const hlsDataUri = 'data:application/x-mpegurl;charset=utf-8,%23EXTM3U%0D%0A%0D%0A%23EXT-X-MEDIA%3ATYPE%3DAUDIO%2CGROUP-ID%3D%22bipbop_audio%22%2CLANGUAGE%3D%22eng%22%2CNAME%3D%22BipBop%20Audio%201%22%2CAUTOSELECT%3DYES%2CDEFAULT%3DYES%0D%0A%23EXT-X-MEDIA%3ATYPE%3DAUDIO%2CGROUP-ID%3D%22bipbop_audio%22%2CLANGUAGE%3D%22eng%22%2CNAME%3D%22BipBop%20Audio%202%22%2CAUTOSELECT%3DNO%2CDEFAULT%3DNO%2CURI%3D%22https%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Falternate_audio_aac_sinewave%2Fprog_index.m3u8%22%0D%0A%0D%0A%0D%0A%23EXT-X-MEDIA%3ATYPE%3DSUBTITLES%2CGROUP-ID%3D%22subs%22%2CNAME%3D%22English%22%2CDEFAULT%3DYES%2CAUTOSELECT%3DYES%2CFORCED%3DNO%2CLANGUAGE%3D%22en%22%2CCHARACTERISTICS%3D%22public.accessibility.transcribes-spoken-dialog%2C%20public.accessibility.describes-music-and-sound%22%2CURI%3D%22https%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fsubtitles%2Feng%2Fprog_index.m3u8%22%0D%0A%23EXT-X-MEDIA%3ATYPE%3DSUBTITLES%2CGROUP-ID%3D%22subs%22%2CNAME%3D%22English%20%28Forced%29%22%2CDEFAULT%3DNO%2CAUTOSELECT%3DNO%2CFORCED%3DYES%2CLANGUAGE%3D%22en%22%2CURI%3D%22https%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fsubtitles%2Feng_forced%2Fprog_index.m3u8%22%0D%0A%23EXT-X-MEDIA%3ATYPE%3DSUBTITLES%2CGROUP-ID%3D%22subs%22%2CNAME%3D%22Fran%C3%83%C2%A7ais%22%2CDEFAULT%3DNO%2CAUTOSELECT%3DYES%2CFORCED%3DNO%2CLANGUAGE%3D%22fr%22%2CCHARACTERISTICS%3D%22public.accessibility.transcribes-spoken-dialog%2C%20public.accessibility.describes-music-and-sound%22%2CURI%3D%22https%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fsubtitles%2Ffra%2Fprog_index.m3u8%22%0D%0A%23EXT-X-MEDIA%3ATYPE%3DSUBTITLES%2CGROUP-ID%3D%22subs%22%2CNAME%3D%22Fran%C3%83%C2%A7ais%20%28Forced%29%22%2CDEFAULT%3DNO%2CAUTOSELECT%3DNO%2CFORCED%3DYES%2CLANGUAGE%3D%22fr%22%2CURI%3D%22https%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fsubtitles%2Ffra_forced%2Fprog_index.m3u8%22%0D%0A%23EXT-X-MEDIA%3ATYPE%3DSUBTITLES%2CGROUP-ID%3D%22subs%22%2CNAME%3D%22Espa%C3%83%C2%B1ol%22%2CDEFAULT%3DNO%2CAUTOSELECT%3DYES%2CFORCED%3DNO%2CLANGUAGE%3D%22es%22%2CCHARACTERISTICS%3D%22public.accessibility.transcribes-spoken-dialog%2C%20public.accessibility.describes-music-and-sound%22%2CURI%3D%22https%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fsubtitles%2Fspa%2Fprog_index.m3u8%22%0D%0A%23EXT-X-MEDIA%3ATYPE%3DSUBTITLES%2CGROUP-ID%3D%22subs%22%2CNAME%3D%22Espa%C3%83%C2%B1ol%20%28Forced%29%22%2CDEFAULT%3DNO%2CAUTOSELECT%3DNO%2CFORCED%3DYES%2CLANGUAGE%3D%22es%22%2CURI%3D%22https%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fsubtitles%2Fspa_forced%2Fprog_index.m3u8%22%0D%0A%23EXT-X-MEDIA%3ATYPE%3DSUBTITLES%2CGROUP-ID%3D%22subs%22%2CNAME%3D%22%C3%A6%C2%97%C2%A5%C3%A6%C2%9C%C2%AC%C3%A8%C2%AA%C2%9E%22%2CDEFAULT%3DNO%2CAUTOSELECT%3DYES%2CFORCED%3DNO%2CLANGUAGE%3D%22ja%22%2CCHARACTERISTICS%3D%22public.accessibility.transcribes-spoken-dialog%2C%20public.accessibility.describes-music-and-sound%22%2CURI%3D%22https%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fsubtitles%2Fjpn%2Fprog_index.m3u8%22%0D%0A%23EXT-X-MEDIA%3ATYPE%3DSUBTITLES%2CGROUP-ID%3D%22subs%22%2CNAME%3D%22%C3%A6%C2%97%C2%A5%C3%A6%C2%9C%C2%AC%C3%A8%C2%AA%C2%9E%20%28Forced%29%22%2CDEFAULT%3DNO%2CAUTOSELECT%3DNO%2CFORCED%3DYES%2CLANGUAGE%3D%22ja%22%2CURI%3D%22https%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fsubtitles%2Fjpn_forced%2Fprog_index.m3u8%22%0D%0A%0D%0A%0D%0A%23EXT-X-STREAM-INF%3ABANDWIDTH%3D263851%2CCODECS%3D%22mp4a.40.2%2C%20avc1.4d400d%22%2CRESOLUTION%3D416x234%2CAUDIO%3D%22bipbop_audio%22%2CSUBTITLES%3D%22subs%22%0D%0Ahttps%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fgear1%2Fprog_index.m3u8%0D%0A%0D%0A%23EXT-X-STREAM-INF%3ABANDWIDTH%3D577610%2CCODECS%3D%22mp4a.40.2%2C%20avc1.4d401e%22%2CRESOLUTION%3D640x360%2CAUDIO%3D%22bipbop_audio%22%2CSUBTITLES%3D%22subs%22%0D%0Ahttps%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fgear2%2Fprog_index.m3u8%0D%0A%0D%0A%23EXT-X-STREAM-INF%3ABANDWIDTH%3D915905%2CCODECS%3D%22mp4a.40.2%2C%20avc1.4d401f%22%2CRESOLUTION%3D960x540%2CAUDIO%3D%22bipbop_audio%22%2CSUBTITLES%3D%22subs%22%0D%0Ahttps%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fgear3%2Fprog_index.m3u8%0D%0A%0D%0A%23EXT-X-STREAM-INF%3ABANDWIDTH%3D1030138%2CCODECS%3D%22mp4a.40.2%2C%20avc1.4d401f%22%2CRESOLUTION%3D1280x720%2CAUDIO%3D%22bipbop_audio%22%2CSUBTITLES%3D%22subs%22%0D%0Ahttps%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fgear4%2Fprog_index.m3u8%0D%0A%0D%0A%23EXT-X-STREAM-INF%3ABANDWIDTH%3D1924009%2CCODECS%3D%22mp4a.40.2%2C%20avc1.4d401f%22%2CRESOLUTION%3D1920x1080%2CAUDIO%3D%22bipbop_audio%22%2CSUBTITLES%3D%22subs%22%0D%0Ahttps%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fgear5%2Fprog_index.m3u8%0D%0A%0D%0A%23EXT-X-STREAM-INF%3ABANDWIDTH%3D41457%2CCODECS%3D%22mp4a.40.2%22%2CAUDIO%3D%22bipbop_audio%22%2CSUBTITLES%3D%22subs%22%0D%0Ahttps%3A%2F%2Fd2zihajmogu5jn.cloudfront.net%2Fbipbop-advanced%2Fgear0%2Fprog_index.m3u8'; -QUnit[testFn]('hls data uri', function(assert) { +QUnit.test('hls data uri', function(assert) { const done = assert.async(); const player = this.player; @@ -488,7 +481,7 @@ QUnit[testFn]('hls data uri', function(assert) { const dashDataUri = 'data:application/dash+xml;charset=utf-8,%3CMPD%20mediaPresentationDuration=%22PT634.566S%22%20minBufferTime=%22PT2.00S%22%20profiles=%22urn:hbbtv:dash:profile:isoff-live:2012,urn:mpeg:dash:profile:isoff-live:2011%22%20type=%22static%22%20xmlns=%22urn:mpeg:dash:schema:mpd:2011%22%20xmlns:xsi=%22http://www.w3.org/2001/XMLSchema-instance%22%20xsi:schemaLocation=%22urn:mpeg:DASH:schema:MPD:2011%20DASH-MPD.xsd%22%3E%20%3CBaseURL%3Ehttps://dash.akamaized.net/akamai/bbb_30fps/%3C/BaseURL%3E%20%3CPeriod%3E%20%20%3CAdaptationSet%20mimeType=%22video/mp4%22%20contentType=%22video%22%20subsegmentAlignment=%22true%22%20subsegmentStartsWithSAP=%221%22%20par=%2216:9%22%3E%20%20%20%3CSegmentTemplate%20duration=%22120%22%20timescale=%2230%22%20media=%22$RepresentationID$/$RepresentationID$_$Number$.m4v%22%20startNumber=%221%22%20initialization=%22$RepresentationID$/$RepresentationID$_0.m4v%22/%3E%20%20%20%3CRepresentation%20id=%22bbb_30fps_1024x576_2500k%22%20codecs=%22avc1.64001f%22%20bandwidth=%223134488%22%20width=%221024%22%20height=%22576%22%20frameRate=%2230%22%20sar=%221:1%22%20scanType=%22progressive%22/%3E%20%20%20%3CRepresentation%20id=%22bbb_30fps_1280x720_4000k%22%20codecs=%22avc1.64001f%22%20bandwidth=%224952892%22%20width=%221280%22%20height=%22720%22%20frameRate=%2230%22%20sar=%221:1%22%20scanType=%22progressive%22/%3E%20%20%20%3CRepresentation%20id=%22bbb_30fps_1920x1080_8000k%22%20codecs=%22avc1.640028%22%20bandwidth=%229914554%22%20width=%221920%22%20height=%221080%22%20frameRate=%2230%22%20sar=%221:1%22%20scanType=%22progressive%22/%3E%20%20%20%3CRepresentation%20id=%22bbb_30fps_320x180_200k%22%20codecs=%22avc1.64000d%22%20bandwidth=%22254320%22%20width=%22320%22%20height=%22180%22%20frameRate=%2230%22%20sar=%221:1%22%20scanType=%22progressive%22/%3E%20%20%20%3CRepresentation%20id=%22bbb_30fps_320x180_400k%22%20codecs=%22avc1.64000d%22%20bandwidth=%22507246%22%20width=%22320%22%20height=%22180%22%20frameRate=%2230%22%20sar=%221:1%22%20scanType=%22progressive%22/%3E%20%20%20%3CRepresentation%20id=%22bbb_30fps_480x270_600k%22%20codecs=%22avc1.640015%22%20bandwidth=%22759798%22%20width=%22480%22%20height=%22270%22%20frameRate=%2230%22%20sar=%221:1%22%20scanType=%22progressive%22/%3E%20%20%20%3CRepresentation%20id=%22bbb_30fps_640x360_1000k%22%20codecs=%22avc1.64001e%22%20bandwidth=%221254758%22%20width=%22640%22%20height=%22360%22%20frameRate=%2230%22%20sar=%221:1%22%20scanType=%22progressive%22/%3E%20%20%20%3CRepresentation%20id=%22bbb_30fps_640x360_800k%22%20codecs=%22avc1.64001e%22%20bandwidth=%221013310%22%20width=%22640%22%20height=%22360%22%20frameRate=%2230%22%20sar=%221:1%22%20scanType=%22progressive%22/%3E%20%20%20%3CRepresentation%20id=%22bbb_30fps_768x432_1500k%22%20codecs=%22avc1.64001e%22%20bandwidth=%221883700%22%20width=%22768%22%20height=%22432%22%20frameRate=%2230%22%20sar=%221:1%22%20scanType=%22progressive%22/%3E%20%20%20%3CRepresentation%20id=%22bbb_30fps_3840x2160_12000k%22%20codecs=%22avc1.640033%22%20bandwidth=%2214931538%22%20width=%223840%22%20height=%222160%22%20frameRate=%2230%22%20sar=%221:1%22%20scanType=%22progressive%22/%3E%20%20%3C/AdaptationSet%3E%20%20%3CAdaptationSet%20mimeType=%22audio/mp4%22%20contentType=%22audio%22%20subsegmentAlignment=%22true%22%20subsegmentStartsWithSAP=%221%22%3E%20%20%20%3CAccessibility%20schemeIdUri=%22urn:tva:metadata:cs:AudioPurposeCS:2007%22%20value=%226%22/%3E%20%20%20%3CRole%20schemeIdUri=%22urn:mpeg:dash:role:2011%22%20value=%22main%22/%3E%20%20%20%3CSegmentTemplate%20duration=%22192512%22%20timescale=%2248000%22%20media=%22$RepresentationID$/$RepresentationID$_$Number$.m4a%22%20startNumber=%221%22%20initialization=%22$RepresentationID$/$RepresentationID$_0.m4a%22/%3E%20%20%20%3CRepresentation%20id=%22bbb_a64k%22%20codecs=%22mp4a.40.5%22%20bandwidth=%2267071%22%20audioSamplingRate=%2248000%22%3E%20%20%20%20%3CAudioChannelConfiguration%20schemeIdUri=%22urn:mpeg:dash:23003:3:audio_channel_configuration:2011%22%20value=%222%22/%3E%20%20%20%3C/Representation%3E%20%20%3C/AdaptationSet%3E%20%3C/Period%3E%3C/MPD%3E'; -QUnit[testFn]('dash data uri', function(assert) { +QUnit.test('dash data uri', function(assert) { const done = assert.async(); const player = this.player; @@ -504,7 +497,7 @@ QUnit[testFn]('dash data uri', function(assert) { }); }); -QUnit[testFn]('dash manifest object', function(assert) { +QUnit.test('dash manifest object', function(assert) { const done = assert.async(); const player = this.player; @@ -519,7 +512,7 @@ QUnit[testFn]('dash manifest object', function(assert) { }); }); -QUnit[testFn]('hls manifest object', function(assert) { +QUnit.test('hls manifest object', function(assert) { const done = assert.async(); const player = this.player; diff --git a/test/playlist-controller.test.js b/test/playlist-controller.test.js index 3c563c1ef..33c45e974 100644 --- a/test/playlist-controller.test.js +++ b/test/playlist-controller.test.js @@ -59,10 +59,8 @@ const sharedHooks = { this.requests = this.env.requests; this.mse = useFakeMediaSource(); - if (!videojs.browser.IE_VERSION) { - this.oldDevicePixelRatio = window.devicePixelRatio; - window.devicePixelRatio = 1; - } + this.oldDevicePixelRatio = window.devicePixelRatio; + window.devicePixelRatio = 1; // force the HLS tech to run this.origSupportsNativeHls = videojs.Vhs.supportsNativeHls; @@ -638,7 +636,7 @@ QUnit.test('seeks in place for fast quality switch on non-IE/Edge browsers', fun seeks++; }); - let timeBeforeSwitch = this.player.currentTime(); + const timeBeforeSwitch = this.player.currentTime(); // mock buffered values so removes are processed segmentLoader.sourceUpdater_.audioBuffer.buffered = createTimeRanges([[0, 10]]); @@ -650,10 +648,6 @@ QUnit.test('seeks in place for fast quality switch on non-IE/Edge browsers', fun segmentLoader.sourceUpdater_.videoBuffer.trigger('updateend'); this.clock.tick(1); - // we seek an additional 0.04s on edge and ie - if (videojs.browser.IS_EDGE || videojs.browser.IE_VERSION) { - timeBeforeSwitch += 0.04; - } assert.equal( this.player.currentTime(), timeBeforeSwitch, @@ -836,120 +830,6 @@ QUnit.test('demuxed timeToLoadedData, mediaAppends, appendsToLoadedData stats', }); }); -QUnit.test('seeks forward 0.04 sec for fast quality switch on Edge', function(assert) { - const oldIEVersion = videojs.browser.IE_VERSION; - const oldIsEdge = videojs.browser.IS_EDGE; - let seeks = 0; - - this.playlistController.mediaSource.trigger('sourceopen'); - // main - this.standardXHRResponse(this.requests.shift()); - // media - this.standardXHRResponse(this.requests.shift()); - - const segmentLoader = this.playlistController.mainSegmentLoader_; - - return requestAndAppendSegment({ - request: this.requests.shift(), - segmentLoader, - clock: this.clock - }).then(() => { - // media is changed - this.playlistController.selectPlaylist = () => { - const playlists = this.playlistController.main().playlists; - const currentPlaylist = this.playlistController.media(); - - return playlists.find((playlist) => playlist !== currentPlaylist); - }; - - this.player.tech_.on('seeking', function() { - seeks++; - }); - - const timeBeforeSwitch = this.player.currentTime(); - - videojs.browser.IE_VERSION = null; - videojs.browser.IS_EDGE = true; - - // mock buffered values so removes are processed - segmentLoader.sourceUpdater_.audioBuffer.buffered = createTimeRanges([[0, 10]]); - segmentLoader.sourceUpdater_.videoBuffer.buffered = createTimeRanges([[0, 10]]); - - this.playlistController.fastQualityChange_(); - // trigger updateend to indicate the end of the remove operation - segmentLoader.sourceUpdater_.audioBuffer.trigger('updateend'); - segmentLoader.sourceUpdater_.videoBuffer.trigger('updateend'); - this.clock.tick(1); - - assert.equal( - this.player.currentTime(), - timeBeforeSwitch + 0.04, - 'seeks forward on fast quality switch' - ); - assert.equal(seeks, 1, 'seek event occurs on fast quality switch'); - - videojs.browser.IE_VERSION = oldIEVersion; - videojs.browser.IS_EDGE = oldIsEdge; - }); -}); - -QUnit.test('seeks forward 0.04 sec for fast quality switch on IE', function(assert) { - const oldIEVersion = videojs.browser.IE_VERSION; - const oldIsEdge = videojs.browser.IS_EDGE; - let seeks = 0; - - this.playlistController.mediaSource.trigger('sourceopen'); - // main - this.standardXHRResponse(this.requests.shift()); - // media - this.standardXHRResponse(this.requests.shift()); - - const segmentLoader = this.playlistController.mainSegmentLoader_; - - return requestAndAppendSegment({ - request: this.requests.shift(), - segmentLoader, - clock: this.clock - }).then(() => { - // media is changed - this.playlistController.selectPlaylist = () => { - const playlists = this.playlistController.main().playlists; - const currentPlaylist = this.playlistController.media(); - - return playlists.find((playlist) => playlist !== currentPlaylist); - }; - - this.player.tech_.on('seeking', function() { - seeks++; - }); - - const timeBeforeSwitch = this.player.currentTime(); - - videojs.browser.IE_VERSION = 11; - videojs.browser.IS_EDGE = false; - - // mock buffered values so removes are processed - segmentLoader.sourceUpdater_.audioBuffer.buffered = createTimeRanges([[0, 10]]); - segmentLoader.sourceUpdater_.videoBuffer.buffered = createTimeRanges([[0, 10]]); - - this.playlistController.fastQualityChange_(); - // trigger updateend to indicate the end of the remove operation - segmentLoader.sourceUpdater_.audioBuffer.trigger('updateend'); - segmentLoader.sourceUpdater_.videoBuffer.trigger('updateend'); - this.clock.tick(1); - - assert.equal( - this.player.currentTime(), - timeBeforeSwitch + 0.04, - 'seeks forward on fast quality switch' - ); - assert.equal(seeks, 1, 'seek event occurs on fast quality switch'); - - videojs.browser.IE_VERSION = oldIEVersion; - videojs.browser.IS_EDGE = oldIsEdge; - }); -}); - QUnit.test('audio segment loader is reset on audio track change', function(assert) { this.requests.length = 0; this.player.dispose(); diff --git a/test/playlist-loader.test.js b/test/playlist-loader.test.js index 96f67a801..c642db048 100644 --- a/test/playlist-loader.test.js +++ b/test/playlist-loader.test.js @@ -1,5 +1,4 @@ import QUnit from 'qunit'; -import videojs from 'video.js'; import { default as PlaylistLoader, updateSegments, @@ -2422,435 +2421,433 @@ QUnit.module('Playlist Loader', function(hooks) { assert.equal(this.requests.length, 1, 'playlist re-requested'); }); - if (!videojs.browser.IE_VERSION) { - QUnit.module('llhls', { - beforeEach() { - this.fakeVhs.options_ = {llhls: true}; - this.loader = new PlaylistLoader('http://example.com/media.m3u8', this.fakeVhs); + QUnit.module('llhls', { + beforeEach() { + this.fakeVhs.options_ = {llhls: true}; + this.loader = new PlaylistLoader('http://example.com/media.m3u8', this.fakeVhs); - this.loader.load(); - - }, - afterEach() { - this.loader.dispose(); - } - }); - - QUnit.test('#EXT-X-SKIP does not add initial empty segments', function(assert) { - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXT-X-SKIP:SKIPPED-SEGMENTS=10\n' + - '#EXTINF:2\n' + - 'low-1.ts\n' - ); - assert.equal(this.loader.media().segments.length, 1, 'only 1 segment'); - }); - - QUnit.test('#EXT-X-SKIP merges skipped segments', function(assert) { - let playlist = - '#EXTM3U\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n'; - - for (let i = 0; i < 10; i++) { - playlist += '#EXTINF:2\n'; - playlist += `segment-${i}.ts\n`; - } - - this.requests.shift().respond(200, null, playlist); - assert.equal(this.loader.media().segments.length, 10, '10 segments'); - - this.loader.trigger('mediaupdatetimeout'); - - const skippedPlaylist = - '#EXTM3U\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXT-X-SKIP:SKIPPED-SEGMENTS=10\n' + - '#EXTINF:2\n' + - 'segment-10.ts\n'; - - this.requests.shift().respond(200, null, skippedPlaylist); - - assert.equal(this.loader.media().segments.length, 11, '11 segments'); - - this.loader.media().segments.forEach(function(s, i) { - if (i < 10) { - assert.ok(s.hasOwnProperty('skipped'), 'has skipped property'); - assert.false(s.skipped, 'skipped property is false'); - } - - assert.equal(s.uri, `segment-${i}.ts`, 'segment uri as expected'); - }); - - this.loader.trigger('mediaupdatetimeout'); - - const skippedPlaylist2 = - '#EXTM3U\n' + - '#EXT-X-MEDIA-SEQUENCE:1\n' + - '#EXT-X-SKIP:SKIPPED-SEGMENTS=10\n' + - '#EXTINF:2\n' + - 'segment-11.ts\n'; - - this.requests.shift().respond(200, null, skippedPlaylist2); + this.loader.load(); - this.loader.media().segments.forEach(function(s, i) { - if (i < 10) { - assert.ok(s.hasOwnProperty('skipped'), 'has skipped property'); - assert.false(s.skipped, 'skipped property is false'); - } + }, + afterEach() { + this.loader.dispose(); + } + }); - assert.equal(s.uri, `segment-${i + 1}.ts`, 'segment uri as expected'); - }); - }); + QUnit.test('#EXT-X-SKIP does not add initial empty segments', function(assert) { + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXT-X-SKIP:SKIPPED-SEGMENTS=10\n' + + '#EXTINF:2\n' + + 'low-1.ts\n' + ); + assert.equal(this.loader.media().segments.length, 1, 'only 1 segment'); + }); - QUnit.test('#EXT-X-PRELOAD with parts to added to segment list', function(assert) { - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-PART-INF:PART-TARGET=1\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXTINF:2\n' + - 'low-1.ts\n' + - '#EXT-X-PART:URI="part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="part2.ts",DURATION=1\n' - ); - const media = this.loader.media(); + QUnit.test('#EXT-X-SKIP merges skipped segments', function(assert) { + let playlist = + '#EXTM3U\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n'; - assert.equal(media.segments.length, 2, '2 segments'); - assert.deepEqual( - media.preloadSegment, - media.segments[media.segments.length - 1], - 'last segment is preloadSegment' - ); - }); + for (let i = 0; i < 10; i++) { + playlist += '#EXTINF:2\n'; + playlist += `segment-${i}.ts\n`; + } - QUnit.test('#EXT-X-PRELOAD without parts not added to segment list', function(assert) { - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-PART-INF:PART-TARGET=1\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXTINF:2\n' + - 'low-1.ts\n' + - '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="part1.ts"\n' - ); - const media = this.loader.media(); + this.requests.shift().respond(200, null, playlist); + assert.equal(this.loader.media().segments.length, 10, '10 segments'); - assert.equal(media.segments.length, 1, '1 segment'); - assert.notDeepEqual( - media.preloadSegment, - media.segments[media.segments.length - 1], - 'last segment is not preloadSegment' - ); - }); + this.loader.trigger('mediaupdatetimeout'); - QUnit.test('#EXT-X-PART added to segments', function(assert) { - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-PART-INF:PART-TARGET=1\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXTINF:2\n' + - 'segment0.ts\n' + - '#EXT-X-PART:URI="segment1-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment1-part2.ts",DURATION=1\n' + - 'segment1.ts\n' + - '#EXT-X-PART:URI="segment2-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment2-part2.ts",DURATION=1\n' + - 'segment2.ts\n' + - '#EXT-X-PART:URI="segment3-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment3-part2.ts",DURATION=1\n' + - 'segment3.ts\n' - ); - const segments = this.loader.media().segments; + const skippedPlaylist = + '#EXTM3U\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXT-X-SKIP:SKIPPED-SEGMENTS=10\n' + + '#EXTINF:2\n' + + 'segment-10.ts\n'; - assert.equal(segments.length, 4, '4 segments'); - assert.notOk(segments[0].parts, 'no parts for first segment'); - assert.equal(segments[1].parts.length, 2, 'parts for second segment'); - assert.equal(segments[2].parts.length, 2, 'parts for third segment'); - assert.equal(segments[3].parts.length, 2, 'parts for forth segment'); - }); + this.requests.shift().respond(200, null, skippedPlaylist); - QUnit.test('Adds _HLS_skip=YES to url when CAN-SKIP-UNTIL is set', function(assert) { - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-PART-INF:PART-TARGET=1\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXT-X-SERVER-CONTROL:CAN-SKIP-UNTIL=3\n' + - '#EXTINF:2\n' + - 'segment0.ts\n' + - '#EXTINF:2\n' + - 'segment1.ts\n' + - '#EXTINF:2\n' + - 'segment2.ts\n' + - '#EXTINF:2\n' + - 'segment3.ts\n' + - '#EXTINF:2\n' + - 'segment4.ts\n' + - '#EXTINF:2\n' + - 'segment5.ts\n' + - '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + - 'segment6.ts\n' + - '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + - 'segment7.ts\n' + - '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment8-part2.ts",DURATION=1\n' + - 'segment8.ts\n' - ); + assert.equal(this.loader.media().segments.length, 11, '11 segments'); - this.loader.trigger('mediaupdatetimeout'); + this.loader.media().segments.forEach(function(s, i) { + if (i < 10) { + assert.ok(s.hasOwnProperty('skipped'), 'has skipped property'); + assert.false(s.skipped, 'skipped property is false'); + } - assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_skip=YES'); + assert.equal(s.uri, `segment-${i}.ts`, 'segment uri as expected'); }); - QUnit.test('Adds _HLS_skip=v2 to url when CAN-SKIP-UNTIL/CAN-SKIP-DATERANGES is set', function(assert) { - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-PART-INF:PART-TARGET=1\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXT-X-SERVER-CONTROL:CAN-SKIP-UNTIL=3,CAN-SKIP-DATERANGES=YES\n' + - '#EXTINF:2\n' + - 'segment0.ts\n' + - '#EXTINF:2\n' + - 'segment1.ts\n' + - '#EXTINF:2\n' + - 'segment2.ts\n' + - '#EXTINF:2\n' + - 'segment3.ts\n' + - '#EXTINF:2\n' + - 'segment4.ts\n' + - '#EXTINF:2\n' + - 'segment5.ts\n' + - '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + - 'segment6.ts\n' + - '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + - 'segment7.ts\n' + - '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment8-part2.ts",DURATION=1\n' + - 'segment8.ts\n' - ); - - this.loader.trigger('mediaupdatetimeout'); + this.loader.trigger('mediaupdatetimeout'); - assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_skip=v2'); - }); + const skippedPlaylist2 = + '#EXTM3U\n' + + '#EXT-X-MEDIA-SEQUENCE:1\n' + + '#EXT-X-SKIP:SKIPPED-SEGMENTS=10\n' + + '#EXTINF:2\n' + + 'segment-11.ts\n'; - QUnit.test('Adds _HLS_part= and _HLS_msn= when we have a part preload hints and parts', function(assert) { - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-PART-INF:PART-TARGET=1\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES\n' + - '#EXTINF:2\n' + - 'segment0.ts\n' + - '#EXTINF:2\n' + - 'segment1.ts\n' + - '#EXTINF:2\n' + - 'segment2.ts\n' + - '#EXTINF:2\n' + - 'segment3.ts\n' + - '#EXTINF:2\n' + - 'segment4.ts\n' + - '#EXTINF:2\n' + - 'segment5.ts\n' + - '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + - 'segment6.ts\n' + - '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + - 'segment7.ts\n' + - '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + - '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="segment8-part2.ts"\n' - ); + this.requests.shift().respond(200, null, skippedPlaylist2); - this.loader.trigger('mediaupdatetimeout'); + this.loader.media().segments.forEach(function(s, i) { + if (i < 10) { + assert.ok(s.hasOwnProperty('skipped'), 'has skipped property'); + assert.false(s.skipped, 'skipped property is false'); + } - assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_msn=8&_HLS_part=1'); + assert.equal(s.uri, `segment-${i + 1}.ts`, 'segment uri as expected'); }); + }); - QUnit.test('Adds _HLS_part= and _HLS_msn= when we have only a part preload hint', function(assert) { - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-PART-INF:PART-TARGET=1\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES\n' + - '#EXTINF:2\n' + - 'segment0.ts\n' + - '#EXTINF:2\n' + - 'segment1.ts\n' + - '#EXTINF:2\n' + - 'segment2.ts\n' + - '#EXTINF:2\n' + - 'segment3.ts\n' + - '#EXTINF:2\n' + - 'segment4.ts\n' + - '#EXTINF:2\n' + - 'segment5.ts\n' + - '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + - 'segment6.ts\n' + - '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + - 'segment7.ts\n' + - '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="segment8-part1.ts"\n' - ); - - this.loader.trigger('mediaupdatetimeout'); - - assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_msn=7&_HLS_part=0'); - }); + QUnit.test('#EXT-X-PRELOAD with parts to added to segment list', function(assert) { + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-PART-INF:PART-TARGET=1\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXTINF:2\n' + + 'low-1.ts\n' + + '#EXT-X-PART:URI="part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="part2.ts",DURATION=1\n' + ); + const media = this.loader.media(); - QUnit.test('does not add _HLS_part= when we have only a preload parts without preload hints', function(assert) { - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-PART-INF:PART-TARGET=1\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES\n' + - '#EXTINF:2\n' + - 'segment0.ts\n' + - '#EXTINF:2\n' + - 'segment1.ts\n' + - '#EXTINF:2\n' + - 'segment2.ts\n' + - '#EXTINF:2\n' + - 'segment3.ts\n' + - '#EXTINF:2\n' + - 'segment4.ts\n' + - '#EXTINF:2\n' + - 'segment5.ts\n' + - '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + - 'segment6.ts\n' + - '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + - 'segment7.ts\n' + - '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' - ); + assert.equal(media.segments.length, 2, '2 segments'); + assert.deepEqual( + media.preloadSegment, + media.segments[media.segments.length - 1], + 'last segment is preloadSegment' + ); + }); - this.loader.trigger('mediaupdatetimeout'); + QUnit.test('#EXT-X-PRELOAD without parts not added to segment list', function(assert) { + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-PART-INF:PART-TARGET=1\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXTINF:2\n' + + 'low-1.ts\n' + + '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="part1.ts"\n' + ); + const media = this.loader.media(); - assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_msn=8'); - }); + assert.equal(media.segments.length, 1, '1 segment'); + assert.notDeepEqual( + media.preloadSegment, + media.segments[media.segments.length - 1], + 'last segment is not preloadSegment' + ); + }); - QUnit.test('Adds only _HLS_msn= when we have segment info', function(assert) { - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-PART-INF:PART-TARGET=1\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES\n' + - '#EXTINF:2\n' + - 'segment0.ts\n' + - '#EXTINF:2\n' + - 'segment1.ts\n' + - '#EXTINF:2\n' + - 'segment2.ts\n' + - '#EXTINF:2\n' + - 'segment3.ts\n' + - '#EXTINF:2\n' + - 'segment4.ts\n' + - '#EXTINF:2\n' + - 'segment5.ts\n' + - '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + - 'segment6.ts\n' + - '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + - 'segment7.ts\n' + - '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment8-part2.ts",DURATION=1\n' + - 'segment8.ts\n' - ); + QUnit.test('#EXT-X-PART added to segments', function(assert) { + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-PART-INF:PART-TARGET=1\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXTINF:2\n' + + 'segment0.ts\n' + + '#EXT-X-PART:URI="segment1-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment1-part2.ts",DURATION=1\n' + + 'segment1.ts\n' + + '#EXT-X-PART:URI="segment2-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment2-part2.ts",DURATION=1\n' + + 'segment2.ts\n' + + '#EXT-X-PART:URI="segment3-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment3-part2.ts",DURATION=1\n' + + 'segment3.ts\n' + ); + const segments = this.loader.media().segments; + + assert.equal(segments.length, 4, '4 segments'); + assert.notOk(segments[0].parts, 'no parts for first segment'); + assert.equal(segments[1].parts.length, 2, 'parts for second segment'); + assert.equal(segments[2].parts.length, 2, 'parts for third segment'); + assert.equal(segments[3].parts.length, 2, 'parts for forth segment'); + }); - this.loader.trigger('mediaupdatetimeout'); + QUnit.test('Adds _HLS_skip=YES to url when CAN-SKIP-UNTIL is set', function(assert) { + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-PART-INF:PART-TARGET=1\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXT-X-SERVER-CONTROL:CAN-SKIP-UNTIL=3\n' + + '#EXTINF:2\n' + + 'segment0.ts\n' + + '#EXTINF:2\n' + + 'segment1.ts\n' + + '#EXTINF:2\n' + + 'segment2.ts\n' + + '#EXTINF:2\n' + + 'segment3.ts\n' + + '#EXTINF:2\n' + + 'segment4.ts\n' + + '#EXTINF:2\n' + + 'segment5.ts\n' + + '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + + 'segment6.ts\n' + + '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + + 'segment7.ts\n' + + '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment8-part2.ts",DURATION=1\n' + + 'segment8.ts\n' + ); + + this.loader.trigger('mediaupdatetimeout'); + + assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_skip=YES'); + }); - assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_msn=9'); - }); + QUnit.test('Adds _HLS_skip=v2 to url when CAN-SKIP-UNTIL/CAN-SKIP-DATERANGES is set', function(assert) { + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-PART-INF:PART-TARGET=1\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXT-X-SERVER-CONTROL:CAN-SKIP-UNTIL=3,CAN-SKIP-DATERANGES=YES\n' + + '#EXTINF:2\n' + + 'segment0.ts\n' + + '#EXTINF:2\n' + + 'segment1.ts\n' + + '#EXTINF:2\n' + + 'segment2.ts\n' + + '#EXTINF:2\n' + + 'segment3.ts\n' + + '#EXTINF:2\n' + + 'segment4.ts\n' + + '#EXTINF:2\n' + + 'segment5.ts\n' + + '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + + 'segment6.ts\n' + + '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + + 'segment7.ts\n' + + '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment8-part2.ts",DURATION=1\n' + + 'segment8.ts\n' + ); + + this.loader.trigger('mediaupdatetimeout'); + + assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_skip=v2'); + }); - QUnit.test('can add all query directives', function(assert) { - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-PART-INF:PART-TARGET=1\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,CAN-SKIP-UNTIL=3\n' + - '#EXTINF:2\n' + - 'segment0.ts\n' + - '#EXTINF:2\n' + - 'segment1.ts\n' + - '#EXTINF:2\n' + - 'segment2.ts\n' + - '#EXTINF:2\n' + - 'segment3.ts\n' + - '#EXTINF:2\n' + - 'segment4.ts\n' + - '#EXTINF:2\n' + - 'segment5.ts\n' + - '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + - 'segment6.ts\n' + - '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + - 'segment7.ts\n' + - '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + - '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="segment8-part2.ts"\n' - ); + QUnit.test('Adds _HLS_part= and _HLS_msn= when we have a part preload hints and parts', function(assert) { + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-PART-INF:PART-TARGET=1\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES\n' + + '#EXTINF:2\n' + + 'segment0.ts\n' + + '#EXTINF:2\n' + + 'segment1.ts\n' + + '#EXTINF:2\n' + + 'segment2.ts\n' + + '#EXTINF:2\n' + + 'segment3.ts\n' + + '#EXTINF:2\n' + + 'segment4.ts\n' + + '#EXTINF:2\n' + + 'segment5.ts\n' + + '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + + 'segment6.ts\n' + + '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + + 'segment7.ts\n' + + '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + + '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="segment8-part2.ts"\n' + ); + + this.loader.trigger('mediaupdatetimeout'); + + assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_msn=8&_HLS_part=1'); + }); - this.loader.trigger('mediaupdatetimeout'); + QUnit.test('Adds _HLS_part= and _HLS_msn= when we have only a part preload hint', function(assert) { + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-PART-INF:PART-TARGET=1\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES\n' + + '#EXTINF:2\n' + + 'segment0.ts\n' + + '#EXTINF:2\n' + + 'segment1.ts\n' + + '#EXTINF:2\n' + + 'segment2.ts\n' + + '#EXTINF:2\n' + + 'segment3.ts\n' + + '#EXTINF:2\n' + + 'segment4.ts\n' + + '#EXTINF:2\n' + + 'segment5.ts\n' + + '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + + 'segment6.ts\n' + + '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + + 'segment7.ts\n' + + '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="segment8-part1.ts"\n' + ); + + this.loader.trigger('mediaupdatetimeout'); + + assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_msn=7&_HLS_part=0'); + }); - assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_skip=YES&_HLS_msn=8&_HLS_part=1'); - }); + QUnit.test('does not add _HLS_part= when we have only a preload parts without preload hints', function(assert) { + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-PART-INF:PART-TARGET=1\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES\n' + + '#EXTINF:2\n' + + 'segment0.ts\n' + + '#EXTINF:2\n' + + 'segment1.ts\n' + + '#EXTINF:2\n' + + 'segment2.ts\n' + + '#EXTINF:2\n' + + 'segment3.ts\n' + + '#EXTINF:2\n' + + 'segment4.ts\n' + + '#EXTINF:2\n' + + 'segment5.ts\n' + + '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + + 'segment6.ts\n' + + '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + + 'segment7.ts\n' + + '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + ); + + this.loader.trigger('mediaupdatetimeout'); + + assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_msn=8'); + }); - QUnit.test('works with existing query directives', function(assert) { - // clear existing requests - this.requests.length = 0; + QUnit.test('Adds only _HLS_msn= when we have segment info', function(assert) { + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-PART-INF:PART-TARGET=1\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES\n' + + '#EXTINF:2\n' + + 'segment0.ts\n' + + '#EXTINF:2\n' + + 'segment1.ts\n' + + '#EXTINF:2\n' + + 'segment2.ts\n' + + '#EXTINF:2\n' + + 'segment3.ts\n' + + '#EXTINF:2\n' + + 'segment4.ts\n' + + '#EXTINF:2\n' + + 'segment5.ts\n' + + '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + + 'segment6.ts\n' + + '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + + 'segment7.ts\n' + + '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment8-part2.ts",DURATION=1\n' + + 'segment8.ts\n' + ); + + this.loader.trigger('mediaupdatetimeout'); + + assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_msn=9'); + }); - this.loader.dispose(); - this.loader = new PlaylistLoader('http://example.com/media.m3u8?foo=test', this.fakeVhs); + QUnit.test('can add all query directives', function(assert) { + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-PART-INF:PART-TARGET=1\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,CAN-SKIP-UNTIL=3\n' + + '#EXTINF:2\n' + + 'segment0.ts\n' + + '#EXTINF:2\n' + + 'segment1.ts\n' + + '#EXTINF:2\n' + + 'segment2.ts\n' + + '#EXTINF:2\n' + + 'segment3.ts\n' + + '#EXTINF:2\n' + + 'segment4.ts\n' + + '#EXTINF:2\n' + + 'segment5.ts\n' + + '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + + 'segment6.ts\n' + + '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + + 'segment7.ts\n' + + '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + + '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="segment8-part2.ts"\n' + ); + + this.loader.trigger('mediaupdatetimeout'); + + assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?_HLS_skip=YES&_HLS_msn=8&_HLS_part=1'); + }); - this.loader.load(); + QUnit.test('works with existing query directives', function(assert) { + // clear existing requests + this.requests.length = 0; - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-PART-INF:PART-TARGET=1\n' + - '#EXT-X-MEDIA-SEQUENCE:0\n' + - '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,CAN-SKIP-UNTIL=3\n' + - '#EXTINF:2\n' + - 'segment0.ts\n' + - '#EXTINF:2\n' + - 'segment1.ts\n' + - '#EXTINF:2\n' + - 'segment2.ts\n' + - '#EXTINF:2\n' + - 'segment3.ts\n' + - '#EXTINF:2\n' + - 'segment4.ts\n' + - '#EXTINF:2\n' + - 'segment5.ts\n' + - '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + - 'segment6.ts\n' + - '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + - 'segment7.ts\n' + - '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + - '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="segment8-part2.ts"\n' - ); + this.loader.dispose(); + this.loader = new PlaylistLoader('http://example.com/media.m3u8?foo=test', this.fakeVhs); - this.loader.trigger('mediaupdatetimeout'); + this.loader.load(); - assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?foo=test&_HLS_skip=YES&_HLS_msn=8&_HLS_part=1'); - }); - } + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-PART-INF:PART-TARGET=1\n' + + '#EXT-X-MEDIA-SEQUENCE:0\n' + + '#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,CAN-SKIP-UNTIL=3\n' + + '#EXTINF:2\n' + + 'segment0.ts\n' + + '#EXTINF:2\n' + + 'segment1.ts\n' + + '#EXTINF:2\n' + + 'segment2.ts\n' + + '#EXTINF:2\n' + + 'segment3.ts\n' + + '#EXTINF:2\n' + + 'segment4.ts\n' + + '#EXTINF:2\n' + + 'segment5.ts\n' + + '#EXT-X-PART:URI="segment6-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment6-part2.ts",DURATION=1\n' + + 'segment6.ts\n' + + '#EXT-X-PART:URI="segment7-part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="segment7-part2.ts",DURATION=1\n' + + 'segment7.ts\n' + + '#EXT-X-PART:URI="segment8-part1.ts",DURATION=1\n' + + '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="segment8-part2.ts"\n' + ); + + this.loader.trigger('mediaupdatetimeout'); + + assert.equal(this.requests[0].uri, 'http://example.com/media.m3u8?foo=test&_HLS_skip=YES&_HLS_msn=8&_HLS_part=1'); + }); }); diff --git a/test/playlist.test.js b/test/playlist.test.js index 9e6f2c6d6..a02c4f9cd 100644 --- a/test/playlist.test.js +++ b/test/playlist.test.js @@ -2,7 +2,6 @@ import Playlist from '../src/playlist'; import PlaylistLoader from '../src/playlist-loader'; import QUnit from 'qunit'; import xhrFactory from '../src/xhr'; -import videojs from 'video.js'; import { useFakeEnvironment } from './test-helpers'; // needed for plugin registration import '../src/videojs-http-streaming'; @@ -1463,56 +1462,54 @@ QUnit.module('Playlist', function() { } ); - if (!videojs.browser.IE_VERSION) { - QUnit.test('can return a partIndex', function(assert) { - this.fakeVhs.options_ = {llhls: true}; - const loader = new PlaylistLoader('media.m3u8', this.fakeVhs); + QUnit.test('can return a partIndex', function(assert) { + this.fakeVhs.options_ = {llhls: true}; + const loader = new PlaylistLoader('media.m3u8', this.fakeVhs); - loader.load(); + loader.load(); - this.requests.shift().respond( - 200, null, - '#EXTM3U\n' + - '#EXT-X-MEDIA-SEQUENCE:1001\n' + - '#EXTINF:4,\n' + - '1001.ts\n' + - '#EXTINF:5,\n' + - '1002.ts\n' + - '#EXT-X-PART:URI="1003.part1.ts",DURATION=1\n' + - '#EXT-X-PART:URI="1003.part2.ts",DURATION=1\n' + - '#EXT-X-PART:URI="1003.part3.ts",DURATION=1\n' + - '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="1003.part4.ts"\n' - ); + this.requests.shift().respond( + 200, null, + '#EXTM3U\n' + + '#EXT-X-MEDIA-SEQUENCE:1001\n' + + '#EXTINF:4,\n' + + '1001.ts\n' + + '#EXTINF:5,\n' + + '1002.ts\n' + + '#EXT-X-PART:URI="1003.part1.ts",DURATION=1\n' + + '#EXT-X-PART:URI="1003.part2.ts",DURATION=1\n' + + '#EXT-X-PART:URI="1003.part3.ts",DURATION=1\n' + + '#EXT-X-PRELOAD-HINT:TYPE="PART",URI="1003.part4.ts"\n' + ); - const media = loader.media(); + const media = loader.media(); - this.defaults = { - playlist: media, - currentTime: 0, - startingSegmentIndex: 0, - startingPartIndex: null, - startTime: 0 - }; + this.defaults = { + playlist: media, + currentTime: 0, + startingSegmentIndex: 0, + startingPartIndex: null, + startTime: 0 + }; - assert.deepEqual( - this.getMediaInfoForTime({currentTime: 10, startTime: 0}), - {segmentIndex: 2, startTime: 9, partIndex: 0}, - 'returns expected part/segment' - ); + assert.deepEqual( + this.getMediaInfoForTime({currentTime: 10, startTime: 0}), + {segmentIndex: 2, startTime: 9, partIndex: 0}, + 'returns expected part/segment' + ); - assert.deepEqual( - this.getMediaInfoForTime({currentTime: 11, startTime: 0}), - {segmentIndex: 2, startTime: 10, partIndex: 1}, - 'returns expected part/segment' - ); + assert.deepEqual( + this.getMediaInfoForTime({currentTime: 11, startTime: 0}), + {segmentIndex: 2, startTime: 10, partIndex: 1}, + 'returns expected part/segment' + ); - assert.deepEqual( - this.getMediaInfoForTime({currentTime: 11, segmentIndex: -15}), - {segmentIndex: 2, startTime: 10, partIndex: 1}, - 'returns expected part/segment' - ); - }); - } + assert.deepEqual( + this.getMediaInfoForTime({currentTime: 11, segmentIndex: -15}), + {segmentIndex: 2, startTime: 10, partIndex: 1}, + 'returns expected part/segment' + ); + }); QUnit.test('liveEdgeDelay works as expected', function(assert) { const media = { diff --git a/test/sanity.test.js b/test/sanity.test.js index 0f8e29c18..d45cb98e8 100644 --- a/test/sanity.test.js +++ b/test/sanity.test.js @@ -11,11 +11,7 @@ QUnit.test('the environment is sane', function(assert) { assert.strictEqual(typeof sinon, 'object', 'sinon exists'); assert.strictEqual(typeof videojs, 'function', 'videojs exists'); assert.strictEqual(typeof window.MediaSource, 'function', 'MediaSource is a function'); - if (videojs.browser.IE_VERSION) { - assert.strictEqual(typeof window.URL, 'object', 'URL is an object'); - } else { - assert.strictEqual(typeof window.URL, 'function', 'URL is a function'); - } + assert.strictEqual(typeof window.URL, 'function', 'URL is a function'); assert.strictEqual(typeof videojs.Vhs, 'object', 'Vhs is an object'); assert.strictEqual( typeof videojs.VhsSourceHandler, diff --git a/test/source-updater.test.js b/test/source-updater.test.js index d3c042328..4ca5d57f2 100644 --- a/test/source-updater.test.js +++ b/test/source-updater.test.js @@ -9,21 +9,9 @@ import { QUOTA_EXCEEDED_ERR } from '../src/error-codes'; import {createTimeRanges} from '../src/util/vjs-compat'; const checkInitialDuration = function({duration}) { - // ie sometimes sets duration to infinity earlier then expected - if (videojs.browser.IS_EDGE || videojs.browser.IE_VERSION) { - QUnit.assert.ok(Number.isNaN(duration) || !Number.isFinite(duration), 'starting duration as expected'); - } else { - QUnit.assert.ok(Number.isNaN(duration), 'starting duration as expected'); - } + QUnit.assert.ok(Number.isNaN(duration), 'starting duration as expected'); }; -let testOrSkip = 'test'; - -// some tests just don't work reliably on ie11 or edge -if (videojs.browser.IS_EDGE || videojs.browser.IE_VERSION) { - testOrSkip = 'skip'; -} - const concatSegments = (...segments) => { let byteLength = segments.reduce((acc, cv) => { acc += cv.byteLength; @@ -962,7 +950,7 @@ QUnit.test( } ); -QUnit[testOrSkip]('setDuration waits for audio buffer to finish updating', function(assert) { +QUnit.test('setDuration waits for audio buffer to finish updating', function(assert) { const done = assert.async(); assert.expect(5); @@ -1013,50 +1001,48 @@ QUnit.test('setDuration waits for video buffer to finish updating', function(ass assert.ok(this.sourceUpdater.updating(), 'updating during appends'); }); -if (!videojs.browser.IS_EDGE) { - QUnit.test( - 'setDuration waits for both audio and video buffers to finish updating', - function(assert) { - const done = assert.async(); - let appendsFinished = 0; +QUnit.test( + 'setDuration waits for both audio and video buffers to finish updating', + function(assert) { + const done = assert.async(); + let appendsFinished = 0; - assert.expect(7); + assert.expect(7); - this.sourceUpdater.createSourceBuffers({ - audio: 'mp4a.40.2', - video: 'avc1.4D001E' - }); + this.sourceUpdater.createSourceBuffers({ + audio: 'mp4a.40.2', + video: 'avc1.4D001E' + }); - assert.notOk(this.sourceUpdater.updating(), 'not updating by default'); + assert.notOk(this.sourceUpdater.updating(), 'not updating by default'); - const checkDuration = () => { - // duration is set to infinity if content is appended before an explicit duration is - // set https://w3c.github.io/media-source/#sourcebuffer-init-segment-received - assert.equal(this.mediaSource.duration, Infinity, 'duration not set on media source'); + const checkDuration = () => { + // duration is set to infinity if content is appended before an explicit duration is + // set https://w3c.github.io/media-source/#sourcebuffer-init-segment-received + assert.equal(this.mediaSource.duration, Infinity, 'duration not set on media source'); - if (appendsFinished === 0) { - // try to set the duration while one of the buffers is still updating, this should - // happen after the other setDuration call - this.sourceUpdater.setDuration(12, () => { - assert.equal(this.mediaSource.duration, 12, 'set duration on media source'); - done(); - }); - } + if (appendsFinished === 0) { + // try to set the duration while one of the buffers is still updating, this should + // happen after the other setDuration call + this.sourceUpdater.setDuration(12, () => { + assert.equal(this.mediaSource.duration, 12, 'set duration on media source'); + done(); + }); + } - appendsFinished++; - }; + appendsFinished++; + }; - this.sourceUpdater.appendBuffer({type: 'video', bytes: mp4VideoTotal()}, checkDuration); - this.sourceUpdater.appendBuffer({type: 'audio', bytes: mp4AudioTotal()}, checkDuration); - this.sourceUpdater.setDuration(11, () => { - assert.equal(this.mediaSource.duration, 11, 'set duration on media source'); - }); + this.sourceUpdater.appendBuffer({type: 'video', bytes: mp4VideoTotal()}, checkDuration); + this.sourceUpdater.appendBuffer({type: 'audio', bytes: mp4AudioTotal()}, checkDuration); + this.sourceUpdater.setDuration(11, () => { + assert.equal(this.mediaSource.duration, 11, 'set duration on media source'); + }); - checkInitialDuration(this.mediaSource); - assert.ok(this.sourceUpdater.updating(), 'updating during appends'); - } - ); -} + checkInitialDuration(this.mediaSource); + assert.ok(this.sourceUpdater.updating(), 'updating during appends'); + } +); QUnit.test( 'setDuration blocks audio and video queue entries until it finishes', @@ -1318,7 +1304,7 @@ QUnit.test('dispose removes sourceopen listener', function(assert) { }); }); -QUnit[testOrSkip]('audio appends are delayed until video append for the first append', function(assert) { +QUnit.test('audio appends are delayed until video append for the first append', function(assert) { const done = assert.async(); let audioAppend = false; let videoAppend = false; diff --git a/test/videojs-http-streaming.test.js b/test/videojs-http-streaming.test.js index 5c06bb993..13cf4e8a5 100644 --- a/test/videojs-http-streaming.test.js +++ b/test/videojs-http-streaming.test.js @@ -53,13 +53,6 @@ import {version as mpdVersion} from 'mpd-parser/package.json'; import {version as m3u8Version} from 'm3u8-parser/package.json'; import {version as aesVersion} from 'aes-decrypter/package.json'; -let testOrSkip = 'test'; - -// some tests just don't work reliably on ie11 or edge -if (videojs.browser.IS_EDGE || videojs.browser.IE_VERSION) { - testOrSkip = 'skip'; -} - const ogVhsHandlerSetupQualityLevels = videojs.VhsHandler.prototype.setupQualityLevels_; // do a shallow copy of the properties of source onto the target object @@ -78,10 +71,9 @@ QUnit.module('VHS', { this.mse = useFakeMediaSource(); this.clock = this.env.clock; this.old = {}; - if (!videojs.browser.IE_VERSION) { - this.old.devicePixelRatio = window.devicePixelRatio; - window.devicePixelRatio = 1; - } + this.old.devicePixelRatio = window.devicePixelRatio; + window.devicePixelRatio = 1; + // store functionality that some tests need to mock this.old.GlobalOptions = merge(videojs.options); @@ -404,37 +396,6 @@ QUnit.test('autoplay seeks to the live point after media source open', function( assert.notEqual(currentTime, 0, 'seeked on autoplay'); }); -QUnit.test( - 'autoplay seeks to the live point after tech fires loadedmetadata in ie11', - function(assert) { - videojs.browser.IE_VERSION = 11; - let currentTime = 0; - - this.player.autoplay(true); - this.player.on('seeking', () => { - currentTime = this.player.currentTime(); - }); - this.player.src({ - src: 'liveStart30sBefore.m3u8', - type: 'application/vnd.apple.mpegurl' - }); - - this.clock.tick(1); - - openMediaSource(this.player, this.clock); - this.player.tech_.trigger('play'); - this.standardXHRResponse(this.requests.shift()); - this.clock.tick(1); - - assert.equal(currentTime, 0, 'have not played yet'); - - this.player.tech_.trigger('loadedmetadata'); - this.clock.tick(1); - - assert.notEqual(currentTime, 0, 'seeked after tech is ready'); - } -); - QUnit.test( 'duration is set when the source opens after the playlist is loaded', function(assert) { @@ -950,7 +911,7 @@ QUnit.module('NetworkInformationApi', hooks => { window.navigator = this.ogNavigator; }); - QUnit[testOrSkip]( + QUnit.test( 'bandwidth returns networkInformation.downlink when useNetworkInformationApi option is enabled', function(assert) { this.resetNavigatorConnection({ @@ -973,7 +934,7 @@ QUnit.module('NetworkInformationApi', hooks => { } ); - QUnit[testOrSkip]( + QUnit.test( 'bandwidth uses player-estimated bandwidth when its value is greater than networkInformation.downLink and both values are >= 10 Mbps', function(assert) { this.resetNavigatorConnection({ @@ -997,7 +958,7 @@ QUnit.module('NetworkInformationApi', hooks => { } ); - QUnit[testOrSkip]( + QUnit.test( 'bandwidth uses network-information-api bandwidth when its value is less than the player bandwidth and 10 Mbps', function(assert) { this.resetNavigatorConnection({ @@ -1021,7 +982,7 @@ QUnit.module('NetworkInformationApi', hooks => { } ); - QUnit[testOrSkip]( + QUnit.test( 'bandwidth uses player-estimated bandwidth when networkInformation is not supported', function(assert) { // Nullify the `connection` property on Navigator @@ -4447,21 +4408,11 @@ QUnit.test('eme waitingforkey event triggers another setup', function(assert) { vhs.playlistController_.sourceUpdater_.trigger('createdsourcebuffers'); - // Since IE11 doesn't initialize media keys early, in this test IE11 will always have - // one less call than in other browsers. - if (videojs.browser.IE_VERSION === 11) { - assert.equal(createKeySessionCalls, 0, 'did not call createKeySessions_ yet'); - } else { - assert.equal(createKeySessionCalls, 1, 'called createKeySessions_ once'); - } + assert.equal(createKeySessionCalls, 1, 'called createKeySessions_ once'); this.player.tech_.trigger({type: 'waitingforkey', status: 'usable'}); - if (videojs.browser.IE_VERSION === 11) { - assert.equal(createKeySessionCalls, 1, 'called createKeySessions_ once'); - } else { - assert.equal(createKeySessionCalls, 2, 'called createKeySessions_ again'); - } + assert.equal(createKeySessionCalls, 2, 'called createKeySessions_ again'); }); QUnit.test('integration: configures eme for DASH on source buffer creation', function(assert) { @@ -4604,13 +4555,8 @@ QUnit.test('integration: updates source updater after eme init', function(assert sourceUpdater.on( 'createdsourcebuffers', () => { - let expected = false; + const expected = false; - // IE initializes eme syncronously directly after source buffer - // creation - if (videojs.browser.IE_VERSION) { - expected = true; - } assert.equal(sourceUpdater.hasInitializedAnyEme(), expected, 'correct eme state'); } ); @@ -4632,7 +4578,7 @@ QUnit.test('integration: updates source updater after eme init', function(assert this.standardXHRResponse(this.requests.shift(), audioSegment()); }); -QUnit[testOrSkip]('player error when key session creation rejects promise', function(assert) { +QUnit.test('player error when key session creation rejects promise', function(assert) { const done = assert.async(); this.player.error = (errorObject) => { @@ -4741,7 +4687,7 @@ QUnit.test( } ); -QUnit[testOrSkip]( +QUnit.test( 'stores bandwidth and throughput in localStorage when global option is true', function(assert) { videojs.options.vhs = { @@ -4770,7 +4716,7 @@ QUnit[testOrSkip]( } ); -QUnit[testOrSkip]( +QUnit.test( 'stores bandwidth and throughput in localStorage when player option is true', function(assert) { this.player.dispose(); @@ -4805,7 +4751,7 @@ QUnit[testOrSkip]( } ); -QUnit[testOrSkip]( +QUnit.test( 'stores bandwidth and throughput in localStorage when source option is true', function(assert) { this.player.dispose(); @@ -4835,7 +4781,7 @@ QUnit[testOrSkip]( } ); -QUnit[testOrSkip]( +QUnit.test( 'source localStorage option takes priority over player option', function(assert) { this.player.dispose(); @@ -4871,7 +4817,7 @@ QUnit[testOrSkip]( } ); -QUnit[testOrSkip]( +QUnit.test( 'does not store bandwidth and throughput in localStorage by default', function(assert) { this.player.dispose(); @@ -4897,7 +4843,7 @@ QUnit[testOrSkip]( } ); -QUnit[testOrSkip]('retrieves bandwidth and throughput from localStorage', function(assert) { +QUnit.test('retrieves bandwidth and throughput from localStorage', function(assert) { window.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify({ bandwidth: 33, throughput: 44 @@ -4959,7 +4905,7 @@ QUnit[testOrSkip]('retrieves bandwidth and throughput from localStorage', functi videojs.options.vhs = origVhsOptions; }); -QUnit[testOrSkip]( +QUnit.test( 'does not retrieve bandwidth and throughput from localStorage when stored value is not as expected', function(assert) { // bad value