189 lines
7.5 KiB
JavaScript
189 lines
7.5 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
|
|
var _createClass = function () { 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
|
|
var _events = require('../events');
|
|
|
|
var _events2 = _interopRequireDefault(_events);
|
|
|
|
var _demuxerInline = require('../demux/demuxer-inline');
|
|
|
|
var _demuxerInline2 = _interopRequireDefault(_demuxerInline);
|
|
|
|
var _demuxerWorker = require('../demux/demuxer-worker');
|
|
|
|
var _demuxerWorker2 = _interopRequireDefault(_demuxerWorker);
|
|
|
|
var _logger = require('../utils/logger');
|
|
|
|
var _errors = require('../errors');
|
|
|
|
var _events3 = require('events');
|
|
|
|
var _events4 = _interopRequireDefault(_events3);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
var Demuxer = function () {
|
|
function Demuxer(hls, id) {
|
|
_classCallCheck(this, Demuxer);
|
|
|
|
this.hls = hls;
|
|
this.id = id;
|
|
// observer setup
|
|
var observer = this.observer = new _events4.default();
|
|
var config = hls.config;
|
|
observer.trigger = function trigger(event) {
|
|
for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
data[_key - 1] = arguments[_key];
|
|
}
|
|
|
|
observer.emit.apply(observer, [event, event].concat(data));
|
|
};
|
|
|
|
observer.off = function off(event) {
|
|
for (var _len2 = arguments.length, data = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
|
data[_key2 - 1] = arguments[_key2];
|
|
}
|
|
|
|
observer.removeListener.apply(observer, [event].concat(data));
|
|
};
|
|
|
|
var forwardMessage = function (ev, data) {
|
|
data = data || {};
|
|
data.frag = this.frag;
|
|
data.id = this.id;
|
|
hls.trigger(ev, data);
|
|
}.bind(this);
|
|
|
|
// forward events to main thread
|
|
observer.on(_events2.default.FRAG_DECRYPTED, forwardMessage);
|
|
observer.on(_events2.default.FRAG_PARSING_INIT_SEGMENT, forwardMessage);
|
|
observer.on(_events2.default.FRAG_PARSING_DATA, forwardMessage);
|
|
observer.on(_events2.default.FRAG_PARSED, forwardMessage);
|
|
observer.on(_events2.default.ERROR, forwardMessage);
|
|
observer.on(_events2.default.FRAG_PARSING_METADATA, forwardMessage);
|
|
observer.on(_events2.default.FRAG_PARSING_USERDATA, forwardMessage);
|
|
observer.on(_events2.default.INIT_PTS_FOUND, forwardMessage);
|
|
|
|
var typeSupported = {
|
|
mp4: MediaSource.isTypeSupported('video/mp4'),
|
|
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
|
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"')
|
|
};
|
|
// navigator.vendor is not always available in Web Worker
|
|
// refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
|
|
var vendor = navigator.vendor;
|
|
if (config.enableWorker && typeof Worker !== 'undefined') {
|
|
_logger.logger.log('demuxing in webworker');
|
|
var w = void 0;
|
|
try {
|
|
var work = require('webworkify');
|
|
w = this.w = work(_demuxerWorker2.default);
|
|
this.onwmsg = this.onWorkerMessage.bind(this);
|
|
w.addEventListener('message', this.onwmsg);
|
|
w.onerror = function (event) {
|
|
hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.OTHER_ERROR, details: _errors.ErrorDetails.INTERNAL_EXCEPTION, fatal: true, event: 'demuxerWorker', err: { message: event.message + ' (' + event.filename + ':' + event.lineno + ')' } });
|
|
};
|
|
w.postMessage({ cmd: 'init', typeSupported: typeSupported, vendor: vendor, id: id, config: JSON.stringify(config) });
|
|
} catch (err) {
|
|
_logger.logger.error('error while initializing DemuxerWorker, fallback on DemuxerInline');
|
|
if (w) {
|
|
// revoke the Object URL that was used to create demuxer worker, so as not to leak it
|
|
URL.revokeObjectURL(w.objectURL);
|
|
}
|
|
this.demuxer = new _demuxerInline2.default(observer, typeSupported, config, vendor);
|
|
this.w = undefined;
|
|
}
|
|
} else {
|
|
this.demuxer = new _demuxerInline2.default(observer, typeSupported, config, vendor);
|
|
}
|
|
}
|
|
|
|
_createClass(Demuxer, [{
|
|
key: 'destroy',
|
|
value: function destroy() {
|
|
var w = this.w;
|
|
if (w) {
|
|
w.removeEventListener('message', this.onwmsg);
|
|
w.terminate();
|
|
this.w = null;
|
|
} else {
|
|
var demuxer = this.demuxer;
|
|
if (demuxer) {
|
|
demuxer.destroy();
|
|
this.demuxer = null;
|
|
}
|
|
}
|
|
var observer = this.observer;
|
|
if (observer) {
|
|
observer.removeAllListeners();
|
|
this.observer = null;
|
|
}
|
|
}
|
|
}, {
|
|
key: 'push',
|
|
value: function push(data, initSegment, audioCodec, videoCodec, frag, duration, accurateTimeOffset, defaultInitPTS) {
|
|
var w = this.w;
|
|
var timeOffset = !isNaN(frag.startDTS) ? frag.startDTS : frag.start;
|
|
var decryptdata = frag.decryptdata;
|
|
var lastFrag = this.frag;
|
|
var discontinuity = !(lastFrag && frag.cc === lastFrag.cc);
|
|
var trackSwitch = !(lastFrag && frag.level === lastFrag.level);
|
|
var nextSN = lastFrag && frag.sn === lastFrag.sn + 1;
|
|
var contiguous = !trackSwitch && nextSN;
|
|
if (discontinuity) {
|
|
_logger.logger.log(this.id + ':discontinuity detected');
|
|
}
|
|
if (trackSwitch) {
|
|
_logger.logger.log(this.id + ':switch detected');
|
|
}
|
|
this.frag = frag;
|
|
if (w) {
|
|
// post fragment payload as transferable objects (no copy)
|
|
w.postMessage({ cmd: 'demux', data: data, decryptdata: decryptdata, initSegment: initSegment, audioCodec: audioCodec, videoCodec: videoCodec, timeOffset: timeOffset, discontinuity: discontinuity, trackSwitch: trackSwitch, contiguous: contiguous, duration: duration, accurateTimeOffset: accurateTimeOffset, defaultInitPTS: defaultInitPTS }, [data]);
|
|
} else {
|
|
var demuxer = this.demuxer;
|
|
if (demuxer) {
|
|
demuxer.push(data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS);
|
|
}
|
|
}
|
|
}
|
|
}, {
|
|
key: 'onWorkerMessage',
|
|
value: function onWorkerMessage(ev) {
|
|
var data = ev.data,
|
|
hls = this.hls;
|
|
//console.log('onWorkerMessage:' + data.event);
|
|
switch (data.event) {
|
|
case 'init':
|
|
// revoke the Object URL that was used to create demuxer worker, so as not to leak it
|
|
URL.revokeObjectURL(this.w.objectURL);
|
|
break;
|
|
// special case for FRAG_PARSING_DATA: data1 and data2 are transferable objects
|
|
case _events2.default.FRAG_PARSING_DATA:
|
|
data.data.data1 = new Uint8Array(data.data1);
|
|
if (data.data2) {
|
|
data.data.data2 = new Uint8Array(data.data2);
|
|
}
|
|
/* falls through */
|
|
default:
|
|
data.data = data.data || {};
|
|
data.data.frag = this.frag;
|
|
data.data.id = this.id;
|
|
hls.trigger(data.event, data.data);
|
|
break;
|
|
}
|
|
}
|
|
}]);
|
|
|
|
return Demuxer;
|
|
}();
|
|
|
|
exports.default = Demuxer; |