Skip to content

Commit

Permalink
MP4Generator: Generate .mp3 box for mp3 audio track in InitSegment
Browse files Browse the repository at this point in the history
This commit makes mp3 audio playback works well in FireFox.
  • Loading branch information
xqq committed Mar 7, 2017
1 parent e1db184 commit 8dbea65
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 17 deletions.
31 changes: 17 additions & 14 deletions src/demux/flv-demuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,6 @@ class FLVDemuxer {
meta.channelCount = misc.channelCount;
meta.codec = misc.codec;
meta.config = misc.config;
meta.esdsSubType = 0x40; // Audio 14496-3 AAC Main
// The decode result of an aac sample is 1024 PCM samples
meta.refSampleDuration = Math.floor(1024 / meta.audioSampleRate * meta.timescale);
Log.v(this.TAG, 'Parsed AudioSpecificConfig');
Expand Down Expand Up @@ -516,16 +515,17 @@ class FLVDemuxer {
}
} else if (soundFormat === 2) { // MP3
if (!meta.codec) {
// We need metadata for mp3 audio track, extract info from frame header
let misc = this._parseMP3AudioData(arrayBuffer, dataOffset + 1, dataSize - 1, true);
if (misc == undefined) {
return;
}
meta.audioSampleRate = misc.samplingRate;
meta.channelConfig = misc.channelCount;
meta.codec = misc.codec;
meta.esdsSubType = 0x6B;
// The decode result of an mp3 sample is 1152 PCM samples
meta.refSampleDuration = Math.floor(1152 / meta.audioSampleRate * meta.timescale);
Log.v(this.TAG, 'Parsed MP3 frame header');
Log.v(this.TAG, 'Parsed MPEG Audio Frame Header');

this._audioInitialMetadataDispatched = true;
this._onTrackMetadata('audio', meta);
Expand All @@ -534,7 +534,7 @@ class FLVDemuxer {
mi.audioCodec = meta.codec;
mi.audioSampleRate = meta.audioSampleRate;
mi.audioChannelCount = meta.channelCount;
mi.audioBitrate = misc.bitRate;
mi.audioDataRate = misc.bitRate;
if (mi.hasVideo) {
if (mi.videoCodec != null) {
mi.mimeType = 'video/x-flv; codecs="' + mi.videoCodec + ',' + mi.audioCodec + '"';
Expand All @@ -545,16 +545,17 @@ class FLVDemuxer {
if (mi.isComplete()) {
this._onMediaInfo(mi);
}
} else {
let data = this._parseMP3AudioData(arrayBuffer, dataOffset + 1, dataSize - 1, false);
if (data == undefined) {
return;
}
let dts = this._timestampBase + tagTimestamp;
let mp3Sample = {unit: data, dts: dts, pts: dts};
track.samples.push(mp3Sample);
track.length += data.length;
}

// This packet is always a valid audio packet, extract it
let data = this._parseMP3AudioData(arrayBuffer, dataOffset + 1, dataSize - 1, false);
if (data == undefined) {
return;
}
let dts = this._timestampBase + tagTimestamp;
let mp3Sample = {unit: data, dts: dts, pts: dts};
track.samples.push(mp3Sample);
track.length += data.length;
}
}

Expand Down Expand Up @@ -706,6 +707,8 @@ class FLVDemuxer {
let bit_rate = 0;
let object_type = 34; // Layer-3, listed in MPEG-4 Audio Object Types

let codec = 'mp3';

switch (ver) {
case 0: // MPEG 2.5
sample_rate = this._mpegAudioV25SampleRateTable[sampling_freq_index];
Expand Down Expand Up @@ -743,7 +746,7 @@ class FLVDemuxer {
bitRate: bit_rate,
samplingRate: sample_rate,
channelCount: channel_count,
codec: 'mp4a.40.' + object_type
codec: codec
};
} else {
result = array;
Expand Down
29 changes: 26 additions & 3 deletions src/remux/mp4-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class MP4 {
stco: [], stsc: [], stsd: [], stsz: [],
stts: [], tfdt: [], tfhd: [], traf: [],
trak: [], trun: [], trex: [], tkhd: [],
vmhd: [], smhd: []
vmhd: [], smhd: [], '.mp3': []
};

for (let name in MP4.types) {
Expand Down Expand Up @@ -318,12 +318,36 @@ class MP4 {
// Sample description box
static stsd(meta) {
if (meta.type === 'audio') {
if (meta.codec === 'mp3') {
return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.mp3(meta));
}
// else: aac -> mp4a
return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.mp4a(meta));
} else {
return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.avc1(meta));
}
}

static mp3(meta) {
let channelCount = meta.channelCount;
let sampleRate = meta.audioSampleRate;

let data = new Uint8Array([
0x00, 0x00, 0x00, 0x00, // reserved(4)
0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
0x00, 0x00, 0x00, 0x00,
0x00, channelCount, // channelCount(2)
0x00, 0x10, // sampleSize(2)
0x00, 0x00, 0x00, 0x00, // reserved(4)
(sampleRate >>> 8) & 0xFF, // Audio sample rate
(sampleRate) & 0xFF,
0x00, 0x00
]);

return MP4.box(MP4.types['.mp3'], data);
}

static mp4a(meta) {
let channelCount = meta.channelCount;
let sampleRate = meta.audioSampleRate;
Expand All @@ -345,7 +369,6 @@ class MP4 {
}

static esds(meta) {
let esdsSubType = meta.esdsSubType;
let config = meta.config || [];
let configSize = config.length;
let data = new Uint8Array([
Expand All @@ -358,7 +381,7 @@ class MP4 {

0x04, // descriptor_type
0x0F + configSize, // length
esdsSubType, // codec
0x40, // codec: mpeg4_audio
0x15, // stream_type: Audio
0x00, 0x00, 0x00, // buffer_size
0x00, 0x00, 0x00, 0x00, // maxBitrate
Expand Down

0 comments on commit 8dbea65

Please sign in to comment.