mediabunny 1.53.1 → 1.55.0
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 +916 -46
- package/dist/bundles/mediabunny.min.cjs +14 -14
- package/dist/bundles/mediabunny.min.mjs +14 -14
- package/dist/bundles/mediabunny.mjs +916 -46
- package/dist/bundles/mediabunny.node.cjs +916 -46
- package/dist/mediabunny.d.ts +77 -2
- package/dist/modules/shared/dts-misc.d.ts +17 -0
- package/dist/modules/shared/dts-misc.d.ts.map +1 -0
- package/dist/modules/shared/dts-misc.js +26 -0
- package/dist/modules/src/codec-data.d.ts +98 -1
- package/dist/modules/src/codec-data.d.ts.map +1 -1
- package/dist/modules/src/codec-data.js +346 -1
- package/dist/modules/src/codec.d.ts +6 -3
- package/dist/modules/src/codec.d.ts.map +1 -1
- package/dist/modules/src/codec.js +25 -2
- package/dist/modules/src/encode.d.ts.map +1 -1
- package/dist/modules/src/encode.js +3 -2
- package/dist/modules/src/index.d.ts +1 -1
- package/dist/modules/src/index.d.ts.map +1 -1
- package/dist/modules/src/input-track.d.ts +80 -0
- package/dist/modules/src/input-track.d.ts.map +1 -1
- package/dist/modules/src/input-track.js +300 -0
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-boxes.js +16 -4
- package/dist/modules/src/isobmff/isobmff-demuxer.d.ts +2 -1
- package/dist/modules/src/isobmff/isobmff-demuxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-demuxer.js +44 -9
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-muxer.js +5 -2
- package/dist/modules/src/matroska/ebml.d.ts.map +1 -1
- package/dist/modules/src/matroska/ebml.js +1 -0
- package/dist/modules/src/matroska/matroska-demuxer.d.ts +2 -1
- package/dist/modules/src/matroska/matroska-demuxer.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-demuxer.js +30 -12
- package/dist/modules/src/matroska/matroska-muxer.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-muxer.js +10 -1
- package/dist/modules/src/media-sink.d.ts.map +1 -1
- package/dist/modules/src/media-sink.js +9 -3
- 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 +8 -0
- package/dist/modules/src/mpeg-ts/mpeg-ts-demuxer.d.ts +2 -1
- package/dist/modules/src/mpeg-ts/mpeg-ts-demuxer.d.ts.map +1 -1
- package/dist/modules/src/mpeg-ts/mpeg-ts-demuxer.js +149 -11
- package/dist/modules/src/mpeg-ts/mpeg-ts-misc.d.ts +5 -0
- package/dist/modules/src/mpeg-ts/mpeg-ts-misc.d.ts.map +1 -1
- package/dist/modules/src/mpeg-ts/mpeg-ts-muxer.d.ts.map +1 -1
- package/dist/modules/src/mpeg-ts/mpeg-ts-muxer.js +9 -2
- package/dist/modules/src/output-format.js +1 -1
- package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
- package/dist/modules/src/wave/wave-demuxer.d.ts +1 -1
- package/package.json +2 -2
- package/src/codec-data.ts +494 -1
- package/src/codec.ts +27 -2
- package/src/encode.ts +3 -2
- package/src/index.ts +2 -0
- package/src/input-track.ts +479 -0
- package/src/isobmff/isobmff-boxes.ts +35 -4
- package/src/isobmff/isobmff-demuxer.ts +49 -7
- package/src/isobmff/isobmff-muxer.ts +6 -2
- package/src/matroska/ebml.ts +1 -0
- package/src/matroska/matroska-demuxer.ts +32 -11
- package/src/matroska/matroska-muxer.ts +10 -1
- package/src/media-sink.ts +11 -3
- package/src/misc.ts +11 -0
- package/src/mpeg-ts/mpeg-ts-demuxer.ts +186 -11
- package/src/mpeg-ts/mpeg-ts-misc.ts +5 -0
- package/src/mpeg-ts/mpeg-ts-muxer.ts +7 -2
- package/src/output-format.ts +1 -1
|
@@ -590,6 +590,14 @@ var Mediabunny = (() => {
|
|
|
590
590
|
}
|
|
591
591
|
return ret;
|
|
592
592
|
};
|
|
593
|
+
var popcount = (value) => {
|
|
594
|
+
let count = 0;
|
|
595
|
+
while (value !== 0) {
|
|
596
|
+
value &= value - 1;
|
|
597
|
+
count++;
|
|
598
|
+
}
|
|
599
|
+
return count;
|
|
600
|
+
};
|
|
593
601
|
var ISO_639_2_REGEX = /^[a-z]{3}$/;
|
|
594
602
|
var isIso639Dash2LanguageCode = (x) => {
|
|
595
603
|
return ISO_639_2_REGEX.test(x);
|
|
@@ -1528,7 +1536,8 @@ var Mediabunny = (() => {
|
|
|
1528
1536
|
"vorbis",
|
|
1529
1537
|
"flac",
|
|
1530
1538
|
"ac3",
|
|
1531
|
-
"eac3"
|
|
1539
|
+
"eac3",
|
|
1540
|
+
"dts"
|
|
1532
1541
|
];
|
|
1533
1542
|
var AUDIO_CODECS = [
|
|
1534
1543
|
...NON_PCM_AUDIO_CODECS,
|
|
@@ -1717,6 +1726,16 @@ var Mediabunny = (() => {
|
|
|
1717
1726
|
"apco"
|
|
1718
1727
|
// ProRes 422 Proxy
|
|
1719
1728
|
];
|
|
1729
|
+
var DTS_FOURCCS = [
|
|
1730
|
+
"dtsc",
|
|
1731
|
+
// DTS core
|
|
1732
|
+
"dtsh",
|
|
1733
|
+
// DTS-HD, core plus extension substreams
|
|
1734
|
+
"dtsl",
|
|
1735
|
+
// DTS-HD Lossless, no core
|
|
1736
|
+
"dtse"
|
|
1737
|
+
// DTS Express
|
|
1738
|
+
];
|
|
1720
1739
|
var PRORES_PROFILE_TARGET_BITRATES = [
|
|
1721
1740
|
{ fourCc: "apco", bitrate: 45e6, alpha: false },
|
|
1722
1741
|
// 422 Proxy
|
|
@@ -1992,13 +2011,15 @@ var Mediabunny = (() => {
|
|
|
1992
2011
|
return "ac-3";
|
|
1993
2012
|
} else if (codec === "eac3") {
|
|
1994
2013
|
return "ec-3";
|
|
2014
|
+
} else if (codec === "dts") {
|
|
2015
|
+
return "dtsc";
|
|
1995
2016
|
} else if (PCM_AUDIO_CODECS.includes(codec)) {
|
|
1996
2017
|
return codec;
|
|
1997
2018
|
}
|
|
1998
2019
|
throw new TypeError(`Unhandled codec '${codec}'.`);
|
|
1999
2020
|
};
|
|
2000
2021
|
var extractAudioCodecString = (trackInfo) => {
|
|
2001
|
-
const { codec, codecDescription, aacCodecInfo } = trackInfo;
|
|
2022
|
+
const { codec, codecDescription, aacCodecInfo, dtsFormat } = trackInfo;
|
|
2002
2023
|
if (codec === "aac") {
|
|
2003
2024
|
if (!aacCodecInfo) {
|
|
2004
2025
|
throw new TypeError("AAC codec info must be provided.");
|
|
@@ -2027,6 +2048,8 @@ var Mediabunny = (() => {
|
|
|
2027
2048
|
return "ac-3";
|
|
2028
2049
|
} else if (codec === "eac3") {
|
|
2029
2050
|
return "ec-3";
|
|
2051
|
+
} else if (codec === "dts") {
|
|
2052
|
+
return dtsFormat ?? "dtsc";
|
|
2030
2053
|
} else if (codec && PCM_AUDIO_CODECS.includes(codec)) {
|
|
2031
2054
|
return codec;
|
|
2032
2055
|
}
|
|
@@ -2114,6 +2137,8 @@ var Mediabunny = (() => {
|
|
|
2114
2137
|
return "ac3";
|
|
2115
2138
|
} else if (codecString === "ec-3" || codecString === "eac3") {
|
|
2116
2139
|
return "eac3";
|
|
2140
|
+
} else if (DTS_FOURCCS.includes(codecString)) {
|
|
2141
|
+
return "dts";
|
|
2117
2142
|
} else if (codecString === "ulaw") {
|
|
2118
2143
|
return "ulaw";
|
|
2119
2144
|
} else if (codecString === "alaw") {
|
|
@@ -2301,7 +2326,8 @@ var Mediabunny = (() => {
|
|
|
2301
2326
|
"alaw",
|
|
2302
2327
|
"pcm",
|
|
2303
2328
|
"ac-3",
|
|
2304
|
-
"ec-3"
|
|
2329
|
+
"ec-3",
|
|
2330
|
+
"dts"
|
|
2305
2331
|
];
|
|
2306
2332
|
var validateAudioChunkMetadata = (metadata, trackCodec) => {
|
|
2307
2333
|
if (!metadata) {
|
|
@@ -2390,6 +2416,12 @@ var Mediabunny = (() => {
|
|
|
2390
2416
|
if (metadata.decoderConfig.codec !== "ec-3") {
|
|
2391
2417
|
throw new TypeError('Audio chunk metadata decoder configuration codec string for EC-3 must be "ec-3".');
|
|
2392
2418
|
}
|
|
2419
|
+
} else if (metadata.decoderConfig.codec.startsWith("dts")) {
|
|
2420
|
+
if (!DTS_FOURCCS.includes(metadata.decoderConfig.codec)) {
|
|
2421
|
+
throw new TypeError(
|
|
2422
|
+
`Audio chunk metadata decoder configuration codec string for DTS must be one of the following four-character codes: ${DTS_FOURCCS.join(", ")}.`
|
|
2423
|
+
);
|
|
2424
|
+
}
|
|
2393
2425
|
} else if (metadata.decoderConfig.codec.startsWith("pcm") || metadata.decoderConfig.codec.startsWith("ulaw") || metadata.decoderConfig.codec.startsWith("alaw")) {
|
|
2394
2426
|
if (!PCM_AUDIO_CODECS.includes(metadata.decoderConfig.codec)) {
|
|
2395
2427
|
throw new TypeError(
|
|
@@ -5059,6 +5091,364 @@ var Mediabunny = (() => {
|
|
|
5059
5091
|
}
|
|
5060
5092
|
return channels;
|
|
5061
5093
|
};
|
|
5094
|
+
var DTS_EXSS_SYNC_WORD = 1683496997;
|
|
5095
|
+
var DTS_CORE_FRAME_HEADER_SIZE = 18;
|
|
5096
|
+
var DTS_EXSS_HEADER_PREFIX_SIZE = 10;
|
|
5097
|
+
var DTS_EXSS_MAX_HEADER_SIZE = 4096;
|
|
5098
|
+
var DTS_PCM_BLOCK_SAMPLES = 32;
|
|
5099
|
+
var DTS_SPECIFIC_BOX_SIZE = 20;
|
|
5100
|
+
var DTS_SUBBAND_SAMPLES = 8;
|
|
5101
|
+
var DTS_CORE_SAMPLE_RATES = [
|
|
5102
|
+
0,
|
|
5103
|
+
8e3,
|
|
5104
|
+
16e3,
|
|
5105
|
+
32e3,
|
|
5106
|
+
0,
|
|
5107
|
+
0,
|
|
5108
|
+
11025,
|
|
5109
|
+
22050,
|
|
5110
|
+
44100,
|
|
5111
|
+
0,
|
|
5112
|
+
0,
|
|
5113
|
+
12e3,
|
|
5114
|
+
24e3,
|
|
5115
|
+
48e3,
|
|
5116
|
+
96e3,
|
|
5117
|
+
192e3
|
|
5118
|
+
];
|
|
5119
|
+
var DTS_CORE_BIT_RATES = [
|
|
5120
|
+
32e3,
|
|
5121
|
+
56e3,
|
|
5122
|
+
64e3,
|
|
5123
|
+
96e3,
|
|
5124
|
+
112e3,
|
|
5125
|
+
128e3,
|
|
5126
|
+
192e3,
|
|
5127
|
+
224e3,
|
|
5128
|
+
256e3,
|
|
5129
|
+
32e4,
|
|
5130
|
+
384e3,
|
|
5131
|
+
448e3,
|
|
5132
|
+
512e3,
|
|
5133
|
+
576e3,
|
|
5134
|
+
64e4,
|
|
5135
|
+
768e3,
|
|
5136
|
+
96e4,
|
|
5137
|
+
1024e3,
|
|
5138
|
+
1152e3,
|
|
5139
|
+
128e4,
|
|
5140
|
+
1344e3,
|
|
5141
|
+
1408e3,
|
|
5142
|
+
1411200,
|
|
5143
|
+
1472e3,
|
|
5144
|
+
1536e3,
|
|
5145
|
+
192e4,
|
|
5146
|
+
2048e3,
|
|
5147
|
+
3072e3,
|
|
5148
|
+
384e4,
|
|
5149
|
+
0,
|
|
5150
|
+
0,
|
|
5151
|
+
0
|
|
5152
|
+
];
|
|
5153
|
+
var DTS_PCM_RESOLUTIONS = [16, 16, 20, 20, 0, 24, 24, 0];
|
|
5154
|
+
var DTS_AMODE_CHANNEL_COUNTS = [1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8];
|
|
5155
|
+
var DTS_AMODE_CHANNEL_LAYOUTS = [
|
|
5156
|
+
1,
|
|
5157
|
+
2,
|
|
5158
|
+
2,
|
|
5159
|
+
2,
|
|
5160
|
+
2,
|
|
5161
|
+
3,
|
|
5162
|
+
18,
|
|
5163
|
+
19,
|
|
5164
|
+
6,
|
|
5165
|
+
7,
|
|
5166
|
+
518,
|
|
5167
|
+
323,
|
|
5168
|
+
83,
|
|
5169
|
+
519,
|
|
5170
|
+
582,
|
|
5171
|
+
535
|
|
5172
|
+
];
|
|
5173
|
+
var DTS_CHANNEL_LAYOUT_LFE1 = 8;
|
|
5174
|
+
var DTS_CHANNEL_LAYOUT_PAIR_MASK = 44646;
|
|
5175
|
+
var DTS_EXSS_REF_CLOCKS = [32e3, 44100, 48e3, 0];
|
|
5176
|
+
var DTS_EXSS_SAMPLE_RATES = [
|
|
5177
|
+
8e3,
|
|
5178
|
+
16e3,
|
|
5179
|
+
32e3,
|
|
5180
|
+
64e3,
|
|
5181
|
+
128e3,
|
|
5182
|
+
22050,
|
|
5183
|
+
44100,
|
|
5184
|
+
88200,
|
|
5185
|
+
176400,
|
|
5186
|
+
352800,
|
|
5187
|
+
12e3,
|
|
5188
|
+
24e3,
|
|
5189
|
+
48e3,
|
|
5190
|
+
96e3,
|
|
5191
|
+
192e3,
|
|
5192
|
+
384e3
|
|
5193
|
+
];
|
|
5194
|
+
var DTS_SPECIFIC_BOX_FRAME_DURATIONS = [512, 1024, 2048, 4096];
|
|
5195
|
+
var parseDtsFrame = (data) => {
|
|
5196
|
+
const core = parseDtsCoreFrameHeader(data);
|
|
5197
|
+
const view2 = toDataView(data);
|
|
5198
|
+
let offset = core ? Math.ceil(core.frameSize / 4) * 4 : 0;
|
|
5199
|
+
let firstExss = null;
|
|
5200
|
+
while (offset + 4 <= data.length && view2.getUint32(offset) === DTS_EXSS_SYNC_WORD) {
|
|
5201
|
+
const exss = parseDtsExssHeader(data.subarray(offset));
|
|
5202
|
+
if (!exss) {
|
|
5203
|
+
break;
|
|
5204
|
+
}
|
|
5205
|
+
firstExss ??= exss;
|
|
5206
|
+
offset += exss.frameSize;
|
|
5207
|
+
}
|
|
5208
|
+
if (core) {
|
|
5209
|
+
return {
|
|
5210
|
+
frameSize: firstExss ? offset : core.frameSize,
|
|
5211
|
+
sampleRate: core.sampleRate,
|
|
5212
|
+
numberOfChannels: core.numberOfChannels,
|
|
5213
|
+
sampleCount: core.sampleCount,
|
|
5214
|
+
channelLayout: core.channelLayout,
|
|
5215
|
+
pcmResolution: core.pcmResolution,
|
|
5216
|
+
bitRate: core.bitRate,
|
|
5217
|
+
core,
|
|
5218
|
+
hasExtensions: firstExss !== null
|
|
5219
|
+
};
|
|
5220
|
+
}
|
|
5221
|
+
if (!firstExss?.asset) {
|
|
5222
|
+
return null;
|
|
5223
|
+
}
|
|
5224
|
+
const { asset } = firstExss;
|
|
5225
|
+
return {
|
|
5226
|
+
frameSize: offset,
|
|
5227
|
+
sampleRate: asset.sampleRate,
|
|
5228
|
+
numberOfChannels: asset.numberOfChannels,
|
|
5229
|
+
sampleCount: asset.sampleCount,
|
|
5230
|
+
channelLayout: asset.channelLayout,
|
|
5231
|
+
pcmResolution: asset.pcmResolution,
|
|
5232
|
+
bitRate: 0,
|
|
5233
|
+
core: null,
|
|
5234
|
+
hasExtensions: true
|
|
5235
|
+
};
|
|
5236
|
+
};
|
|
5237
|
+
var extractDtsFourCcFromPacket = (data) => {
|
|
5238
|
+
const frameInfo = parseDtsFrame(data);
|
|
5239
|
+
if (!frameInfo?.core) {
|
|
5240
|
+
return null;
|
|
5241
|
+
}
|
|
5242
|
+
return frameInfo.hasExtensions ? "dtsh" : "dtsc";
|
|
5243
|
+
};
|
|
5244
|
+
var parseDtsCoreFrameHeader = (data) => {
|
|
5245
|
+
if (data.length < DTS_CORE_FRAME_HEADER_SIZE) {
|
|
5246
|
+
return null;
|
|
5247
|
+
}
|
|
5248
|
+
if (data[0] !== 127 || data[1] !== 254 || data[2] !== 128 || data[3] !== 1) {
|
|
5249
|
+
return null;
|
|
5250
|
+
}
|
|
5251
|
+
const bitstream = new Bitstream(data);
|
|
5252
|
+
bitstream.skipBits(32);
|
|
5253
|
+
bitstream.skipBits(1);
|
|
5254
|
+
if (bitstream.readBits(5) !== DTS_PCM_BLOCK_SAMPLES - 1) {
|
|
5255
|
+
return null;
|
|
5256
|
+
}
|
|
5257
|
+
const cpf = bitstream.readBits(1);
|
|
5258
|
+
const npcmblocks = bitstream.readBits(7) + 1;
|
|
5259
|
+
if (npcmblocks % DTS_SUBBAND_SAMPLES !== 0) {
|
|
5260
|
+
return null;
|
|
5261
|
+
}
|
|
5262
|
+
const frameSize = bitstream.readBits(14) + 1;
|
|
5263
|
+
if (frameSize < 96) {
|
|
5264
|
+
return null;
|
|
5265
|
+
}
|
|
5266
|
+
const amode = bitstream.readBits(6);
|
|
5267
|
+
if (amode >= DTS_AMODE_CHANNEL_COUNTS.length) {
|
|
5268
|
+
return null;
|
|
5269
|
+
}
|
|
5270
|
+
const sampleRate = DTS_CORE_SAMPLE_RATES[bitstream.readBits(4)];
|
|
5271
|
+
if (sampleRate === 0) {
|
|
5272
|
+
return null;
|
|
5273
|
+
}
|
|
5274
|
+
const bitRate = DTS_CORE_BIT_RATES[bitstream.readBits(5)];
|
|
5275
|
+
if (bitstream.readBits(1) !== 0) {
|
|
5276
|
+
return null;
|
|
5277
|
+
}
|
|
5278
|
+
bitstream.skipBits(1 + 1 + 1 + 1);
|
|
5279
|
+
bitstream.skipBits(3 + 1 + 1);
|
|
5280
|
+
const lff = bitstream.readBits(2);
|
|
5281
|
+
if (lff === 3) {
|
|
5282
|
+
return null;
|
|
5283
|
+
}
|
|
5284
|
+
bitstream.skipBits(1);
|
|
5285
|
+
if (cpf) {
|
|
5286
|
+
bitstream.skipBits(16);
|
|
5287
|
+
}
|
|
5288
|
+
bitstream.skipBits(1 + 4 + 2);
|
|
5289
|
+
const pcmResolution = DTS_PCM_RESOLUTIONS[bitstream.readBits(3)];
|
|
5290
|
+
if (pcmResolution === 0) {
|
|
5291
|
+
return null;
|
|
5292
|
+
}
|
|
5293
|
+
const lfePresent = lff !== 0;
|
|
5294
|
+
return {
|
|
5295
|
+
frameSize,
|
|
5296
|
+
sampleRate,
|
|
5297
|
+
numberOfChannels: DTS_AMODE_CHANNEL_COUNTS[amode] + (lfePresent ? 1 : 0),
|
|
5298
|
+
sampleCount: npcmblocks * DTS_PCM_BLOCK_SAMPLES,
|
|
5299
|
+
channelLayout: DTS_AMODE_CHANNEL_LAYOUTS[amode] | (lfePresent ? DTS_CHANNEL_LAYOUT_LFE1 : 0),
|
|
5300
|
+
amode,
|
|
5301
|
+
lfePresent,
|
|
5302
|
+
bitRate,
|
|
5303
|
+
pcmResolution
|
|
5304
|
+
};
|
|
5305
|
+
};
|
|
5306
|
+
var parseDtsExssHeader = (data) => {
|
|
5307
|
+
if (data.length < DTS_EXSS_HEADER_PREFIX_SIZE) {
|
|
5308
|
+
return null;
|
|
5309
|
+
}
|
|
5310
|
+
if (data[0] !== 100 || data[1] !== 88 || data[2] !== 32 || data[3] !== 37) {
|
|
5311
|
+
return null;
|
|
5312
|
+
}
|
|
5313
|
+
const bitstream = new Bitstream(data);
|
|
5314
|
+
bitstream.skipBits(32);
|
|
5315
|
+
bitstream.skipBits(8);
|
|
5316
|
+
const extSsIndex = bitstream.readBits(2);
|
|
5317
|
+
const wideHeader = bitstream.readBits(1);
|
|
5318
|
+
const headerSizeBits = 8 + 4 * wideHeader;
|
|
5319
|
+
const frameSizeBits = 16 + 4 * wideHeader;
|
|
5320
|
+
bitstream.skipBits(headerSizeBits);
|
|
5321
|
+
const frameSize = bitstream.readBits(frameSizeBits) + 1;
|
|
5322
|
+
const incomplete = { frameSize, asset: null };
|
|
5323
|
+
if (!bitstream.readBits(1)) {
|
|
5324
|
+
return incomplete;
|
|
5325
|
+
}
|
|
5326
|
+
const refClock = DTS_EXSS_REF_CLOCKS[bitstream.readBits(2)];
|
|
5327
|
+
const frameDurationCycles = 512 * (bitstream.readBits(3) + 1);
|
|
5328
|
+
if (bitstream.readBits(1)) {
|
|
5329
|
+
bitstream.skipBits(32 + 4);
|
|
5330
|
+
}
|
|
5331
|
+
const numAudioPresentations = bitstream.readBits(3) + 1;
|
|
5332
|
+
const numAssets = bitstream.readBits(3) + 1;
|
|
5333
|
+
const activeExssMasks = [];
|
|
5334
|
+
for (let i = 0; i < numAudioPresentations; i++) {
|
|
5335
|
+
activeExssMasks.push(bitstream.readBits(extSsIndex + 1));
|
|
5336
|
+
}
|
|
5337
|
+
for (const mask of activeExssMasks) {
|
|
5338
|
+
bitstream.skipBits(8 * popcount(mask));
|
|
5339
|
+
}
|
|
5340
|
+
if (bitstream.readBits(1)) {
|
|
5341
|
+
bitstream.skipBits(2);
|
|
5342
|
+
const spkrMaskBits = bitstream.readBits(2) + 1 << 2;
|
|
5343
|
+
const numMixOutConfigs = bitstream.readBits(2) + 1;
|
|
5344
|
+
bitstream.skipBits(numMixOutConfigs * spkrMaskBits);
|
|
5345
|
+
}
|
|
5346
|
+
for (let i = 0; i < numAssets; i++) {
|
|
5347
|
+
bitstream.skipBits(frameSizeBits);
|
|
5348
|
+
}
|
|
5349
|
+
bitstream.skipBits(9);
|
|
5350
|
+
bitstream.skipBits(3);
|
|
5351
|
+
if (bitstream.readBits(1)) {
|
|
5352
|
+
bitstream.skipBits(4);
|
|
5353
|
+
}
|
|
5354
|
+
if (bitstream.readBits(1)) {
|
|
5355
|
+
bitstream.skipBits(24);
|
|
5356
|
+
}
|
|
5357
|
+
if (bitstream.readBits(1)) {
|
|
5358
|
+
bitstream.skipBits(8 * (bitstream.readBits(10) + 1));
|
|
5359
|
+
}
|
|
5360
|
+
const pcmResolution = bitstream.readBits(5) + 1;
|
|
5361
|
+
const sampleRate = DTS_EXSS_SAMPLE_RATES[bitstream.readBits(4)];
|
|
5362
|
+
const numberOfChannels = bitstream.readBits(8) + 1;
|
|
5363
|
+
let channelLayout = 0;
|
|
5364
|
+
if (bitstream.readBits(1)) {
|
|
5365
|
+
if (numberOfChannels > 2) {
|
|
5366
|
+
bitstream.skipBits(1);
|
|
5367
|
+
}
|
|
5368
|
+
if (numberOfChannels > 6) {
|
|
5369
|
+
bitstream.skipBits(1);
|
|
5370
|
+
}
|
|
5371
|
+
if (bitstream.readBits(1)) {
|
|
5372
|
+
const spkrMaskBits = bitstream.readBits(2) + 1 << 2;
|
|
5373
|
+
channelLayout = bitstream.readBits(spkrMaskBits);
|
|
5374
|
+
}
|
|
5375
|
+
}
|
|
5376
|
+
if (refClock === 0 || bitstream.getBitsLeft() < 0) {
|
|
5377
|
+
return incomplete;
|
|
5378
|
+
}
|
|
5379
|
+
return {
|
|
5380
|
+
frameSize,
|
|
5381
|
+
asset: {
|
|
5382
|
+
sampleRate,
|
|
5383
|
+
numberOfChannels,
|
|
5384
|
+
sampleCount: Math.round(frameDurationCycles * sampleRate / refClock),
|
|
5385
|
+
channelLayout,
|
|
5386
|
+
pcmResolution
|
|
5387
|
+
}
|
|
5388
|
+
};
|
|
5389
|
+
};
|
|
5390
|
+
var parseDtsSpecificBox = (data) => {
|
|
5391
|
+
if (data.length < DTS_SPECIFIC_BOX_SIZE) {
|
|
5392
|
+
return null;
|
|
5393
|
+
}
|
|
5394
|
+
const view2 = toDataView(data);
|
|
5395
|
+
const sampleRate = view2.getUint32(0);
|
|
5396
|
+
if (sampleRate === 0) {
|
|
5397
|
+
return null;
|
|
5398
|
+
}
|
|
5399
|
+
const bitstream = new Bitstream(data);
|
|
5400
|
+
bitstream.seekToByte(13);
|
|
5401
|
+
const frameDuration = bitstream.readBits(2);
|
|
5402
|
+
bitstream.skipBits(5);
|
|
5403
|
+
const coreLfePresent = bitstream.readBits(1);
|
|
5404
|
+
const coreLayout = bitstream.readBits(6);
|
|
5405
|
+
bitstream.skipBits(14);
|
|
5406
|
+
bitstream.skipBits(1);
|
|
5407
|
+
bitstream.skipBits(3);
|
|
5408
|
+
const channelLayout = bitstream.readBits(16);
|
|
5409
|
+
let numberOfChannels = null;
|
|
5410
|
+
if (channelLayout !== 0) {
|
|
5411
|
+
numberOfChannels = getDtsChannelCount(channelLayout);
|
|
5412
|
+
} else if (coreLayout < DTS_AMODE_CHANNEL_COUNTS.length) {
|
|
5413
|
+
numberOfChannels = DTS_AMODE_CHANNEL_COUNTS[coreLayout] + coreLfePresent;
|
|
5414
|
+
}
|
|
5415
|
+
return {
|
|
5416
|
+
sampleRate,
|
|
5417
|
+
maxBitrate: view2.getUint32(4),
|
|
5418
|
+
avgBitrate: view2.getUint32(8),
|
|
5419
|
+
pcmSampleDepth: data[12],
|
|
5420
|
+
sampleCount: DTS_SPECIFIC_BOX_FRAME_DURATIONS[frameDuration],
|
|
5421
|
+
channelLayout,
|
|
5422
|
+
numberOfChannels
|
|
5423
|
+
};
|
|
5424
|
+
};
|
|
5425
|
+
var buildDtsSpecificBox = (frameInfo) => {
|
|
5426
|
+
const bytes2 = new Uint8Array(DTS_SPECIFIC_BOX_SIZE);
|
|
5427
|
+
const view2 = toDataView(bytes2);
|
|
5428
|
+
view2.setUint32(0, frameInfo.sampleRate);
|
|
5429
|
+
view2.setUint32(4, frameInfo.bitRate);
|
|
5430
|
+
view2.setUint32(8, frameInfo.bitRate);
|
|
5431
|
+
bytes2[12] = frameInfo.pcmResolution;
|
|
5432
|
+
const streamConstruction = frameInfo.core && !frameInfo.hasExtensions ? 1 : 0;
|
|
5433
|
+
const bitstream = new Bitstream(bytes2);
|
|
5434
|
+
bitstream.seekToByte(13);
|
|
5435
|
+
bitstream.writeBits(2, Math.max(DTS_SPECIFIC_BOX_FRAME_DURATIONS.indexOf(frameInfo.sampleCount), 0));
|
|
5436
|
+
bitstream.writeBits(5, streamConstruction);
|
|
5437
|
+
bitstream.writeBits(1, frameInfo.core?.lfePresent ? 1 : 0);
|
|
5438
|
+
bitstream.writeBits(6, frameInfo.core?.amode ?? 0);
|
|
5439
|
+
bitstream.writeBits(14, frameInfo.core ? frameInfo.core.frameSize - 1 : 0);
|
|
5440
|
+
bitstream.writeBits(1, 0);
|
|
5441
|
+
bitstream.writeBits(3, 0);
|
|
5442
|
+
bitstream.writeBits(16, frameInfo.channelLayout);
|
|
5443
|
+
bitstream.writeBits(1, 0);
|
|
5444
|
+
bitstream.writeBits(1, 0);
|
|
5445
|
+
bitstream.writeBits(1, 0);
|
|
5446
|
+
bitstream.writeBits(5, 0);
|
|
5447
|
+
return bytes2;
|
|
5448
|
+
};
|
|
5449
|
+
var getDtsChannelCount = (channelLayout) => {
|
|
5450
|
+
return popcount(channelLayout) + popcount(channelLayout & DTS_CHANNEL_LAYOUT_PAIR_MASK);
|
|
5451
|
+
};
|
|
5062
5452
|
|
|
5063
5453
|
// src/demuxer.ts
|
|
5064
5454
|
var Demuxer = class {
|
|
@@ -6122,6 +6512,7 @@ var Mediabunny = (() => {
|
|
|
6122
6512
|
codec: null,
|
|
6123
6513
|
codecDescription: null,
|
|
6124
6514
|
aacCodecInfo: null,
|
|
6515
|
+
dtsFormat: null,
|
|
6125
6516
|
pcmLittleEndian: false,
|
|
6126
6517
|
pcmSampleSize: null
|
|
6127
6518
|
};
|
|
@@ -6244,6 +6635,9 @@ var Mediabunny = (() => {
|
|
|
6244
6635
|
track.info.codec = "ac3";
|
|
6245
6636
|
} else if (codecName === "ec-3") {
|
|
6246
6637
|
track.info.codec = "eac3";
|
|
6638
|
+
} else if (DTS_FOURCCS.includes(codecName)) {
|
|
6639
|
+
track.info.codec = "dts";
|
|
6640
|
+
track.info.dtsFormat = codecName;
|
|
6247
6641
|
} else if (codecName === "twos") {
|
|
6248
6642
|
if (sampleSize === 8) {
|
|
6249
6643
|
track.info.codec = "pcm-s8";
|
|
@@ -6603,6 +6997,8 @@ var Mediabunny = (() => {
|
|
|
6603
6997
|
track.info.codec = "mp3";
|
|
6604
6998
|
} else if (objectTypeIndication === 221) {
|
|
6605
6999
|
track.info.codec = "vorbis";
|
|
7000
|
+
} else if (objectTypeIndication === 169) {
|
|
7001
|
+
track.info.codec = "dts";
|
|
6606
7002
|
} else {
|
|
6607
7003
|
Logging._warn(
|
|
6608
7004
|
`Unsupported audio codec (objectTypeIndication ${objectTypeIndication}) - discarding track.`
|
|
@@ -6769,6 +7165,26 @@ var Mediabunny = (() => {
|
|
|
6769
7165
|
}
|
|
6770
7166
|
;
|
|
6771
7167
|
break;
|
|
7168
|
+
case "ddts":
|
|
7169
|
+
{
|
|
7170
|
+
const track = this.currentTrack;
|
|
7171
|
+
if (!track) {
|
|
7172
|
+
break;
|
|
7173
|
+
}
|
|
7174
|
+
assert(track.info?.type === "audio");
|
|
7175
|
+
const bytes2 = readBytes(slice, Math.min(boxInfo.contentSize, DTS_SPECIFIC_BOX_SIZE));
|
|
7176
|
+
const config = parseDtsSpecificBox(bytes2);
|
|
7177
|
+
if (!config) {
|
|
7178
|
+
Logging._warn("Invalid ddts box contents, ignoring.");
|
|
7179
|
+
break;
|
|
7180
|
+
}
|
|
7181
|
+
track.info.sampleRate = config.sampleRate;
|
|
7182
|
+
if (config.numberOfChannels !== null) {
|
|
7183
|
+
track.info.numberOfChannels = config.numberOfChannels;
|
|
7184
|
+
}
|
|
7185
|
+
}
|
|
7186
|
+
;
|
|
7187
|
+
break;
|
|
6772
7188
|
case "stts":
|
|
6773
7189
|
{
|
|
6774
7190
|
const track = this.currentTrack;
|
|
@@ -8184,7 +8600,7 @@ var Mediabunny = (() => {
|
|
|
8184
8600
|
var IsobmffAudioTrackBacking = class extends IsobmffTrackBacking {
|
|
8185
8601
|
constructor(internalTrack) {
|
|
8186
8602
|
super(internalTrack);
|
|
8187
|
-
this.
|
|
8603
|
+
this.decoderConfigPromise = null;
|
|
8188
8604
|
this.internalTrack = internalTrack;
|
|
8189
8605
|
}
|
|
8190
8606
|
getType() {
|
|
@@ -8203,12 +8619,18 @@ var Mediabunny = (() => {
|
|
|
8203
8619
|
if (!this.internalTrack.info.codec) {
|
|
8204
8620
|
return null;
|
|
8205
8621
|
}
|
|
8206
|
-
return this.
|
|
8207
|
-
|
|
8208
|
-
|
|
8209
|
-
|
|
8210
|
-
|
|
8211
|
-
|
|
8622
|
+
return this.decoderConfigPromise ??= (async () => {
|
|
8623
|
+
if (this.internalTrack.info.codec === "dts" && !this.internalTrack.info.dtsFormat) {
|
|
8624
|
+
const firstPacket = await this.getFirstPacket({});
|
|
8625
|
+
this.internalTrack.info.dtsFormat = firstPacket && extractDtsFourCcFromPacket(firstPacket.data);
|
|
8626
|
+
}
|
|
8627
|
+
return {
|
|
8628
|
+
codec: extractAudioCodecString(this.internalTrack.info),
|
|
8629
|
+
numberOfChannels: this.internalTrack.info.numberOfChannels,
|
|
8630
|
+
sampleRate: this.internalTrack.info.sampleRate,
|
|
8631
|
+
description: this.internalTrack.info.codecDescription ?? void 0
|
|
8632
|
+
};
|
|
8633
|
+
})();
|
|
8212
8634
|
}
|
|
8213
8635
|
};
|
|
8214
8636
|
var getSampleIndexForTimestamp = (sampleTable, timescaleUnits) => {
|
|
@@ -9055,6 +9477,7 @@ var Mediabunny = (() => {
|
|
|
9055
9477
|
"flac": "A_FLAC",
|
|
9056
9478
|
"ac3": "A_AC3",
|
|
9057
9479
|
"eac3": "A_EAC3",
|
|
9480
|
+
"dts": "A_DTS",
|
|
9058
9481
|
"pcm-u8": "A_PCM/INT/LIT",
|
|
9059
9482
|
"pcm-s16": "A_PCM/INT/LIT",
|
|
9060
9483
|
"pcm-s16be": "A_PCM/INT/BIG",
|
|
@@ -9749,6 +10172,13 @@ var Mediabunny = (() => {
|
|
|
9749
10172
|
} else if (codecIdWithoutSuffix === CODEC_STRING_MAP.eac3) {
|
|
9750
10173
|
this.currentTrack.info.codec = "eac3";
|
|
9751
10174
|
this.currentTrack.info.codecDescription = this.currentTrack.codecPrivate;
|
|
10175
|
+
} else if (codecIdWithoutSuffix === CODEC_STRING_MAP.dts) {
|
|
10176
|
+
this.currentTrack.info.codec = "dts";
|
|
10177
|
+
if (this.currentTrack.codecId === "A_DTS/EXPRESS") {
|
|
10178
|
+
this.currentTrack.info.dtsFormat = "dtse";
|
|
10179
|
+
} else if (this.currentTrack.codecId === "A_DTS/LOSSLESS") {
|
|
10180
|
+
this.currentTrack.info.dtsFormat = "dtsl";
|
|
10181
|
+
}
|
|
9752
10182
|
} else if (this.currentTrack.codecId === "A_PCM/INT/LIT") {
|
|
9753
10183
|
if (this.currentTrack.info.bitDepth === 8) {
|
|
9754
10184
|
this.currentTrack.info.codec = "pcm-u8";
|
|
@@ -9823,7 +10253,8 @@ var Mediabunny = (() => {
|
|
|
9823
10253
|
bitDepth: -1,
|
|
9824
10254
|
codec: null,
|
|
9825
10255
|
codecDescription: null,
|
|
9826
|
-
aacCodecInfo: null
|
|
10256
|
+
aacCodecInfo: null,
|
|
10257
|
+
dtsFormat: null
|
|
9827
10258
|
};
|
|
9828
10259
|
}
|
|
9829
10260
|
}
|
|
@@ -11056,7 +11487,7 @@ var Mediabunny = (() => {
|
|
|
11056
11487
|
var MatroskaAudioTrackBacking = class extends MatroskaTrackBacking {
|
|
11057
11488
|
constructor(internalTrack) {
|
|
11058
11489
|
super(internalTrack);
|
|
11059
|
-
this.
|
|
11490
|
+
this.decoderConfigPromise = null;
|
|
11060
11491
|
this.internalTrack = internalTrack;
|
|
11061
11492
|
}
|
|
11062
11493
|
getType() {
|
|
@@ -11075,16 +11506,23 @@ var Mediabunny = (() => {
|
|
|
11075
11506
|
if (!this.internalTrack.info.codec) {
|
|
11076
11507
|
return null;
|
|
11077
11508
|
}
|
|
11078
|
-
return this.
|
|
11079
|
-
codec
|
|
11080
|
-
|
|
11081
|
-
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11509
|
+
return this.decoderConfigPromise ??= (async () => {
|
|
11510
|
+
if (this.internalTrack.info.codec === "dts" && !this.internalTrack.info.dtsFormat) {
|
|
11511
|
+
const firstPacket = await this.getFirstPacket({});
|
|
11512
|
+
this.internalTrack.info.dtsFormat = firstPacket && extractDtsFourCcFromPacket(firstPacket.data);
|
|
11513
|
+
}
|
|
11514
|
+
return {
|
|
11515
|
+
codec: extractAudioCodecString({
|
|
11516
|
+
codec: this.internalTrack.info.codec,
|
|
11517
|
+
codecDescription: this.internalTrack.info.codecDescription,
|
|
11518
|
+
aacCodecInfo: this.internalTrack.info.aacCodecInfo,
|
|
11519
|
+
dtsFormat: this.internalTrack.info.dtsFormat
|
|
11520
|
+
}),
|
|
11521
|
+
numberOfChannels: this.internalTrack.info.numberOfChannels,
|
|
11522
|
+
sampleRate: this.internalTrack.info.sampleRate,
|
|
11523
|
+
description: this.internalTrack.info.codecDescription ?? void 0
|
|
11524
|
+
};
|
|
11525
|
+
})();
|
|
11088
11526
|
}
|
|
11089
11527
|
};
|
|
11090
11528
|
|
|
@@ -13737,6 +14175,15 @@ var Mediabunny = (() => {
|
|
|
13737
14175
|
|
|
13738
14176
|
// src/mpeg-ts/mpeg-ts-demuxer.ts
|
|
13739
14177
|
var MISSING_PTS_ERROR_MESSAGE = "PES packet is missing PTS where it was expected. PES packets without PTS are not currently supported. If you think this file should be supported, please report it.";
|
|
14178
|
+
var REGISTRATION_DESCRIPTOR_TAG = 5;
|
|
14179
|
+
var HDMV_FORMAT_IDENTIFIER = 1212435798;
|
|
14180
|
+
var HDPR_FORMAT_IDENTIFIER = 1212436562;
|
|
14181
|
+
var DTS_FORMAT_IDENTIFIER_PREFIX = 1146376960;
|
|
14182
|
+
var BLU_RAY_DTS_STREAM_TYPES = /* @__PURE__ */ new Set([
|
|
14183
|
+
133 /* BLU_RAY_DTS_HD */,
|
|
14184
|
+
134 /* BLU_RAY_DTS_HD_MASTER */,
|
|
14185
|
+
162 /* BLU_RAY_DTS_EXPRESS_SECONDARY */
|
|
14186
|
+
]);
|
|
13740
14187
|
var ignoredStreamTypes = /* @__PURE__ */ new Set();
|
|
13741
14188
|
var MpegTsDemuxer = class extends Demuxer {
|
|
13742
14189
|
constructor(input) {
|
|
@@ -13845,7 +14292,19 @@ var Mediabunny = (() => {
|
|
|
13845
14292
|
const pcrPid = bitstream.readBits(13);
|
|
13846
14293
|
bitstream.skipBits(6);
|
|
13847
14294
|
const programInfoLength = bitstream.readBits(10);
|
|
13848
|
-
bitstream.
|
|
14295
|
+
const programInfoEndPos = bitstream.pos + 8 * programInfoLength;
|
|
14296
|
+
let isBluRayProgram = false;
|
|
14297
|
+
while (bitstream.pos < programInfoEndPos) {
|
|
14298
|
+
const descriptorTag = bitstream.readBits(8);
|
|
14299
|
+
const descriptorLength = bitstream.readBits(8);
|
|
14300
|
+
const descriptorEndPos = bitstream.pos + 8 * descriptorLength;
|
|
14301
|
+
if (descriptorTag === REGISTRATION_DESCRIPTOR_TAG && descriptorLength >= 4) {
|
|
14302
|
+
const formatIdentifier = bitstream.readBits(32);
|
|
14303
|
+
isBluRayProgram ||= formatIdentifier === HDMV_FORMAT_IDENTIFIER || formatIdentifier === HDPR_FORMAT_IDENTIFIER;
|
|
14304
|
+
}
|
|
14305
|
+
bitstream.pos = descriptorEndPos;
|
|
14306
|
+
}
|
|
14307
|
+
bitstream.pos = programInfoEndPos;
|
|
13849
14308
|
while (8 * (sectionLength + BYTES_BEFORE_SECTION_LENGTH) - bitstream.pos > BITS_IN_CRC_32) {
|
|
13850
14309
|
const streamType = bitstream.readBits(8);
|
|
13851
14310
|
bitstream.skipBits(3);
|
|
@@ -13855,18 +14314,26 @@ var Mediabunny = (() => {
|
|
|
13855
14314
|
const esInfoEndPos = bitstream.pos + 8 * esInfoLength;
|
|
13856
14315
|
let hasAc3Descriptor = false;
|
|
13857
14316
|
let hasEac3Descriptor = false;
|
|
14317
|
+
let hasDtsDescriptor = false;
|
|
13858
14318
|
while (bitstream.pos < esInfoEndPos) {
|
|
13859
14319
|
const descriptorTag = bitstream.readBits(8);
|
|
13860
14320
|
const descriptorLength = bitstream.readBits(8);
|
|
14321
|
+
const descriptorEndPos = bitstream.pos + 8 * descriptorLength;
|
|
13861
14322
|
if (descriptorTag === 106) {
|
|
13862
14323
|
hasAc3Descriptor = true;
|
|
13863
14324
|
} else if (descriptorTag === 122 || descriptorTag === 204) {
|
|
13864
14325
|
hasEac3Descriptor = true;
|
|
14326
|
+
} else if (descriptorTag === 123) {
|
|
14327
|
+
hasDtsDescriptor = true;
|
|
14328
|
+
} else if (descriptorTag === REGISTRATION_DESCRIPTOR_TAG && descriptorLength >= 4) {
|
|
14329
|
+
const formatIdentifier = bitstream.readBits(32);
|
|
14330
|
+
hasDtsDescriptor ||= (formatIdentifier & 4294967040) === DTS_FORMAT_IDENTIFIER_PREFIX;
|
|
13865
14331
|
}
|
|
13866
|
-
bitstream.
|
|
14332
|
+
bitstream.pos = descriptorEndPos;
|
|
13867
14333
|
}
|
|
13868
14334
|
let info = null;
|
|
13869
|
-
|
|
14335
|
+
const effectiveStreamType = isBluRayProgram && BLU_RAY_DTS_STREAM_TYPES.has(streamType) ? 130 /* DTS */ : streamType;
|
|
14336
|
+
switch (effectiveStreamType) {
|
|
13870
14337
|
case 27 /* AVC */:
|
|
13871
14338
|
case 36 /* HEVC */:
|
|
13872
14339
|
{
|
|
@@ -13897,24 +14364,27 @@ var Mediabunny = (() => {
|
|
|
13897
14364
|
case 15 /* AAC */:
|
|
13898
14365
|
case 129 /* AC3_SYSTEM_A */:
|
|
13899
14366
|
case 135 /* EAC3_SYSTEM_A */:
|
|
14367
|
+
case 130 /* DTS */:
|
|
14368
|
+
case 138 /* DTS_ATSC */:
|
|
13900
14369
|
{
|
|
13901
14370
|
let codec;
|
|
13902
|
-
if (
|
|
14371
|
+
if (effectiveStreamType === 3 /* MP3_MPEG1 */ || effectiveStreamType === 4 /* MP3_MPEG2 */) {
|
|
13903
14372
|
codec = "mp3";
|
|
13904
|
-
} else if (
|
|
14373
|
+
} else if (effectiveStreamType === 15 /* AAC */) {
|
|
13905
14374
|
codec = "aac";
|
|
13906
|
-
} else if (
|
|
14375
|
+
} else if (effectiveStreamType === 129 /* AC3_SYSTEM_A */) {
|
|
13907
14376
|
codec = "ac3";
|
|
13908
|
-
} else if (
|
|
14377
|
+
} else if (effectiveStreamType === 135 /* EAC3_SYSTEM_A */) {
|
|
13909
14378
|
codec = "eac3";
|
|
13910
14379
|
} else {
|
|
13911
|
-
|
|
14380
|
+
codec = "dts";
|
|
13912
14381
|
}
|
|
13913
14382
|
info = {
|
|
13914
14383
|
type: "audio",
|
|
13915
14384
|
codec,
|
|
13916
14385
|
decoderConfig: null,
|
|
13917
14386
|
aacCodecInfo: null,
|
|
14387
|
+
dtsFormat: null,
|
|
13918
14388
|
numberOfChannels: -1,
|
|
13919
14389
|
sampleRate: -1
|
|
13920
14390
|
};
|
|
@@ -13929,6 +14399,7 @@ var Mediabunny = (() => {
|
|
|
13929
14399
|
codec: "eac3",
|
|
13930
14400
|
decoderConfig: null,
|
|
13931
14401
|
aacCodecInfo: null,
|
|
14402
|
+
dtsFormat: null,
|
|
13932
14403
|
numberOfChannels: -1,
|
|
13933
14404
|
sampleRate: -1
|
|
13934
14405
|
};
|
|
@@ -13938,6 +14409,17 @@ var Mediabunny = (() => {
|
|
|
13938
14409
|
codec: "ac3",
|
|
13939
14410
|
decoderConfig: null,
|
|
13940
14411
|
aacCodecInfo: null,
|
|
14412
|
+
dtsFormat: null,
|
|
14413
|
+
numberOfChannels: -1,
|
|
14414
|
+
sampleRate: -1
|
|
14415
|
+
};
|
|
14416
|
+
} else if (hasDtsDescriptor) {
|
|
14417
|
+
info = {
|
|
14418
|
+
type: "audio",
|
|
14419
|
+
codec: "dts",
|
|
14420
|
+
decoderConfig: null,
|
|
14421
|
+
aacCodecInfo: null,
|
|
14422
|
+
dtsFormat: null,
|
|
13941
14423
|
numberOfChannels: -1,
|
|
13942
14424
|
sampleRate: -1
|
|
13943
14425
|
};
|
|
@@ -14157,6 +14639,18 @@ var Mediabunny = (() => {
|
|
|
14157
14639
|
}
|
|
14158
14640
|
elementaryStream.info.numberOfChannels = getEac3ChannelCount(frameInfo);
|
|
14159
14641
|
elementaryStream.info.sampleRate = sampleRate;
|
|
14642
|
+
} else if (elementaryStream.info.codec === "dts") {
|
|
14643
|
+
const frameInfo = parseDtsFrame(context.suppliedPacket.data);
|
|
14644
|
+
if (!frameInfo) {
|
|
14645
|
+
throw new Error(
|
|
14646
|
+
"Invalid DTS audio stream; could not read frame header from first packet."
|
|
14647
|
+
);
|
|
14648
|
+
}
|
|
14649
|
+
elementaryStream.info.numberOfChannels = frameInfo.numberOfChannels;
|
|
14650
|
+
elementaryStream.info.sampleRate = frameInfo.sampleRate;
|
|
14651
|
+
if (frameInfo.core) {
|
|
14652
|
+
elementaryStream.info.dtsFormat = frameInfo.hasExtensions ? "dtsh" : "dtsc";
|
|
14653
|
+
}
|
|
14160
14654
|
} else {
|
|
14161
14655
|
throw new Error("Unhandled.");
|
|
14162
14656
|
}
|
|
@@ -14164,7 +14658,8 @@ var Mediabunny = (() => {
|
|
|
14164
14658
|
codec: extractAudioCodecString({
|
|
14165
14659
|
codec: elementaryStream.info.codec,
|
|
14166
14660
|
codecDescription: null,
|
|
14167
|
-
aacCodecInfo: elementaryStream.info.aacCodecInfo
|
|
14661
|
+
aacCodecInfo: elementaryStream.info.aacCodecInfo,
|
|
14662
|
+
dtsFormat: elementaryStream.info.dtsFormat
|
|
14168
14663
|
}),
|
|
14169
14664
|
numberOfChannels: elementaryStream.info.numberOfChannels,
|
|
14170
14665
|
sampleRate: elementaryStream.info.sampleRate
|
|
@@ -15312,6 +15807,63 @@ var Mediabunny = (() => {
|
|
|
15312
15807
|
samplesPerFrame * TIMESCALE / elementaryStream.info.sampleRate
|
|
15313
15808
|
);
|
|
15314
15809
|
return this.supplyPacket(remaining2, duration);
|
|
15810
|
+
} else if (codec === "dts") {
|
|
15811
|
+
if (byte !== 127 && byte !== 100) {
|
|
15812
|
+
continue;
|
|
15813
|
+
}
|
|
15814
|
+
this.skip(-1);
|
|
15815
|
+
const possibleSyncPos = this.currentPos;
|
|
15816
|
+
let remaining2 = this.ensureBuffered(DTS_CORE_FRAME_HEADER_SIZE);
|
|
15817
|
+
if (remaining2 instanceof Promise) remaining2 = await remaining2;
|
|
15818
|
+
if (remaining2 < DTS_CORE_FRAME_HEADER_SIZE) {
|
|
15819
|
+
return;
|
|
15820
|
+
}
|
|
15821
|
+
const headerBytes = this.readBytes(DTS_CORE_FRAME_HEADER_SIZE);
|
|
15822
|
+
const core = parseDtsCoreFrameHeader(headerBytes);
|
|
15823
|
+
let leadingExss = core ? null : parseDtsExssHeader(headerBytes);
|
|
15824
|
+
if (!core && !leadingExss) {
|
|
15825
|
+
this.seekTo(possibleSyncPos + 1);
|
|
15826
|
+
continue;
|
|
15827
|
+
}
|
|
15828
|
+
if (leadingExss && !leadingExss.asset) {
|
|
15829
|
+
this.seekTo(possibleSyncPos);
|
|
15830
|
+
const headerBound = Math.min(leadingExss.frameSize, DTS_EXSS_MAX_HEADER_SIZE);
|
|
15831
|
+
let remaining3 = this.ensureBuffered(headerBound);
|
|
15832
|
+
if (remaining3 instanceof Promise) remaining3 = await remaining3;
|
|
15833
|
+
leadingExss = parseDtsExssHeader(this.readBytes(remaining3)) ?? leadingExss;
|
|
15834
|
+
}
|
|
15835
|
+
let frameSize = core ? core.frameSize : leadingExss.frameSize;
|
|
15836
|
+
if (core) {
|
|
15837
|
+
let nextSubstreamPos = Math.ceil(core.frameSize / 4) * 4;
|
|
15838
|
+
while (true) {
|
|
15839
|
+
this.seekTo(possibleSyncPos);
|
|
15840
|
+
const neededBytes = nextSubstreamPos + DTS_EXSS_HEADER_PREFIX_SIZE;
|
|
15841
|
+
let remaining3 = this.ensureBuffered(neededBytes);
|
|
15842
|
+
if (remaining3 instanceof Promise) remaining3 = await remaining3;
|
|
15843
|
+
if (remaining3 < neededBytes) {
|
|
15844
|
+
break;
|
|
15845
|
+
}
|
|
15846
|
+
this.seekTo(possibleSyncPos + nextSubstreamPos);
|
|
15847
|
+
const exss = parseDtsExssHeader(this.readBytes(DTS_EXSS_HEADER_PREFIX_SIZE));
|
|
15848
|
+
if (!exss) {
|
|
15849
|
+
break;
|
|
15850
|
+
}
|
|
15851
|
+
nextSubstreamPos += exss.frameSize;
|
|
15852
|
+
frameSize = nextSubstreamPos;
|
|
15853
|
+
}
|
|
15854
|
+
}
|
|
15855
|
+
const sampleCount = core?.sampleCount ?? leadingExss.asset?.sampleCount;
|
|
15856
|
+
if (sampleCount === void 0) {
|
|
15857
|
+
this.seekTo(possibleSyncPos + 1);
|
|
15858
|
+
continue;
|
|
15859
|
+
}
|
|
15860
|
+
this.seekTo(possibleSyncPos);
|
|
15861
|
+
remaining2 = this.ensureBuffered(frameSize);
|
|
15862
|
+
if (remaining2 instanceof Promise) remaining2 = await remaining2;
|
|
15863
|
+
const duration = Math.round(
|
|
15864
|
+
sampleCount * TIMESCALE / elementaryStream.info.sampleRate
|
|
15865
|
+
);
|
|
15866
|
+
return this.supplyPacket(remaining2, duration);
|
|
15315
15867
|
} else {
|
|
15316
15868
|
throw new Error("Unhandled.");
|
|
15317
15869
|
}
|
|
@@ -21938,8 +22490,10 @@ var Mediabunny = (() => {
|
|
|
21938
22490
|
// 64kbps base for Vorbis
|
|
21939
22491
|
ac3: 384e3,
|
|
21940
22492
|
// 384kbps base for AC-3
|
|
21941
|
-
eac3: 192e3
|
|
22493
|
+
eac3: 192e3,
|
|
21942
22494
|
// 192kbps base for E-AC-3
|
|
22495
|
+
dts: 768e3
|
|
22496
|
+
// 768kbps base for DTS
|
|
21943
22497
|
};
|
|
21944
22498
|
const baseBitrate = baseRates[codec];
|
|
21945
22499
|
if (!baseBitrate) {
|
|
@@ -22072,7 +22626,7 @@ var Mediabunny = (() => {
|
|
|
22072
22626
|
throw new TypeError("bitrate must be a positive integer or a quality.");
|
|
22073
22627
|
}
|
|
22074
22628
|
validateVideoEncodingAdditionalOptions(codec, restOptions);
|
|
22075
|
-
const resolvedQuality = resolveQuality(quality, bitrate) ?? new Quality(
|
|
22629
|
+
const resolvedQuality = resolveQuality(quality, bitrate) ?? new Quality("medium");
|
|
22076
22630
|
let candidates;
|
|
22077
22631
|
try {
|
|
22078
22632
|
candidates = buildVideoEncoderConfigs({
|
|
@@ -22181,7 +22735,7 @@ var Mediabunny = (() => {
|
|
|
22181
22735
|
throw new TypeError("bitrate must be a positive integer.");
|
|
22182
22736
|
}
|
|
22183
22737
|
validateAudioEncodingAdditionalOptions(codec, restOptions);
|
|
22184
|
-
const resolvedQuality = resolveQuality(quality, bitrate) ?? new Quality(
|
|
22738
|
+
const resolvedQuality = resolveQuality(quality, bitrate) ?? new Quality("medium");
|
|
22185
22739
|
const encoderConfig = buildAudioEncoderConfig({
|
|
22186
22740
|
codec,
|
|
22187
22741
|
numberOfChannels,
|
|
@@ -23312,8 +23866,12 @@ var Mediabunny = (() => {
|
|
|
23312
23866
|
void this.customDecoderCallSerializer.call(() => this.customDecoder.close());
|
|
23313
23867
|
} else {
|
|
23314
23868
|
assert(this.decoder);
|
|
23315
|
-
this.decoder.
|
|
23316
|
-
|
|
23869
|
+
if (this.decoder.state !== "closed") {
|
|
23870
|
+
this.decoder.close();
|
|
23871
|
+
}
|
|
23872
|
+
if (this.alphaDecoder && this.alphaDecoder.state !== "closed") {
|
|
23873
|
+
this.alphaDecoder.close();
|
|
23874
|
+
}
|
|
23317
23875
|
this.colorQueue.forEach((x) => x.close());
|
|
23318
23876
|
this.colorQueue.length = 0;
|
|
23319
23877
|
this.alphaQueue.forEach((x) => x?.close());
|
|
@@ -23906,7 +24464,9 @@ var Mediabunny = (() => {
|
|
|
23906
24464
|
void this.customDecoderCallSerializer.call(() => this.customDecoder.close());
|
|
23907
24465
|
} else {
|
|
23908
24466
|
assert(this.decoder);
|
|
23909
|
-
this.decoder.
|
|
24467
|
+
if (this.decoder.state !== "closed") {
|
|
24468
|
+
this.decoder.close();
|
|
24469
|
+
}
|
|
23910
24470
|
}
|
|
23911
24471
|
}
|
|
23912
24472
|
};
|
|
@@ -24778,6 +25338,100 @@ var Mediabunny = (() => {
|
|
|
24778
25338
|
assert(decoderConfig);
|
|
24779
25339
|
return determineVideoPacketType(codec, decoderConfig, packet.data);
|
|
24780
25340
|
}
|
|
25341
|
+
/**
|
|
25342
|
+
* Computes frame rate metrics for this video track, i.e. estimates the video's frame rate. Frame rate is never
|
|
25343
|
+
* determined from file metadata (which is unreliable) but is always deduced directly from the actual frame
|
|
25344
|
+
* timestamps.
|
|
25345
|
+
*/
|
|
25346
|
+
async computeFrameRateMetrics(options = {}) {
|
|
25347
|
+
if (!options || typeof options !== "object") {
|
|
25348
|
+
throw new TypeError("options must be an object.");
|
|
25349
|
+
}
|
|
25350
|
+
if (options.targetPacketCount !== void 0 && (!Number.isFinite(options.targetPacketCount) || options.targetPacketCount < 0)) {
|
|
25351
|
+
throw new TypeError("options.targetPacketCount must be a non-negative number.");
|
|
25352
|
+
}
|
|
25353
|
+
const timeResolution = await this.getTimeResolution();
|
|
25354
|
+
const targetPacketCount = options.targetPacketCount ?? 256;
|
|
25355
|
+
const sink = new EncodedPacketSink(this);
|
|
25356
|
+
const timestamps = [];
|
|
25357
|
+
let maxTimestamp = -Infinity;
|
|
25358
|
+
let probedPacketCount = 0;
|
|
25359
|
+
for await (const packet of sink.packets(void 0, void 0, { metadataOnly: true })) {
|
|
25360
|
+
if (timestamps.length >= targetPacketCount && packet.timestamp >= maxTimestamp) {
|
|
25361
|
+
break;
|
|
25362
|
+
}
|
|
25363
|
+
timestamps.push(packet.timestamp);
|
|
25364
|
+
maxTimestamp = Math.max(maxTimestamp, packet.timestamp);
|
|
25365
|
+
probedPacketCount++;
|
|
25366
|
+
}
|
|
25367
|
+
const ticks = new Float64Array(timestamps.length);
|
|
25368
|
+
for (let i = 0; i < timestamps.length; i++) {
|
|
25369
|
+
ticks[i] = Math.round(timestamps[i] * timeResolution);
|
|
25370
|
+
}
|
|
25371
|
+
ticks.sort();
|
|
25372
|
+
let n = 1;
|
|
25373
|
+
for (let i = 1; i < ticks.length; i++) {
|
|
25374
|
+
if (ticks[i] !== ticks[n - 1]) {
|
|
25375
|
+
ticks[n++] = ticks[i];
|
|
25376
|
+
}
|
|
25377
|
+
}
|
|
25378
|
+
if (n < 2) {
|
|
25379
|
+
return {
|
|
25380
|
+
underlyingFrameRate: null,
|
|
25381
|
+
bestGuessFrameRate: timeResolution,
|
|
25382
|
+
minFrameRate: timeResolution,
|
|
25383
|
+
maxFrameRate: timeResolution,
|
|
25384
|
+
averageFrameRate: timeResolution,
|
|
25385
|
+
medianFrameRate: timeResolution,
|
|
25386
|
+
frameRateIsConstant: true,
|
|
25387
|
+
probedPacketCount
|
|
25388
|
+
};
|
|
25389
|
+
}
|
|
25390
|
+
const activeTicks = ticks.subarray(0, n);
|
|
25391
|
+
const underlyingFrameRate = findUnderlyingFrameRate(activeTicks, timeResolution);
|
|
25392
|
+
const unitRate = underlyingFrameRate ?? timeResolution;
|
|
25393
|
+
const ticksPerFrame = underlyingFrameRate !== null ? timeResolution / underlyingFrameRate : null;
|
|
25394
|
+
const histogram = /* @__PURE__ */ new Map();
|
|
25395
|
+
let minDifference = Infinity;
|
|
25396
|
+
let maxDifference = -Infinity;
|
|
25397
|
+
let totalDifference = 0;
|
|
25398
|
+
for (let i = 1; i < n; i++) {
|
|
25399
|
+
const tickDifference = activeTicks[i] - activeTicks[i - 1];
|
|
25400
|
+
const difference = ticksPerFrame !== null ? Math.max(1, Math.round(tickDifference / ticksPerFrame)) : tickDifference;
|
|
25401
|
+
histogram.set(difference, (histogram.get(difference) ?? 0) + 1);
|
|
25402
|
+
minDifference = Math.min(minDifference, difference);
|
|
25403
|
+
maxDifference = Math.max(maxDifference, difference);
|
|
25404
|
+
totalDifference += difference;
|
|
25405
|
+
}
|
|
25406
|
+
const differenceCount = n - 1;
|
|
25407
|
+
const sortedDifferences = [...histogram.keys()].sort((a, b) => a - b);
|
|
25408
|
+
const middleA = differenceCount - 1 >> 1;
|
|
25409
|
+
const middleB = differenceCount >> 1;
|
|
25410
|
+
let medianDifferenceA = 0;
|
|
25411
|
+
let medianDifferenceB = 0;
|
|
25412
|
+
let cumulativeCount = 0;
|
|
25413
|
+
for (const difference of sortedDifferences) {
|
|
25414
|
+
cumulativeCount += histogram.get(difference);
|
|
25415
|
+
if (medianDifferenceA === 0 && cumulativeCount > middleA) {
|
|
25416
|
+
medianDifferenceA = difference;
|
|
25417
|
+
}
|
|
25418
|
+
if (cumulativeCount > middleB) {
|
|
25419
|
+
medianDifferenceB = difference;
|
|
25420
|
+
break;
|
|
25421
|
+
}
|
|
25422
|
+
}
|
|
25423
|
+
const medianFrameRate = (unitRate / medianDifferenceA + unitRate / medianDifferenceB) / 2;
|
|
25424
|
+
return {
|
|
25425
|
+
underlyingFrameRate,
|
|
25426
|
+
bestGuessFrameRate: underlyingFrameRate !== null ? underlyingFrameRate : getBestGuessFrameRate(medianFrameRate),
|
|
25427
|
+
minFrameRate: unitRate / maxDifference,
|
|
25428
|
+
maxFrameRate: unitRate / minDifference,
|
|
25429
|
+
averageFrameRate: unitRate * differenceCount / totalDifference,
|
|
25430
|
+
medianFrameRate,
|
|
25431
|
+
frameRateIsConstant: underlyingFrameRate !== null && minDifference === 1 && maxDifference === 1,
|
|
25432
|
+
probedPacketCount
|
|
25433
|
+
};
|
|
25434
|
+
}
|
|
24781
25435
|
};
|
|
24782
25436
|
var InputAudioTrack = class extends InputTrack {
|
|
24783
25437
|
/** @internal */
|
|
@@ -24995,6 +25649,183 @@ var Mediabunny = (() => {
|
|
|
24995
25649
|
return 0;
|
|
24996
25650
|
}).map((x) => x.track);
|
|
24997
25651
|
};
|
|
25652
|
+
var findUnderlyingFrameRate = (ticks, resolution) => {
|
|
25653
|
+
const MAX_DENOMINATOR = 1e6;
|
|
25654
|
+
const MIN_INLIER_RATIO = 0.98;
|
|
25655
|
+
const DELTA_TOLERANCE = 1 + 1e-9;
|
|
25656
|
+
const MAX_EFFECTIVE_FRAME_SPAN = 1e3;
|
|
25657
|
+
const KNOWN_FRAME_RATES = [
|
|
25658
|
+
12,
|
|
25659
|
+
15,
|
|
25660
|
+
20,
|
|
25661
|
+
24e3 / 1001,
|
|
25662
|
+
24,
|
|
25663
|
+
25,
|
|
25664
|
+
3e4 / 1001,
|
|
25665
|
+
30,
|
|
25666
|
+
48,
|
|
25667
|
+
50,
|
|
25668
|
+
6e4 / 1001,
|
|
25669
|
+
60,
|
|
25670
|
+
100,
|
|
25671
|
+
12e4 / 1001,
|
|
25672
|
+
120,
|
|
25673
|
+
144,
|
|
25674
|
+
240
|
|
25675
|
+
];
|
|
25676
|
+
if (ticks.length < 2) {
|
|
25677
|
+
return null;
|
|
25678
|
+
}
|
|
25679
|
+
const gaps = new Float64Array(ticks.length - 1);
|
|
25680
|
+
for (let i = 1; i < ticks.length; i++) {
|
|
25681
|
+
const gap = ticks[i] - ticks[i - 1];
|
|
25682
|
+
if (!(gap > 0)) {
|
|
25683
|
+
return null;
|
|
25684
|
+
}
|
|
25685
|
+
gaps[i - 1] = gap;
|
|
25686
|
+
}
|
|
25687
|
+
const sortedGaps = gaps.slice();
|
|
25688
|
+
sortedGaps.sort();
|
|
25689
|
+
let period = sortedGaps[Math.floor(sortedGaps.length * 0.05)];
|
|
25690
|
+
for (let iteration = 0; iteration < 6; iteration++) {
|
|
25691
|
+
let totalTicks2 = 0;
|
|
25692
|
+
let totalFrames2 = 0;
|
|
25693
|
+
for (const gap of gaps) {
|
|
25694
|
+
const multiple = Math.max(1, Math.round(gap / period));
|
|
25695
|
+
if (Math.abs(gap - multiple * period) >= DELTA_TOLERANCE) {
|
|
25696
|
+
continue;
|
|
25697
|
+
}
|
|
25698
|
+
totalTicks2 += gap;
|
|
25699
|
+
totalFrames2 += multiple;
|
|
25700
|
+
}
|
|
25701
|
+
if (totalFrames2 === 0) {
|
|
25702
|
+
return null;
|
|
25703
|
+
}
|
|
25704
|
+
const refinedPeriod = totalTicks2 / totalFrames2;
|
|
25705
|
+
if (Math.abs(refinedPeriod - period) <= 1e-12 * Math.max(1, period)) {
|
|
25706
|
+
period = refinedPeriod;
|
|
25707
|
+
break;
|
|
25708
|
+
}
|
|
25709
|
+
period = refinedPeriod;
|
|
25710
|
+
}
|
|
25711
|
+
let inlierCount = 0;
|
|
25712
|
+
let totalTicks = 0;
|
|
25713
|
+
let totalFrames = 0;
|
|
25714
|
+
for (const gap of gaps) {
|
|
25715
|
+
const multiple = Math.max(1, Math.round(gap / period));
|
|
25716
|
+
if (Math.abs(gap - multiple * period) >= DELTA_TOLERANCE) {
|
|
25717
|
+
continue;
|
|
25718
|
+
}
|
|
25719
|
+
inlierCount++;
|
|
25720
|
+
totalTicks += gap;
|
|
25721
|
+
totalFrames += multiple;
|
|
25722
|
+
}
|
|
25723
|
+
if (inlierCount / gaps.length < MIN_INLIER_RATIO) {
|
|
25724
|
+
return null;
|
|
25725
|
+
}
|
|
25726
|
+
period = totalTicks / totalFrames;
|
|
25727
|
+
const uncertainty = 1 / Math.min(
|
|
25728
|
+
totalFrames,
|
|
25729
|
+
MAX_EFFECTIVE_FRAME_SPAN
|
|
25730
|
+
);
|
|
25731
|
+
const periodLo = Math.max(Number.EPSILON, period - uncertainty);
|
|
25732
|
+
const periodHi = period + uncertainty;
|
|
25733
|
+
const fpsLo = resolution / periodHi;
|
|
25734
|
+
const fpsHi = resolution / periodLo;
|
|
25735
|
+
const fittedFps = resolution / period;
|
|
25736
|
+
let fps = null;
|
|
25737
|
+
let bestKnownError = Infinity;
|
|
25738
|
+
for (const candidate of KNOWN_FRAME_RATES) {
|
|
25739
|
+
if (candidate < fpsLo || candidate > fpsHi) {
|
|
25740
|
+
continue;
|
|
25741
|
+
}
|
|
25742
|
+
const error = Math.abs(candidate / fittedFps - 1);
|
|
25743
|
+
if (error < bestKnownError) {
|
|
25744
|
+
fps = candidate;
|
|
25745
|
+
bestKnownError = error;
|
|
25746
|
+
}
|
|
25747
|
+
}
|
|
25748
|
+
if (fps === null) {
|
|
25749
|
+
const periodFraction = simplestFractionBetween(
|
|
25750
|
+
periodLo,
|
|
25751
|
+
periodHi,
|
|
25752
|
+
MAX_DENOMINATOR
|
|
25753
|
+
);
|
|
25754
|
+
const fpsFraction = simplestFractionBetween(
|
|
25755
|
+
fpsLo,
|
|
25756
|
+
fpsHi,
|
|
25757
|
+
MAX_DENOMINATOR
|
|
25758
|
+
);
|
|
25759
|
+
if (fpsFraction && (!periodFraction || fpsFraction.den < periodFraction.den || fpsFraction.den === periodFraction.den && fpsFraction.num <= periodFraction.num)) {
|
|
25760
|
+
fps = fpsFraction.num / fpsFraction.den;
|
|
25761
|
+
} else if (periodFraction) {
|
|
25762
|
+
fps = resolution * periodFraction.den / periodFraction.num;
|
|
25763
|
+
} else {
|
|
25764
|
+
return null;
|
|
25765
|
+
}
|
|
25766
|
+
}
|
|
25767
|
+
const finalPeriod = resolution / fps;
|
|
25768
|
+
let finalInlierCount = 0;
|
|
25769
|
+
for (const gap of gaps) {
|
|
25770
|
+
const multiple = Math.max(1, Math.round(gap / finalPeriod));
|
|
25771
|
+
if (Math.abs(gap - multiple * finalPeriod) < DELTA_TOLERANCE) {
|
|
25772
|
+
finalInlierCount++;
|
|
25773
|
+
}
|
|
25774
|
+
}
|
|
25775
|
+
if (finalInlierCount / gaps.length < MIN_INLIER_RATIO) {
|
|
25776
|
+
return null;
|
|
25777
|
+
}
|
|
25778
|
+
return fps;
|
|
25779
|
+
};
|
|
25780
|
+
var simplestFractionBetween = (lo, hi, maxDenominator) => {
|
|
25781
|
+
for (let den = 1; den <= maxDenominator; den++) {
|
|
25782
|
+
const num = Math.floor(lo * den) + 1;
|
|
25783
|
+
if (num / den < hi) {
|
|
25784
|
+
return simplifyRational({ num, den });
|
|
25785
|
+
}
|
|
25786
|
+
}
|
|
25787
|
+
return null;
|
|
25788
|
+
};
|
|
25789
|
+
var getBestGuessFrameRate = (frameRate) => {
|
|
25790
|
+
const SPECIAL_FRAME_RATES = [
|
|
25791
|
+
24 / 1.001,
|
|
25792
|
+
30 / 1.001,
|
|
25793
|
+
60 / 1.001,
|
|
25794
|
+
120 / 1.001
|
|
25795
|
+
];
|
|
25796
|
+
const COMMON_FRAME_RATES = [
|
|
25797
|
+
12,
|
|
25798
|
+
15,
|
|
25799
|
+
20,
|
|
25800
|
+
24,
|
|
25801
|
+
25,
|
|
25802
|
+
30,
|
|
25803
|
+
48,
|
|
25804
|
+
50,
|
|
25805
|
+
60,
|
|
25806
|
+
100,
|
|
25807
|
+
120,
|
|
25808
|
+
144,
|
|
25809
|
+
240
|
|
25810
|
+
];
|
|
25811
|
+
const SPECIAL_TOLERANCE = 5e-4;
|
|
25812
|
+
const COMMON_TOLERANCE = 0.025;
|
|
25813
|
+
for (const candidate of SPECIAL_FRAME_RATES) {
|
|
25814
|
+
if (Math.abs(candidate / frameRate - 1) <= SPECIAL_TOLERANCE) {
|
|
25815
|
+
return candidate;
|
|
25816
|
+
}
|
|
25817
|
+
}
|
|
25818
|
+
let best = frameRate;
|
|
25819
|
+
let bestError = Infinity;
|
|
25820
|
+
for (const candidate of COMMON_FRAME_RATES) {
|
|
25821
|
+
const error = Math.abs(candidate / frameRate - 1);
|
|
25822
|
+
if (error <= COMMON_TOLERANCE && error < bestError) {
|
|
25823
|
+
best = candidate;
|
|
25824
|
+
bestError = error;
|
|
25825
|
+
}
|
|
25826
|
+
}
|
|
25827
|
+
return best;
|
|
25828
|
+
};
|
|
24998
25829
|
|
|
24999
25830
|
// src/input.ts
|
|
25000
25831
|
polyfillSymbolDispose();
|
|
@@ -27597,7 +28428,11 @@ var Mediabunny = (() => {
|
|
|
27597
28428
|
trackData
|
|
27598
28429
|
);
|
|
27599
28430
|
} else if (trackData.type === "audio") {
|
|
27600
|
-
const boxName = audioCodecToBoxName(
|
|
28431
|
+
const boxName = audioCodecToBoxName(
|
|
28432
|
+
trackData.track.source._codec,
|
|
28433
|
+
trackData.info.decoderConfig.codec,
|
|
28434
|
+
trackData.muxer.isQuickTime
|
|
28435
|
+
);
|
|
27601
28436
|
assert(boxName);
|
|
27602
28437
|
sampleDescription = soundSampleDescription(
|
|
27603
28438
|
boxName,
|
|
@@ -27887,7 +28722,11 @@ var Mediabunny = (() => {
|
|
|
27887
28722
|
};
|
|
27888
28723
|
var frma = (trackData) => {
|
|
27889
28724
|
return box("frma", [
|
|
27890
|
-
ascii(audioCodecToBoxName(
|
|
28725
|
+
ascii(audioCodecToBoxName(
|
|
28726
|
+
trackData.track.source._codec,
|
|
28727
|
+
trackData.info.decoderConfig.codec,
|
|
28728
|
+
trackData.muxer.isQuickTime
|
|
28729
|
+
))
|
|
27891
28730
|
]);
|
|
27892
28731
|
};
|
|
27893
28732
|
var enda = (trackData) => {
|
|
@@ -28008,6 +28847,16 @@ var Mediabunny = (() => {
|
|
|
28008
28847
|
}
|
|
28009
28848
|
return box("dec3", [...bytes2]);
|
|
28010
28849
|
};
|
|
28850
|
+
var ddts = (trackData) => {
|
|
28851
|
+
assert(trackData.info.primingPacket);
|
|
28852
|
+
const frameInfo = parseDtsFrame(trackData.info.primingPacket.data);
|
|
28853
|
+
if (!frameInfo) {
|
|
28854
|
+
throw new Error(
|
|
28855
|
+
"Couldn't extract DTS frame info from the audio packet. Ensure the packets contain valid DTS frames as specified in ETSI TS 102 114."
|
|
28856
|
+
);
|
|
28857
|
+
}
|
|
28858
|
+
return box("ddts", [...buildDtsSpecificBox(frameInfo)]);
|
|
28859
|
+
};
|
|
28011
28860
|
var subtitleSampleDescription = (compressionType, trackData) => box(compressionType, [
|
|
28012
28861
|
Array(6).fill(0),
|
|
28013
28862
|
// Reserved
|
|
@@ -28659,7 +29508,7 @@ var Mediabunny = (() => {
|
|
|
28659
29508
|
av1: av1C,
|
|
28660
29509
|
prores: null
|
|
28661
29510
|
};
|
|
28662
|
-
var audioCodecToBoxName = (codec, isQuickTime) => {
|
|
29511
|
+
var audioCodecToBoxName = (codec, fullCodecString, isQuickTime) => {
|
|
28663
29512
|
switch (codec) {
|
|
28664
29513
|
case "aac":
|
|
28665
29514
|
return "mp4a";
|
|
@@ -28683,6 +29532,8 @@ var Mediabunny = (() => {
|
|
|
28683
29532
|
return "ac-3";
|
|
28684
29533
|
case "eac3":
|
|
28685
29534
|
return "ec-3";
|
|
29535
|
+
case "dts":
|
|
29536
|
+
return fullCodecString;
|
|
28686
29537
|
}
|
|
28687
29538
|
if (isQuickTime) {
|
|
28688
29539
|
switch (codec) {
|
|
@@ -28748,6 +29599,8 @@ var Mediabunny = (() => {
|
|
|
28748
29599
|
return dac3;
|
|
28749
29600
|
case "eac3":
|
|
28750
29601
|
return dec3;
|
|
29602
|
+
case "dts":
|
|
29603
|
+
return ddts;
|
|
28751
29604
|
}
|
|
28752
29605
|
if (isQuickTime) {
|
|
28753
29606
|
switch (codec) {
|
|
@@ -29699,10 +30552,13 @@ var Mediabunny = (() => {
|
|
|
29699
30552
|
});
|
|
29700
30553
|
requiresAdtsStripping = true;
|
|
29701
30554
|
}
|
|
29702
|
-
if (
|
|
29703
|
-
if (
|
|
30555
|
+
if (!packet) {
|
|
30556
|
+
if (track.source._codec === "ac3" || track.source._codec === "eac3") {
|
|
29704
30557
|
throw new Error("AC-3/E-AC-3 require a priming packet.");
|
|
29705
30558
|
}
|
|
30559
|
+
if (track.source._codec === "dts") {
|
|
30560
|
+
throw new Error("DTS requires a priming packet.");
|
|
30561
|
+
}
|
|
29706
30562
|
}
|
|
29707
30563
|
const newTrackData = {
|
|
29708
30564
|
muxer: this,
|
|
@@ -30679,8 +31535,15 @@ var Mediabunny = (() => {
|
|
|
30679
31535
|
const tracksElement = { id: 374648427 /* Tracks */, data: [] };
|
|
30680
31536
|
this.tracksElement = tracksElement;
|
|
30681
31537
|
for (const trackData of this.trackDatas) {
|
|
30682
|
-
|
|
31538
|
+
let codecId = CODEC_STRING_MAP[trackData.track.source._codec];
|
|
30683
31539
|
assert(codecId);
|
|
31540
|
+
if (trackData.type === "audio" && trackData.track.source._codec === "dts") {
|
|
31541
|
+
if (trackData.info.decoderConfig.codec === "dtse") {
|
|
31542
|
+
codecId = "A_DTS/EXPRESS";
|
|
31543
|
+
} else if (trackData.info.decoderConfig.codec === "dtsl") {
|
|
31544
|
+
codecId = "A_DTS/LOSSLESS";
|
|
31545
|
+
}
|
|
31546
|
+
}
|
|
30684
31547
|
let seekPreRollNs = 0;
|
|
30685
31548
|
if (trackData.type === "audio" && trackData.track.source._codec === "opus") {
|
|
30686
31549
|
seekPreRollNs = 1e6 * 80;
|
|
@@ -32186,7 +33049,7 @@ ${cue.notes ?? ""}`;
|
|
|
32186
33049
|
validateAudioChunkMetadata(meta, track.source._codec);
|
|
32187
33050
|
assert(meta?.decoderConfig);
|
|
32188
33051
|
const codec = track.source._codec;
|
|
32189
|
-
assert(codec === "aac" || codec === "mp3" || codec === "ac3" || codec === "eac3");
|
|
33052
|
+
assert(codec === "aac" || codec === "mp3" || codec === "ac3" || codec === "eac3" || codec === "dts");
|
|
32190
33053
|
let streamType;
|
|
32191
33054
|
let streamId;
|
|
32192
33055
|
switch (codec) {
|
|
@@ -32218,6 +33081,13 @@ ${cue.notes ?? ""}`;
|
|
|
32218
33081
|
}
|
|
32219
33082
|
;
|
|
32220
33083
|
break;
|
|
33084
|
+
case "dts":
|
|
33085
|
+
{
|
|
33086
|
+
streamType = 130 /* DTS */;
|
|
33087
|
+
streamId = 189;
|
|
33088
|
+
}
|
|
33089
|
+
;
|
|
33090
|
+
break;
|
|
32221
33091
|
}
|
|
32222
33092
|
const pid = FIRST_TRACK_PID + this.trackDatas.length;
|
|
32223
33093
|
const newTrackData = {
|
|
@@ -32376,7 +33246,7 @@ ${cue.notes ?? ""}`;
|
|
|
32376
33246
|
}
|
|
32377
33247
|
prepareAudioPacket(trackData, packet, meta) {
|
|
32378
33248
|
const codec = trackData.track.source._codec;
|
|
32379
|
-
if (codec === "mp3" || codec === "ac3" || codec === "eac3") {
|
|
33249
|
+
if (codec === "mp3" || codec === "ac3" || codec === "eac3" || codec === "dts") {
|
|
32380
33250
|
return packet.data;
|
|
32381
33251
|
}
|
|
32382
33252
|
if (trackData.inputIsAdts === null) {
|
|
@@ -37023,7 +37893,7 @@ ${cue.notes ?? ""}`;
|
|
|
37023
37893
|
getSupportedCodecs() {
|
|
37024
37894
|
return [
|
|
37025
37895
|
...VIDEO_CODECS.filter((codec) => ["avc", "hevc"].includes(codec)),
|
|
37026
|
-
...AUDIO_CODECS.filter((codec) => ["aac", "mp3", "ac3", "eac3"].includes(codec))
|
|
37896
|
+
...AUDIO_CODECS.filter((codec) => ["aac", "mp3", "ac3", "eac3", "dts"].includes(codec))
|
|
37027
37897
|
];
|
|
37028
37898
|
}
|
|
37029
37899
|
get supportsVideoRotationMetadata() {
|