feat: Add Be and tbd skill, also added Roadmap file

This commit is contained in:
2026-05-10 16:32:12 -04:00
parent 3500ade13f
commit 0bb8885802
29587 changed files with 10611695 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
'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; }; }(); /**
* AAC demuxer
*/
var _adts = require('./adts');
var _adts2 = _interopRequireDefault(_adts);
var _logger = require('../utils/logger');
var _id = require('../demux/id3');
var _id2 = _interopRequireDefault(_id);
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 AACDemuxer = function () {
function AACDemuxer(observer, remuxer, config) {
_classCallCheck(this, AACDemuxer);
this.observer = observer;
this.config = config;
this.remuxer = remuxer;
}
_createClass(AACDemuxer, [{
key: 'resetInitSegment',
value: function resetInitSegment(initSegment, audioCodec, videoCodec, duration) {
this._audioTrack = { container: 'audio/adts', type: 'audio', id: -1, sequenceNumber: 0, isAAC: true, samples: [], len: 0, manifestCodec: audioCodec, duration: duration, inputTimeScale: 90000 };
}
}, {
key: 'resetTimeStamp',
value: function resetTimeStamp() {}
}, {
key: 'append',
// feed incoming data to the front of the parsing pipeline
value: function append(data, timeOffset, contiguous, accurateTimeOffset) {
var track = this._audioTrack,
id3Data = _id2.default.getID3Data(data, 0),
pts = 90 * _id2.default.getTimeStamp(id3Data),
frameIndex = 0,
stamp = pts,
length = data.length,
offset = id3Data.length;
var id3Samples = [{ pts: stamp, dts: stamp, data: id3Data }];
while (offset < length - 1) {
if (_adts2.default.isHeader(data, offset) && offset + 5 < length) {
_adts2.default.initTrackConfig(track, this.observer, data, offset, track.manifestCodec);
var frame = _adts2.default.appendFrame(track, data, offset, pts, frameIndex);
if (frame) {
offset += frame.length;
stamp = frame.sample.pts;
frameIndex++;
} else {
_logger.logger.log('Unable to parse AAC frame');
break;
}
} else if (_id2.default.isHeader(data, offset)) {
id3Data = _id2.default.getID3Data(data, offset);
id3Samples.push({ pts: stamp, dts: stamp, data: id3Data });
offset += id3Data.length;
} else {
//nothing found, keep looking
offset++;
}
}
this.remuxer.remux(track, { samples: [] }, { samples: id3Samples, inputTimeScale: 90000 }, { samples: [] }, timeOffset, contiguous, accurateTimeOffset);
}
}, {
key: 'destroy',
value: function destroy() {}
}], [{
key: 'probe',
value: function probe(data) {
// check if data contains ID3 timestamp and ADTS sync word
var offset, length;
var id3Data = _id2.default.getID3Data(data, 0);
if (id3Data && _id2.default.getTimeStamp(id3Data) !== undefined) {
// Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
// Layer bits (position 14 and 15) in header should be always 0 for ADTS
// More info https://wiki.multimedia.cx/index.php?title=ADTS
for (offset = id3Data.length, length = Math.min(data.length - 1, offset + 100); offset < length; offset++) {
if (_adts2.default.probe(data, offset)) {
_logger.logger.log('ADTS sync word found !');
return true;
}
}
}
return false;
}
}]);
return AACDemuxer;
}();
exports.default = AACDemuxer;

225
Skills/@be/be/node_modules/hls.js/lib/demux/adts.js generated vendored Normal file
View File

@@ -0,0 +1,225 @@
'use strict';
var _logger = require('../utils/logger');
var _errors = require('../errors');
/**
* ADTS parser helper
*/
var ADTS = {
getAudioConfig: function getAudioConfig(observer, data, offset, audioCodec) {
var adtsObjectType,
// :int
adtsSampleingIndex,
// :int
adtsExtensionSampleingIndex,
// :int
adtsChanelConfig,
// :int
config,
userAgent = navigator.userAgent.toLowerCase(),
manifestCodec = audioCodec,
adtsSampleingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
// byte 2
adtsObjectType = ((data[offset + 2] & 0xC0) >>> 6) + 1;
adtsSampleingIndex = (data[offset + 2] & 0x3C) >>> 2;
if (adtsSampleingIndex > adtsSampleingRates.length - 1) {
observer.trigger(Event.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: 'invalid ADTS sampling index:' + adtsSampleingIndex });
return;
}
adtsChanelConfig = (data[offset + 2] & 0x01) << 2;
// byte 3
adtsChanelConfig |= (data[offset + 3] & 0xC0) >>> 6;
_logger.logger.log('manifest codec:' + audioCodec + ',ADTS data:type:' + adtsObjectType + ',sampleingIndex:' + adtsSampleingIndex + '[' + adtsSampleingRates[adtsSampleingIndex] + 'Hz],channelConfig:' + adtsChanelConfig);
// firefox: freq less than 24kHz = AAC SBR (HE-AAC)
if (/firefox/i.test(userAgent)) {
if (adtsSampleingIndex >= 6) {
adtsObjectType = 5;
config = new Array(4);
// HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies
// there is a factor 2 between frame sample rate and output sample rate
// multiply frequency by 2 (see table below, equivalent to substract 3)
adtsExtensionSampleingIndex = adtsSampleingIndex - 3;
} else {
adtsObjectType = 2;
config = new Array(2);
adtsExtensionSampleingIndex = adtsSampleingIndex;
}
// Android : always use AAC
} else if (userAgent.indexOf('android') !== -1) {
adtsObjectType = 2;
config = new Array(2);
adtsExtensionSampleingIndex = adtsSampleingIndex;
} else {
/* for other browsers (Chrome/Vivaldi/Opera ...)
always force audio type to be HE-AAC SBR, as some browsers do not support audio codec switch properly (like Chrome ...)
*/
adtsObjectType = 5;
config = new Array(4);
// if (manifest codec is HE-AAC or HE-AACv2) OR (manifest codec not specified AND frequency less than 24kHz)
if (audioCodec && (audioCodec.indexOf('mp4a.40.29') !== -1 || audioCodec.indexOf('mp4a.40.5') !== -1) || !audioCodec && adtsSampleingIndex >= 6) {
// HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies
// there is a factor 2 between frame sample rate and output sample rate
// multiply frequency by 2 (see table below, equivalent to substract 3)
adtsExtensionSampleingIndex = adtsSampleingIndex - 3;
} else {
// if (manifest codec is AAC) AND (frequency less than 24kHz AND nb channel is 1) OR (manifest codec not specified and mono audio)
// Chrome fails to play back with low frequency AAC LC mono when initialized with HE-AAC. This is not a problem with stereo.
if (audioCodec && audioCodec.indexOf('mp4a.40.2') !== -1 && (adtsSampleingIndex >= 6 && adtsChanelConfig === 1 || /vivaldi/i.test(userAgent)) || !audioCodec && adtsChanelConfig === 1) {
adtsObjectType = 2;
config = new Array(2);
}
adtsExtensionSampleingIndex = adtsSampleingIndex;
}
}
/* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config
ISO 14496-3 (AAC).pdf - Table 1.13 — Syntax of AudioSpecificConfig()
Audio Profile / Audio Object Type
0: Null
1: AAC Main
2: AAC LC (Low Complexity)
3: AAC SSR (Scalable Sample Rate)
4: AAC LTP (Long Term Prediction)
5: SBR (Spectral Band Replication)
6: AAC Scalable
sampling freq
0: 96000 Hz
1: 88200 Hz
2: 64000 Hz
3: 48000 Hz
4: 44100 Hz
5: 32000 Hz
6: 24000 Hz
7: 22050 Hz
8: 16000 Hz
9: 12000 Hz
10: 11025 Hz
11: 8000 Hz
12: 7350 Hz
13: Reserved
14: Reserved
15: frequency is written explictly
Channel Configurations
These are the channel configurations:
0: Defined in AOT Specifc Config
1: 1 channel: front-center
2: 2 channels: front-left, front-right
*/
// audioObjectType = profile => profile, the MPEG-4 Audio Object Type minus 1
config[0] = adtsObjectType << 3;
// samplingFrequencyIndex
config[0] |= (adtsSampleingIndex & 0x0E) >> 1;
config[1] |= (adtsSampleingIndex & 0x01) << 7;
// channelConfiguration
config[1] |= adtsChanelConfig << 3;
if (adtsObjectType === 5) {
// adtsExtensionSampleingIndex
config[1] |= (adtsExtensionSampleingIndex & 0x0E) >> 1;
config[2] = (adtsExtensionSampleingIndex & 0x01) << 7;
// adtsObjectType (force to 2, chrome is checking that object type is less than 5 ???
// https://chromium.googlesource.com/chromium/src.git/+/master/media/formats/mp4/aac.cc
config[2] |= 2 << 2;
config[3] = 0;
}
return { config: config, samplerate: adtsSampleingRates[adtsSampleingIndex], channelCount: adtsChanelConfig, codec: 'mp4a.40.' + adtsObjectType, manifestCodec: manifestCodec };
},
isHeaderPattern: function isHeaderPattern(data, offset) {
return data[offset] === 0xff && (data[offset + 1] & 0xf6) === 0xf0;
},
getHeaderLength: function getHeaderLength(data, offset) {
return !!(data[offset + 1] & 0x01) ? 7 : 9;
},
getFullFrameLength: function getFullFrameLength(data, offset) {
return (data[offset + 3] & 0x03) << 11 | data[offset + 4] << 3 | (data[offset + 5] & 0xE0) >>> 5;
},
isHeader: function isHeader(data, offset) {
// Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
// Layer bits (position 14 and 15) in header should be always 0 for ADTS
// More info https://wiki.multimedia.cx/index.php?title=ADTS
if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) {
return true;
}
return false;
},
probe: function probe(data, offset) {
// same as isHeader but we also check that ADTS frame follows last ADTS frame
// or end of data is reached
if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) {
// ADTS header Length
var headerLength = this.getHeaderLength(data, offset);
// ADTS frame Length
var frameLength = headerLength;
if (offset + 5 < data.length) {
frameLength = this.getFullFrameLength(data, offset);
}
var newOffset = offset + frameLength;
if (newOffset === data.length || newOffset + 1 < data.length && this.isHeaderPattern(data, newOffset)) {
return true;
}
}
return false;
},
initTrackConfig: function initTrackConfig(track, observer, data, offset, audioCodec) {
if (!track.samplerate) {
var config = this.getAudioConfig(observer, data, offset, audioCodec);
track.config = config.config;
track.samplerate = config.samplerate;
track.channelCount = config.channelCount;
track.codec = config.codec;
track.manifestCodec = config.manifestCodec;
_logger.logger.log('parsed codec:' + track.codec + ',rate:' + config.samplerate + ',nb channel:' + config.channelCount);
}
},
getFrameDuration: function getFrameDuration(samplerate) {
return 1024 * 90000 / samplerate;
},
appendFrame: function appendFrame(track, data, offset, pts, frameIndex) {
var frameDuration = this.getFrameDuration(track.samplerate);
var header = this.parseFrameHeader(data, offset, pts, frameIndex, frameDuration);
if (header) {
var stamp = header.stamp;
var headerLength = header.headerLength;
var frameLength = header.frameLength;
//logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`);
var aacSample = { unit: data.subarray(offset + headerLength, offset + headerLength + frameLength), pts: stamp, dts: stamp };
track.samples.push(aacSample);
track.len += frameLength;
return { sample: aacSample, length: frameLength + headerLength };
}
return undefined;
},
parseFrameHeader: function parseFrameHeader(data, offset, pts, frameIndex, frameDuration) {
var headerLength, frameLength, stamp;
var length = data.length;
// The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header
headerLength = this.getHeaderLength(data, offset);
// retrieve frame size
frameLength = this.getFullFrameLength(data, offset);
frameLength -= headerLength;
if (frameLength > 0 && offset + headerLength + frameLength <= length) {
stamp = pts + frameIndex * frameDuration;
//logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`);
return { headerLength: headerLength, frameLength: frameLength, stamp: stamp };
}
return undefined;
}
};
module.exports = ADTS;

View File

@@ -0,0 +1,148 @@
'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; }; }(); /* inline demuxer.
* probe fragments and instantiate appropriate demuxer depending on content type (TSDemuxer, AACDemuxer, ...)
*/
var _events = require('../events');
var _events2 = _interopRequireDefault(_events);
var _errors = require('../errors');
var _decrypter = require('../crypt/decrypter');
var _decrypter2 = _interopRequireDefault(_decrypter);
var _aacdemuxer = require('../demux/aacdemuxer');
var _aacdemuxer2 = _interopRequireDefault(_aacdemuxer);
var _mp4demuxer = require('../demux/mp4demuxer');
var _mp4demuxer2 = _interopRequireDefault(_mp4demuxer);
var _tsdemuxer = require('../demux/tsdemuxer');
var _tsdemuxer2 = _interopRequireDefault(_tsdemuxer);
var _mp3demuxer = require('../demux/mp3demuxer');
var _mp3demuxer2 = _interopRequireDefault(_mp3demuxer);
var _mp4Remuxer = require('../remux/mp4-remuxer');
var _mp4Remuxer2 = _interopRequireDefault(_mp4Remuxer);
var _passthroughRemuxer = require('../remux/passthrough-remuxer');
var _passthroughRemuxer2 = _interopRequireDefault(_passthroughRemuxer);
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 DemuxerInline = function () {
function DemuxerInline(observer, typeSupported, config, vendor) {
_classCallCheck(this, DemuxerInline);
this.observer = observer;
this.typeSupported = typeSupported;
this.config = config;
this.vendor = vendor;
}
_createClass(DemuxerInline, [{
key: 'destroy',
value: function destroy() {
var demuxer = this.demuxer;
if (demuxer) {
demuxer.destroy();
}
}
}, {
key: 'push',
value: function push(data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS) {
if (data.byteLength > 0 && decryptdata != null && decryptdata.key != null && decryptdata.method === 'AES-128') {
var decrypter = this.decrypter;
if (decrypter == null) {
decrypter = this.decrypter = new _decrypter2.default(this.observer, this.config);
}
var localthis = this;
// performance.now() not available on WebWorker, at least on Safari Desktop
var startTime;
try {
startTime = performance.now();
} catch (error) {
startTime = Date.now();
}
decrypter.decrypt(data, decryptdata.key.buffer, decryptdata.iv.buffer, function (decryptedData) {
var endTime;
try {
endTime = performance.now();
} catch (error) {
endTime = Date.now();
}
localthis.observer.trigger(_events2.default.FRAG_DECRYPTED, { stats: { tstart: startTime, tdecrypt: endTime } });
localthis.pushDecrypted(new Uint8Array(decryptedData), decryptdata, new Uint8Array(initSegment), audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS);
});
} else {
this.pushDecrypted(new Uint8Array(data), decryptdata, new Uint8Array(initSegment), audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS);
}
}
}, {
key: 'pushDecrypted',
value: function pushDecrypted(data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS) {
var demuxer = this.demuxer;
if (!demuxer ||
// in case of continuity change, we might switch from content type (AAC container to TS container for example)
// so let's check that current demuxer is still valid
discontinuity && !this.probe(data)) {
var observer = this.observer;
var typeSupported = this.typeSupported;
var config = this.config;
// probing order is AAC/MP3/TS/MP4
var muxConfig = [{ demux: _aacdemuxer2.default, remux: _mp4Remuxer2.default }, { demux: _mp3demuxer2.default, remux: _mp4Remuxer2.default }, { demux: _tsdemuxer2.default, remux: _mp4Remuxer2.default }, { demux: _mp4demuxer2.default, remux: _passthroughRemuxer2.default }];
// probe for content type
for (var i = 0, len = muxConfig.length; i < len; i++) {
var mux = muxConfig[i];
var probe = mux.demux.probe;
if (probe(data)) {
var _remuxer = this.remuxer = new mux.remux(observer, config, typeSupported, this.vendor);
demuxer = new mux.demux(observer, _remuxer, config, typeSupported);
this.probe = probe;
break;
}
}
if (!demuxer) {
observer.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: 'no demux matching with content found' });
return;
}
this.demuxer = demuxer;
}
var remuxer = this.remuxer;
if (discontinuity || trackSwitch) {
demuxer.resetInitSegment(initSegment, audioCodec, videoCodec, duration);
remuxer.resetInitSegment();
}
if (discontinuity) {
demuxer.resetTimeStamp(defaultInitPTS);
remuxer.resetTimeStamp(defaultInitPTS);
}
if (typeof demuxer.setDecryptData === 'function') {
demuxer.setDecryptData(decryptdata);
}
demuxer.append(data, timeOffset, contiguous, accurateTimeOffset);
}
}]);
return DemuxerInline;
}();
exports.default = DemuxerInline;

View File

@@ -0,0 +1,101 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _demuxerInline = require('../demux/demuxer-inline');
var _demuxerInline2 = _interopRequireDefault(_demuxerInline);
var _events = require('../events');
var _events2 = _interopRequireDefault(_events);
var _logger = require('../utils/logger');
var _events3 = require('events');
var _events4 = _interopRequireDefault(_events3);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* demuxer web worker.
* - listen to worker message, and trigger DemuxerInline upon reception of Fragments.
* - provides MP4 Boxes back to main thread using [transferable objects](https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast) in order to minimize message passing overhead.
*/
var DemuxerWorker = function DemuxerWorker(self) {
// observer setup
var observer = new _events4.default();
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 forwardMessage(ev, data) {
self.postMessage({ event: ev, data: data });
};
self.addEventListener('message', function (ev) {
var data = ev.data;
//console.log('demuxer cmd:' + data.cmd);
switch (data.cmd) {
case 'init':
var config = JSON.parse(data.config);
self.demuxer = new _demuxerInline2.default(observer, data.typeSupported, config, data.vendor);
try {
(0, _logger.enableLogs)(config.debug === true);
} catch (err) {
console.warn('demuxerWorker: unable to enable logs');
}
// signal end of worker init
forwardMessage('init', null);
break;
case 'demux':
self.demuxer.push(data.data, data.decryptdata, data.initSegment, data.audioCodec, data.videoCodec, data.timeOffset, data.discontinuity, data.trackSwitch, data.contiguous, data.duration, data.accurateTimeOffset, data.defaultInitPTS);
break;
default:
break;
}
});
// 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_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);
// special case for FRAG_PARSING_DATA: pass data1/data2 as transferable object (no copy)
observer.on(_events2.default.FRAG_PARSING_DATA, function (ev, data) {
var transferable = [];
var message = { event: ev, data: data };
if (data.data1) {
message.data1 = data.data1.buffer;
transferable.push(data.data1.buffer);
delete data.data1;
}
if (data.data2) {
message.data2 = data.data2.buffer;
transferable.push(data.data2.buffer);
delete data.data2;
}
self.postMessage(message, transferable);
});
};
exports.default = DemuxerWorker;

189
Skills/@be/be/node_modules/hls.js/lib/demux/demuxer.js generated vendored Normal file
View File

@@ -0,0 +1,189 @@
'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;

View File

@@ -0,0 +1,370 @@
'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; }; }(); /**
* Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.
*/
var _logger = require('../utils/logger');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var ExpGolomb = function () {
function ExpGolomb(data) {
_classCallCheck(this, ExpGolomb);
this.data = data;
// the number of bytes left to examine in this.data
this.bytesAvailable = data.byteLength;
// the current word being examined
this.word = 0; // :uint
// the number of bits left to examine in the current word
this.bitsAvailable = 0; // :uint
}
// ():void
_createClass(ExpGolomb, [{
key: 'loadWord',
value: function loadWord() {
var data = this.data,
bytesAvailable = this.bytesAvailable,
position = data.byteLength - bytesAvailable,
workingBytes = new Uint8Array(4),
availableBytes = Math.min(4, bytesAvailable);
if (availableBytes === 0) {
throw new Error('no bytes available');
}
workingBytes.set(data.subarray(position, position + availableBytes));
this.word = new DataView(workingBytes.buffer).getUint32(0);
// track the amount of this.data that has been processed
this.bitsAvailable = availableBytes * 8;
this.bytesAvailable -= availableBytes;
}
// (count:int):void
}, {
key: 'skipBits',
value: function skipBits(count) {
var skipBytes; // :int
if (this.bitsAvailable > count) {
this.word <<= count;
this.bitsAvailable -= count;
} else {
count -= this.bitsAvailable;
skipBytes = count >> 3;
count -= skipBytes >> 3;
this.bytesAvailable -= skipBytes;
this.loadWord();
this.word <<= count;
this.bitsAvailable -= count;
}
}
// (size:int):uint
}, {
key: 'readBits',
value: function readBits(size) {
var bits = Math.min(this.bitsAvailable, size),
// :uint
valu = this.word >>> 32 - bits; // :uint
if (size > 32) {
_logger.logger.error('Cannot read more than 32 bits at a time');
}
this.bitsAvailable -= bits;
if (this.bitsAvailable > 0) {
this.word <<= bits;
} else if (this.bytesAvailable > 0) {
this.loadWord();
}
bits = size - bits;
if (bits > 0 && this.bitsAvailable) {
return valu << bits | this.readBits(bits);
} else {
return valu;
}
}
// ():uint
}, {
key: 'skipLZ',
value: function skipLZ() {
var leadingZeroCount; // :uint
for (leadingZeroCount = 0; leadingZeroCount < this.bitsAvailable; ++leadingZeroCount) {
if (0 !== (this.word & 0x80000000 >>> leadingZeroCount)) {
// the first bit of working word is 1
this.word <<= leadingZeroCount;
this.bitsAvailable -= leadingZeroCount;
return leadingZeroCount;
}
}
// we exhausted word and still have not found a 1
this.loadWord();
return leadingZeroCount + this.skipLZ();
}
// ():void
}, {
key: 'skipUEG',
value: function skipUEG() {
this.skipBits(1 + this.skipLZ());
}
// ():void
}, {
key: 'skipEG',
value: function skipEG() {
this.skipBits(1 + this.skipLZ());
}
// ():uint
}, {
key: 'readUEG',
value: function readUEG() {
var clz = this.skipLZ(); // :uint
return this.readBits(clz + 1) - 1;
}
// ():int
}, {
key: 'readEG',
value: function readEG() {
var valu = this.readUEG(); // :int
if (0x01 & valu) {
// the number is odd if the low order bit is set
return 1 + valu >>> 1; // add 1 to make it even, and divide by 2
} else {
return -1 * (valu >>> 1); // divide by two then make it negative
}
}
// Some convenience functions
// :Boolean
}, {
key: 'readBoolean',
value: function readBoolean() {
return 1 === this.readBits(1);
}
// ():int
}, {
key: 'readUByte',
value: function readUByte() {
return this.readBits(8);
}
// ():int
}, {
key: 'readUShort',
value: function readUShort() {
return this.readBits(16);
}
// ():int
}, {
key: 'readUInt',
value: function readUInt() {
return this.readBits(32);
}
/**
* Advance the ExpGolomb decoder past a scaling list. The scaling
* list is optionally transmitted as part of a sequence parameter
* set and is not relevant to transmuxing.
* @param count {number} the number of entries in this scaling list
* @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
*/
}, {
key: 'skipScalingList',
value: function skipScalingList(count) {
var lastScale = 8,
nextScale = 8,
j,
deltaScale;
for (j = 0; j < count; j++) {
if (nextScale !== 0) {
deltaScale = this.readEG();
nextScale = (lastScale + deltaScale + 256) % 256;
}
lastScale = nextScale === 0 ? lastScale : nextScale;
}
}
/**
* Read a sequence parameter set and return some interesting video
* properties. A sequence parameter set is the H264 metadata that
* describes the properties of upcoming video frames.
* @param data {Uint8Array} the bytes of a sequence parameter set
* @return {object} an object with configuration parsed from the
* sequence parameter set, including the dimensions of the
* associated video frames.
*/
}, {
key: 'readSPS',
value: function readSPS() {
var frameCropLeftOffset = 0,
frameCropRightOffset = 0,
frameCropTopOffset = 0,
frameCropBottomOffset = 0,
profileIdc,
profileCompat,
levelIdc,
numRefFramesInPicOrderCntCycle,
picWidthInMbsMinus1,
picHeightInMapUnitsMinus1,
frameMbsOnlyFlag,
scalingListCount,
i,
readUByte = this.readUByte.bind(this),
readBits = this.readBits.bind(this),
readUEG = this.readUEG.bind(this),
readBoolean = this.readBoolean.bind(this),
skipBits = this.skipBits.bind(this),
skipEG = this.skipEG.bind(this),
skipUEG = this.skipUEG.bind(this),
skipScalingList = this.skipScalingList.bind(this);
readUByte();
profileIdc = readUByte(); // profile_idc
profileCompat = readBits(5); // constraint_set[0-4]_flag, u(5)
skipBits(3); // reserved_zero_3bits u(3),
levelIdc = readUByte(); //level_idc u(8)
skipUEG(); // seq_parameter_set_id
// some profiles have more optional data we don't need
if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
var chromaFormatIdc = readUEG();
if (chromaFormatIdc === 3) {
skipBits(1); // separate_colour_plane_flag
}
skipUEG(); // bit_depth_luma_minus8
skipUEG(); // bit_depth_chroma_minus8
skipBits(1); // qpprime_y_zero_transform_bypass_flag
if (readBoolean()) {
// seq_scaling_matrix_present_flag
scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
for (i = 0; i < scalingListCount; i++) {
if (readBoolean()) {
// seq_scaling_list_present_flag[ i ]
if (i < 6) {
skipScalingList(16);
} else {
skipScalingList(64);
}
}
}
}
}
skipUEG(); // log2_max_frame_num_minus4
var picOrderCntType = readUEG();
if (picOrderCntType === 0) {
readUEG(); //log2_max_pic_order_cnt_lsb_minus4
} else if (picOrderCntType === 1) {
skipBits(1); // delta_pic_order_always_zero_flag
skipEG(); // offset_for_non_ref_pic
skipEG(); // offset_for_top_to_bottom_field
numRefFramesInPicOrderCntCycle = readUEG();
for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
skipEG(); // offset_for_ref_frame[ i ]
}
}
skipUEG(); // max_num_ref_frames
skipBits(1); // gaps_in_frame_num_value_allowed_flag
picWidthInMbsMinus1 = readUEG();
picHeightInMapUnitsMinus1 = readUEG();
frameMbsOnlyFlag = readBits(1);
if (frameMbsOnlyFlag === 0) {
skipBits(1); // mb_adaptive_frame_field_flag
}
skipBits(1); // direct_8x8_inference_flag
if (readBoolean()) {
// frame_cropping_flag
frameCropLeftOffset = readUEG();
frameCropRightOffset = readUEG();
frameCropTopOffset = readUEG();
frameCropBottomOffset = readUEG();
}
var pixelRatio = [1, 1];
if (readBoolean()) {
// vui_parameters_present_flag
if (readBoolean()) {
// aspect_ratio_info_present_flag
var aspectRatioIdc = readUByte();
switch (aspectRatioIdc) {
case 1:
pixelRatio = [1, 1];break;
case 2:
pixelRatio = [12, 11];break;
case 3:
pixelRatio = [10, 11];break;
case 4:
pixelRatio = [16, 11];break;
case 5:
pixelRatio = [40, 33];break;
case 6:
pixelRatio = [24, 11];break;
case 7:
pixelRatio = [20, 11];break;
case 8:
pixelRatio = [32, 11];break;
case 9:
pixelRatio = [80, 33];break;
case 10:
pixelRatio = [18, 11];break;
case 11:
pixelRatio = [15, 11];break;
case 12:
pixelRatio = [64, 33];break;
case 13:
pixelRatio = [160, 99];break;
case 14:
pixelRatio = [4, 3];break;
case 15:
pixelRatio = [3, 2];break;
case 16:
pixelRatio = [2, 1];break;
case 255:
{
pixelRatio = [readUByte() << 8 | readUByte(), readUByte() << 8 | readUByte()];
break;
}
}
}
}
return {
width: Math.ceil((picWidthInMbsMinus1 + 1) * 16 - frameCropLeftOffset * 2 - frameCropRightOffset * 2),
height: (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 - (frameMbsOnlyFlag ? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset),
pixelRatio: pixelRatio
};
}
}, {
key: 'readSliceType',
value: function readSliceType() {
// skip NALu type
this.readUByte();
// discard first_mb_in_slice
this.readUEG();
// return slice_type
return this.readUEG();
}
}]);
return ExpGolomb;
}();
exports.default = ExpGolomb;

372
Skills/@be/be/node_modules/hls.js/lib/demux/id3.js generated vendored Normal file
View File

@@ -0,0 +1,372 @@
'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; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* ID3 parser
*/
var ID3 = function () {
function ID3() {
_classCallCheck(this, ID3);
}
_createClass(ID3, null, [{
key: 'isHeader',
/**
* Returns true if an ID3 header can be found at offset in data
* @param {Uint8Array} data - The data to search in
* @param {number} offset - The offset at which to start searching
* @return {boolean} - True if an ID3 header is found
*/
value: function isHeader(data, offset) {
/*
* http://id3.org/id3v2.3.0
* [0] = 'I'
* [1] = 'D'
* [2] = '3'
* [3,4] = {Version}
* [5] = {Flags}
* [6-9] = {ID3 Size}
*
* An ID3v2 tag can be detected with the following pattern:
* $49 44 33 yy yy xx zz zz zz zz
* Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
*/
if (offset + 10 <= data.length) {
//look for 'ID3' identifier
if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
//check version is within range
if (data[offset + 3] < 0xFF && data[offset + 4] < 0xFF) {
//check size is within range
if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
return true;
}
}
}
}
return false;
}
/**
* Returns true if an ID3 footer can be found at offset in data
* @param {Uint8Array} data - The data to search in
* @param {number} offset - The offset at which to start searching
* @return {boolean} - True if an ID3 footer is found
*/
}, {
key: 'isFooter',
value: function isFooter(data, offset) {
/*
* The footer is a copy of the header, but with a different identifier
*/
if (offset + 10 <= data.length) {
//look for '3DI' identifier
if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
//check version is within range
if (data[offset + 3] < 0xFF && data[offset + 4] < 0xFF) {
//check size is within range
if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
return true;
}
}
}
}
return false;
}
/**
* Returns any adjacent ID3 tags found in data starting at offset, as one block of data
* @param {Uint8Array} data - The data to search in
* @param {number} offset - The offset at which to start searching
* @return {Uint8Array} - The block of data containing any ID3 tags found
*/
}, {
key: 'getID3Data',
value: function getID3Data(data, offset) {
var front = offset;
var length = 0;
while (ID3.isHeader(data, offset)) {
//ID3 header is 10 bytes
length += 10;
var size = ID3._readSize(data, offset + 6);
length += size;
if (ID3.isFooter(data, offset + 10)) {
//ID3 footer is 10 bytes
length += 10;
}
offset += length;
}
if (length > 0) {
return data.subarray(front, front + length);
}
return undefined;
}
}, {
key: '_readSize',
value: function _readSize(data, offset) {
var size = 0;
size = (data[offset] & 0x7f) << 21;
size |= (data[offset + 1] & 0x7f) << 14;
size |= (data[offset + 2] & 0x7f) << 7;
size |= data[offset + 3] & 0x7f;
return size;
}
/**
* Searches for the Elementary Stream timestamp found in the ID3 data chunk
* @param {Uint8Array} data - Block of data containing one or more ID3 tags
* @return {number} - The timestamp
*/
}, {
key: 'getTimeStamp',
value: function getTimeStamp(data) {
var frames = ID3.getID3Frames(data);
for (var i = 0; i < frames.length; i++) {
var frame = frames[i];
if (ID3.isTimeStampFrame(frame)) {
return ID3._readTimeStamp(frame);
}
}
return undefined;
}
/**
* Returns true if the ID3 frame is an Elementary Stream timestamp frame
* @param {ID3 frame} frame
*/
}, {
key: 'isTimeStampFrame',
value: function isTimeStampFrame(frame) {
return frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp';
}
}, {
key: '_getFrameData',
value: function _getFrameData(data) {
/*
Frame ID $xx xx xx xx (four characters)
Size $xx xx xx xx
Flags $xx xx
*/
var type = String.fromCharCode(data[0], data[1], data[2], data[3]);
var size = ID3._readSize(data, 4);
//skip frame id, size, and flags
var offset = 10;
return { type: type, size: size, data: data.subarray(offset, offset + size) };
}
/**
* Returns an array of ID3 frames found in all the ID3 tags in the id3Data
* @param {Uint8Array} id3Data - The ID3 data containing one or more ID3 tags
* @return {ID3 frame[]} - Array of ID3 frame objects
*/
}, {
key: 'getID3Frames',
value: function getID3Frames(id3Data) {
var offset = 0;
var frames = [];
while (ID3.isHeader(id3Data, offset)) {
var size = ID3._readSize(id3Data, offset + 6);
//skip past ID3 header
offset += 10;
var end = offset + size;
//loop through frames in the ID3 tag
while (offset + 8 < end) {
var frameData = ID3._getFrameData(id3Data.subarray(offset));
var frame = ID3._decodeFrame(frameData);
if (frame) {
frames.push(frame);
}
//skip frame header and frame data
offset += frameData.size + 10;
}
if (ID3.isFooter(id3Data, offset)) {
offset += 10;
}
}
return frames;
}
}, {
key: '_decodeFrame',
value: function _decodeFrame(frame) {
if (frame.type === 'PRIV') {
return ID3._decodePrivFrame(frame);
} else if (frame.type[0] === 'T') {
return ID3._decodeTextFrame(frame);
} else if (frame.type[0] === 'W') {
return ID3._decodeURLFrame(frame);
}
return undefined;
}
}, {
key: '_readTimeStamp',
value: function _readTimeStamp(timeStampFrame) {
if (timeStampFrame.data.byteLength === 8) {
var data = new Uint8Array(timeStampFrame.data);
// timestamp is 33 bit expressed as a big-endian eight-octet number,
// with the upper 31 bits set to zero.
var pts33Bit = data[3] & 0x1;
var timestamp = (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];
timestamp /= 45;
if (pts33Bit) {
timestamp += 47721858.84; // 2^32 / 90
}
return Math.round(timestamp);
}
return undefined;
}
}, {
key: '_decodePrivFrame',
value: function _decodePrivFrame(frame) {
/*
Format: <text string>\0<binary data>
*/
if (frame.size < 2) {
return undefined;
}
var owner = ID3._utf8ArrayToStr(frame.data);
var privateData = new Uint8Array(frame.data.subarray(owner.length + 1));
return { key: frame.type, info: owner, data: privateData.buffer };
}
}, {
key: '_decodeTextFrame',
value: function _decodeTextFrame(frame) {
if (frame.size < 2) {
return undefined;
}
if (frame.type === 'TXXX') {
/*
Format:
[0] = {Text Encoding}
[1-?] = {Description}\0{Value}
*/
var index = 1;
var description = ID3._utf8ArrayToStr(frame.data.subarray(index));
index += description.length + 1;
var value = ID3._utf8ArrayToStr(frame.data.subarray(index));
return { key: frame.type, info: description, data: value };
} else {
/*
Format:
[0] = {Text Encoding}
[1-?] = {Value}
*/
var text = ID3._utf8ArrayToStr(frame.data.subarray(1));
return { key: frame.type, data: text };
}
}
}, {
key: '_decodeURLFrame',
value: function _decodeURLFrame(frame) {
if (frame.type === 'WXXX') {
/*
Format:
[0] = {Text Encoding}
[1-?] = {Description}\0{URL}
*/
if (frame.size < 2) {
return undefined;
}
var index = 1;
var description = ID3._utf8ArrayToStr(frame.data.subarray(index));
index += description.length + 1;
var value = ID3._utf8ArrayToStr(frame.data.subarray(index));
return { key: frame.type, info: description, data: value };
} else {
/*
Format:
[0-?] = {URL}
*/
var url = ID3._utf8ArrayToStr(frame.data);
return { key: frame.type, data: url };
}
}
// http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
/* utf.js - UTF-8 <=> UTF-16 convertion
*
* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
* Version: 1.0
* LastModified: Dec 25 1999
* This library is free. You can redistribute it and/or modify it.
*/
}, {
key: '_utf8ArrayToStr',
value: function _utf8ArrayToStr(array) {
var char2 = void 0;
var char3 = void 0;
var out = '';
var i = 0;
var length = array.length;
while (i < length) {
var c = array[i++];
switch (c >> 4) {
case 0:
return out;
case 1:case 2:case 3:case 4:case 5:case 6:case 7:
// 0xxxxxxx
out += String.fromCharCode(c);
break;
case 12:case 13:
// 110x xxxx 10xx xxxx
char2 = array[i++];
out += String.fromCharCode((c & 0x1F) << 6 | char2 & 0x3F);
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = array[i++];
char3 = array[i++];
out += String.fromCharCode((c & 0x0F) << 12 | (char2 & 0x3F) << 6 | (char3 & 0x3F) << 0);
break;
}
}
return out;
}
}]);
return ID3;
}();
exports.default = ID3;

View File

@@ -0,0 +1,109 @@
'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; }; }(); /**
* MP3 demuxer
*/
var _id = require('../demux/id3');
var _id2 = _interopRequireDefault(_id);
var _logger = require('../utils/logger');
var _mpegaudio = require('./mpegaudio');
var _mpegaudio2 = _interopRequireDefault(_mpegaudio);
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 MP3Demuxer = function () {
function MP3Demuxer(observer, remuxer, config) {
_classCallCheck(this, MP3Demuxer);
this.observer = observer;
this.config = config;
this.remuxer = remuxer;
}
_createClass(MP3Demuxer, [{
key: 'resetInitSegment',
value: function resetInitSegment(initSegment, audioCodec, videoCodec, duration) {
this._audioTrack = { container: 'audio/mpeg', type: 'audio', id: -1, sequenceNumber: 0, isAAC: false, samples: [], len: 0, manifestCodec: audioCodec, duration: duration, inputTimeScale: 90000 };
}
}, {
key: 'resetTimeStamp',
value: function resetTimeStamp() {}
}, {
key: 'append',
// feed incoming data to the front of the parsing pipeline
value: function append(data, timeOffset, contiguous, accurateTimeOffset) {
var id3Data = _id2.default.getID3Data(data, 0);
var pts = 90 * _id2.default.getTimeStamp(id3Data);
var offset = id3Data.length;
var length = data.length;
var frameIndex = 0,
stamp = 0;
var track = this._audioTrack;
var id3Samples = [{ pts: pts, dts: pts, data: id3Data }];
while (offset < length) {
if (_mpegaudio2.default.isHeader(data, offset)) {
var frame = _mpegaudio2.default.appendFrame(track, data, offset, pts, frameIndex);
if (frame) {
offset += frame.length;
stamp = frame.sample.pts;
frameIndex++;
} else {
//logger.log('Unable to parse Mpeg audio frame');
break;
}
} else if (_id2.default.isHeader(data, offset)) {
id3Data = _id2.default.getID3Data(data, offset);
id3Samples.push({ pts: stamp, dts: stamp, data: id3Data });
offset += id3Data.length;
} else {
//nothing found, keep looking
offset++;
}
}
this.remuxer.remux(track, { samples: [] }, { samples: id3Samples, inputTimeScale: 90000 }, { samples: [] }, timeOffset, contiguous, accurateTimeOffset);
}
}, {
key: 'destroy',
value: function destroy() {}
}], [{
key: 'probe',
value: function probe(data) {
// check if data contains ID3 timestamp and MPEG sync word
var offset, length;
var id3Data = _id2.default.getID3Data(data, 0);
if (id3Data && _id2.default.getTimeStamp(id3Data) !== undefined) {
// Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
// Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
// More info http://www.mp3-tech.org/programmer/frame_header.html
for (offset = id3Data.length, length = Math.min(data.length - 1, offset + 100); offset < length; offset++) {
if (_mpegaudio2.default.probe(data, offset)) {
_logger.logger.log('MPEG Audio sync word found !');
return true;
}
}
}
return false;
}
}]);
return MP3Demuxer;
}();
exports.default = MP3Demuxer;

View File

@@ -0,0 +1,323 @@
'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; }; }(); /**
* MP4 demuxer
*/
//import {logger} from '../utils/logger';
var _events = require('../events');
var _events2 = _interopRequireDefault(_events);
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 UINT32_MAX = Math.pow(2, 32) - 1;
var MP4Demuxer = function () {
function MP4Demuxer(observer, remuxer) {
_classCallCheck(this, MP4Demuxer);
this.observer = observer;
this.remuxer = remuxer;
}
_createClass(MP4Demuxer, [{
key: 'resetTimeStamp',
value: function resetTimeStamp(initPTS) {
this.initPTS = initPTS;
}
}, {
key: 'resetInitSegment',
value: function resetInitSegment(initSegment, audioCodec, videoCodec, duration) {
//jshint unused:false
if (initSegment && initSegment.byteLength) {
var initData = this.initData = MP4Demuxer.parseInitSegment(initSegment);
var tracks = {};
if (initData.audio) {
tracks.audio = { container: 'audio/mp4', codec: audioCodec, initSegment: duration ? initSegment : null };
}
if (initData.video) {
tracks.video = { container: 'video/mp4', codec: videoCodec, initSegment: duration ? initSegment : null };
}
this.observer.trigger(_events2.default.FRAG_PARSING_INIT_SEGMENT, { tracks: tracks });
} else {
if (audioCodec) {
this.audioCodec = audioCodec;
}
if (videoCodec) {
this.videoCodec = videoCodec;
}
}
}
}, {
key: 'append',
// feed incoming data to the front of the parsing pipeline
value: function append(data, timeOffset, contiguous, accurateTimeOffset) {
var initData = this.initData;
if (!initData) {
this.resetInitSegment(data, this.audioCodec, this.videoCodec);
initData = this.initData;
}
var startDTS = void 0,
initPTS = this.initPTS;
if (initPTS === undefined) {
var _startDTS = MP4Demuxer.getStartDTS(initData, data);
this.initPTS = initPTS = _startDTS - timeOffset;
this.observer.trigger(_events2.default.INIT_PTS_FOUND, { initPTS: initPTS });
}
MP4Demuxer.offsetStartDTS(initData, data, initPTS);
startDTS = MP4Demuxer.getStartDTS(initData, data);
this.remuxer.remux(initData.audio, initData.video, null, null, startDTS, contiguous, accurateTimeOffset, data);
}
}, {
key: 'destroy',
value: function destroy() {}
}], [{
key: 'probe',
value: function probe(data) {
if (data.length >= 8) {
var dataType = MP4Demuxer.bin2str(data.subarray(4, 8));
return ['moof', 'ftyp', 'styp'].indexOf(dataType) >= 0;
}
return false;
}
}, {
key: 'bin2str',
value: function bin2str(buffer) {
return String.fromCharCode.apply(null, buffer);
}
}, {
key: 'readUint32',
value: function readUint32(buffer, offset) {
if (buffer.data) {
offset += buffer.start;
buffer = buffer.data;
}
var val = buffer[offset] << 24 | buffer[offset + 1] << 16 | buffer[offset + 2] << 8 | buffer[offset + 3];
return val < 0 ? 4294967296 + val : val;
}
}, {
key: 'writeUint32',
value: function writeUint32(buffer, offset, value) {
if (buffer.data) {
offset += buffer.start;
buffer = buffer.data;
}
buffer[offset] = value >> 24;
buffer[offset + 1] = value >> 16 & 0xff;
buffer[offset + 2] = value >> 8 & 0xff;
buffer[offset + 3] = value & 0xff;
}
// Find the data for a box specified by its path
}, {
key: 'findBox',
value: function findBox(data, path) {
var results = [],
i,
size,
type,
end,
subresults,
start,
endbox;
if (data.data) {
start = data.start;
end = data.end;
data = data.data;
} else {
start = 0;
end = data.byteLength;
}
if (!path.length) {
// short-circuit the search for empty paths
return null;
}
for (i = start; i < end;) {
size = MP4Demuxer.readUint32(data, i);
type = MP4Demuxer.bin2str(data.subarray(i + 4, i + 8));
endbox = size > 1 ? i + size : end;
if (type === path[0]) {
if (path.length === 1) {
// this is the end of the path and we've found the box we were
// looking for
results.push({ data: data, start: i + 8, end: endbox });
} else {
// recursively search for the next box along the path
subresults = MP4Demuxer.findBox({ data: data, start: i + 8, end: endbox }, path.slice(1));
if (subresults.length) {
results = results.concat(subresults);
}
}
}
i = endbox;
}
// we've finished searching all of data
return results;
}
/**
* Parses an MP4 initialization segment and extracts stream type and
* timescale values for any declared tracks. Timescale values indicate the
* number of clock ticks per second to assume for time-based values
* elsewhere in the MP4.
*
* To determine the start time of an MP4, you need two pieces of
* information: the timescale unit and the earliest base media decode
* time. Multiple timescales can be specified within an MP4 but the
* base media decode time is always expressed in the timescale from
* the media header box for the track:
* ```
* moov > trak > mdia > mdhd.timescale
* moov > trak > mdia > hdlr
* ```
* @param init {Uint8Array} the bytes of the init segment
* @return {object} a hash of track type to timescale values or null if
* the init segment is malformed.
*/
}, {
key: 'parseInitSegment',
value: function parseInitSegment(initSegment) {
var result = [];
var traks = MP4Demuxer.findBox(initSegment, ['moov', 'trak']);
traks.forEach(function (trak) {
var tkhd = MP4Demuxer.findBox(trak, ['tkhd'])[0];
if (tkhd) {
var version = tkhd.data[tkhd.start];
var index = version === 0 ? 12 : 20;
var trackId = MP4Demuxer.readUint32(tkhd, index);
var mdhd = MP4Demuxer.findBox(trak, ['mdia', 'mdhd'])[0];
if (mdhd) {
version = mdhd.data[mdhd.start];
index = version === 0 ? 12 : 20;
var timescale = MP4Demuxer.readUint32(mdhd, index);
var hdlr = MP4Demuxer.findBox(trak, ['mdia', 'hdlr'])[0];
if (hdlr) {
var hdlrType = MP4Demuxer.bin2str(hdlr.data.subarray(hdlr.start + 8, hdlr.start + 12));
var type = { 'soun': 'audio', 'vide': 'video' }[hdlrType];
if (type) {
result[trackId] = { timescale: timescale, type: type };
result[type] = { timescale: timescale, id: trackId };
}
}
}
}
});
return result;
}
/**
* Determine the base media decode start time, in seconds, for an MP4
* fragment. If multiple fragments are specified, the earliest time is
* returned.
*
* The base media decode time can be parsed from track fragment
* metadata:
* ```
* moof > traf > tfdt.baseMediaDecodeTime
* ```
* It requires the timescale value from the mdhd to interpret.
*
* @param timescale {object} a hash of track ids to timescale values.
* @return {number} the earliest base media decode start time for the
* fragment, in seconds
*/
}, {
key: 'getStartDTS',
value: function getStartDTS(initData, fragment) {
var trafs, baseTimes, result;
// we need info from two childrend of each track fragment box
trafs = MP4Demuxer.findBox(fragment, ['moof', 'traf']);
// determine the start times for each track
baseTimes = [].concat.apply([], trafs.map(function (traf) {
return MP4Demuxer.findBox(traf, ['tfhd']).map(function (tfhd) {
var id, scale, baseTime;
// get the track id from the tfhd
id = MP4Demuxer.readUint32(tfhd, 4);
// assume a 90kHz clock if no timescale was specified
scale = initData[id].timescale || 90e3;
// get the base media decode time from the tfdt
baseTime = MP4Demuxer.findBox(traf, ['tfdt']).map(function (tfdt) {
var version, result;
version = tfdt.data[tfdt.start];
result = MP4Demuxer.readUint32(tfdt, 4);
if (version === 1) {
result *= Math.pow(2, 32);
result += MP4Demuxer.readUint32(tfdt, 8);
}
return result;
})[0];
baseTime = baseTime || Infinity;
// convert base time to seconds
return baseTime / scale;
});
}));
// return the minimum
result = Math.min.apply(null, baseTimes);
return isFinite(result) ? result : 0;
}
}, {
key: 'offsetStartDTS',
value: function offsetStartDTS(initData, fragment, timeOffset) {
MP4Demuxer.findBox(fragment, ['moof', 'traf']).map(function (traf) {
return MP4Demuxer.findBox(traf, ['tfhd']).map(function (tfhd) {
// get the track id from the tfhd
var id = MP4Demuxer.readUint32(tfhd, 4);
// assume a 90kHz clock if no timescale was specified
var timescale = initData[id].timescale || 90e3;
// get the base media decode time from the tfdt
MP4Demuxer.findBox(traf, ['tfdt']).map(function (tfdt) {
var version = tfdt.data[tfdt.start];
var baseMediaDecodeTime = MP4Demuxer.readUint32(tfdt, 4);
if (version === 0) {
MP4Demuxer.writeUint32(tfdt, 4, baseMediaDecodeTime - timeOffset * timescale);
} else {
baseMediaDecodeTime *= Math.pow(2, 32);
baseMediaDecodeTime += MP4Demuxer.readUint32(tfdt, 8);
baseMediaDecodeTime -= timeOffset * timescale;
var upper = Math.floor(baseMediaDecodeTime / (UINT32_MAX + 1));
var lower = Math.floor(baseMediaDecodeTime % (UINT32_MAX + 1));
MP4Demuxer.writeUint32(tfdt, 4, upper);
MP4Demuxer.writeUint32(tfdt, 8, lower);
}
});
});
});
}
}]);
return MP4Demuxer;
}();
exports.default = MP4Demuxer;

View File

@@ -0,0 +1,93 @@
"use strict";
/**
* MPEG parser helper
*/
var MpegAudio = {
BitratesMap: [32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160],
SamplingRateMap: [44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000],
appendFrame: function appendFrame(track, data, offset, pts, frameIndex) {
// Using http://www.datavoyage.com/mpgscript/mpeghdr.htm as a reference
if (offset + 24 > data.length) {
return undefined;
}
var header = this.parseHeader(data, offset);
if (header && offset + header.frameLength <= data.length) {
var frameDuration = 1152 * 90000 / header.sampleRate;
var stamp = pts + frameIndex * frameDuration;
var sample = { unit: data.subarray(offset, offset + header.frameLength), pts: stamp, dts: stamp };
track.config = [];
track.channelCount = header.channelCount;
track.samplerate = header.sampleRate;
track.samples.push(sample);
track.len += header.frameLength;
return { sample: sample, length: header.frameLength };
}
return undefined;
},
parseHeader: function parseHeader(data, offset) {
var headerB = data[offset + 1] >> 3 & 3;
var headerC = data[offset + 1] >> 1 & 3;
var headerE = data[offset + 2] >> 4 & 15;
var headerF = data[offset + 2] >> 2 & 3;
var headerG = !!(data[offset + 2] & 2);
if (headerB !== 1 && headerE !== 0 && headerE !== 15 && headerF !== 3) {
var columnInBitrates = headerB === 3 ? 3 - headerC : headerC === 3 ? 3 : 4;
var bitRate = MpegAudio.BitratesMap[columnInBitrates * 14 + headerE - 1] * 1000;
var columnInSampleRates = headerB === 3 ? 0 : headerB === 2 ? 1 : 2;
var sampleRate = MpegAudio.SamplingRateMap[columnInSampleRates * 3 + headerF];
var padding = headerG ? 1 : 0;
var channelCount = data[offset + 3] >> 6 === 3 ? 1 : 2; // If bits of channel mode are `11` then it is a single channel (Mono)
var frameLength = headerC === 3 ? (headerB === 3 ? 12 : 6) * bitRate / sampleRate + padding << 2 : (headerB === 3 ? 144 : 72) * bitRate / sampleRate + padding | 0;
return { sampleRate: sampleRate, channelCount: channelCount, frameLength: frameLength };
}
return undefined;
},
isHeaderPattern: function isHeaderPattern(data, offset) {
return data[offset] === 0xff && (data[offset + 1] & 0xe0) === 0xe0 && (data[offset + 1] & 0x06) !== 0x00;
},
isHeader: function isHeader(data, offset) {
// Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
// Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
// More info http://www.mp3-tech.org/programmer/frame_header.html
if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) {
return true;
}
return false;
},
probe: function probe(data, offset) {
// same as isHeader but we also check that MPEG frame follows last MPEG frame
// or end of data is reached
if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) {
// MPEG header Length
var headerLength = 4;
// MPEG frame Length
var header = this.parseHeader(data, offset);
var frameLength = headerLength;
if (header && header.frameLength) {
frameLength = header.frameLength;
}
var newOffset = offset + frameLength;
if (newOffset === data.length || newOffset + 1 < data.length && this.isHeaderPattern(data, newOffset)) {
return true;
}
}
return false;
}
};
module.exports = MpegAudio;

View File

@@ -0,0 +1,149 @@
'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; }; }(); /**
* SAMPLE-AES decrypter
*/
var _decrypter = require('../crypt/decrypter');
var _decrypter2 = _interopRequireDefault(_decrypter);
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 SampleAesDecrypter = function () {
function SampleAesDecrypter(observer, config, decryptdata, discardEPB) {
_classCallCheck(this, SampleAesDecrypter);
this.decryptdata = decryptdata;
this.discardEPB = discardEPB;
this.decrypter = new _decrypter2.default(observer, config);
}
_createClass(SampleAesDecrypter, [{
key: 'decryptBuffer',
value: function decryptBuffer(encryptedData, callback) {
this.decrypter.decrypt(encryptedData, this.decryptdata.key.buffer, this.decryptdata.iv.buffer, callback);
}
// AAC - encrypt all full 16 bytes blocks starting from offset 16
}, {
key: 'decryptAacSample',
value: function decryptAacSample(samples, sampleIndex, callback, sync) {
var curUnit = samples[sampleIndex].unit;
var encryptedData = curUnit.subarray(16, curUnit.length - curUnit.length % 16);
var encryptedBuffer = encryptedData.buffer.slice(encryptedData.byteOffset, encryptedData.byteOffset + encryptedData.length);
var localthis = this;
this.decryptBuffer(encryptedBuffer, function (decryptedData) {
decryptedData = new Uint8Array(decryptedData);
curUnit.set(decryptedData, 16);
if (!sync) {
localthis.decryptAacSamples(samples, sampleIndex + 1, callback);
}
});
}
}, {
key: 'decryptAacSamples',
value: function decryptAacSamples(samples, sampleIndex, callback) {
for (;; sampleIndex++) {
if (sampleIndex >= samples.length) {
callback();
return;
}
if (samples[sampleIndex].unit.length < 32) {
continue;
}
var sync = this.decrypter.isSync();
this.decryptAacSample(samples, sampleIndex, callback, sync);
if (!sync) {
return;
}
}
}
// AVC - encrypt one 16 bytes block out of ten, starting from offset 32
}, {
key: 'getAvcEncryptedData',
value: function getAvcEncryptedData(decodedData) {
var encryptedDataLen = Math.floor((decodedData.length - 48) / 160) * 16 + 16;
var encryptedData = new Int8Array(encryptedDataLen);
var outputPos = 0;
for (var inputPos = 32; inputPos <= decodedData.length - 16; inputPos += 160, outputPos += 16) {
encryptedData.set(decodedData.subarray(inputPos, inputPos + 16), outputPos);
}
return encryptedData;
}
}, {
key: 'getAvcDecryptedUnit',
value: function getAvcDecryptedUnit(decodedData, decryptedData) {
decryptedData = new Uint8Array(decryptedData);
var inputPos = 0;
for (var outputPos = 32; outputPos <= decodedData.length - 16; outputPos += 160, inputPos += 16) {
decodedData.set(decryptedData.subarray(inputPos, inputPos + 16), outputPos);
}
return decodedData;
}
}, {
key: 'decryptAvcSample',
value: function decryptAvcSample(samples, sampleIndex, unitIndex, callback, curUnit, sync) {
var decodedData = this.discardEPB(curUnit.data);
var encryptedData = this.getAvcEncryptedData(decodedData);
var localthis = this;
this.decryptBuffer(encryptedData.buffer, function (decryptedData) {
curUnit.data = localthis.getAvcDecryptedUnit(decodedData, decryptedData);
if (!sync) {
localthis.decryptAvcSamples(samples, sampleIndex, unitIndex + 1, callback);
}
});
}
}, {
key: 'decryptAvcSamples',
value: function decryptAvcSamples(samples, sampleIndex, unitIndex, callback) {
for (;; sampleIndex++, unitIndex = 0) {
if (sampleIndex >= samples.length) {
callback();
return;
}
var curUnits = samples[sampleIndex].units;
for (;; unitIndex++) {
if (unitIndex >= curUnits.length) {
break;
}
var curUnit = curUnits[unitIndex];
if (curUnit.length <= 48 || curUnit.type !== 1 && curUnit.type !== 5) {
continue;
}
var sync = this.decrypter.isSync();
this.decryptAvcSample(samples, sampleIndex, unitIndex, callback, curUnit, sync);
if (!sync) {
return;
}
}
}
}
}]);
return SampleAesDecrypter;
}();
exports.default = SampleAesDecrypter;

1045
Skills/@be/be/node_modules/hls.js/lib/demux/tsdemuxer.js generated vendored Normal file

File diff suppressed because it is too large Load Diff