mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
get api libs from bower
This commit is contained in:
parent
def418714f
commit
f36e664503
97 changed files with 16860 additions and 197 deletions
208
dashboard-ui/bower_components/hls.js/src/demux/aacdemuxer.js
vendored
Normal file
208
dashboard-ui/bower_components/hls.js/src/demux/aacdemuxer.js
vendored
Normal file
|
@ -0,0 +1,208 @@
|
|||
/**
|
||||
* AAC demuxer
|
||||
*/
|
||||
import {logger} from '../utils/logger';
|
||||
import ID3 from '../demux/id3';
|
||||
import {ErrorTypes, ErrorDetails} from '../errors';
|
||||
|
||||
class AACDemuxer {
|
||||
|
||||
constructor(observer,remuxerClass) {
|
||||
this.observer = observer;
|
||||
this.remuxerClass = remuxerClass;
|
||||
this.remuxer = new this.remuxerClass(observer);
|
||||
this._aacTrack = {type: 'audio', id :-1, sequenceNumber: 0, samples : [], len : 0};
|
||||
}
|
||||
|
||||
static probe(data) {
|
||||
// check if data contains ID3 timestamp and ADTS sync worc
|
||||
var id3 = new ID3(data), adtsStartOffset,len;
|
||||
if(id3.hasTimeStamp) {
|
||||
// look for ADTS header (0xFFFx)
|
||||
for (adtsStartOffset = id3.length, len = data.length; adtsStartOffset < len - 1; adtsStartOffset++) {
|
||||
if ((data[adtsStartOffset] === 0xff) && (data[adtsStartOffset+1] & 0xf0) === 0xf0) {
|
||||
//logger.log('ADTS sync word found !');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// feed incoming data to the front of the parsing pipeline
|
||||
push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) {
|
||||
var id3 = new ID3(data), adtsStartOffset,len, track = this._aacTrack, pts = id3.timeStamp, config, nbSamples,adtsFrameSize,adtsHeaderLen,stamp,aacSample;
|
||||
// look for ADTS header (0xFFFx)
|
||||
for (adtsStartOffset = id3.length, len = data.length; adtsStartOffset < len - 1; adtsStartOffset++) {
|
||||
if ((data[adtsStartOffset] === 0xff) && (data[adtsStartOffset+1] & 0xf0) === 0xf0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!track.audiosamplerate) {
|
||||
config = this._ADTStoAudioConfig(data, adtsStartOffset, audioCodec);
|
||||
track.config = config.config;
|
||||
track.audiosamplerate = config.samplerate;
|
||||
track.channelCount = config.channelCount;
|
||||
track.codec = config.codec;
|
||||
track.timescale = this.remuxer.timescale;
|
||||
track.duration = this.remuxer.timescale * duration;
|
||||
logger.log(`parsed codec:${track.codec},rate:${config.samplerate},nb channel:${config.channelCount}`);
|
||||
}
|
||||
nbSamples = 0;
|
||||
while ((adtsStartOffset + 5) < len) {
|
||||
// retrieve frame size
|
||||
adtsFrameSize = ((data[adtsStartOffset + 3] & 0x03) << 11);
|
||||
// byte 4
|
||||
adtsFrameSize |= (data[adtsStartOffset + 4] << 3);
|
||||
// byte 5
|
||||
adtsFrameSize |= ((data[adtsStartOffset + 5] & 0xE0) >>> 5);
|
||||
adtsHeaderLen = (!!(data[adtsStartOffset + 1] & 0x01) ? 7 : 9);
|
||||
adtsFrameSize -= adtsHeaderLen;
|
||||
stamp = Math.round(90*pts + nbSamples * 1024 * 90000 / track.audiosamplerate);
|
||||
//stamp = pes.pts;
|
||||
//console.log('AAC frame, offset/length/pts:' + (adtsStartOffset+7) + '/' + adtsFrameSize + '/' + stamp.toFixed(0));
|
||||
if ((adtsFrameSize > 0) && ((adtsStartOffset + adtsHeaderLen + adtsFrameSize) <= len)) {
|
||||
aacSample = {unit: data.subarray(adtsStartOffset + adtsHeaderLen, adtsStartOffset + adtsHeaderLen + adtsFrameSize), pts: stamp, dts: stamp};
|
||||
track.samples.push(aacSample);
|
||||
track.len += adtsFrameSize;
|
||||
adtsStartOffset += adtsFrameSize + adtsHeaderLen;
|
||||
nbSamples++;
|
||||
// look for ADTS header (0xFFFx)
|
||||
for ( ; adtsStartOffset < (len - 1); adtsStartOffset++) {
|
||||
if ((data[adtsStartOffset] === 0xff) && ((data[adtsStartOffset + 1] & 0xf0) === 0xf0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.remuxer.remux(this._aacTrack,{samples : []}, {samples : []}, timeOffset);
|
||||
}
|
||||
|
||||
_ADTStoAudioConfig(data, offset, audioCodec) {
|
||||
var adtsObjectType, // :int
|
||||
adtsSampleingIndex, // :int
|
||||
adtsExtensionSampleingIndex, // :int
|
||||
adtsChanelConfig, // :int
|
||||
config,
|
||||
userAgent = navigator.userAgent.toLowerCase(),
|
||||
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) {
|
||||
this.observer.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: 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.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 (userAgent.indexOf('firefox') !== -1) {
|
||||
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 ...)
|
||||
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 (manifest codec not specified AND frequency less than 24kHz)
|
||||
if ((audioCodec && 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 OR nb channel is 1)
|
||||
if (audioCodec && audioCodec.indexOf('mp4a.40.2') !== -1 && (adtsSampleingIndex >= 6 || 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)};
|
||||
}
|
||||
|
||||
destroy() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default AACDemuxer;
|
Loading…
Add table
Add a link
Reference in a new issue