Skip to content

Commit e9ea7e2

Browse files
committed
perf(Mp4Generator): assemble segment data in a single allocation
1 parent 5c836b1 commit e9ea7e2

1 file changed

Lines changed: 38 additions & 17 deletions

File tree

lib/util/mp4_generator.js

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ goog.provide('shaka.util.Mp4Generator');
88

99
goog.require('goog.asserts');
1010
goog.require('shaka.device.DeviceFactory');
11+
goog.require('shaka.util.BufferUtils');
1112
goog.require('shaka.util.Lazy');
1213
goog.require('shaka.util.ManifestParserUtils');
1314
goog.require('shaka.util.Uint8ArrayUtils');
@@ -673,11 +674,38 @@ shaka.util.Mp4Generator = class {
673674
* @return {!Uint8Array}
674675
*/
675676
segmentData() {
676-
const segmentDataArray = [];
677+
const Mp4Generator = shaka.util.Mp4Generator;
678+
const boxHeaderSize = Mp4Generator.BOX_HEADER_SIZE_;
679+
// Assemble whole segment into one allocation
680+
const streams = [];
681+
// Running sum of bytes needed for the final segment buffer.
682+
let total = 0;
677683
for (const streamInfo of this.streamInfos_) {
678-
segmentDataArray.push(this.moof_(streamInfo), this.mdat_(streamInfo));
684+
const moof = this.moof_(streamInfo);
685+
const samples = streamInfo.data ? streamInfo.data.samples : [];
686+
// Sum of sample byte lengths for this stream's mdat payload.
687+
let mdatPayload = 0;
688+
for (const sample of samples) {
689+
mdatPayload += sample.data.byteLength;
690+
}
691+
const mdatSize = boxHeaderSize + mdatPayload;
692+
streams.push({moof, samples, mdatSize});
693+
total += moof.byteLength + mdatSize;
694+
}
695+
const result = shaka.util.BufferUtils.toUint8(new ArrayBuffer(total));
696+
// Current byte position in the output buffer.
697+
let offset = 0;
698+
for (const {moof, samples, mdatSize} of streams) {
699+
result.set(moof, offset);
700+
offset += moof.byteLength;
701+
this.writeUint32_(result, mdatSize, offset);
702+
result.set(Mp4Generator.MDAT_TYPE_.value(), offset + 4);
703+
offset += boxHeaderSize;
704+
for (const sample of samples) {
705+
result.set(sample.data, offset);
706+
offset += sample.data.byteLength;
707+
}
679708
}
680-
const result = shaka.util.Uint8ArrayUtils.concat(...segmentDataArray);
681709
return result;
682710
}
683711

@@ -849,20 +877,6 @@ shaka.util.Mp4Generator = class {
849877
return box;
850878
}
851879

852-
/**
853-
* Generate a MDAT box
854-
*
855-
* @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
856-
* @return {!Uint8Array}
857-
* @private
858-
*/
859-
mdat_(streamInfo) {
860-
const Mp4Generator = shaka.util.Mp4Generator;
861-
const samples = streamInfo.data ? streamInfo.data.samples : [];
862-
const allData = samples.map((sample) => sample.data);
863-
return Mp4Generator.box('mdat', ...allData);
864-
}
865-
866880
/**
867881
* @param {!Uint8Array} bytes
868882
* @param {number} value
@@ -1002,6 +1016,13 @@ shaka.util.Mp4Generator.BOX_TYPES_ = new Map();
10021016
*/
10031017
shaka.util.Mp4Generator.BOX_HEADER_SIZE_ = 8;
10041018

1019+
/**
1020+
* 'mdat' box-type bytes (ASCII).
1021+
* @private {!shaka.util.Lazy<!Uint8Array>}
1022+
*/
1023+
shaka.util.Mp4Generator.MDAT_TYPE_ =
1024+
new shaka.util.Lazy(() => new Uint8Array([0x6d, 0x64, 0x61, 0x74]));
1025+
10051026
/**
10061027
* Template MVHD (version 1, 112 bytes).
10071028
* Dynamic fields: timescale [20], upperDur [24], lowerDur [28].

0 commit comments

Comments
 (0)