1
0
Fork 0
mirror of https://github.com/DanielnetoDotCom/YouPHPTube synced 2025-10-05 02:39:46 +02:00

add inputmask

This commit is contained in:
DanieL 2022-09-21 13:51:50 -03:00
parent ab84f1e730
commit e07838c6c7
203 changed files with 29712 additions and 5216 deletions

View file

@ -1,3 +1,20 @@
<a name="2.14.3"></a>
## [2.14.3](https://github.com/videojs/http-streaming/compare/v2.14.2...v2.14.3) (2022-08-31)
### Bug Fixes
* cache aes keys for text tracks ([#973](https://github.com/videojs/http-streaming/issues/973)) ([#1228](https://github.com/videojs/http-streaming/issues/1228)) ([721e1bf](https://github.com/videojs/http-streaming/commit/721e1bf))
* output-restricted event handling for unplayable streams ([#1305](https://github.com/videojs/http-streaming/issues/1305)) ([23bbf84](https://github.com/videojs/http-streaming/commit/23bbf84))
### Chores
* **docs:** Remove outdated information in collaborators' guide ([#1271](https://github.com/videojs/http-streaming/issues/1271)) ([5223427](https://github.com/videojs/http-streaming/commit/5223427))
### Tests
* change source for live DASH playback test to fix test failures ([#1303](https://github.com/videojs/http-streaming/issues/1303)) ([e39e27d](https://github.com/videojs/http-streaming/commit/e39e27d))
* fix IE11 encrypted VTT tests by using an actual encrypted VTT segment ([#1291](https://github.com/videojs/http-streaming/issues/1291)) ([97e02fb](https://github.com/videojs/http-streaming/commit/97e02fb))
<a name="2.14.2"></a>
## [2.14.2](https://github.com/videojs/http-streaming/compare/v2.14.1...v2.14.2) (2022-04-13)

View file

@ -1,4 +1,4 @@
/*! @name @videojs/http-streaming @version 2.14.2 @license Apache-2.0 */
/*! @name @videojs/http-streaming @version 2.14.3 @license Apache-2.0 */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('video.js'), require('@xmldom/xmldom')) :
typeof define === 'function' && define.amd ? define(['exports', 'video.js', '@xmldom/xmldom'], factory) :
@ -9928,7 +9928,7 @@
return fn;
};
/* rollup-plugin-worker-factory start for worker!/Users/bclifford/Code/vhs-release-test/src/transmuxer-worker.js */
/* rollup-plugin-worker-factory start for worker!/Users/abarstow/videojs/http-streaming/src/transmuxer-worker.js */
var workerCode$1 = transform(function (self) {
/**
* mux.js
@ -18731,7 +18731,7 @@
};
});
var TransmuxWorker = factory(workerCode$1);
/* rollup-plugin-worker-factory end for worker!/Users/bclifford/Code/vhs-release-test/src/transmuxer-worker.js */
/* rollup-plugin-worker-factory end for worker!/Users/abarstow/videojs/http-streaming/src/transmuxer-worker.js */
var handleData_ = function handleData_(event, transmuxedData, callback) {
var _event$data$segment = event.data.segment,
@ -25606,7 +25606,12 @@
var segmentInfo = this.pendingSegment_; // although the VTT segment loader bandwidth isn't really used, it's good to
// maintain functionality between segment loaders
this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats);
this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats); // if this request included a segment key, save that data in the cache
if (simpleSegment.key) {
this.segmentKey(simpleSegment.key, true);
}
this.state = 'APPENDING'; // used for tests
this.trigger('appending');
@ -26545,7 +26550,7 @@
return TimelineChangeController;
}(videojs__default["default"].EventTarget);
/* rollup-plugin-worker-factory start for worker!/Users/bclifford/Code/vhs-release-test/src/decrypter-worker.js */
/* rollup-plugin-worker-factory start for worker!/Users/abarstow/videojs/http-streaming/src/decrypter-worker.js */
var workerCode = transform(function (self) {
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@ -27262,7 +27267,7 @@
};
});
var Decrypter = factory(workerCode);
/* rollup-plugin-worker-factory end for worker!/Users/bclifford/Code/vhs-release-test/src/decrypter-worker.js */
/* rollup-plugin-worker-factory end for worker!/Users/abarstow/videojs/http-streaming/src/decrypter-worker.js */
/**
* Convert the properties of an HLS track into an audioTrackKind.
@ -31091,7 +31096,7 @@
initPlugin(this, options);
};
var version$4 = "2.14.2";
var version$4 = "2.14.3";
var version$3 = "6.0.1";
@ -32114,12 +32119,34 @@
audioMedia: audioPlaylistLoader && audioPlaylistLoader.media()
});
this.player_.tech_.on('keystatuschange', function (e) {
if (e.status === 'output-restricted') {
_this5.masterPlaylistController_.blacklistCurrentPlaylist({
playlist: _this5.masterPlaylistController_.media(),
message: "DRM keystatus changed to " + e.status + ". Playlist will fail to play. Check for HDCP content.",
blacklistDuration: Infinity
});
if (e.status !== 'output-restricted') {
return;
}
var masterPlaylist = _this5.masterPlaylistController_.master();
if (!masterPlaylist || !masterPlaylist.playlists) {
return;
}
var excludedHDPlaylists = []; // Assume all HD streams are unplayable and exclude them from ABR selection
masterPlaylist.playlists.forEach(function (playlist) {
if (playlist && playlist.attributes && playlist.attributes.RESOLUTION && playlist.attributes.RESOLUTION.height >= 720) {
if (!playlist.excludeUntil || playlist.excludeUntil < Infinity) {
playlist.excludeUntil = Infinity;
excludedHDPlaylists.push(playlist);
}
}
});
if (excludedHDPlaylists.length) {
var _videojs$log;
(_videojs$log = videojs__default["default"].log).warn.apply(_videojs$log, ['DRM keystatus changed to "output-restricted." Removing the following HD playlists ' + 'that will most likely fail to play and clearing the buffer. ' + 'This may be due to HDCP restrictions on the stream and the capabilities of the current device.'].concat(excludedHDPlaylists)); // Clear the buffer before switching playlists, since it may already contain unplayable segments
_this5.masterPlaylistController_.fastQualityChange_();
}
});
this.handleWaitingForKey_ = this.handleWaitingForKey_.bind(this);

View file

@ -1,4 +1,4 @@
/*! @name @videojs/http-streaming @version 2.14.2 @license Apache-2.0 */
/*! @name @videojs/http-streaming @version 2.14.3 @license Apache-2.0 */
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
@ -4084,7 +4084,7 @@ var getWorkerString = function getWorkerString(fn) {
return fn.toString().replace(/^function.+?{/, '').slice(0, -1);
};
/* rollup-plugin-worker-factory start for worker!/Users/bclifford/Code/vhs-release-test/src/transmuxer-worker.js */
/* rollup-plugin-worker-factory start for worker!/Users/abarstow/videojs/http-streaming/src/transmuxer-worker.js */
var workerCode$1 = transform(getWorkerString(function () {
/**
* mux.js
@ -12887,7 +12887,7 @@ var workerCode$1 = transform(getWorkerString(function () {
};
}));
var TransmuxWorker = factory(workerCode$1);
/* rollup-plugin-worker-factory end for worker!/Users/bclifford/Code/vhs-release-test/src/transmuxer-worker.js */
/* rollup-plugin-worker-factory end for worker!/Users/abarstow/videojs/http-streaming/src/transmuxer-worker.js */
var handleData_ = function handleData_(event, transmuxedData, callback) {
var _event$data$segment = event.data.segment,
@ -19702,7 +19702,12 @@ var VTTSegmentLoader = /*#__PURE__*/function (_SegmentLoader) {
var segmentInfo = this.pendingSegment_; // although the VTT segment loader bandwidth isn't really used, it's good to
// maintain functionality between segment loaders
this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats);
this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats); // if this request included a segment key, save that data in the cache
if (simpleSegment.key) {
this.segmentKey(simpleSegment.key, true);
}
this.state = 'APPENDING'; // used for tests
this.trigger('appending');
@ -20641,7 +20646,7 @@ var TimelineChangeController = /*#__PURE__*/function (_videojs$EventTarget) {
return TimelineChangeController;
}(videojs__default["default"].EventTarget);
/* rollup-plugin-worker-factory start for worker!/Users/bclifford/Code/vhs-release-test/src/decrypter-worker.js */
/* rollup-plugin-worker-factory start for worker!/Users/abarstow/videojs/http-streaming/src/decrypter-worker.js */
var workerCode = transform(getWorkerString(function () {
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@ -21358,7 +21363,7 @@ var workerCode = transform(getWorkerString(function () {
};
}));
var Decrypter = factory(workerCode);
/* rollup-plugin-worker-factory end for worker!/Users/bclifford/Code/vhs-release-test/src/decrypter-worker.js */
/* rollup-plugin-worker-factory end for worker!/Users/abarstow/videojs/http-streaming/src/decrypter-worker.js */
/**
* Convert the properties of an HLS track into an audioTrackKind.
@ -25187,7 +25192,7 @@ var reloadSourceOnError = function reloadSourceOnError(options) {
initPlugin(this, options);
};
var version$4 = "2.14.2";
var version$4 = "2.14.3";
var version$3 = "6.0.1";
@ -26210,12 +26215,34 @@ var VhsHandler = /*#__PURE__*/function (_Component) {
audioMedia: audioPlaylistLoader && audioPlaylistLoader.media()
});
this.player_.tech_.on('keystatuschange', function (e) {
if (e.status === 'output-restricted') {
_this5.masterPlaylistController_.blacklistCurrentPlaylist({
playlist: _this5.masterPlaylistController_.media(),
message: "DRM keystatus changed to " + e.status + ". Playlist will fail to play. Check for HDCP content.",
blacklistDuration: Infinity
});
if (e.status !== 'output-restricted') {
return;
}
var masterPlaylist = _this5.masterPlaylistController_.master();
if (!masterPlaylist || !masterPlaylist.playlists) {
return;
}
var excludedHDPlaylists = []; // Assume all HD streams are unplayable and exclude them from ABR selection
masterPlaylist.playlists.forEach(function (playlist) {
if (playlist && playlist.attributes && playlist.attributes.RESOLUTION && playlist.attributes.RESOLUTION.height >= 720) {
if (!playlist.excludeUntil || playlist.excludeUntil < Infinity) {
playlist.excludeUntil = Infinity;
excludedHDPlaylists.push(playlist);
}
}
});
if (excludedHDPlaylists.length) {
var _videojs$log;
(_videojs$log = videojs__default["default"].log).warn.apply(_videojs$log, ['DRM keystatus changed to "output-restricted." Removing the following HD playlists ' + 'that will most likely fail to play and clearing the buffer. ' + 'This may be due to HDCP restrictions on the stream and the capabilities of the current device.'].concat(excludedHDPlaylists)); // Clear the buffer before switching playlists, since it may already contain unplayable segments
_this5.masterPlaylistController_.fastQualityChange_();
}
});
this.handleWaitingForKey_ = this.handleWaitingForKey_.bind(this);

View file

@ -1,4 +1,4 @@
/*! @name @videojs/http-streaming @version 2.14.2 @license Apache-2.0 */
/*! @name @videojs/http-streaming @version 2.14.3 @license Apache-2.0 */
import _assertThisInitialized from '@babel/runtime/helpers/assertThisInitialized';
import _inheritsLoose from '@babel/runtime/helpers/inheritsLoose';
import document from 'global/document';
@ -4070,7 +4070,7 @@ var getWorkerString = function getWorkerString(fn) {
return fn.toString().replace(/^function.+?{/, '').slice(0, -1);
};
/* rollup-plugin-worker-factory start for worker!/Users/bclifford/Code/vhs-release-test/src/transmuxer-worker.js */
/* rollup-plugin-worker-factory start for worker!/Users/abarstow/videojs/http-streaming/src/transmuxer-worker.js */
var workerCode$1 = transform(getWorkerString(function () {
/**
* mux.js
@ -12873,7 +12873,7 @@ var workerCode$1 = transform(getWorkerString(function () {
};
}));
var TransmuxWorker = factory(workerCode$1);
/* rollup-plugin-worker-factory end for worker!/Users/bclifford/Code/vhs-release-test/src/transmuxer-worker.js */
/* rollup-plugin-worker-factory end for worker!/Users/abarstow/videojs/http-streaming/src/transmuxer-worker.js */
var handleData_ = function handleData_(event, transmuxedData, callback) {
var _event$data$segment = event.data.segment,
@ -19688,7 +19688,12 @@ var VTTSegmentLoader = /*#__PURE__*/function (_SegmentLoader) {
var segmentInfo = this.pendingSegment_; // although the VTT segment loader bandwidth isn't really used, it's good to
// maintain functionality between segment loaders
this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats);
this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats); // if this request included a segment key, save that data in the cache
if (simpleSegment.key) {
this.segmentKey(simpleSegment.key, true);
}
this.state = 'APPENDING'; // used for tests
this.trigger('appending');
@ -20627,7 +20632,7 @@ var TimelineChangeController = /*#__PURE__*/function (_videojs$EventTarget) {
return TimelineChangeController;
}(videojs.EventTarget);
/* rollup-plugin-worker-factory start for worker!/Users/bclifford/Code/vhs-release-test/src/decrypter-worker.js */
/* rollup-plugin-worker-factory start for worker!/Users/abarstow/videojs/http-streaming/src/decrypter-worker.js */
var workerCode = transform(getWorkerString(function () {
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@ -21344,7 +21349,7 @@ var workerCode = transform(getWorkerString(function () {
};
}));
var Decrypter = factory(workerCode);
/* rollup-plugin-worker-factory end for worker!/Users/bclifford/Code/vhs-release-test/src/decrypter-worker.js */
/* rollup-plugin-worker-factory end for worker!/Users/abarstow/videojs/http-streaming/src/decrypter-worker.js */
/**
* Convert the properties of an HLS track into an audioTrackKind.
@ -25173,7 +25178,7 @@ var reloadSourceOnError = function reloadSourceOnError(options) {
initPlugin(this, options);
};
var version$4 = "2.14.2";
var version$4 = "2.14.3";
var version$3 = "6.0.1";
@ -26196,12 +26201,34 @@ var VhsHandler = /*#__PURE__*/function (_Component) {
audioMedia: audioPlaylistLoader && audioPlaylistLoader.media()
});
this.player_.tech_.on('keystatuschange', function (e) {
if (e.status === 'output-restricted') {
_this5.masterPlaylistController_.blacklistCurrentPlaylist({
playlist: _this5.masterPlaylistController_.media(),
message: "DRM keystatus changed to " + e.status + ". Playlist will fail to play. Check for HDCP content.",
blacklistDuration: Infinity
});
if (e.status !== 'output-restricted') {
return;
}
var masterPlaylist = _this5.masterPlaylistController_.master();
if (!masterPlaylist || !masterPlaylist.playlists) {
return;
}
var excludedHDPlaylists = []; // Assume all HD streams are unplayable and exclude them from ABR selection
masterPlaylist.playlists.forEach(function (playlist) {
if (playlist && playlist.attributes && playlist.attributes.RESOLUTION && playlist.attributes.RESOLUTION.height >= 720) {
if (!playlist.excludeUntil || playlist.excludeUntil < Infinity) {
playlist.excludeUntil = Infinity;
excludedHDPlaylists.push(playlist);
}
}
});
if (excludedHDPlaylists.length) {
var _videojs$log;
(_videojs$log = videojs.log).warn.apply(_videojs$log, ['DRM keystatus changed to "output-restricted." Removing the following HD playlists ' + 'that will most likely fail to play and clearing the buffer. ' + 'This may be due to HDCP restrictions on the stream and the capabilities of the current device.'].concat(excludedHDPlaylists)); // Clear the buffer before switching playlists, since it may already contain unplayable segments
_this5.masterPlaylistController_.fastQualityChange_();
}
});
this.handleWaitingForKey_ = this.handleWaitingForKey_.bind(this);

View file

@ -1,4 +1,4 @@
/*! @name @videojs/http-streaming @version 2.14.2 @license Apache-2.0 */
/*! @name @videojs/http-streaming @version 2.14.3 @license Apache-2.0 */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('video.js'), require('@xmldom/xmldom')) :
typeof define === 'function' && define.amd ? define(['exports', 'video.js', '@xmldom/xmldom'], factory) :
@ -9875,7 +9875,7 @@
return fn.toString().replace(/^function.+?{/, '').slice(0, -1);
};
/* rollup-plugin-worker-factory start for worker!/Users/bclifford/Code/vhs-release-test/src/transmuxer-worker.js */
/* rollup-plugin-worker-factory start for worker!/Users/abarstow/videojs/http-streaming/src/transmuxer-worker.js */
var workerCode$1 = transform(getWorkerString(function () {
/**
* mux.js
@ -18678,7 +18678,7 @@
};
}));
var TransmuxWorker = factory(workerCode$1);
/* rollup-plugin-worker-factory end for worker!/Users/bclifford/Code/vhs-release-test/src/transmuxer-worker.js */
/* rollup-plugin-worker-factory end for worker!/Users/abarstow/videojs/http-streaming/src/transmuxer-worker.js */
var handleData_ = function handleData_(event, transmuxedData, callback) {
var _event$data$segment = event.data.segment,
@ -25553,7 +25553,12 @@
var segmentInfo = this.pendingSegment_; // although the VTT segment loader bandwidth isn't really used, it's good to
// maintain functionality between segment loaders
this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats);
this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats); // if this request included a segment key, save that data in the cache
if (simpleSegment.key) {
this.segmentKey(simpleSegment.key, true);
}
this.state = 'APPENDING'; // used for tests
this.trigger('appending');
@ -26492,7 +26497,7 @@
return TimelineChangeController;
}(videojs__default["default"].EventTarget);
/* rollup-plugin-worker-factory start for worker!/Users/bclifford/Code/vhs-release-test/src/decrypter-worker.js */
/* rollup-plugin-worker-factory start for worker!/Users/abarstow/videojs/http-streaming/src/decrypter-worker.js */
var workerCode = transform(getWorkerString(function () {
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@ -27209,7 +27214,7 @@
};
}));
var Decrypter = factory(workerCode);
/* rollup-plugin-worker-factory end for worker!/Users/bclifford/Code/vhs-release-test/src/decrypter-worker.js */
/* rollup-plugin-worker-factory end for worker!/Users/abarstow/videojs/http-streaming/src/decrypter-worker.js */
/**
* Convert the properties of an HLS track into an audioTrackKind.
@ -31038,7 +31043,7 @@
initPlugin(this, options);
};
var version$4 = "2.14.2";
var version$4 = "2.14.3";
var version$3 = "6.0.1";
@ -32061,12 +32066,34 @@
audioMedia: audioPlaylistLoader && audioPlaylistLoader.media()
});
this.player_.tech_.on('keystatuschange', function (e) {
if (e.status === 'output-restricted') {
_this5.masterPlaylistController_.blacklistCurrentPlaylist({
playlist: _this5.masterPlaylistController_.media(),
message: "DRM keystatus changed to " + e.status + ". Playlist will fail to play. Check for HDCP content.",
blacklistDuration: Infinity
});
if (e.status !== 'output-restricted') {
return;
}
var masterPlaylist = _this5.masterPlaylistController_.master();
if (!masterPlaylist || !masterPlaylist.playlists) {
return;
}
var excludedHDPlaylists = []; // Assume all HD streams are unplayable and exclude them from ABR selection
masterPlaylist.playlists.forEach(function (playlist) {
if (playlist && playlist.attributes && playlist.attributes.RESOLUTION && playlist.attributes.RESOLUTION.height >= 720) {
if (!playlist.excludeUntil || playlist.excludeUntil < Infinity) {
playlist.excludeUntil = Infinity;
excludedHDPlaylists.push(playlist);
}
}
});
if (excludedHDPlaylists.length) {
var _videojs$log;
(_videojs$log = videojs__default["default"].log).warn.apply(_videojs$log, ['DRM keystatus changed to "output-restricted." Removing the following HD playlists ' + 'that will most likely fail to play and clearing the buffer. ' + 'This may be due to HDCP restrictions on the stream and the capabilities of the current device.'].concat(excludedHDPlaylists)); // Clear the buffer before switching playlists, since it may already contain unplayable segments
_this5.masterPlaylistController_.fastQualityChange_();
}
});
this.handleWaitingForKey_ = this.handleWaitingForKey_.bind(this);

File diff suppressed because one or more lines are too long

View file

@ -203,6 +203,52 @@ $ mv init-stream0.webm webmVideoInit.webm
$ mv chunk-stream0-00001.webm webmVideo.webm
```
### subtitlesEncrypted.vtt
Run subtitles.vtt through subtle crypto. As an example:
```javascript
const fs = require('fs');
const { subtle } = require('crypto').webcrypto;
// first segment has media index 0, so should have the following IV
const DEFAULT_IV = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
const getCryptoKey = async (bytes, iv = DEFAULT_IV) => {
const algorithm = { name: 'AES-CBC', iv };
const extractable = true;
const usages = ['encrypt', 'decrypt'];
return subtle.importKey('raw', bytes, algorithm, extractable, usages);
};
const run = async () => {
const keyFilePath = process.argv[2];
const segmentFilePath = process.argv[3];
const keyBytes = fs.readFileSync(keyFilePath);
const segmentBytes = fs.readFileSync(segmentFilePath);
const key = await getCryptoKey(keyBytes);
const encryptedBytes = await subtle.encrypt({
name: 'AES-CBC',
iv: DEFAULT_IV,
}, key, segmentBytes);
fs.writeFileSync('./encrypted.vtt', new Buffer(encryptedBytes));
console.log(`Wrote ${encryptedBytes.length} bytes to encrypted.vtt:`);
};
run();
```
To use the script:
```
$ node index.js encryptionKey.key subtitles.vtt
```
## Other useful commands
### Joined (audio and video) initialization segment (for HLS)

View file

@ -1,6 +1,6 @@
{
"name": "@videojs/http-streaming",
"version": "2.14.2",
"version": "2.14.3",
"description": "Play back HLS and DASH with Video.js, even where it's not natively supported",
"main": "dist/videojs-http-streaming.cjs.js",
"module": "dist/videojs-http-streaming.es.js",

View file

@ -21,7 +21,7 @@ const getManifests = () => (fs.readdirSync(manifestsDir) || [])
.map((f) => path.resolve(manifestsDir, f));
const getSegments = () => (fs.readdirSync(segmentsDir) || [])
.filter((f) => ((/\.(ts|mp4|key|webm|aac|ac3)/).test(path.extname(f))))
.filter((f) => ((/\.(ts|mp4|key|webm|aac|ac3|vtt)/).test(path.extname(f))))
.map((f) => path.resolve(segmentsDir, f));
const buildManifestString = function() {

View file

@ -0,0 +1,654 @@
/*! @name @videojs/http-streaming @version 2.5.0 @license Apache-2.0 */
var decrypterWorker = (function () {
'use strict';
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
var createClass = _createClass;
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
var inheritsLoose = _inheritsLoose;
/**
* @file stream.js
*/
/**
* A lightweight readable stream implemention that handles event dispatching.
*
* @class Stream
*/
var Stream = /*#__PURE__*/function () {
function Stream() {
this.listeners = {};
}
/**
* Add a listener for a specified event type.
*
* @param {string} type the event name
* @param {Function} listener the callback to be invoked when an event of
* the specified type occurs
*/
var _proto = Stream.prototype;
_proto.on = function on(type, listener) {
if (!this.listeners[type]) {
this.listeners[type] = [];
}
this.listeners[type].push(listener);
}
/**
* Remove a listener for a specified event type.
*
* @param {string} type the event name
* @param {Function} listener a function previously registered for this
* type of event through `on`
* @return {boolean} if we could turn it off or not
*/
;
_proto.off = function off(type, listener) {
if (!this.listeners[type]) {
return false;
}
var index = this.listeners[type].indexOf(listener); // TODO: which is better?
// In Video.js we slice listener functions
// on trigger so that it does not mess up the order
// while we loop through.
//
// Here we slice on off so that the loop in trigger
// can continue using it's old reference to loop without
// messing up the order.
this.listeners[type] = this.listeners[type].slice(0);
this.listeners[type].splice(index, 1);
return index > -1;
}
/**
* Trigger an event of the specified type on this stream. Any additional
* arguments to this function are passed as parameters to event listeners.
*
* @param {string} type the event name
*/
;
_proto.trigger = function trigger(type) {
var callbacks = this.listeners[type];
if (!callbacks) {
return;
} // Slicing the arguments on every invocation of this method
// can add a significant amount of overhead. Avoid the
// intermediate object creation for the common case of a
// single callback argument
if (arguments.length === 2) {
var length = callbacks.length;
for (var i = 0; i < length; ++i) {
callbacks[i].call(this, arguments[1]);
}
} else {
var args = Array.prototype.slice.call(arguments, 1);
var _length = callbacks.length;
for (var _i = 0; _i < _length; ++_i) {
callbacks[_i].apply(this, args);
}
}
}
/**
* Destroys the stream and cleans up.
*/
;
_proto.dispose = function dispose() {
this.listeners = {};
}
/**
* Forwards all `data` events on this stream to the destination stream. The
* destination stream should provide a method `push` to receive the data
* events as they arrive.
*
* @param {Stream} destination the stream that will receive all `data` events
* @see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options
*/
;
_proto.pipe = function pipe(destination) {
this.on('data', function (data) {
destination.push(data);
});
};
return Stream;
}();
/*! @name pkcs7 @version 1.0.4 @license Apache-2.0 */
/**
* Returns the subarray of a Uint8Array without PKCS#7 padding.
*
* @param padded {Uint8Array} unencrypted bytes that have been padded
* @return {Uint8Array} the unpadded bytes
* @see http://tools.ietf.org/html/rfc5652
*/
function unpad(padded) {
return padded.subarray(0, padded.byteLength - padded[padded.byteLength - 1]);
}
/*! @name aes-decrypter @version 3.1.2 @license Apache-2.0 */
/**
* @file aes.js
*
* This file contains an adaptation of the AES decryption algorithm
* from the Standford Javascript Cryptography Library. That work is
* covered by the following copyright and permissions notice:
*
* Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation
* are those of the authors and should not be interpreted as representing
* official policies, either expressed or implied, of the authors.
*/
/**
* Expand the S-box tables.
*
* @private
*/
var precompute = function precompute() {
var tables = [[[], [], [], [], []], [[], [], [], [], []]];
var encTable = tables[0];
var decTable = tables[1];
var sbox = encTable[4];
var sboxInv = decTable[4];
var i;
var x;
var xInv;
var d = [];
var th = [];
var x2;
var x4;
var x8;
var s;
var tEnc;
var tDec; // Compute double and third tables
for (i = 0; i < 256; i++) {
th[(d[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i;
}
for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {
// Compute sbox
s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4;
s = s >> 8 ^ s & 255 ^ 99;
sbox[x] = s;
sboxInv[s] = x; // Compute MixColumns
x8 = d[x4 = d[x2 = d[x]]];
tDec = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100;
tEnc = d[s] * 0x101 ^ s * 0x1010100;
for (i = 0; i < 4; i++) {
encTable[i][x] = tEnc = tEnc << 24 ^ tEnc >>> 8;
decTable[i][s] = tDec = tDec << 24 ^ tDec >>> 8;
}
} // Compactify. Considerable speedup on Firefox.
for (i = 0; i < 5; i++) {
encTable[i] = encTable[i].slice(0);
decTable[i] = decTable[i].slice(0);
}
return tables;
};
var aesTables = null;
/**
* Schedule out an AES key for both encryption and decryption. This
* is a low-level class. Use a cipher mode to do bulk encryption.
*
* @class AES
* @param key {Array} The key as an array of 4, 6 or 8 words.
*/
var AES = /*#__PURE__*/function () {
function AES(key) {
/**
* The expanded S-box and inverse S-box tables. These will be computed
* on the client so that we don't have to send them down the wire.
*
* There are two tables, _tables[0] is for encryption and
* _tables[1] is for decryption.
*
* The first 4 sub-tables are the expanded S-box with MixColumns. The
* last (_tables[01][4]) is the S-box itself.
*
* @private
*/
// if we have yet to precompute the S-box tables
// do so now
if (!aesTables) {
aesTables = precompute();
} // then make a copy of that object for use
this._tables = [[aesTables[0][0].slice(), aesTables[0][1].slice(), aesTables[0][2].slice(), aesTables[0][3].slice(), aesTables[0][4].slice()], [aesTables[1][0].slice(), aesTables[1][1].slice(), aesTables[1][2].slice(), aesTables[1][3].slice(), aesTables[1][4].slice()]];
var i;
var j;
var tmp;
var sbox = this._tables[0][4];
var decTable = this._tables[1];
var keyLen = key.length;
var rcon = 1;
if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {
throw new Error('Invalid aes key size');
}
var encKey = key.slice(0);
var decKey = [];
this._key = [encKey, decKey]; // schedule encryption keys
for (i = keyLen; i < 4 * keyLen + 28; i++) {
tmp = encKey[i - 1]; // apply sbox
if (i % keyLen === 0 || keyLen === 8 && i % keyLen === 4) {
tmp = sbox[tmp >>> 24] << 24 ^ sbox[tmp >> 16 & 255] << 16 ^ sbox[tmp >> 8 & 255] << 8 ^ sbox[tmp & 255]; // shift rows and add rcon
if (i % keyLen === 0) {
tmp = tmp << 8 ^ tmp >>> 24 ^ rcon << 24;
rcon = rcon << 1 ^ (rcon >> 7) * 283;
}
}
encKey[i] = encKey[i - keyLen] ^ tmp;
} // schedule decryption keys
for (j = 0; i; j++, i--) {
tmp = encKey[j & 3 ? i : i - 4];
if (i <= 4 || j < 4) {
decKey[j] = tmp;
} else {
decKey[j] = decTable[0][sbox[tmp >>> 24]] ^ decTable[1][sbox[tmp >> 16 & 255]] ^ decTable[2][sbox[tmp >> 8 & 255]] ^ decTable[3][sbox[tmp & 255]];
}
}
}
/**
* Decrypt 16 bytes, specified as four 32-bit words.
*
* @param {number} encrypted0 the first word to decrypt
* @param {number} encrypted1 the second word to decrypt
* @param {number} encrypted2 the third word to decrypt
* @param {number} encrypted3 the fourth word to decrypt
* @param {Int32Array} out the array to write the decrypted words
* into
* @param {number} offset the offset into the output array to start
* writing results
* @return {Array} The plaintext.
*/
var _proto = AES.prototype;
_proto.decrypt = function decrypt(encrypted0, encrypted1, encrypted2, encrypted3, out, offset) {
var key = this._key[1]; // state variables a,b,c,d are loaded with pre-whitened data
var a = encrypted0 ^ key[0];
var b = encrypted3 ^ key[1];
var c = encrypted2 ^ key[2];
var d = encrypted1 ^ key[3];
var a2;
var b2;
var c2; // key.length === 2 ?
var nInnerRounds = key.length / 4 - 2;
var i;
var kIndex = 4;
var table = this._tables[1]; // load up the tables
var table0 = table[0];
var table1 = table[1];
var table2 = table[2];
var table3 = table[3];
var sbox = table[4]; // Inner rounds. Cribbed from OpenSSL.
for (i = 0; i < nInnerRounds; i++) {
a2 = table0[a >>> 24] ^ table1[b >> 16 & 255] ^ table2[c >> 8 & 255] ^ table3[d & 255] ^ key[kIndex];
b2 = table0[b >>> 24] ^ table1[c >> 16 & 255] ^ table2[d >> 8 & 255] ^ table3[a & 255] ^ key[kIndex + 1];
c2 = table0[c >>> 24] ^ table1[d >> 16 & 255] ^ table2[a >> 8 & 255] ^ table3[b & 255] ^ key[kIndex + 2];
d = table0[d >>> 24] ^ table1[a >> 16 & 255] ^ table2[b >> 8 & 255] ^ table3[c & 255] ^ key[kIndex + 3];
kIndex += 4;
a = a2;
b = b2;
c = c2;
} // Last round.
for (i = 0; i < 4; i++) {
out[(3 & -i) + offset] = sbox[a >>> 24] << 24 ^ sbox[b >> 16 & 255] << 16 ^ sbox[c >> 8 & 255] << 8 ^ sbox[d & 255] ^ key[kIndex++];
a2 = a;
a = b;
b = c;
c = d;
d = a2;
}
};
return AES;
}();
/**
* A wrapper around the Stream class to use setTimeout
* and run stream "jobs" Asynchronously
*
* @class AsyncStream
* @extends Stream
*/
var AsyncStream = /*#__PURE__*/function (_Stream) {
inheritsLoose(AsyncStream, _Stream);
function AsyncStream() {
var _this;
_this = _Stream.call(this, Stream) || this;
_this.jobs = [];
_this.delay = 1;
_this.timeout_ = null;
return _this;
}
/**
* process an async job
*
* @private
*/
var _proto = AsyncStream.prototype;
_proto.processJob_ = function processJob_() {
this.jobs.shift()();
if (this.jobs.length) {
this.timeout_ = setTimeout(this.processJob_.bind(this), this.delay);
} else {
this.timeout_ = null;
}
}
/**
* push a job into the stream
*
* @param {Function} job the job to push into the stream
*/
;
_proto.push = function push(job) {
this.jobs.push(job);
if (!this.timeout_) {
this.timeout_ = setTimeout(this.processJob_.bind(this), this.delay);
}
};
return AsyncStream;
}(Stream);
/**
* Convert network-order (big-endian) bytes into their little-endian
* representation.
*/
var ntoh = function ntoh(word) {
return word << 24 | (word & 0xff00) << 8 | (word & 0xff0000) >> 8 | word >>> 24;
};
/**
* Decrypt bytes using AES-128 with CBC and PKCS#7 padding.
*
* @param {Uint8Array} encrypted the encrypted bytes
* @param {Uint32Array} key the bytes of the decryption key
* @param {Uint32Array} initVector the initialization vector (IV) to
* use for the first round of CBC.
* @return {Uint8Array} the decrypted bytes
*
* @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
* @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29
* @see https://tools.ietf.org/html/rfc2315
*/
var decrypt = function decrypt(encrypted, key, initVector) {
// word-level access to the encrypted bytes
var encrypted32 = new Int32Array(encrypted.buffer, encrypted.byteOffset, encrypted.byteLength >> 2);
var decipher = new AES(Array.prototype.slice.call(key)); // byte and word-level access for the decrypted output
var decrypted = new Uint8Array(encrypted.byteLength);
var decrypted32 = new Int32Array(decrypted.buffer); // temporary variables for working with the IV, encrypted, and
// decrypted data
var init0;
var init1;
var init2;
var init3;
var encrypted0;
var encrypted1;
var encrypted2;
var encrypted3; // iteration variable
var wordIx; // pull out the words of the IV to ensure we don't modify the
// passed-in reference and easier access
init0 = initVector[0];
init1 = initVector[1];
init2 = initVector[2];
init3 = initVector[3]; // decrypt four word sequences, applying cipher-block chaining (CBC)
// to each decrypted block
for (wordIx = 0; wordIx < encrypted32.length; wordIx += 4) {
// convert big-endian (network order) words into little-endian
// (javascript order)
encrypted0 = ntoh(encrypted32[wordIx]);
encrypted1 = ntoh(encrypted32[wordIx + 1]);
encrypted2 = ntoh(encrypted32[wordIx + 2]);
encrypted3 = ntoh(encrypted32[wordIx + 3]); // decrypt the block
decipher.decrypt(encrypted0, encrypted1, encrypted2, encrypted3, decrypted32, wordIx); // XOR with the IV, and restore network byte-order to obtain the
// plaintext
decrypted32[wordIx] = ntoh(decrypted32[wordIx] ^ init0);
decrypted32[wordIx + 1] = ntoh(decrypted32[wordIx + 1] ^ init1);
decrypted32[wordIx + 2] = ntoh(decrypted32[wordIx + 2] ^ init2);
decrypted32[wordIx + 3] = ntoh(decrypted32[wordIx + 3] ^ init3); // setup the IV for the next round
init0 = encrypted0;
init1 = encrypted1;
init2 = encrypted2;
init3 = encrypted3;
}
return decrypted;
};
/**
* The `Decrypter` class that manages decryption of AES
* data through `AsyncStream` objects and the `decrypt`
* function
*
* @param {Uint8Array} encrypted the encrypted bytes
* @param {Uint32Array} key the bytes of the decryption key
* @param {Uint32Array} initVector the initialization vector (IV) to
* @param {Function} done the function to run when done
* @class Decrypter
*/
var Decrypter = /*#__PURE__*/function () {
function Decrypter(encrypted, key, initVector, done) {
var step = Decrypter.STEP;
var encrypted32 = new Int32Array(encrypted.buffer);
var decrypted = new Uint8Array(encrypted.byteLength);
var i = 0;
this.asyncStream_ = new AsyncStream(); // split up the encryption job and do the individual chunks asynchronously
this.asyncStream_.push(this.decryptChunk_(encrypted32.subarray(i, i + step), key, initVector, decrypted));
for (i = step; i < encrypted32.length; i += step) {
initVector = new Uint32Array([ntoh(encrypted32[i - 4]), ntoh(encrypted32[i - 3]), ntoh(encrypted32[i - 2]), ntoh(encrypted32[i - 1])]);
this.asyncStream_.push(this.decryptChunk_(encrypted32.subarray(i, i + step), key, initVector, decrypted));
} // invoke the done() callback when everything is finished
this.asyncStream_.push(function () {
// remove pkcs#7 padding from the decrypted bytes
done(null, unpad(decrypted));
});
}
/**
* a getter for step the maximum number of bytes to process at one time
*
* @return {number} the value of step 32000
*/
var _proto = Decrypter.prototype;
/**
* @private
*/
_proto.decryptChunk_ = function decryptChunk_(encrypted, key, initVector, decrypted) {
return function () {
var bytes = decrypt(encrypted, key, initVector);
decrypted.set(bytes, encrypted.byteOffset);
};
};
createClass(Decrypter, null, [{
key: "STEP",
get: function get() {
// 4 * 8000;
return 32000;
}
}]);
return Decrypter;
}();
/**
* @file bin-utils.js
*/
/**
* Creates an object for sending to a web worker modifying properties that are TypedArrays
* into a new object with seperated properties for the buffer, byteOffset, and byteLength.
*
* @param {Object} message
* Object of properties and values to send to the web worker
* @return {Object}
* Modified message with TypedArray values expanded
* @function createTransferableMessage
*/
var createTransferableMessage = function createTransferableMessage(message) {
var transferable = {};
Object.keys(message).forEach(function (key) {
var value = message[key];
if (ArrayBuffer.isView(value)) {
transferable[key] = {
bytes: value.buffer,
byteOffset: value.byteOffset,
byteLength: value.byteLength
};
} else {
transferable[key] = value;
}
});
return transferable;
};
/* global self */
/**
* 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
*/
var DecrypterWorker = function DecrypterWorker(self) {
self.onmessage = function (event) {
var data = event.data;
var encrypted = new Uint8Array(data.encrypted.bytes, data.encrypted.byteOffset, data.encrypted.byteLength);
var key = new Uint32Array(data.key.bytes, data.key.byteOffset, data.key.byteLength / 4);
var 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 */
};
};
var decrypterWorker = new DecrypterWorker(self);
return decrypterWorker;
}());

File diff suppressed because it is too large Load diff

View file

@ -1061,12 +1061,40 @@ class VhsHandler extends Component {
});
this.player_.tech_.on('keystatuschange', (e) => {
if (e.status === 'output-restricted') {
this.masterPlaylistController_.blacklistCurrentPlaylist({
playlist: this.masterPlaylistController_.media(),
message: `DRM keystatus changed to ${e.status}. Playlist will fail to play. Check for HDCP content.`,
blacklistDuration: Infinity
});
if (e.status !== 'output-restricted') {
return;
}
const masterPlaylist = this.masterPlaylistController_.master();
if (!masterPlaylist || !masterPlaylist.playlists) {
return;
}
const excludedHDPlaylists = [];
// Assume all HD streams are unplayable and exclude them from ABR selection
masterPlaylist.playlists.forEach(playlist => {
if (playlist && playlist.attributes && playlist.attributes.RESOLUTION &&
playlist.attributes.RESOLUTION.height >= 720) {
if (!playlist.excludeUntil || playlist.excludeUntil < Infinity) {
playlist.excludeUntil = Infinity;
excludedHDPlaylists.push(playlist);
}
}
});
if (excludedHDPlaylists.length) {
videojs.log.warn(
'DRM keystatus changed to "output-restricted." Removing the following HD playlists ' +
'that will most likely fail to play and clearing the buffer. ' +
'This may be due to HDCP restrictions on the stream and the capabilities of the current device.',
...excludedHDPlaylists
);
// Clear the buffer before switching playlists, since it may already contain unplayable segments
this.masterPlaylistController_.fastQualityChange_();
}
});

View file

@ -280,6 +280,11 @@ export default class VTTSegmentLoader extends SegmentLoader {
// maintain functionality between segment loaders
this.saveBandwidthRelatedStats_(segmentInfo.duration, simpleSegment.stats);
// if this request included a segment key, save that data in the cache
if (simpleSegment.key) {
this.segmentKey(simpleSegment.key, true);
}
this.state = 'APPENDING';
// used for tests