From d17649ec2c79356dce64bb1efa6ed9c9fdbf1cc9 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 24 May 2019 12:02:28 -0700 Subject: [PATCH 1/2] Cache buffer.byteLength in NalByteStream.push Significant speedup in (pre-Chromium) Edge, especially for high bitrates such as uncompressed or lightly-compressed frames. Previously, buffer.byteLength and buffer.length got looked up multiple times per byte processed in Edge, leading to higher CPU usage. --- lib/codecs/h264.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/codecs/h264.js b/lib/codecs/h264.js index 1b66cdad..ec619c8a 100644 --- a/lib/codecs/h264.js +++ b/lib/codecs/h264.js @@ -40,6 +40,7 @@ NalByteStream = function() { swapBuffer.set(data.data, buffer.byteLength); buffer = swapBuffer; } + var len = buffer.byteLength; // Rec. ITU-T H.264, Annex B // scan for NAL unit boundaries @@ -52,7 +53,7 @@ NalByteStream = function() { // ^ sync point ^ i // advance the sync point to a NAL start, if necessary - for (; syncPoint < buffer.byteLength - 3; syncPoint++) { + for (; syncPoint < len - 3; syncPoint++) { if (buffer[syncPoint + 2] === 1) { // the sync point is properly aligned i = syncPoint + 5; @@ -60,7 +61,7 @@ NalByteStream = function() { } } - while (i < buffer.byteLength) { + while (i < len) { // look at the current byte to determine if we've hit the end of // a NAL unit boundary switch (buffer[i]) { @@ -82,7 +83,7 @@ NalByteStream = function() { // drop trailing zeroes do { i++; - } while (buffer[i] !== 1 && i < buffer.length); + } while (buffer[i] !== 1 && i < len); syncPoint = i - 2; i += 3; break; From 46e4327a2c6c33feaf9b50a7848a34cbb38c9bbf Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 1 Jun 2019 02:16:08 -0700 Subject: [PATCH 2/2] Basic support for FLAC-in-MP4 audio tracks Allows for creating an MP4 stream with FLAC contents using the MP4 box generation functions or AudioSegmentStream. Use codec string 'fLaC' and specify a 'metadata' field in the track info with the FLAC METADATA_BLOCK_HEADER fields to go into the dfLa box. See https://github.com/xiph/flac/blob/master/doc/isoflac.txt for details of the MP4 embedding of FLAC audio. Also allows variable-length audio packets in AudioSegmentStream FLAC may have variable-length packets, so allow passing a duration in samples on incoming frames. This gets FLAC with, say, 960 samples per frame working consistently in Firefox and Chrome. --- lib/mp4/audio-frame-utils.js | 2 +- lib/mp4/mp4-generator.js | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/mp4/audio-frame-utils.js b/lib/mp4/audio-frame-utils.js index faa5f4ab..93813d3f 100644 --- a/lib/mp4/audio-frame-utils.js +++ b/lib/mp4/audio-frame-utils.js @@ -121,7 +121,7 @@ var generateSampleTable = function(frames) { currentFrame = frames[i]; samples.push({ size: currentFrame.data.byteLength, - duration: 1024 // For AAC audio, all samples contain 1024 samples + duration: currentFrame.duration || 1024 // For AAC audio, all samples contain 1024 samples }); } return samples; diff --git a/lib/mp4/mp4-generator.js b/lib/mp4/mp4-generator.js index 032a7ba2..74f4806f 100644 --- a/lib/mp4/mp4-generator.js +++ b/lib/mp4/mp4-generator.js @@ -11,7 +11,7 @@ var UINT32_MAX = Math.pow(2, 32) - 1; -var box, dinf, esds, ftyp, mdat, mfhd, minf, moof, moov, mvex, mvhd, +var box, dfLa, dinf, esds, ftyp, mdat, mfhd, minf, moof, moov, mvex, mvhd, trak, tkhd, mdia, mdhd, hdlr, sdtp, stbl, stsd, traf, trex, trun, types, MAJOR_BRAND, MINOR_VERSION, AVC1_BRAND, VIDEO_HDLR, AUDIO_HDLR, HDLR_TYPES, VMHD, SMHD, DREF, STCO, STSC, STSZ, STTS; @@ -23,10 +23,12 @@ var box, dinf, esds, ftyp, mdat, mfhd, minf, moof, moov, mvex, mvhd, avc1: [], // codingname avcC: [], btrt: [], + dfLa: [], dinf: [], dref: [], esds: [], ftyp: [], + fLaC: [], hdlr: [], mdat: [], mdhd: [], @@ -184,6 +186,13 @@ box = function(type) { return result; }; +dfLa = function(track) { + return box(types.dfLa, new Uint8Array([ + 0x00, // version + 0x00, 0x00, 0x00 // flags + ]), track.metadata || []); +}; + dinf = function() { return box(types.dinf, box(types.dref, DREF)); }; @@ -465,7 +474,10 @@ stbl = function(track) { }; audioSample = function(track) { - return box(types.mp4a, new Uint8Array([ + var audioSampleBox = new Uint8Array([ + + // FLACSampleEntry extends AudioSampleEntry + // https://github.com/xiph/flac/blob/master/doc/isoflac.txt // SampleEntry, ISO/IEC 14496-12 0x00, 0x00, 0x00, @@ -488,7 +500,11 @@ stbl = function(track) { 0x00, 0x00 // samplerate, 16.16 // MP4AudioSampleEntry, ISO/IEC 14496-14 - ]), esds(track)); + ]); + if (track.codec === 'fLaC') { + return box(types.fLaC, audioSampleBox, dfLa(track)); + } + return box(types.mp4a, audioSampleBox, esds(track)); }; }());