Browse Source

chore: better worker build and synchronous web worker (#1033)

pull/1060/head
Brandon Casey 5 years ago
committed by GitHub
parent
commit
f0732afc4f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      index.html
  2. 15
      package-lock.json
  3. 2
      package.json
  4. 18
      scripts/index-demo-page.js
  5. 68
      scripts/rollup.config.js
  6. 67
      src/decrypter-worker.js
  7. 2
      src/master-playlist-controller.js
  8. 2
      src/segment-loader.js
  9. 28
      src/transmuxer-worker.js
  10. 2
      test/loader-common.js
  11. 5
      test/media-segment-request.test.js
  12. 2
      test/segment-transmuxer.test.js
  13. 2
      test/transmuxer-worker.test.js

4
index.html

@ -53,6 +53,10 @@
<input id=minified type="checkbox">
Minified VHS (reloads player)
</label>
<label>
<input id=sync-workers type="checkbox">
Synchronous Web Workers (reloads player)
</label>
<label>
<input id=liveui type="checkbox">
Enable the live UI (reloads player)

15
package-lock.json

@ -1114,12 +1114,6 @@
"to-fast-properties": "^2.0.0"
}
},
"@gkatsev/rollup-plugin-bundle-worker": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@gkatsev/rollup-plugin-bundle-worker/-/rollup-plugin-bundle-worker-1.0.2.tgz",
"integrity": "sha512-Jq0JfThRZvmuDn0Sx3TTi0uf2ZhIDnx08l9af4741gCMghyT26zxR/DNPoPJCGDc1QFLohYdCWsMn21XFDt46Q==",
"dev": true
},
"@rollup/plugin-babel": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.2.2.tgz",
@ -7632,6 +7626,15 @@
"terser": "^5.0.0"
}
},
"rollup-plugin-worker-factory": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/rollup-plugin-worker-factory/-/rollup-plugin-worker-factory-0.4.1.tgz",
"integrity": "sha512-qqN1tPc2aaNrOknaN8NMwt/Ud75kx2rV4kfhdNKvnRyK8dmdVphL3mJWhM+jcD41SfKuJo/lOSp7bvSUDc0bvg==",
"dev": true,
"requires": {
"rollup": "^2.34.2"
}
},
"rollup-pluginutils": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",

2
package.json

@ -65,7 +65,6 @@
"video.js": "^6 || ^7"
},
"devDependencies": {
"@gkatsev/rollup-plugin-bundle-worker": "^1.0.2",
"@rollup/plugin-replace": "^2.3.4",
"@videojs/generator-helpers": "~2.0.1",
"d3": "^3.4.8",
@ -77,6 +76,7 @@
"lodash-compat": "^3.10.0",
"nomnoml": "^0.3.0",
"rollup": "^2.36.1",
"rollup-plugin-worker-factory": "^0.4.1",
"shelljs": "^0.8.4",
"sinon": "^8.1.1",
"url-toolkit": "^2.2.1",

18
scripts/index-demo-page.js

@ -217,7 +217,7 @@
representationsEl.selectedIndex = selectedIndex;
};
['debug', 'autoplay', 'muted', 'minified', 'liveui', 'partial', 'url', 'type', 'keysystems', 'buffer-water', 'override-native'].forEach(function(name) {
['debug', 'autoplay', 'muted', 'minified', 'sync-workers', 'liveui', 'partial', 'url', 'type', 'keysystems', 'buffer-water', 'override-native'].forEach(function(name) {
stateEls[name] = document.getElementById(name);
});
@ -244,6 +244,13 @@
window.player.autoplay(event.target.checked);
});
stateEls['sync-workers'].addEventListener('change', function(event) {
saveState();
// reload the player and scripts
stateEls.minified.dispatchEvent(newEvent('change'));
});
stateEls.debug.addEventListener('change', function(event) {
saveState();
window.videojs.log.level(event.target.checked ? 'debug' : 'info');
@ -281,12 +288,17 @@
'node_modules/video.js/dist/alt/video.core',
'node_modules/videojs-contrib-eme/dist/videojs-contrib-eme',
'node_modules/videojs-contrib-quality-levels/dist/videojs-contrib-quality-levels',
'node_modules/videojs-http-source-selector/dist/videojs-http-source-selector',
'dist/videojs-http-streaming'
'node_modules/videojs-http-source-selector/dist/videojs-http-source-selector'
].map(function(url) {
return url + (event.target.checked ? '.min' : '') + '.js';
});
if (stateEls['sync-workers'].checked) {
urls.push('dist/videojs-http-streaming-sync-workers.js');
} else {
urls.push('dist/videojs-http-streaming' + (event.target.checked ? '.min' : '') + '.js');
}
saveState();
if (window.player) {

68
scripts/rollup.config.js

@ -1,9 +1,10 @@
const generate = require('videojs-generate-rollup-config');
const worker = require('@gkatsev/rollup-plugin-bundle-worker');
const worker = require('rollup-plugin-worker-factory');
const {terser} = require('rollup-plugin-terser');
const createTestData = require('./create-test-data.js');
const replace = require('@rollup/plugin-replace');
let syncWorker;
// see https://github.com/videojs/videojs-generate-rollup-config
// for options
const options = {
@ -26,11 +27,13 @@ const options = {
});
},
plugins(defaults) {
defaults.module.splice(2, 0, 'worker');
defaults.browser.splice(2, 0, 'worker');
defaults.test.splice(3, 0, 'worker');
defaults.test.splice(0, 0, 'createTestData');
// add worker and createTestData to the front of plugin lists
defaults.module.unshift('worker');
defaults.browser.unshift('worker');
// change this to `syncWorker` for syncronous web worker
// during unit tests
defaults.test.unshift('worker');
defaults.test.unshift('createTestData');
// istanbul is only in the list for regular builds and not watch
if (defaults.test.indexOf('istanbul') !== -1) {
@ -41,20 +44,35 @@ const options = {
return defaults;
},
primedPlugins(defaults) {
return Object.assign(defaults, {
defaults = Object.assign(defaults, {
replace: replace({
// single quote replace
"require('@videojs/vhs-utils/es": "require('@videojs/vhs-utils/cjs",
// double quote replace
'require("@videojs/vhs-utils/es': 'require("@videojs/vhs-utils/cjs'
}),
worker: worker(),
uglify: terser({
output: {comments: 'some'},
compress: {passes: 2}
}),
createTestData: createTestData()
});
defaults.worker = worker({type: 'browser', plugins: [
defaults.resolve,
defaults.json,
defaults.commonjs,
defaults.babel
]});
defaults.syncWorker = syncWorker = worker({type: 'mock', plugins: [
defaults.resolve,
defaults.json,
defaults.commonjs,
defaults.babel
]});
return defaults;
},
babel(defaults) {
const presetEnvSettings = defaults.presets[0][1];
@ -75,27 +93,19 @@ if (process.env.CI_TEST_TYPE) {
}
const config = generate(options);
if (config.builds.browser) {
config.builds.syncWorkers = config.makeBuild('browser', {
output: {
name: 'httpStreaming',
format: 'umd',
file: 'dist/videojs-http-streaming-sync-workers.js'
}
});
config.builds.syncWorkers.plugins[0] = syncWorker;
}
// Add additonal builds/customization here!
// export the builds to rollup
export default [
config.makeBuild('browser', {
input: 'src/decrypter-worker.js',
output: {
format: 'iife',
name: 'decrypterWorker',
file: 'src/decrypter-worker.worker.js'
},
external: []
}),
config.makeBuild('browser', {
input: 'src/transmuxer-worker.js',
output: {
format: 'iife',
name: 'transmuxerWorker',
file: 'src/transmuxer-worker.worker.js'
},
external: []
})
].concat(Object.values(config.builds));
export default Object.values(config.builds);

67
src/decrypter-worker.js

@ -6,43 +6,36 @@ import { createTransferableMessage } from './bin-utils';
* Our web worker interface so that things can talk to aes-decrypter
* that will be running in a web worker. the scope is passed to this by
* webworkify.
*
* @param {Object} self
* the scope for the web worker
*/
const DecrypterWorker = function(self) {
self.onmessage = function(event) {
const data = event.data;
const encrypted = new Uint8Array(
data.encrypted.bytes,
data.encrypted.byteOffset,
data.encrypted.byteLength
);
const key = new Uint32Array(
data.key.bytes,
data.key.byteOffset,
data.key.byteLength / 4
);
const iv = new Uint32Array(
data.iv.bytes,
data.iv.byteOffset,
data.iv.byteLength / 4
);
self.onmessage = function(event) {
const data = event.data;
const encrypted = new Uint8Array(
data.encrypted.bytes,
data.encrypted.byteOffset,
data.encrypted.byteLength
);
const key = new Uint32Array(
data.key.bytes,
data.key.byteOffset,
data.key.byteLength / 4
);
const iv = new Uint32Array(
data.iv.bytes,
data.iv.byteOffset,
data.iv.byteLength / 4
);
/* eslint-disable no-new, handle-callback-err */
new Decrypter(
encrypted,
key,
iv,
function(err, bytes) {
self.postMessage(createTransferableMessage({
source: data.source,
decrypted: bytes
}), [bytes.buffer]);
}
);
/* eslint-enable */
};
/* eslint-disable no-new, handle-callback-err */
new Decrypter(
encrypted,
key,
iv,
function(err, bytes) {
self.postMessage(createTransferableMessage({
source: data.source,
decrypted: bytes
}), [bytes.buffer]);
}
);
/* eslint-enable */
};
export default new DecrypterWorker(self);

2
src/master-playlist-controller.js

@ -13,7 +13,7 @@ import videojs from 'video.js';
import { updateAdCues } from './ad-cue-tags';
import SyncController from './sync-controller';
import TimelineChangeController from './timeline-change-controller';
import Decrypter from 'worker!./decrypter-worker.worker.js';
import Decrypter from 'worker!./decrypter-worker.js';
import Config from './config';
import {
parseCodecs,

2
src/segment-loader.js

@ -7,7 +7,7 @@ import Config from './config';
import window from 'global/window';
import { initSegmentId, segmentKeyId } from './bin-utils';
import { mediaSegmentRequest, REQUEST_ERRORS } from './media-segment-request';
import TransmuxWorker from 'worker!./transmuxer-worker.worker.js';
import TransmuxWorker from 'worker!./transmuxer-worker.js';
import segmentTransmuxer from './segment-transmuxer';
import { TIME_FUDGE_FACTOR, timeUntilRebuffer as timeUntilRebuffer_ } from './ranges';
import { minRebufferMaxBandwidthSelector } from './playlist-selectors';

28
src/transmuxer-worker.js

@ -435,23 +435,19 @@ class MessageHandlers {
*
* @param {Object} self the scope for the web worker
*/
const TransmuxerWorker = function(self) {
self.onmessage = function(event) {
if (event.data.action === 'init' && event.data.options) {
this.messageHandlers = new MessageHandlers(self, event.data.options);
return;
}
self.onmessage = function(event) {
if (event.data.action === 'init' && event.data.options) {
this.messageHandlers = new MessageHandlers(self, event.data.options);
return;
}
if (!this.messageHandlers) {
this.messageHandlers = new MessageHandlers(self);
}
if (!this.messageHandlers) {
this.messageHandlers = new MessageHandlers(self);
}
if (event.data && event.data.action && event.data.action !== 'init') {
if (this.messageHandlers[event.data.action]) {
this.messageHandlers[event.data.action](event.data);
}
if (event.data && event.data.action && event.data.action !== 'init') {
if (this.messageHandlers[event.data.action]) {
this.messageHandlers[event.data.action](event.data);
}
};
}
};
export default new TransmuxerWorker(self);

2
test/loader-common.js

@ -13,7 +13,7 @@ import { MasterPlaylistController } from '../src/master-playlist-controller';
import SourceUpdater from '../src/source-updater';
import SyncController from '../src/sync-controller';
import TimelineChangeController from '../src/timeline-change-controller';
import Decrypter from 'worker!../src/decrypter-worker.worker.js';
import Decrypter from 'worker!../src/decrypter-worker.js';
import window from 'global/window';
/* eslint-disable no-unused-vars */
// we need this so that it can register VHS with videojs

5
test/media-segment-request.test.js

@ -8,8 +8,8 @@ import {
standardXHRResponse,
downloadProgress
} from './test-helpers';
import TransmuxWorker from 'worker!../src/transmuxer-worker.worker.js';
import Decrypter from 'worker!../src/decrypter-worker.worker.js';
import TransmuxWorker from 'worker!../src/transmuxer-worker.js';
import Decrypter from 'worker!../src/decrypter-worker.js';
import {dispose as segmentTransmuxerDispose} from '../src/segment-transmuxer.js';
import {
aacWithoutId3 as aacWithoutId3Segment,
@ -1443,4 +1443,3 @@ QUnit.skip('id3 callback does not fire if partial data has no ID3 tags', functio
// it should be fixed to account for only partial data
this.standardXHRResponse(request, muxedSegment());
});

2
test/segment-transmuxer.test.js

@ -1,6 +1,6 @@
import QUnit from 'qunit';
import sinon from 'sinon';
import TransmuxWorker from 'worker!../src/transmuxer-worker.worker.js';
import TransmuxWorker from 'worker!../src/transmuxer-worker.js';
import {
muxed as muxedSegment,
caption as captionSegment,

2
test/transmuxer-worker.test.js

@ -1,5 +1,5 @@
import QUnit from 'qunit';
import TransmuxWorker from 'worker!../src/transmuxer-worker.worker.js';
import TransmuxWorker from 'worker!../src/transmuxer-worker.js';
import {
mp4Captions as mp4CaptionsSegment,
muxed as muxedSegment,

Loading…
Cancel
Save