���� JFIF �� � ( %"1"%)+...383,7(-.-
![]() Server : Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.4.20 System : Linux st2.domain.com 3.10.0-1127.10.1.el7.x86_64 #1 SMP Wed Jun 3 14:28:03 UTC 2020 x86_64 User : apache ( 48) PHP Version : 7.4.20 Disable Function : NONE Directory : /var/www/html/netphim/layout/default/node_modules/hls.js/src/demux/ |
/** * MPEG parser helper */ import { DemuxedAudioTrack } from '../types/demuxer'; let chromeVersion: number | null = null; const 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, ]; const SamplingRateMap = [ 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000, ]; const SamplesCoefficients = [ // MPEG 2.5 [ 0, // Reserved 72, // Layer3 144, // Layer2 12, // Layer1 ], // Reserved [ 0, // Reserved 0, // Layer3 0, // Layer2 0, // Layer1 ], // MPEG 2 [ 0, // Reserved 72, // Layer3 144, // Layer2 12, // Layer1 ], // MPEG 1 [ 0, // Reserved 144, // Layer3 144, // Layer2 12, // Layer1 ], ]; const BytesInSlot = [ 0, // Reserved 1, // Layer3 1, // Layer2 4, // Layer1 ]; export function appendFrame( track: DemuxedAudioTrack, data: Uint8Array, offset: number, pts: number, frameIndex: number ) { // Using http://www.datavoyage.com/mpgscript/mpeghdr.htm as a reference if (offset + 24 > data.length) { return; } const header = parseHeader(data, offset); if (header && offset + header.frameLength <= data.length) { const frameDuration = (header.samplesPerFrame * 90000) / header.sampleRate; const stamp = pts + frameIndex * frameDuration; const 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); return { sample, length: header.frameLength, missing: 0 }; } } export function parseHeader(data: Uint8Array, offset: number) { const mpegVersion = (data[offset + 1] >> 3) & 3; const mpegLayer = (data[offset + 1] >> 1) & 3; const bitRateIndex = (data[offset + 2] >> 4) & 15; const sampleRateIndex = (data[offset + 2] >> 2) & 3; if ( mpegVersion !== 1 && bitRateIndex !== 0 && bitRateIndex !== 15 && sampleRateIndex !== 3 ) { const paddingBit = (data[offset + 2] >> 1) & 1; const channelMode = data[offset + 3] >> 6; const columnInBitrates = mpegVersion === 3 ? 3 - mpegLayer : mpegLayer === 3 ? 3 : 4; const bitRate = BitratesMap[columnInBitrates * 14 + bitRateIndex - 1] * 1000; const columnInSampleRates = mpegVersion === 3 ? 0 : mpegVersion === 2 ? 1 : 2; const sampleRate = SamplingRateMap[columnInSampleRates * 3 + sampleRateIndex]; const channelCount = channelMode === 3 ? 1 : 2; // If bits of channel mode are `11` then it is a single channel (Mono) const sampleCoefficient = SamplesCoefficients[mpegVersion][mpegLayer]; const bytesInSlot = BytesInSlot[mpegLayer]; const samplesPerFrame = sampleCoefficient * 8 * bytesInSlot; const frameLength = Math.floor((sampleCoefficient * bitRate) / sampleRate + paddingBit) * bytesInSlot; if (chromeVersion === null) { const userAgent = navigator.userAgent || ''; const result = userAgent.match(/Chrome\/(\d+)/i); chromeVersion = result ? parseInt(result[1]) : 0; } const needChromeFix = !!chromeVersion && chromeVersion <= 87; if ( needChromeFix && mpegLayer === 2 && bitRate >= 224000 && channelMode === 0 ) { // Work around bug in Chromium by setting channelMode to dual-channel (01) instead of stereo (00) data[offset + 3] = data[offset + 3] | 0x80; } return { sampleRate, channelCount, frameLength, samplesPerFrame }; } } export function isHeaderPattern(data: Uint8Array, offset: number): boolean { return ( data[offset] === 0xff && (data[offset + 1] & 0xe0) === 0xe0 && (data[offset + 1] & 0x06) !== 0x00 ); } export function isHeader(data: Uint8Array, offset: number): boolean { // 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 return offset + 1 < data.length && isHeaderPattern(data, offset); } export function canParse(data: Uint8Array, offset: number): boolean { const headerSize = 4; return isHeaderPattern(data, offset) && headerSize <= data.length - offset; } export function probe(data: Uint8Array, offset: number): boolean { // 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 && isHeaderPattern(data, offset)) { // MPEG header Length const headerLength = 4; // MPEG frame Length const header = parseHeader(data, offset); let frameLength = headerLength; if (header?.frameLength) { frameLength = header.frameLength; } const newOffset = offset + frameLength; return newOffset === data.length || isHeader(data, newOffset); } return false; }