diff --git a/lib/mss/mss_parser.js b/lib/mss/mss_parser.js index 356cd8f91f..0f3260d740 100644 --- a/lib/mss/mss_parser.js +++ b/lib/mss/mss_parser.js @@ -632,6 +632,7 @@ shaka.mss.MssParser = class { timescale: stream.mssPrivateData.timescale, duration: stream.mssPrivateData.duration, videoNalus: videoNalus, + audioConfig: new Uint8Array([]), data: null, // Data is not necessary for init segement. stream: stream, }; diff --git a/lib/transmuxer/mp3_transmuxer.js b/lib/transmuxer/mp3_transmuxer.js index c5d3b18bb1..3323348e0f 100644 --- a/lib/transmuxer/mp3_transmuxer.js +++ b/lib/transmuxer/mp3_transmuxer.js @@ -170,6 +170,7 @@ shaka.transmuxer.Mp3Transmuxer = class { timescale: sampleRate, duration: duration, videoNalus: [], + audioConfig: new Uint8Array([]), data: { sequenceNumber: this.frameIndex_, baseMediaDecodeTime: baseMediaDecodeTime, diff --git a/lib/util/mp4_generator.js b/lib/util/mp4_generator.js index 50ff84d7c5..7bfc375806 100644 --- a/lib/util/mp4_generator.js +++ b/lib/util/mp4_generator.js @@ -33,6 +33,9 @@ shaka.util.Mp4Generator = class { /** @private {!Array.} */ this.videoNalus_ = streamInfo.videoNalus; + /** @private {!Uint8Array} */ + this.audioConfig_ = streamInfo.audioConfig; + /** @private {number} */ this.sequenceNumber_ = 0; @@ -310,6 +313,10 @@ shaka.util.Mp4Generator = class { this.stream_.codecs.includes('mp3') || this.stream_.codecs.includes('mp4a.40.34')) { bytes = this.mp3_(); + } else if (this.stream_.codecs.includes('ac-3')) { + bytes = this.ac3_(); + } else if (this.stream_.codecs.includes('ec-3')) { + bytes = this.ec3_(); } else { bytes = this.mp4a_(); } @@ -471,6 +478,50 @@ shaka.util.Mp4Generator = class { return Mp4Generator.box('.mp3', this.audioStsd_()); } + /** + * Generate a AC-3 box + * + * @return {!Uint8Array} + * @private + */ + ac3_() { + const Mp4Generator = shaka.util.Mp4Generator; + const dac3Box = Mp4Generator.box('dac3', this.audioConfig_); + + let sinfBox = new Uint8Array([]); + if (this.stream_.encrypted) { + sinfBox = this.sinf_(); + } + + let boxName = 'ac-3'; + if (this.stream_.encrypted) { + boxName = 'enca'; + } + return Mp4Generator.box(boxName, this.audioStsd_(), dac3Box, sinfBox); + } + + /** + * Generate a EC-3 box + * + * @return {!Uint8Array} + * @private + */ + ec3_() { + const Mp4Generator = shaka.util.Mp4Generator; + const dec3Box = Mp4Generator.box('dec3', this.audioConfig_); + + let sinfBox = new Uint8Array([]); + if (this.stream_.encrypted) { + sinfBox = this.sinf_(); + } + + let boxName = 'ec-3'; + if (this.stream_.encrypted) { + boxName = 'enca'; + } + return Mp4Generator.box(boxName, this.audioStsd_(), dec3Box, sinfBox); + } + /** * Generate a MP4A box * @@ -479,7 +530,12 @@ shaka.util.Mp4Generator = class { */ mp4a_() { const Mp4Generator = shaka.util.Mp4Generator; - const esdsBox = Mp4Generator.box('esds', this.esds_()); + let esdsBox; + if (this.audioConfig_.byteLength > 0) { + esdsBox = Mp4Generator.box('esds', this.audioConfig_); + } else { + esdsBox = Mp4Generator.box('esds', this.esds_()); + } let sinfBox = new Uint8Array([]); if (this.stream_.encrypted) { @@ -1144,6 +1200,7 @@ shaka.util.Mp4Generator.DINF_ = new Uint8Array([]); * timescale: number, * duration: number, * videoNalus: !Array., + * audioConfig: !Uint8Array, * data: ?shaka.util.Mp4Generator.Data, * stream: !shaka.extern.Stream * }} @@ -1154,6 +1211,8 @@ shaka.util.Mp4Generator.DINF_ = new Uint8Array([]); * The Stream's duration. * @property {!Array.} videoNalus * The stream's video nalus. + * @property {!Uint8Array} audioConfig + * The stream's audio config. * @property {?shaka.util.Mp4Generator.Data} data * The stream's data. * @property {!shaka.extern.Stream} stream