mediabunny 1.56.0 → 1.56.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundles/mediabunny.cjs +128 -26
- package/dist/bundles/mediabunny.min.cjs +11 -11
- package/dist/bundles/mediabunny.min.mjs +11 -11
- package/dist/bundles/mediabunny.mjs +128 -26
- package/dist/bundles/mediabunny.node.cjs +128 -26
- package/dist/mediabunny.d.ts +6 -4
- package/dist/modules/shared/bitstream.d.ts +1 -0
- package/dist/modules/shared/bitstream.d.ts.map +1 -1
- package/dist/modules/shared/bitstream.js +10 -1
- package/dist/modules/src/codec-data.d.ts +12 -0
- package/dist/modules/src/codec-data.d.ts.map +1 -1
- package/dist/modules/src/codec-data.js +98 -20
- package/dist/modules/src/conversion.js +1 -1
- package/dist/modules/src/media-sink.d.ts.map +1 -1
- package/dist/modules/src/media-sink.js +34 -9
- package/dist/modules/src/metadata.d.ts +6 -4
- package/dist/modules/src/metadata.d.ts.map +1 -1
- package/dist/modules/src/metadata.js +2 -1
- package/dist/modules/src/misc.d.ts +1 -0
- package/dist/modules/src/misc.d.ts.map +1 -1
- package/dist/modules/src/misc.js +7 -0
- package/dist/modules/src/resample.d.ts.map +1 -1
- package/dist/modules/src/resample.js +6 -2
- package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/codec-data.ts +112 -20
- package/src/conversion.ts +1 -1
- package/src/media-sink.ts +39 -8
- package/src/metadata.ts +8 -5
- package/src/misc.ts +8 -0
- package/src/resample.ts +6 -2
|
@@ -273,6 +273,13 @@ var Mediabunny = (() => {
|
|
|
273
273
|
const result = (1 << leadingZeroBits) - 1 + bitstream.readBits(leadingZeroBits);
|
|
274
274
|
return result;
|
|
275
275
|
};
|
|
276
|
+
var writeExpGolomb = (bitstream, value) => {
|
|
277
|
+
const codeNum = value + 1;
|
|
278
|
+
const leadingZeroBits = Math.floor(Math.log2(codeNum));
|
|
279
|
+
bitstream.writeBits(leadingZeroBits, 0);
|
|
280
|
+
bitstream.writeBits(1, 1);
|
|
281
|
+
bitstream.writeBits(leadingZeroBits, codeNum - 2 ** leadingZeroBits);
|
|
282
|
+
};
|
|
276
283
|
var readSignedExpGolomb = (bitstream) => {
|
|
277
284
|
const codeNum = readExpGolomb(bitstream);
|
|
278
285
|
return (codeNum & 1) === 0 ? -(codeNum >> 1) : codeNum + 1 >> 1;
|
|
@@ -1299,9 +1306,9 @@ var Mediabunny = (() => {
|
|
|
1299
1306
|
throw new TypeError("tags.raw, when provided, must be an object.");
|
|
1300
1307
|
}
|
|
1301
1308
|
for (const value of Object.values(tags.raw)) {
|
|
1302
|
-
if (value !== null && typeof value !== "string" && !(value instanceof Uint8Array) && !(value instanceof RichImageData) && !(value instanceof AttachedFile) && !isRecordStringString(value)) {
|
|
1309
|
+
if (value !== null && typeof value !== "string" && !(Array.isArray(value) && value.every((x) => typeof x === "string")) && !(value instanceof Uint8Array) && !(value instanceof RichImageData) && !(value instanceof AttachedFile) && !isRecordStringString(value)) {
|
|
1303
1310
|
throw new TypeError(
|
|
1304
|
-
"Each value in tags.raw must be a string, Uint8Array, RichImageData, AttachedFile, Record<string, string>, or null."
|
|
1311
|
+
"Each value in tags.raw must be a string, string array, Uint8Array, RichImageData, AttachedFile, Record<string, string>, or null."
|
|
1305
1312
|
);
|
|
1306
1313
|
}
|
|
1307
1314
|
}
|
|
@@ -1387,6 +1394,16 @@ var Mediabunny = (() => {
|
|
|
1387
1394
|
}
|
|
1388
1395
|
this.pos = end;
|
|
1389
1396
|
}
|
|
1397
|
+
copyBits(n, other) {
|
|
1398
|
+
let i = 0;
|
|
1399
|
+
for (i; i < n - 7; i += 8) {
|
|
1400
|
+
this.writeBits(8, other.readBits(8));
|
|
1401
|
+
}
|
|
1402
|
+
const leftover = n - i;
|
|
1403
|
+
if (leftover > 0) {
|
|
1404
|
+
this.writeBits(leftover, other.readBits(leftover));
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1390
1407
|
readAlignedByte() {
|
|
1391
1408
|
if (this.pos % 8 !== 0) {
|
|
1392
1409
|
throw new Error("Bitstream is not byte-aligned.");
|
|
@@ -1663,6 +1680,19 @@ var Mediabunny = (() => {
|
|
|
1663
1680
|
}
|
|
1664
1681
|
return new Uint8Array(result);
|
|
1665
1682
|
};
|
|
1683
|
+
var addEmulationPreventionBytes = (data) => {
|
|
1684
|
+
const result = [];
|
|
1685
|
+
let zeroCount = 0;
|
|
1686
|
+
for (const byte of data) {
|
|
1687
|
+
if (zeroCount === 2 && byte <= 3) {
|
|
1688
|
+
result.push(3);
|
|
1689
|
+
zeroCount = 0;
|
|
1690
|
+
}
|
|
1691
|
+
result.push(byte);
|
|
1692
|
+
zeroCount = byte === 0 ? zeroCount + 1 : 0;
|
|
1693
|
+
}
|
|
1694
|
+
return new Uint8Array(result);
|
|
1695
|
+
};
|
|
1666
1696
|
var ANNEX_B_START_CODE = new Uint8Array([0, 0, 0, 1]);
|
|
1667
1697
|
var concatNalUnitsInAnnexB = (nalUnits) => {
|
|
1668
1698
|
const totalLength = nalUnits.reduce((a, b) => a + ANNEX_B_START_CODE.byteLength + b.byteLength, 0);
|
|
@@ -1782,8 +1812,7 @@ var Mediabunny = (() => {
|
|
|
1782
1812
|
bytes2.push(pps[i]);
|
|
1783
1813
|
}
|
|
1784
1814
|
}
|
|
1785
|
-
if (record.avcProfileIndication === 100 || record.avcProfileIndication === 110 || record.avcProfileIndication === 122 || record.avcProfileIndication === 144) {
|
|
1786
|
-
assert(record.chromaFormat !== null);
|
|
1815
|
+
if ((record.avcProfileIndication === 100 || record.avcProfileIndication === 110 || record.avcProfileIndication === 122 || record.avcProfileIndication === 144) && record.chromaFormat !== null) {
|
|
1787
1816
|
assert(record.bitDepthLumaMinus8 !== null);
|
|
1788
1817
|
assert(record.bitDepthChromaMinus8 !== null);
|
|
1789
1818
|
assert(record.sequenceParameterSetExt !== null);
|
|
@@ -1883,7 +1912,8 @@ var Mediabunny = (() => {
|
|
|
1883
1912
|
};
|
|
1884
1913
|
var parseAvcSps = (sps) => {
|
|
1885
1914
|
try {
|
|
1886
|
-
const
|
|
1915
|
+
const emulationUnpreventedBytes = removeEmulationPreventionBytes(sps);
|
|
1916
|
+
const bitstream = new Bitstream(emulationUnpreventedBytes);
|
|
1887
1917
|
bitstream.skipBits(1);
|
|
1888
1918
|
bitstream.skipBits(2);
|
|
1889
1919
|
const nalUnitType = bitstream.readBits(5);
|
|
@@ -1979,6 +2009,9 @@ var Mediabunny = (() => {
|
|
|
1979
2009
|
let pixelAspectRatio = { num: 1, den: 1 };
|
|
1980
2010
|
let numReorderFrames = null;
|
|
1981
2011
|
let maxDecFrameBuffering = null;
|
|
2012
|
+
let bitstreamRestrictionFlagBitOffset = null;
|
|
2013
|
+
let bitstreamRestrictionFlag = null;
|
|
2014
|
+
const vuiParametersFlagBitOffset = bitstream.pos;
|
|
1982
2015
|
const vuiParametersPresentFlag = bitstream.readBits(1);
|
|
1983
2016
|
if (vuiParametersPresentFlag) {
|
|
1984
2017
|
const aspectRatioInfoPresentFlag = bitstream.readBits(1);
|
|
@@ -2034,7 +2067,8 @@ var Mediabunny = (() => {
|
|
|
2034
2067
|
bitstream.skipBits(1);
|
|
2035
2068
|
}
|
|
2036
2069
|
bitstream.skipBits(1);
|
|
2037
|
-
|
|
2070
|
+
bitstreamRestrictionFlagBitOffset = bitstream.pos;
|
|
2071
|
+
bitstreamRestrictionFlag = bitstream.readBits(1);
|
|
2038
2072
|
if (bitstreamRestrictionFlag) {
|
|
2039
2073
|
bitstream.skipBits(1);
|
|
2040
2074
|
readExpGolomb(bitstream);
|
|
@@ -2068,6 +2102,7 @@ var Mediabunny = (() => {
|
|
|
2068
2102
|
}
|
|
2069
2103
|
assert(maxDecFrameBuffering !== null);
|
|
2070
2104
|
return {
|
|
2105
|
+
emulationUnpreventedBytes,
|
|
2071
2106
|
profileIdc,
|
|
2072
2107
|
constraintFlags,
|
|
2073
2108
|
levelIdc,
|
|
@@ -2085,7 +2120,10 @@ var Mediabunny = (() => {
|
|
|
2085
2120
|
transferCharacteristics,
|
|
2086
2121
|
fullRangeFlag,
|
|
2087
2122
|
numReorderFrames,
|
|
2088
|
-
maxDecFrameBuffering
|
|
2123
|
+
maxDecFrameBuffering,
|
|
2124
|
+
vuiParametersFlagBitOffset,
|
|
2125
|
+
bitstreamRestrictionFlagBitOffset,
|
|
2126
|
+
bitstreamRestrictionFlag
|
|
2089
2127
|
};
|
|
2090
2128
|
} catch (error) {
|
|
2091
2129
|
Logging._error("Error parsing AVC SPS:", error);
|
|
@@ -2106,6 +2144,40 @@ var Mediabunny = (() => {
|
|
|
2106
2144
|
bitstream.skipBits(5);
|
|
2107
2145
|
bitstream.skipBits(5);
|
|
2108
2146
|
};
|
|
2147
|
+
var addAvcBitstreamRestriction = (sps) => {
|
|
2148
|
+
assert(sps.bitstreamRestrictionFlag !== 1);
|
|
2149
|
+
const modifiedBytes = new Uint8Array(sps.emulationUnpreventedBytes.byteLength + 64);
|
|
2150
|
+
const oldBitstream = new Bitstream(sps.emulationUnpreventedBytes);
|
|
2151
|
+
const newBitstream = new Bitstream(modifiedBytes);
|
|
2152
|
+
if (sps.bitstreamRestrictionFlag === null) {
|
|
2153
|
+
newBitstream.copyBits(sps.vuiParametersFlagBitOffset, oldBitstream);
|
|
2154
|
+
newBitstream.writeBits(1, 1);
|
|
2155
|
+
newBitstream.writeBits(1, 0);
|
|
2156
|
+
newBitstream.writeBits(1, 0);
|
|
2157
|
+
newBitstream.writeBits(1, 0);
|
|
2158
|
+
newBitstream.writeBits(1, 0);
|
|
2159
|
+
newBitstream.writeBits(1, 0);
|
|
2160
|
+
newBitstream.writeBits(1, 0);
|
|
2161
|
+
newBitstream.writeBits(1, 0);
|
|
2162
|
+
newBitstream.writeBits(1, 0);
|
|
2163
|
+
} else {
|
|
2164
|
+
assert(sps.bitstreamRestrictionFlagBitOffset !== null);
|
|
2165
|
+
newBitstream.copyBits(sps.bitstreamRestrictionFlagBitOffset, oldBitstream);
|
|
2166
|
+
}
|
|
2167
|
+
newBitstream.writeBits(1, 1);
|
|
2168
|
+
newBitstream.writeBits(1, 1);
|
|
2169
|
+
writeExpGolomb(newBitstream, 2);
|
|
2170
|
+
writeExpGolomb(newBitstream, 1);
|
|
2171
|
+
writeExpGolomb(newBitstream, 16);
|
|
2172
|
+
writeExpGolomb(newBitstream, 16);
|
|
2173
|
+
writeExpGolomb(newBitstream, sps.numReorderFrames);
|
|
2174
|
+
writeExpGolomb(newBitstream, sps.maxDecFrameBuffering);
|
|
2175
|
+
newBitstream.writeBits(1, 1);
|
|
2176
|
+
newBitstream.writeBits((8 - newBitstream.pos % 8) % 8, 0);
|
|
2177
|
+
const byteLength = newBitstream.pos / 8;
|
|
2178
|
+
assert(Number.isInteger(byteLength));
|
|
2179
|
+
return addEmulationPreventionBytes(modifiedBytes.subarray(0, byteLength));
|
|
2180
|
+
};
|
|
2109
2181
|
var concatHevcNalUnits = (nalUnits, decoderConfig) => {
|
|
2110
2182
|
if (decoderConfig.description) {
|
|
2111
2183
|
const bytes2 = toUint8Array(decoderConfig.description);
|
|
@@ -3422,7 +3494,13 @@ var Mediabunny = (() => {
|
|
|
3422
3494
|
const key = string.slice(0, separatorIndex).toUpperCase();
|
|
3423
3495
|
const value = string.slice(separatorIndex + 1);
|
|
3424
3496
|
metadataTags.raw ??= {};
|
|
3425
|
-
metadataTags.raw[key]
|
|
3497
|
+
if (Array.isArray(metadataTags.raw[key])) {
|
|
3498
|
+
metadataTags.raw[key] = [...metadataTags.raw[key], value];
|
|
3499
|
+
} else if (typeof metadataTags.raw[key] === "string") {
|
|
3500
|
+
metadataTags.raw[key] = [metadataTags.raw[key], value];
|
|
3501
|
+
} else {
|
|
3502
|
+
metadataTags.raw[key] ??= value;
|
|
3503
|
+
}
|
|
3426
3504
|
switch (key) {
|
|
3427
3505
|
case "TITLE":
|
|
3428
3506
|
{
|
|
@@ -3569,7 +3647,7 @@ var Mediabunny = (() => {
|
|
|
3569
3647
|
currentView.setUint32(0, encodedVendorString.length, true);
|
|
3570
3648
|
currentBuffer.set(encodedVendorString, 4);
|
|
3571
3649
|
commentHeaderParts.push(currentBuffer);
|
|
3572
|
-
const writtenTags =
|
|
3650
|
+
const writtenTags = [];
|
|
3573
3651
|
const addCommentTag = (key, value) => {
|
|
3574
3652
|
const joined = `${key}=${value}`;
|
|
3575
3653
|
const encoded = textEncoder.encode(joined);
|
|
@@ -3578,7 +3656,7 @@ var Mediabunny = (() => {
|
|
|
3578
3656
|
currentView.setUint32(0, encoded.length, true);
|
|
3579
3657
|
currentBuffer.set(encoded, 4);
|
|
3580
3658
|
commentHeaderParts.push(currentBuffer);
|
|
3581
|
-
writtenTags.
|
|
3659
|
+
writtenTags.push(key);
|
|
3582
3660
|
};
|
|
3583
3661
|
for (const { key, value } of keyValueIterator(tags)) {
|
|
3584
3662
|
switch (key) {
|
|
@@ -3620,12 +3698,7 @@ var Mediabunny = (() => {
|
|
|
3620
3698
|
break;
|
|
3621
3699
|
case "date":
|
|
3622
3700
|
{
|
|
3623
|
-
|
|
3624
|
-
if (rawVersion && typeof rawVersion === "string") {
|
|
3625
|
-
addCommentTag("DATE", rawVersion);
|
|
3626
|
-
} else {
|
|
3627
|
-
addCommentTag("DATE", value.toISOString().slice(0, 10));
|
|
3628
|
-
}
|
|
3701
|
+
addCommentTag("DATE", value.toISOString().slice(0, 10));
|
|
3629
3702
|
}
|
|
3630
3703
|
;
|
|
3631
3704
|
break;
|
|
@@ -3714,16 +3787,23 @@ var Mediabunny = (() => {
|
|
|
3714
3787
|
if (tags.raw) {
|
|
3715
3788
|
for (const key in tags.raw) {
|
|
3716
3789
|
const value = tags.raw[key] ?? tags.raw[key.toLowerCase()];
|
|
3717
|
-
if (key === "vendor" || value == null || writtenTags.
|
|
3790
|
+
if (key === "vendor" || value == null || writtenTags.includes(key)) {
|
|
3718
3791
|
continue;
|
|
3719
3792
|
}
|
|
3720
3793
|
if (typeof value === "string") {
|
|
3721
3794
|
addCommentTag(key, value);
|
|
3795
|
+
} else if (Array.isArray(value)) {
|
|
3796
|
+
const isOnlyStrings = value.every((x) => typeof x === "string");
|
|
3797
|
+
if (isOnlyStrings) {
|
|
3798
|
+
for (const elem of value) {
|
|
3799
|
+
addCommentTag(key, elem);
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3722
3802
|
}
|
|
3723
3803
|
}
|
|
3724
3804
|
}
|
|
3725
3805
|
const listLengthBuffer = new Uint8Array(4);
|
|
3726
|
-
toDataView(listLengthBuffer).setUint32(0, writtenTags.
|
|
3806
|
+
toDataView(listLengthBuffer).setUint32(0, writtenTags.length, true);
|
|
3727
3807
|
commentHeaderParts.splice(2, 0, listLengthBuffer);
|
|
3728
3808
|
const commentHeaderLength = commentHeaderParts.reduce((a, b) => a + b.length, 0);
|
|
3729
3809
|
const commentHeader = new Uint8Array(commentHeaderLength);
|
|
@@ -24070,11 +24150,20 @@ var Mediabunny = (() => {
|
|
|
24070
24150
|
);
|
|
24071
24151
|
if (record && record.sequenceParameterSets.length > 0) {
|
|
24072
24152
|
const sps = parseAvcSps(record.sequenceParameterSets[0]);
|
|
24073
|
-
if (sps
|
|
24074
|
-
|
|
24075
|
-
|
|
24076
|
-
|
|
24077
|
-
|
|
24153
|
+
if (sps) {
|
|
24154
|
+
if (sps.frameMbsOnlyFlag === 0) {
|
|
24155
|
+
this.decoderConfig = {
|
|
24156
|
+
...this.decoderConfig,
|
|
24157
|
+
hardwareAcceleration: "prefer-software"
|
|
24158
|
+
};
|
|
24159
|
+
}
|
|
24160
|
+
if (sps.maxDecFrameBuffering !== 0 && sps.bitstreamRestrictionFlag !== 1) {
|
|
24161
|
+
record.sequenceParameterSets[0] = addAvcBitstreamRestriction(sps);
|
|
24162
|
+
this.decoderConfig = {
|
|
24163
|
+
...this.decoderConfig,
|
|
24164
|
+
description: serializeAvcDecoderConfigurationRecord(record)
|
|
24165
|
+
};
|
|
24166
|
+
}
|
|
24078
24167
|
}
|
|
24079
24168
|
}
|
|
24080
24169
|
}
|
|
@@ -24151,6 +24240,19 @@ var Mediabunny = (() => {
|
|
|
24151
24240
|
filteredNalUnits.push(packet.data.subarray(loc.offset, loc.offset + loc.length));
|
|
24152
24241
|
}
|
|
24153
24242
|
}
|
|
24243
|
+
if (!this.decoderConfig.description) {
|
|
24244
|
+
for (let i = 0; i < filteredNalUnits.length; i++) {
|
|
24245
|
+
const nalUnit = filteredNalUnits[i];
|
|
24246
|
+
if (extractNalUnitTypeForAvc(nalUnit[0]) !== 7 /* SPS */) {
|
|
24247
|
+
continue;
|
|
24248
|
+
}
|
|
24249
|
+
const sps = parseAvcSps(nalUnit);
|
|
24250
|
+
if (sps && sps.maxDecFrameBuffering !== 0 && sps.bitstreamRestrictionFlag !== 1) {
|
|
24251
|
+
filteredNalUnits[i] = addAvcBitstreamRestriction(sps);
|
|
24252
|
+
}
|
|
24253
|
+
break;
|
|
24254
|
+
}
|
|
24255
|
+
}
|
|
24154
24256
|
const newData = concatAvcNalUnits(filteredNalUnits, this.decoderConfig);
|
|
24155
24257
|
packet = new EncodedPacket(newData, packet.type, packet.timestamp, packet.duration);
|
|
24156
24258
|
} else if (this.codec === "hevc") {
|
|
@@ -34450,11 +34552,11 @@ ${cue.notes ?? ""}`;
|
|
|
34450
34552
|
};
|
|
34451
34553
|
} else if (sourceNum === 2 && targetNum === 4) {
|
|
34452
34554
|
this.channelMixer = (sourceData, sourceFrameIndex, targetChannelIndex) => {
|
|
34453
|
-
return sourceData[sourceFrameIndex * sourceNum + targetChannelIndex]
|
|
34555
|
+
return targetChannelIndex < 2 ? sourceData[sourceFrameIndex * sourceNum + targetChannelIndex] : 0;
|
|
34454
34556
|
};
|
|
34455
34557
|
} else if (sourceNum === 2 && targetNum === 6) {
|
|
34456
34558
|
this.channelMixer = (sourceData, sourceFrameIndex, targetChannelIndex) => {
|
|
34457
|
-
return sourceData[sourceFrameIndex * sourceNum + targetChannelIndex]
|
|
34559
|
+
return targetChannelIndex < 2 ? sourceData[sourceFrameIndex * sourceNum + targetChannelIndex] : 0;
|
|
34458
34560
|
};
|
|
34459
34561
|
} else if (sourceNum === 4 && targetNum === 1) {
|
|
34460
34562
|
this.channelMixer = (sourceData, sourceFrameIndex) => {
|
|
@@ -39642,7 +39744,7 @@ ${cue.notes ?? ""}`;
|
|
|
39642
39744
|
}
|
|
39643
39745
|
const inputAndOutputFormatMatch = inputFormat.mimeType === this.output.format.mimeType;
|
|
39644
39746
|
const rawTagsAreUnchanged = inputTags.raw === outputTags.raw;
|
|
39645
|
-
if (
|
|
39747
|
+
if (rawTagsAreUnchanged && !inputAndOutputFormatMatch) {
|
|
39646
39748
|
delete outputTags.raw;
|
|
39647
39749
|
}
|
|
39648
39750
|
this.output.setMetadataTags(outputTags);
|