forked from galeksandrp/hls.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request video-dev#1113 from nochev/mpeg-audio-only-support
Mpeg audio only support
- Loading branch information
Showing
8 changed files
with
185 additions
and
103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/** | ||
* MP3 demuxer | ||
*/ | ||
import ID3 from '../demux/id3'; | ||
import MpegAudio from './mpegaudio'; | ||
|
||
class MP3Demuxer { | ||
|
||
constructor(observer, remuxer, config) { | ||
this.observer = observer; | ||
this.config = config; | ||
this.remuxer = remuxer; | ||
} | ||
|
||
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}; | ||
} | ||
|
||
resetTimeStamp() { | ||
} | ||
|
||
static probe(data) { | ||
// check if data contains ID3 timestamp and MPEG sync word | ||
var id3 = new ID3(data), offset, length; | ||
if (id3.hasTimeStamp) { | ||
// 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 = id3.length, length = Math.min(data.length - 1, offset + 100); offset < length; offset++) { | ||
if ((data[offset] === 0xff) && (data[offset+1] & 0xe0) === 0xe0 && (data[offset+1] & 0x06) !== 0x00) { | ||
//logger.log('MPEG sync word found !'); | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
|
||
// feed incoming data to the front of the parsing pipeline | ||
append(data, timeOffset,contiguous,accurateTimeOffset) { | ||
var id3 = new ID3(data); | ||
var pts = 90*id3.timeStamp; | ||
var afterID3 = id3.length; | ||
var offset, length; | ||
|
||
// Look for MPEG header | ||
for (offset = afterID3, length = data.length; offset < length - 1; offset++) { | ||
if ((data[offset] === 0xff) && (data[offset+1] & 0xe0) === 0xe0 && (data[offset+1] & 0x06) !== 0x00) { | ||
break; | ||
} | ||
} | ||
|
||
MpegAudio.parse(this._audioTrack, data, id3.length, pts); | ||
|
||
this.remuxer.remux(this._audioTrack, | ||
{samples : []}, | ||
{samples : [ { pts: pts, dts : pts, data : id3.payload}], inputTimeScale : 90000}, | ||
{samples : []}, | ||
timeOffset, | ||
contiguous, | ||
accurateTimeOffset); | ||
} | ||
|
||
destroy() { | ||
} | ||
} | ||
|
||
export default MP3Demuxer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/** | ||
* MPEG parser helper | ||
*/ | ||
import {logger} from '../utils/logger'; | ||
|
||
const MpegAudio = { | ||
|
||
onFrame: function(track, data, bitRate, sampleRate, channelCount, frameIndex, pts) { | ||
var frameDuration = 1152 * 90000 / sampleRate; | ||
var stamp = pts + frameIndex * frameDuration; | ||
|
||
track.config = []; | ||
track.channelCount = channelCount; | ||
track.samplerate = sampleRate; | ||
track.samples.push({unit: data, pts: stamp, dts: stamp}); | ||
track.len += data.length; | ||
}, | ||
|
||
onNoise: function(data) { | ||
logger.warn('mpeg audio has noise: ' + data.length + ' bytes'); | ||
}, | ||
|
||
parseFrames: function(track, data, start, end, frameIndex, pts) { | ||
var 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]; | ||
var SamplingRateMap = [44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000]; | ||
|
||
if (start + 2 > end) { | ||
return -1; // we need at least 2 bytes to detect sync pattern | ||
} | ||
if (data[start] === 0xFF || (data[start + 1] & 0xE0) === 0xE0) { | ||
// Using http://www.datavoyage.com/mpgscript/mpeghdr.htm as a reference | ||
if (start + 24 > end) { | ||
return -1; | ||
} | ||
var headerB = (data[start + 1] >> 3) & 3; | ||
var headerC = (data[start + 1] >> 1) & 3; | ||
var headerE = (data[start + 2] >> 4) & 15; | ||
var headerF = (data[start + 2] >> 2) & 3; | ||
var headerG = !!(data[start + 2] & 2); | ||
if (headerB !== 1 && headerE !== 0 && headerE !== 15 && headerF !== 3) { | ||
var columnInBitrates = headerB === 3 ? (3 - headerC) : (headerC === 3 ? 3 : 4); | ||
var bitRate = BitratesMap[columnInBitrates * 14 + headerE - 1] * 1000; | ||
var columnInSampleRates = headerB === 3 ? 0 : headerB === 2 ? 1 : 2; | ||
var sampleRate = SamplingRateMap[columnInSampleRates * 3 + headerF]; | ||
var padding = headerG ? 1 : 0; | ||
var channelCount = data[start + 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; | ||
if (start + frameLength > end) { | ||
return -1; | ||
} | ||
|
||
this.onFrame(track, data.subarray(start, start + frameLength), bitRate, sampleRate, channelCount, frameIndex, pts); | ||
|
||
return frameLength; | ||
} | ||
} | ||
// noise or ID3, trying to skip | ||
var offset = start + 2; | ||
while (offset < end) { | ||
if (data[offset - 1] === 0xFF && (data[offset] & 0xE0) === 0xE0) { | ||
// sync pattern is found | ||
this.onNoise(data.subarray(start, offset - 1)); | ||
|
||
return offset - start - 1; | ||
} | ||
offset++; | ||
} | ||
return -1; | ||
}, | ||
|
||
parse: function(track, data, offset, pts) { | ||
var length = data.length; | ||
var frameIndex = 0; | ||
var parsed; | ||
|
||
while (offset < length && | ||
(parsed = this.parseFrames(track, data, offset, length, frameIndex++, pts)) > 0) { | ||
offset += parsed; | ||
} | ||
} | ||
}; | ||
|
||
module.exports = MpegAudio; |
Oops, something went wrong.