@isomp4/box-moof
Version:
Implements encoding and decoding of the moof box type
140 lines (139 loc) • 5.13 kB
JavaScript
import { FullBoxEncoding } from "@isomp4/core";
export var TrackRunSample;
(function (TrackRunSample) {
function parseFlags(flags) {
// Flags is in big-endian format, so first bit fields are high bits
return {
// 4 bits reserved
isLeading: (flags >>> 26 & 0b11),
dependsOn: (flags >>> 24 & 0b11),
isDependedOn: (flags >>> 22 & 0b11),
hasRedundancy: (flags >>> 20 & 0b11),
paddingValue: flags >>> 17 & 0b111,
isSync: (flags >>> 16 & 0b1) === 0,
degradationPriority: flags & 0xFFFF,
};
}
TrackRunSample.parseFlags = parseFlags;
})(TrackRunSample || (TrackRunSample = {}));
export var TrackRunBox;
(function (TrackRunBox) {
function parseFlags(flags) {
return {
dataOffsetPresent: (flags & 0x000001) !== 0,
firstSampleFlagsPresent: (flags & 0x000004) !== 0,
sampleDurationPresent: (flags & 0x000100) !== 0,
sampleSizePresent: (flags & 0x000200) !== 0,
sampleFlagsPresent: (flags & 0x000400) !== 0,
sampleCompositionTimeOffsetsPresent: (flags & 0x000800) !== 0,
};
}
TrackRunBox.parseFlags = parseFlags;
})(TrackRunBox || (TrackRunBox = {}));
class TrackRunBoxEncoding extends FullBoxEncoding {
constructor() {
super("trun");
}
encodingLength(obj) {
return super.encodingLength(obj); // TODO implement
}
encodeTo(obj, buffer) {
const requiredBytes = super.encodeTo(obj, buffer);
if (requiredBytes > 0) {
return requiredBytes;
}
// let offset = this.encodedBytes;
// // TODO implementing encoding
// this.encodedBytes = offset;
return 0;
}
decode(buffer, header) {
const superBox = super.decode(buffer, header);
if (typeof superBox === "number") {
return superBox;
}
let offset = this.decodedBytes;
if (buffer.length < offset + 4) {
return offset + 4;
}
const sampleCount = buffer.readUInt32BE(offset);
offset += 4;
const bflags = TrackRunBox.parseFlags(superBox.flags);
let dataOffset;
if (bflags.dataOffsetPresent) {
if (buffer.length < offset + 4) {
return offset + 4;
}
dataOffset = buffer.readInt32BE(offset); // signed
offset += 4;
}
let firstSampleFlags;
if (bflags.firstSampleFlagsPresent) {
if (bflags.sampleFlagsPresent) {
throw new Error("Malformed input: Sample flags shall not be present!");
}
if (buffer.length < offset + 4) {
return offset + 4;
}
firstSampleFlags = buffer.readUInt32BE(offset);
offset += 4;
}
const bytesPerSample = (bflags.sampleDurationPresent ? 4 : 0) +
(bflags.sampleSizePresent ? 4 : 0) +
(bflags.sampleFlagsPresent ? 4 : 0) +
(bflags.sampleCompositionTimeOffsetsPresent ? 4 : 0);
const bytesForSamples = bytesPerSample * sampleCount;
if (buffer.length < offset + bytesForSamples) {
return offset + bytesForSamples;
}
const samples = [];
for (let i = 0; i < sampleCount; i++) {
let duration;
let size;
let flags;
let compositionTimeOffset;
if (bflags.sampleDurationPresent) {
duration = buffer.readUInt32BE(offset);
offset += 4;
}
if (bflags.sampleSizePresent) {
size = buffer.readUInt32BE(offset);
offset += 4;
}
if (bflags.sampleFlagsPresent) {
flags = buffer.readUInt32BE(offset);
offset += 4;
}
else if (bflags.firstSampleFlagsPresent && i === 0) {
flags = firstSampleFlags;
}
if (bflags.sampleCompositionTimeOffsetsPresent) {
switch (superBox.version) {
case 0:
compositionTimeOffset = buffer.readUInt32BE(offset); // Unsigned
break;
case 1:
compositionTimeOffset = buffer.readInt32BE(offset); // Signed
break;
default:
throw new Error("Unsupported version of trun box: " + superBox.version);
}
offset += 4;
}
samples.push({
duration,
size,
flags,
compositionTimeOffset,
});
}
this.decodedBytes = offset;
return {
...superBox,
dataOffset,
firstSampleFlags,
samples,
};
}
}
export const trun = new TrackRunBoxEncoding();