@remotion/media-parser 4.0.229 → 4.0.231
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/boxes/iso-base-media/esds/decoder-specific-config.d.ts +3 -2
- package/dist/boxes/iso-base-media/esds/decoder-specific-config.js +7 -8
- package/dist/boxes/iso-base-media/esds/esds-descriptors.d.ts +4 -2
- package/dist/boxes/iso-base-media/esds/esds-descriptors.js +5 -4
- package/dist/boxes/iso-base-media/esds/esds.d.ts +3 -1
- package/dist/boxes/iso-base-media/esds/esds.js +2 -2
- package/dist/boxes/iso-base-media/make-track.js +2 -1
- package/dist/boxes/iso-base-media/mdat/mdat.js +13 -7
- package/dist/boxes/iso-base-media/moov/moov.d.ts +3 -1
- package/dist/boxes/iso-base-media/moov/moov.js +2 -2
- package/dist/boxes/iso-base-media/mvhd.js +11 -9
- package/dist/boxes/iso-base-media/parse-icc-profile.d.ts +36 -0
- package/dist/boxes/iso-base-media/parse-icc-profile.js +115 -0
- package/dist/boxes/iso-base-media/process-box.d.ts +5 -4
- package/dist/boxes/iso-base-media/process-box.js +17 -14
- package/dist/boxes/iso-base-media/stsd/colr.d.ts +14 -4
- package/dist/boxes/iso-base-media/stsd/colr.js +13 -1
- package/dist/boxes/iso-base-media/stsd/mebx.d.ts +1 -2
- package/dist/boxes/iso-base-media/stsd/mebx.js +2 -2
- package/dist/boxes/iso-base-media/stsd/samples.d.ts +5 -2
- package/dist/boxes/iso-base-media/stsd/samples.js +7 -6
- package/dist/boxes/iso-base-media/stsd/stsd.js +1 -0
- package/dist/boxes/iso-base-media/to-date.d.ts +1 -0
- package/dist/boxes/iso-base-media/to-date.js +9 -1
- package/dist/boxes/iso-base-media/trak/trak.d.ts +3 -1
- package/dist/boxes/iso-base-media/trak/trak.js +2 -2
- package/dist/boxes/webm/av1-codec-private.js +1 -1
- package/dist/boxes/webm/ebml.d.ts +1 -1
- package/dist/boxes/webm/get-sample-from-block.d.ts +4 -4
- package/dist/boxes/webm/get-sample-from-block.js +4 -2
- package/dist/boxes/webm/make-track.js +1 -0
- package/dist/boxes/webm/parse-webm-header.js +23 -4
- package/dist/boxes/webm/segments/parse-children.d.ts +12 -7
- package/dist/boxes/webm/segments/parse-children.js +67 -57
- package/dist/boxes/webm/segments.d.ts +8 -3
- package/dist/boxes/webm/segments.js +70 -39
- package/dist/buffer-iterator.d.ts +1 -1
- package/dist/buffer-iterator.js +1 -8
- package/dist/create/iso-base-media/codec-specific/avc1.d.ts +2 -0
- package/dist/create/iso-base-media/codec-specific/avc1.js +48 -0
- package/dist/create/iso-base-media/codec-specific/create-codec-specific-data.d.ts +22 -0
- package/dist/create/iso-base-media/codec-specific/create-codec-specific-data.js +36 -0
- package/dist/create/iso-base-media/codec-specific/mp4a.d.ts +2 -0
- package/dist/create/iso-base-media/codec-specific/mp4a.js +90 -0
- package/dist/create/iso-base-media/create-colr.d.ts +6 -0
- package/dist/create/iso-base-media/create-colr.js +26 -0
- package/dist/create/iso-base-media/create-ftyp.d.ts +10 -0
- package/dist/create/iso-base-media/create-ftyp.js +22 -0
- package/dist/create/iso-base-media/create-ilst.d.ts +1 -0
- package/dist/create/iso-base-media/create-ilst.js +14 -0
- package/dist/create/iso-base-media/create-iso-base-media.d.ts +2 -0
- package/dist/create/iso-base-media/create-iso-base-media.js +167 -0
- package/dist/create/iso-base-media/create-mdia.d.ts +5 -0
- package/dist/create/iso-base-media/create-mdia.js +18 -0
- package/dist/create/iso-base-media/create-moov.d.ts +5 -0
- package/dist/create/iso-base-media/create-moov.js +18 -0
- package/dist/create/iso-base-media/create-mvhd.d.ts +10 -0
- package/dist/create/iso-base-media/create-mvhd.js +48 -0
- package/dist/create/iso-base-media/create-trak.d.ts +4 -0
- package/dist/create/iso-base-media/create-trak.js +17 -0
- package/dist/create/iso-base-media/create-udta.d.ts +1 -0
- package/dist/create/iso-base-media/create-udta.js +14 -0
- package/dist/create/iso-base-media/create-url.d.ts +1 -0
- package/dist/create/iso-base-media/create-url.js +16 -0
- package/dist/create/iso-base-media/example-stts.d.ts +3 -0
- package/dist/create/iso-base-media/example-stts.js +2797 -0
- package/dist/create/iso-base-media/ilst/create-cmt.d.ts +1 -0
- package/dist/create/iso-base-media/ilst/create-cmt.js +26 -0
- package/dist/create/iso-base-media/ilst/create-too.d.ts +1 -0
- package/dist/create/iso-base-media/ilst/create-too.js +27 -0
- package/dist/create/iso-base-media/mdia/create-mdhd.d.ts +6 -0
- package/dist/create/iso-base-media/mdia/create-mdhd.js +33 -0
- package/dist/create/iso-base-media/mp4-header.d.ts +6 -0
- package/dist/create/iso-base-media/mp4-header.js +47 -0
- package/dist/create/iso-base-media/primitives.d.ts +15 -0
- package/dist/create/iso-base-media/primitives.js +133 -0
- package/dist/create/iso-base-media/serialize-track.d.ts +9 -0
- package/dist/create/iso-base-media/serialize-track.js +63 -0
- package/dist/create/iso-base-media/trak/create-tkhd.d.ts +27 -0
- package/dist/create/iso-base-media/trak/create-tkhd.js +97 -0
- package/dist/create/iso-base-media/trak/mdia/create-minf.d.ts +4 -0
- package/dist/create/iso-base-media/trak/mdia/create-minf.js +19 -0
- package/dist/create/iso-base-media/trak/mdia/minf/create-dinf.d.ts +1 -0
- package/dist/create/iso-base-media/trak/mdia/minf/create-dinf.js +22 -0
- package/dist/create/iso-base-media/trak/mdia/minf/create-smhd.d.ts +1 -0
- package/dist/create/iso-base-media/trak/mdia/minf/create-smhd.js +20 -0
- package/dist/create/iso-base-media/trak/mdia/minf/create-stbl.d.ts +6 -0
- package/dist/create/iso-base-media/trak/mdia/minf/create-stbl.js +35 -0
- package/dist/create/iso-base-media/trak/mdia/minf/create-vmhd.d.ts +1 -0
- package/dist/create/iso-base-media/trak/mdia/minf/create-vmhd.js +20 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-ctts.d.ts +2 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-ctts.js +45 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stco.d.ts +2 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stco.js +28 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsc.d.ts +2 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsc.js +56 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stss.d.ts +2 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stss.js +23 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsz.d.ts +2 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsz.js +25 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stts.d.ts +2 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stts.js +48 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avc1.d.ts +1 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avc1.js +20 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avcc.d.ts +1 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avcc.js +16 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-pasp.d.ts +1 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-pasp.js +13 -0
- package/dist/create/iso-base-media/udta/create-meta.d.ts +4 -0
- package/dist/create/iso-base-media/udta/create-meta.js +20 -0
- package/dist/create/iso-base-media/udta/meta/create-hdlr.d.ts +1 -0
- package/dist/create/iso-base-media/udta/meta/create-hdlr.js +32 -0
- package/dist/create/make-track-info.d.ts +20 -0
- package/dist/create/make-track-info.js +2 -0
- package/dist/create/{cluster-segment.d.ts → matroska/cluster-segment.d.ts} +1 -1
- package/dist/create/{cluster-segment.js → matroska/cluster-segment.js} +2 -2
- package/dist/create/{cluster.d.ts → matroska/cluster.d.ts} +12 -5
- package/dist/create/{cluster.js → matroska/cluster.js} +23 -20
- package/dist/create/matroska/create-matroska-media.d.ts +2 -0
- package/dist/create/{create-media.js → matroska/create-matroska-media.js} +49 -25
- package/dist/create/matroska/make-duration-with-padding.d.ts +1 -0
- package/dist/create/{make-duration-with-padding.js → matroska/make-duration-with-padding.js} +1 -1
- package/dist/create/{matroska-cues.d.ts → matroska/matroska-cues.d.ts} +1 -1
- package/dist/create/{matroska-cues.js → matroska/matroska-cues.js} +1 -1
- package/dist/create/matroska/matroska-header.d.ts +1 -0
- package/dist/create/{matroska-header.js → matroska/matroska-header.js} +1 -1
- package/dist/create/{matroska-info.d.ts → matroska/matroska-info.d.ts} +1 -1
- package/dist/create/{matroska-info.js → matroska/matroska-info.js} +1 -1
- package/dist/create/matroska/matroska-seek.d.ts +6 -0
- package/dist/create/{matroska-seek.js → matroska/matroska-seek.js} +1 -1
- package/dist/create/{matroska-segment.d.ts → matroska/matroska-segment.d.ts} +1 -1
- package/dist/create/{matroska-segment.js → matroska/matroska-segment.js} +1 -1
- package/dist/create/matroska/matroska-trackentry.d.ts +10 -0
- package/dist/create/{matroska-trackentry.js → matroska/matroska-trackentry.js} +9 -3
- package/dist/create/{create-media.d.ts → media-fn.d.ts} +17 -4
- package/dist/create/media-fn.js +2 -0
- package/dist/create/timescale.d.ts +1 -1
- package/dist/create/timescale.js +2 -2
- package/dist/emit-available-info.d.ts +1 -1
- package/dist/emit-available-info.js +23 -10
- package/dist/esm/buffer.mjs +3 -3
- package/dist/esm/index.mjs +2104 -735
- package/dist/esm/web-fs.mjs +2 -2
- package/dist/get-audio-codec.d.ts +2 -1
- package/dist/get-audio-codec.js +29 -10
- package/dist/get-duration.d.ts +5 -0
- package/dist/get-duration.js +7 -3
- package/dist/get-fps.d.ts +1 -0
- package/dist/get-fps.js +24 -13
- package/dist/get-sample-positions.d.ts +1 -0
- package/dist/get-sample-positions.js +1 -0
- package/dist/get-tracks.d.ts +1 -0
- package/dist/get-video-codec.d.ts +2 -2
- package/dist/get-video-codec.js +6 -6
- package/dist/has-all-info.d.ts +1 -1
- package/dist/has-all-info.js +8 -8
- package/dist/index.d.ts +6 -8
- package/dist/index.js +7 -3
- package/dist/options.d.ts +10 -1
- package/dist/parse-media.js +42 -14
- package/dist/parse-result.d.ts +15 -0
- package/dist/parse-video.d.ts +3 -1
- package/dist/parse-video.js +6 -14
- package/dist/parser-state.d.ts +3 -3
- package/dist/readers/reader.d.ts +2 -2
- package/dist/samples-from-moof.js +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/dist/webcodec-sample-types.d.ts +7 -20
- package/dist/writers/buffer-implementation/writer.d.ts +2 -2
- package/dist/writers/buffer-implementation/writer.js +3 -3
- package/dist/writers/web-fs.js +2 -3
- package/dist/writers/writer.d.ts +5 -3
- package/package.json +3 -3
- package/dist/create/make-duration-with-padding.d.ts +0 -1
- package/dist/create/matroska-header.d.ts +0 -1
- package/dist/create/matroska-seek.d.ts +0 -6
- package/dist/create/matroska-trackentry.d.ts +0 -27
- package/dist/create/polyfill-audio-sample.d.ts +0 -3
- package/dist/create/polyfill-audio-sample.js +0 -15
- package/dist/writers/buffer-implementation/multi-buffer.d.ts +0 -0
- package/dist/writers/buffer-implementation/multi-buffer.js +0 -1
package/dist/esm/index.mjs
CHANGED
|
@@ -1021,7 +1021,1111 @@ var combineUint8Arrays = (arrays) => {
|
|
|
1021
1021
|
return result;
|
|
1022
1022
|
};
|
|
1023
1023
|
|
|
1024
|
-
// src/
|
|
1024
|
+
// src/log.ts
|
|
1025
|
+
var logLevels = ["trace", "verbose", "info", "warn", "error"];
|
|
1026
|
+
var getNumberForLogLevel = (level) => {
|
|
1027
|
+
return logLevels.indexOf(level);
|
|
1028
|
+
};
|
|
1029
|
+
var isEqualOrBelowLogLevel = (currentLevel, level) => {
|
|
1030
|
+
return getNumberForLogLevel(currentLevel) <= getNumberForLogLevel(level);
|
|
1031
|
+
};
|
|
1032
|
+
var Log = {
|
|
1033
|
+
trace: (logLevel, ...args) => {
|
|
1034
|
+
if (isEqualOrBelowLogLevel(logLevel, "trace")) {
|
|
1035
|
+
return console.log(...args);
|
|
1036
|
+
}
|
|
1037
|
+
},
|
|
1038
|
+
verbose: (logLevel, ...args) => {
|
|
1039
|
+
if (isEqualOrBelowLogLevel(logLevel, "verbose")) {
|
|
1040
|
+
return console.log(...args);
|
|
1041
|
+
}
|
|
1042
|
+
},
|
|
1043
|
+
info: (logLevel, ...args) => {
|
|
1044
|
+
if (isEqualOrBelowLogLevel(logLevel, "info")) {
|
|
1045
|
+
return console.log(...args);
|
|
1046
|
+
}
|
|
1047
|
+
},
|
|
1048
|
+
warn: (logLevel, ...args) => {
|
|
1049
|
+
if (isEqualOrBelowLogLevel(logLevel, "warn")) {
|
|
1050
|
+
return console.warn(...args);
|
|
1051
|
+
}
|
|
1052
|
+
},
|
|
1053
|
+
error: (...args) => {
|
|
1054
|
+
return console.error(...args);
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
|
|
1058
|
+
// src/create/iso-base-media/primitives.ts
|
|
1059
|
+
var stringsToUint8Array = (str) => {
|
|
1060
|
+
return new TextEncoder().encode(str);
|
|
1061
|
+
};
|
|
1062
|
+
var numberTo32BitUIntOrInt = (num) => {
|
|
1063
|
+
return new Uint8Array([
|
|
1064
|
+
num >> 24 & 255,
|
|
1065
|
+
num >> 16 & 255,
|
|
1066
|
+
num >> 8 & 255,
|
|
1067
|
+
num & 255
|
|
1068
|
+
]);
|
|
1069
|
+
};
|
|
1070
|
+
var numberTo32BitUIntOrIntLeading128 = (num) => {
|
|
1071
|
+
const arr = [
|
|
1072
|
+
num >> 24 & 255,
|
|
1073
|
+
num >> 16 & 255,
|
|
1074
|
+
num >> 8 & 255,
|
|
1075
|
+
num & 255
|
|
1076
|
+
];
|
|
1077
|
+
for (const i in arr) {
|
|
1078
|
+
if (arr[i] === 0) {
|
|
1079
|
+
arr[i] = 128;
|
|
1080
|
+
} else {
|
|
1081
|
+
break;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
return new Uint8Array(arr);
|
|
1085
|
+
};
|
|
1086
|
+
var numberTo16BitUIntOrInt = (num) => {
|
|
1087
|
+
return new Uint8Array([num >> 8 & 255, num & 255]);
|
|
1088
|
+
};
|
|
1089
|
+
var setFixedPointSignedOrUnsigned1616Number = (num) => {
|
|
1090
|
+
const val = Math.round(num * 2 ** 16);
|
|
1091
|
+
return numberTo32BitUIntOrInt(val);
|
|
1092
|
+
};
|
|
1093
|
+
var setFixedPointSigned230Number = (num) => {
|
|
1094
|
+
const val = Math.round(num * 2 ** 30);
|
|
1095
|
+
return numberTo32BitUIntOrInt(val);
|
|
1096
|
+
};
|
|
1097
|
+
var addSize = (arr) => {
|
|
1098
|
+
return combineUint8Arrays([numberTo32BitUIntOrInt(arr.length + 4), arr]);
|
|
1099
|
+
};
|
|
1100
|
+
var addLeading128Size = (arr) => {
|
|
1101
|
+
return combineUint8Arrays([
|
|
1102
|
+
numberTo32BitUIntOrIntLeading128(arr.length),
|
|
1103
|
+
arr
|
|
1104
|
+
]);
|
|
1105
|
+
};
|
|
1106
|
+
var floatTo16Point1632Bit = (number) => {
|
|
1107
|
+
const fixedNumber = Number(number.toFixed(2));
|
|
1108
|
+
const result = new Uint8Array(4);
|
|
1109
|
+
const tens = Math.floor(fixedNumber / 10);
|
|
1110
|
+
const ones = Math.floor(fixedNumber % 10);
|
|
1111
|
+
const tenths = Math.floor(fixedNumber * 10 % 10);
|
|
1112
|
+
const hundredths = Math.floor(fixedNumber * 100 % 10);
|
|
1113
|
+
result[0] = tens;
|
|
1114
|
+
result[1] = ones;
|
|
1115
|
+
result[2] = tenths;
|
|
1116
|
+
result[3] = hundredths;
|
|
1117
|
+
return result;
|
|
1118
|
+
};
|
|
1119
|
+
var floatTo16Point16_16Bit = (number) => {
|
|
1120
|
+
const fixedNumber = Number(number.toFixed(2));
|
|
1121
|
+
const result = new Uint8Array(2);
|
|
1122
|
+
const ones = Math.floor(fixedNumber % 10);
|
|
1123
|
+
const tenths = Math.floor(fixedNumber * 10 % 10);
|
|
1124
|
+
result[0] = ones;
|
|
1125
|
+
result[1] = tenths;
|
|
1126
|
+
return result;
|
|
1127
|
+
};
|
|
1128
|
+
var serializeMatrix = (matrix) => {
|
|
1129
|
+
return combineUint8Arrays([
|
|
1130
|
+
setFixedPointSignedOrUnsigned1616Number(matrix[0]),
|
|
1131
|
+
setFixedPointSignedOrUnsigned1616Number(matrix[1]),
|
|
1132
|
+
setFixedPointSigned230Number(matrix[2]),
|
|
1133
|
+
setFixedPointSignedOrUnsigned1616Number(matrix[3]),
|
|
1134
|
+
setFixedPointSignedOrUnsigned1616Number(matrix[4]),
|
|
1135
|
+
setFixedPointSigned230Number(matrix[5]),
|
|
1136
|
+
setFixedPointSignedOrUnsigned1616Number(matrix[6]),
|
|
1137
|
+
setFixedPointSignedOrUnsigned1616Number(matrix[7]),
|
|
1138
|
+
setFixedPointSigned230Number(matrix[8])
|
|
1139
|
+
]);
|
|
1140
|
+
};
|
|
1141
|
+
var stringToPascalString = (str) => {
|
|
1142
|
+
const buffer = new Uint8Array(32);
|
|
1143
|
+
for (let i = 0;i < Math.min(str.length, 32); i++) {
|
|
1144
|
+
buffer[i] = str.charCodeAt(i);
|
|
1145
|
+
}
|
|
1146
|
+
return buffer;
|
|
1147
|
+
};
|
|
1148
|
+
var padIsoBaseMediaBytes = (data, totalLength) => {
|
|
1149
|
+
if (data.length - 8 > totalLength) {
|
|
1150
|
+
throw new Error(`Data is longer than the total length: ${data.length - 8} > ${totalLength}`);
|
|
1151
|
+
}
|
|
1152
|
+
if (data.length - 8 === totalLength) {
|
|
1153
|
+
return data;
|
|
1154
|
+
}
|
|
1155
|
+
return combineUint8Arrays([
|
|
1156
|
+
data,
|
|
1157
|
+
addSize(combineUint8Arrays([
|
|
1158
|
+
stringsToUint8Array("free"),
|
|
1159
|
+
new Uint8Array(totalLength - (data.length - 8))
|
|
1160
|
+
]))
|
|
1161
|
+
]);
|
|
1162
|
+
};
|
|
1163
|
+
var IDENTITY_MATRIX = [1, 0, 0, 0, 1, 0, 0, 0, 1];
|
|
1164
|
+
|
|
1165
|
+
// src/create/iso-base-media/create-ftyp.ts
|
|
1166
|
+
var createFtyp = ({
|
|
1167
|
+
majorBrand,
|
|
1168
|
+
minorBrand,
|
|
1169
|
+
compatibleBrands
|
|
1170
|
+
}) => {
|
|
1171
|
+
const type = stringsToUint8Array("ftyp");
|
|
1172
|
+
const majorBrandArr = stringsToUint8Array(majorBrand);
|
|
1173
|
+
const minorBrandArr = numberTo32BitUIntOrInt(minorBrand);
|
|
1174
|
+
const compatibleBrandsArr = combineUint8Arrays(compatibleBrands.map((b) => stringsToUint8Array(b)));
|
|
1175
|
+
return addSize(combineUint8Arrays([
|
|
1176
|
+
type,
|
|
1177
|
+
majorBrandArr,
|
|
1178
|
+
minorBrandArr,
|
|
1179
|
+
compatibleBrandsArr
|
|
1180
|
+
]));
|
|
1181
|
+
};
|
|
1182
|
+
var createIsoBaseMediaFtyp = ({
|
|
1183
|
+
majorBrand,
|
|
1184
|
+
minorBrand,
|
|
1185
|
+
compatibleBrands
|
|
1186
|
+
}) => {
|
|
1187
|
+
return createFtyp({ compatibleBrands, majorBrand, minorBrand });
|
|
1188
|
+
};
|
|
1189
|
+
|
|
1190
|
+
// src/create/iso-base-media/create-ilst.ts
|
|
1191
|
+
var createIlst = (items) => {
|
|
1192
|
+
return addSize(combineUint8Arrays([
|
|
1193
|
+
stringsToUint8Array("ilst"),
|
|
1194
|
+
...items
|
|
1195
|
+
]));
|
|
1196
|
+
};
|
|
1197
|
+
|
|
1198
|
+
// src/create/iso-base-media/create-moov.ts
|
|
1199
|
+
var createMoov = ({
|
|
1200
|
+
mvhd,
|
|
1201
|
+
traks,
|
|
1202
|
+
udta
|
|
1203
|
+
}) => {
|
|
1204
|
+
return addSize(combineUint8Arrays([
|
|
1205
|
+
stringsToUint8Array("moov"),
|
|
1206
|
+
mvhd,
|
|
1207
|
+
...traks,
|
|
1208
|
+
udta
|
|
1209
|
+
]));
|
|
1210
|
+
};
|
|
1211
|
+
|
|
1212
|
+
// src/boxes/iso-base-media/to-date.ts
|
|
1213
|
+
var toUnixTimestamp = (value) => {
|
|
1214
|
+
if (value === 0) {
|
|
1215
|
+
return null;
|
|
1216
|
+
}
|
|
1217
|
+
const baseDate = new Date("1904-01-01T00:00:00Z");
|
|
1218
|
+
return Math.floor(value + baseDate.getTime() / 1000) * 1000;
|
|
1219
|
+
};
|
|
1220
|
+
var fromUnixTimestamp = (value) => {
|
|
1221
|
+
if (value === null) {
|
|
1222
|
+
return 0;
|
|
1223
|
+
}
|
|
1224
|
+
const baseDate = new Date("1904-01-01T00:00:00Z");
|
|
1225
|
+
return Math.floor(value / 1000 - baseDate.getTime() / 1000);
|
|
1226
|
+
};
|
|
1227
|
+
|
|
1228
|
+
// src/create/iso-base-media/create-mvhd.ts
|
|
1229
|
+
var createMvhd = ({
|
|
1230
|
+
timescale,
|
|
1231
|
+
durationInUnits,
|
|
1232
|
+
rate,
|
|
1233
|
+
volume,
|
|
1234
|
+
nextTrackId,
|
|
1235
|
+
matrix,
|
|
1236
|
+
creationTime,
|
|
1237
|
+
modificationTime
|
|
1238
|
+
}) => {
|
|
1239
|
+
if (matrix.length !== 9) {
|
|
1240
|
+
throw new Error("Matrix must be 9 elements long");
|
|
1241
|
+
}
|
|
1242
|
+
const content = combineUint8Arrays([
|
|
1243
|
+
stringsToUint8Array("mvhd"),
|
|
1244
|
+
new Uint8Array([0]),
|
|
1245
|
+
new Uint8Array([0, 0, 0]),
|
|
1246
|
+
creationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(creationTime)),
|
|
1247
|
+
modificationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(modificationTime)),
|
|
1248
|
+
numberTo32BitUIntOrInt(timescale),
|
|
1249
|
+
numberTo32BitUIntOrInt(durationInUnits),
|
|
1250
|
+
floatTo16Point1632Bit(rate),
|
|
1251
|
+
floatTo16Point16_16Bit(volume),
|
|
1252
|
+
new Uint8Array([0, 0]),
|
|
1253
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1254
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1255
|
+
serializeMatrix(matrix),
|
|
1256
|
+
combineUint8Arrays(new Array(6).fill(new Uint8Array([0, 0, 0, 0]))),
|
|
1257
|
+
numberTo32BitUIntOrInt(nextTrackId)
|
|
1258
|
+
]);
|
|
1259
|
+
return addSize(content);
|
|
1260
|
+
};
|
|
1261
|
+
|
|
1262
|
+
// src/create/iso-base-media/create-udta.ts
|
|
1263
|
+
var createUdta = (children) => {
|
|
1264
|
+
return addSize(combineUint8Arrays([
|
|
1265
|
+
stringsToUint8Array("udta"),
|
|
1266
|
+
children
|
|
1267
|
+
]));
|
|
1268
|
+
};
|
|
1269
|
+
|
|
1270
|
+
// src/create/iso-base-media/ilst/create-cmt.ts
|
|
1271
|
+
var createCmt = (comment) => {
|
|
1272
|
+
return addSize(combineUint8Arrays([
|
|
1273
|
+
new Uint8Array([169, 99, 109, 116]),
|
|
1274
|
+
addSize(combineUint8Arrays([
|
|
1275
|
+
stringsToUint8Array("data"),
|
|
1276
|
+
new Uint8Array([0, 0]),
|
|
1277
|
+
new Uint8Array([0, 1]),
|
|
1278
|
+
new Uint8Array([0, 0]),
|
|
1279
|
+
new Uint8Array([0, 0]),
|
|
1280
|
+
stringsToUint8Array(comment)
|
|
1281
|
+
]))
|
|
1282
|
+
]));
|
|
1283
|
+
};
|
|
1284
|
+
|
|
1285
|
+
// src/create/iso-base-media/ilst/create-too.ts
|
|
1286
|
+
var createToo = (value) => {
|
|
1287
|
+
return addSize(combineUint8Arrays([
|
|
1288
|
+
new Uint8Array([169, 116, 111, 111]),
|
|
1289
|
+
addSize(combineUint8Arrays([
|
|
1290
|
+
new Uint8Array([100, 97, 116, 97]),
|
|
1291
|
+
new Uint8Array([0, 0]),
|
|
1292
|
+
new Uint8Array([0, 1]),
|
|
1293
|
+
new Uint8Array([0, 0]),
|
|
1294
|
+
new Uint8Array([0, 0]),
|
|
1295
|
+
stringsToUint8Array(value)
|
|
1296
|
+
]))
|
|
1297
|
+
]));
|
|
1298
|
+
};
|
|
1299
|
+
|
|
1300
|
+
// src/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avcc.ts
|
|
1301
|
+
var createAvccBox = (privateData) => {
|
|
1302
|
+
if (!privateData) {
|
|
1303
|
+
throw new Error("privateData is required");
|
|
1304
|
+
}
|
|
1305
|
+
return addSize(combineUint8Arrays([
|
|
1306
|
+
stringsToUint8Array("avcC"),
|
|
1307
|
+
privateData
|
|
1308
|
+
]));
|
|
1309
|
+
};
|
|
1310
|
+
|
|
1311
|
+
// src/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-pasp.ts
|
|
1312
|
+
var createPasp = (x, y) => {
|
|
1313
|
+
return addSize(combineUint8Arrays([
|
|
1314
|
+
stringsToUint8Array("pasp"),
|
|
1315
|
+
numberTo32BitUIntOrInt(x),
|
|
1316
|
+
numberTo32BitUIntOrInt(y)
|
|
1317
|
+
]));
|
|
1318
|
+
};
|
|
1319
|
+
|
|
1320
|
+
// src/create/iso-base-media/codec-specific/avc1.ts
|
|
1321
|
+
var createAvc1Data = ({
|
|
1322
|
+
avccBox,
|
|
1323
|
+
pasp,
|
|
1324
|
+
width,
|
|
1325
|
+
height,
|
|
1326
|
+
horizontalResolution,
|
|
1327
|
+
verticalResolution,
|
|
1328
|
+
compressorName,
|
|
1329
|
+
depth
|
|
1330
|
+
}) => {
|
|
1331
|
+
return addSize(combineUint8Arrays([
|
|
1332
|
+
stringsToUint8Array("avc1"),
|
|
1333
|
+
new Uint8Array([0, 0, 0, 0, 0, 0]),
|
|
1334
|
+
new Uint8Array([0, 1]),
|
|
1335
|
+
new Uint8Array([0, 0]),
|
|
1336
|
+
new Uint8Array([0, 0]),
|
|
1337
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1338
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1339
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1340
|
+
numberTo16BitUIntOrInt(width),
|
|
1341
|
+
numberTo16BitUIntOrInt(height),
|
|
1342
|
+
setFixedPointSignedOrUnsigned1616Number(horizontalResolution),
|
|
1343
|
+
setFixedPointSignedOrUnsigned1616Number(verticalResolution),
|
|
1344
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1345
|
+
numberTo16BitUIntOrInt(1),
|
|
1346
|
+
stringToPascalString(compressorName),
|
|
1347
|
+
numberTo16BitUIntOrInt(depth),
|
|
1348
|
+
numberTo16BitUIntOrInt(-1),
|
|
1349
|
+
avccBox,
|
|
1350
|
+
pasp
|
|
1351
|
+
]));
|
|
1352
|
+
};
|
|
1353
|
+
|
|
1354
|
+
// src/create/iso-base-media/codec-specific/mp4a.ts
|
|
1355
|
+
var createMp4a = ({
|
|
1356
|
+
sampleRate,
|
|
1357
|
+
channelCount,
|
|
1358
|
+
avgBitrate,
|
|
1359
|
+
maxBitrate,
|
|
1360
|
+
codecPrivate: codecPrivate2
|
|
1361
|
+
}) => {
|
|
1362
|
+
if (!codecPrivate2) {
|
|
1363
|
+
throw new Error("Need codecPrivate for mp4a");
|
|
1364
|
+
}
|
|
1365
|
+
const esdsAtom = addSize(combineUint8Arrays([
|
|
1366
|
+
stringsToUint8Array("esds"),
|
|
1367
|
+
new Uint8Array([0]),
|
|
1368
|
+
new Uint8Array([0, 0, 0]),
|
|
1369
|
+
new Uint8Array([3]),
|
|
1370
|
+
addLeading128Size(combineUint8Arrays([
|
|
1371
|
+
numberTo16BitUIntOrInt(2),
|
|
1372
|
+
new Uint8Array([0]),
|
|
1373
|
+
new Uint8Array([4]),
|
|
1374
|
+
addLeading128Size(combineUint8Arrays([
|
|
1375
|
+
new Uint8Array([64]),
|
|
1376
|
+
new Uint8Array([21]),
|
|
1377
|
+
new Uint8Array([0, 0, 0]),
|
|
1378
|
+
numberTo32BitUIntOrInt(maxBitrate),
|
|
1379
|
+
numberTo32BitUIntOrInt(avgBitrate),
|
|
1380
|
+
new Uint8Array([5]),
|
|
1381
|
+
addLeading128Size(codecPrivate2)
|
|
1382
|
+
])),
|
|
1383
|
+
new Uint8Array([6]),
|
|
1384
|
+
addLeading128Size(new Uint8Array([2]))
|
|
1385
|
+
]))
|
|
1386
|
+
]));
|
|
1387
|
+
return addSize(combineUint8Arrays([
|
|
1388
|
+
stringsToUint8Array("mp4a"),
|
|
1389
|
+
new Uint8Array([0, 0, 0, 0, 0, 0]),
|
|
1390
|
+
numberTo16BitUIntOrInt(1),
|
|
1391
|
+
numberTo16BitUIntOrInt(0),
|
|
1392
|
+
numberTo16BitUIntOrInt(0),
|
|
1393
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1394
|
+
numberTo16BitUIntOrInt(channelCount),
|
|
1395
|
+
numberTo16BitUIntOrInt(16),
|
|
1396
|
+
numberTo16BitUIntOrInt(0),
|
|
1397
|
+
numberTo16BitUIntOrInt(0),
|
|
1398
|
+
setFixedPointSignedOrUnsigned1616Number(sampleRate),
|
|
1399
|
+
esdsAtom
|
|
1400
|
+
]));
|
|
1401
|
+
};
|
|
1402
|
+
|
|
1403
|
+
// src/create/iso-base-media/codec-specific/create-codec-specific-data.ts
|
|
1404
|
+
var createCodecSpecificData = (track) => {
|
|
1405
|
+
if (track.type === "video") {
|
|
1406
|
+
return createAvc1Data({
|
|
1407
|
+
avccBox: createAvccBox(track.codecPrivate),
|
|
1408
|
+
compressorName: "WebCodecs",
|
|
1409
|
+
depth: 24,
|
|
1410
|
+
horizontalResolution: 72,
|
|
1411
|
+
verticalResolution: 72,
|
|
1412
|
+
height: track.height,
|
|
1413
|
+
width: track.width,
|
|
1414
|
+
pasp: createPasp(1, 1),
|
|
1415
|
+
type: "avc1-data"
|
|
1416
|
+
});
|
|
1417
|
+
}
|
|
1418
|
+
if (track.type === "audio") {
|
|
1419
|
+
return createMp4a({
|
|
1420
|
+
type: "mp4a-data",
|
|
1421
|
+
avgBitrate: 128 * 1024,
|
|
1422
|
+
maxBitrate: 128 * 1024,
|
|
1423
|
+
channelCount: track.numberOfChannels,
|
|
1424
|
+
sampleRate: track.sampleRate,
|
|
1425
|
+
codecPrivate: track.codecPrivate
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
throw new Error("Unsupported codec specific data " + track);
|
|
1429
|
+
};
|
|
1430
|
+
|
|
1431
|
+
// src/create/iso-base-media/create-mdia.ts
|
|
1432
|
+
var createMdia = ({
|
|
1433
|
+
mdhd,
|
|
1434
|
+
hdlr,
|
|
1435
|
+
minf
|
|
1436
|
+
}) => {
|
|
1437
|
+
return addSize(combineUint8Arrays([
|
|
1438
|
+
stringsToUint8Array("mdia"),
|
|
1439
|
+
mdhd,
|
|
1440
|
+
hdlr,
|
|
1441
|
+
minf
|
|
1442
|
+
]));
|
|
1443
|
+
};
|
|
1444
|
+
|
|
1445
|
+
// src/truthy.ts
|
|
1446
|
+
function truthy(value) {
|
|
1447
|
+
return Boolean(value);
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
// src/create/iso-base-media/create-trak.ts
|
|
1451
|
+
var createTrak = ({
|
|
1452
|
+
tkhd,
|
|
1453
|
+
mdia
|
|
1454
|
+
}) => {
|
|
1455
|
+
return addSize(combineUint8Arrays([
|
|
1456
|
+
stringsToUint8Array("trak"),
|
|
1457
|
+
tkhd,
|
|
1458
|
+
mdia
|
|
1459
|
+
].filter(truthy)));
|
|
1460
|
+
};
|
|
1461
|
+
|
|
1462
|
+
// src/create/iso-base-media/mdia/create-mdhd.ts
|
|
1463
|
+
var createMdhd = ({
|
|
1464
|
+
creationTime,
|
|
1465
|
+
modificationTime,
|
|
1466
|
+
timescale,
|
|
1467
|
+
duration: duration2
|
|
1468
|
+
}) => {
|
|
1469
|
+
return addSize(combineUint8Arrays([
|
|
1470
|
+
stringsToUint8Array("mdhd"),
|
|
1471
|
+
new Uint8Array([0]),
|
|
1472
|
+
new Uint8Array([0, 0, 0]),
|
|
1473
|
+
creationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(creationTime)),
|
|
1474
|
+
modificationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(modificationTime)),
|
|
1475
|
+
numberTo32BitUIntOrInt(timescale),
|
|
1476
|
+
numberTo32BitUIntOrInt(Math.round(duration2 / 1000 * timescale)),
|
|
1477
|
+
new Uint8Array([85, 196]),
|
|
1478
|
+
new Uint8Array([0, 0])
|
|
1479
|
+
]));
|
|
1480
|
+
};
|
|
1481
|
+
|
|
1482
|
+
// src/create/iso-base-media/trak/create-tkhd.ts
|
|
1483
|
+
var TKHD_FLAGS = {
|
|
1484
|
+
TRACK_ENABLED: 1,
|
|
1485
|
+
TRACK_IN_MOVIE: 2,
|
|
1486
|
+
TRACK_IN_PREVIEW: 4,
|
|
1487
|
+
TRACK_IN_POSTER: 8
|
|
1488
|
+
};
|
|
1489
|
+
var createTkhdForAudio = ({
|
|
1490
|
+
creationTime,
|
|
1491
|
+
modificationTime,
|
|
1492
|
+
flags,
|
|
1493
|
+
trackId,
|
|
1494
|
+
duration: duration2,
|
|
1495
|
+
volume,
|
|
1496
|
+
timescale
|
|
1497
|
+
}) => {
|
|
1498
|
+
return addSize(combineUint8Arrays([
|
|
1499
|
+
stringsToUint8Array("tkhd"),
|
|
1500
|
+
new Uint8Array([0]),
|
|
1501
|
+
new Uint8Array([0, 0, flags]),
|
|
1502
|
+
creationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(creationTime)),
|
|
1503
|
+
modificationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(modificationTime)),
|
|
1504
|
+
numberTo32BitUIntOrInt(trackId),
|
|
1505
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1506
|
+
numberTo32BitUIntOrInt(Math.round(duration2 / 1000 * timescale)),
|
|
1507
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1508
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1509
|
+
new Uint8Array([0, 0]),
|
|
1510
|
+
new Uint8Array([0, 1]),
|
|
1511
|
+
floatTo16Point16_16Bit(volume),
|
|
1512
|
+
new Uint8Array([0, 0]),
|
|
1513
|
+
serializeMatrix(IDENTITY_MATRIX),
|
|
1514
|
+
setFixedPointSignedOrUnsigned1616Number(0),
|
|
1515
|
+
setFixedPointSignedOrUnsigned1616Number(0)
|
|
1516
|
+
]));
|
|
1517
|
+
};
|
|
1518
|
+
var createTkhdForVideo = ({
|
|
1519
|
+
creationTime,
|
|
1520
|
+
modificationTime,
|
|
1521
|
+
duration: duration2,
|
|
1522
|
+
trackId,
|
|
1523
|
+
volume,
|
|
1524
|
+
matrix,
|
|
1525
|
+
width,
|
|
1526
|
+
height,
|
|
1527
|
+
flags,
|
|
1528
|
+
timescale
|
|
1529
|
+
}) => {
|
|
1530
|
+
const content = combineUint8Arrays([
|
|
1531
|
+
stringsToUint8Array("tkhd"),
|
|
1532
|
+
new Uint8Array([0]),
|
|
1533
|
+
new Uint8Array([0, 0, flags]),
|
|
1534
|
+
creationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(creationTime)),
|
|
1535
|
+
modificationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(modificationTime)),
|
|
1536
|
+
numberTo32BitUIntOrInt(trackId),
|
|
1537
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1538
|
+
numberTo32BitUIntOrInt(duration2 / 1000 * timescale),
|
|
1539
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1540
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1541
|
+
new Uint8Array([0, 0]),
|
|
1542
|
+
new Uint8Array([0, 0]),
|
|
1543
|
+
floatTo16Point16_16Bit(volume),
|
|
1544
|
+
new Uint8Array([0, 0]),
|
|
1545
|
+
serializeMatrix(matrix),
|
|
1546
|
+
setFixedPointSignedOrUnsigned1616Number(width),
|
|
1547
|
+
setFixedPointSignedOrUnsigned1616Number(height)
|
|
1548
|
+
]);
|
|
1549
|
+
return addSize(content);
|
|
1550
|
+
};
|
|
1551
|
+
|
|
1552
|
+
// src/create/iso-base-media/trak/mdia/minf/create-dinf.ts
|
|
1553
|
+
var createDinf = () => {
|
|
1554
|
+
return addSize(combineUint8Arrays([
|
|
1555
|
+
stringsToUint8Array("dinf"),
|
|
1556
|
+
addSize(combineUint8Arrays([
|
|
1557
|
+
stringsToUint8Array("dref"),
|
|
1558
|
+
new Uint8Array([0]),
|
|
1559
|
+
new Uint8Array([0, 0, 0]),
|
|
1560
|
+
new Uint8Array([0, 0, 0, 1]),
|
|
1561
|
+
addSize(combineUint8Arrays([
|
|
1562
|
+
stringsToUint8Array("url "),
|
|
1563
|
+
new Uint8Array([0]),
|
|
1564
|
+
new Uint8Array([0, 0, 1])
|
|
1565
|
+
]))
|
|
1566
|
+
]))
|
|
1567
|
+
]));
|
|
1568
|
+
};
|
|
1569
|
+
|
|
1570
|
+
// src/create/iso-base-media/trak/mdia/create-minf.ts
|
|
1571
|
+
var createMinf = ({
|
|
1572
|
+
vmhdAtom,
|
|
1573
|
+
stblAtom
|
|
1574
|
+
}) => {
|
|
1575
|
+
return addSize(combineUint8Arrays([
|
|
1576
|
+
stringsToUint8Array("minf"),
|
|
1577
|
+
vmhdAtom,
|
|
1578
|
+
createDinf(),
|
|
1579
|
+
stblAtom
|
|
1580
|
+
]));
|
|
1581
|
+
};
|
|
1582
|
+
|
|
1583
|
+
// src/create/iso-base-media/trak/mdia/minf/create-smhd.ts
|
|
1584
|
+
var createSmhd = () => {
|
|
1585
|
+
return addSize(combineUint8Arrays([
|
|
1586
|
+
stringsToUint8Array("smhd"),
|
|
1587
|
+
new Uint8Array([0]),
|
|
1588
|
+
new Uint8Array([0, 0, 0]),
|
|
1589
|
+
new Uint8Array([0, 0]),
|
|
1590
|
+
new Uint8Array([0, 0])
|
|
1591
|
+
]));
|
|
1592
|
+
};
|
|
1593
|
+
|
|
1594
|
+
// src/create/iso-base-media/trak/mdia/minf/stbl/create-ctts.ts
|
|
1595
|
+
var makeEntry = (entry) => {
|
|
1596
|
+
return combineUint8Arrays([
|
|
1597
|
+
numberTo32BitUIntOrInt(entry.sampleCount),
|
|
1598
|
+
numberTo32BitUIntOrInt(entry.sampleOffset)
|
|
1599
|
+
]);
|
|
1600
|
+
};
|
|
1601
|
+
var createCttsBox = (samplePositions) => {
|
|
1602
|
+
const offsets = samplePositions.map((s) => s.cts - s.dts);
|
|
1603
|
+
const entries = [];
|
|
1604
|
+
let lastOffset = null;
|
|
1605
|
+
for (const offset of offsets) {
|
|
1606
|
+
if (lastOffset === offset) {
|
|
1607
|
+
entries[entries.length - 1].sampleCount++;
|
|
1608
|
+
} else {
|
|
1609
|
+
entries.push({
|
|
1610
|
+
sampleCount: 1,
|
|
1611
|
+
sampleOffset: offset
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1614
|
+
lastOffset = offset;
|
|
1615
|
+
}
|
|
1616
|
+
const needsCtts = entries.length > 0 && entries.some((e) => e.sampleOffset !== 0);
|
|
1617
|
+
if (!needsCtts) {
|
|
1618
|
+
return null;
|
|
1619
|
+
}
|
|
1620
|
+
return addSize(combineUint8Arrays([
|
|
1621
|
+
stringsToUint8Array("ctts"),
|
|
1622
|
+
new Uint8Array([0]),
|
|
1623
|
+
new Uint8Array([0, 0, 0]),
|
|
1624
|
+
numberTo32BitUIntOrInt(entries.length),
|
|
1625
|
+
...entries.map((e) => makeEntry(e))
|
|
1626
|
+
]));
|
|
1627
|
+
};
|
|
1628
|
+
|
|
1629
|
+
// src/create/iso-base-media/trak/mdia/minf/stbl/create-stco.ts
|
|
1630
|
+
var createStcoAtom = (samplePositions) => {
|
|
1631
|
+
const chunkOffsets = [];
|
|
1632
|
+
let lastChunk;
|
|
1633
|
+
for (const sample of samplePositions) {
|
|
1634
|
+
if (lastChunk !== sample.chunk) {
|
|
1635
|
+
chunkOffsets.push(sample.offset);
|
|
1636
|
+
}
|
|
1637
|
+
lastChunk = sample.chunk;
|
|
1638
|
+
}
|
|
1639
|
+
return addSize(combineUint8Arrays([
|
|
1640
|
+
stringsToUint8Array("stco"),
|
|
1641
|
+
new Uint8Array([0]),
|
|
1642
|
+
new Uint8Array([0, 0, 0]),
|
|
1643
|
+
numberTo32BitUIntOrInt(chunkOffsets.length),
|
|
1644
|
+
...chunkOffsets.map((offset) => numberTo32BitUIntOrInt(offset))
|
|
1645
|
+
]));
|
|
1646
|
+
};
|
|
1647
|
+
|
|
1648
|
+
// src/create/iso-base-media/trak/mdia/minf/stbl/create-stsc.ts
|
|
1649
|
+
var createEntry = (entry) => {
|
|
1650
|
+
return combineUint8Arrays([
|
|
1651
|
+
numberTo32BitUIntOrInt(entry.firstChunk),
|
|
1652
|
+
numberTo32BitUIntOrInt(entry.samplesPerChunk),
|
|
1653
|
+
numberTo32BitUIntOrInt(entry.sampleDescriptionIndex)
|
|
1654
|
+
]);
|
|
1655
|
+
};
|
|
1656
|
+
var createStsc = (samplePositions) => {
|
|
1657
|
+
const entries = [];
|
|
1658
|
+
const deduplicateLastEntry = () => {
|
|
1659
|
+
const lastEntry = entries[entries.length - 1];
|
|
1660
|
+
const secondToLastEntry = entries[entries.length - 2];
|
|
1661
|
+
if (lastEntry && secondToLastEntry && lastEntry.samplesPerChunk === secondToLastEntry.samplesPerChunk && lastEntry.sampleDescriptionIndex === secondToLastEntry.sampleDescriptionIndex) {
|
|
1662
|
+
const lastIndex = entries.length - 1;
|
|
1663
|
+
entries.length = lastIndex;
|
|
1664
|
+
}
|
|
1665
|
+
};
|
|
1666
|
+
let lastChunk;
|
|
1667
|
+
for (const samplePosition of samplePositions) {
|
|
1668
|
+
if (samplePosition.chunk === lastChunk) {
|
|
1669
|
+
entries[entries.length - 1].samplesPerChunk++;
|
|
1670
|
+
} else {
|
|
1671
|
+
deduplicateLastEntry();
|
|
1672
|
+
entries.push({
|
|
1673
|
+
firstChunk: samplePosition.chunk,
|
|
1674
|
+
samplesPerChunk: 1,
|
|
1675
|
+
sampleDescriptionIndex: 1
|
|
1676
|
+
});
|
|
1677
|
+
lastChunk = samplePosition.chunk;
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
deduplicateLastEntry();
|
|
1681
|
+
return addSize(combineUint8Arrays([
|
|
1682
|
+
stringsToUint8Array("stsc"),
|
|
1683
|
+
new Uint8Array([0]),
|
|
1684
|
+
new Uint8Array([0, 0, 0]),
|
|
1685
|
+
numberTo32BitUIntOrInt(entries.length),
|
|
1686
|
+
...entries.map((e) => createEntry(e))
|
|
1687
|
+
]));
|
|
1688
|
+
};
|
|
1689
|
+
|
|
1690
|
+
// src/create/iso-base-media/trak/mdia/minf/stbl/create-stss.ts
|
|
1691
|
+
var createStss = (samplePositions) => {
|
|
1692
|
+
const samples = samplePositions.map((sample, i) => [sample.isKeyframe, i]).filter((s) => s[0]).map((s) => s[1] + 1);
|
|
1693
|
+
return addSize(combineUint8Arrays([
|
|
1694
|
+
stringsToUint8Array("stss"),
|
|
1695
|
+
new Uint8Array([0]),
|
|
1696
|
+
new Uint8Array([0, 0, 0]),
|
|
1697
|
+
numberTo32BitUIntOrInt(samples.length),
|
|
1698
|
+
...samples.map((sample) => numberTo32BitUIntOrInt(sample))
|
|
1699
|
+
]));
|
|
1700
|
+
};
|
|
1701
|
+
|
|
1702
|
+
// src/create/iso-base-media/trak/mdia/minf/stbl/create-stsz.ts
|
|
1703
|
+
var createStsz = (samplePositions) => {
|
|
1704
|
+
const sampleSizes = samplePositions.map((samplePosition) => samplePosition.size);
|
|
1705
|
+
return addSize(combineUint8Arrays([
|
|
1706
|
+
stringsToUint8Array("stsz"),
|
|
1707
|
+
new Uint8Array([0]),
|
|
1708
|
+
new Uint8Array([0, 0, 0]),
|
|
1709
|
+
numberTo32BitUIntOrInt(0),
|
|
1710
|
+
numberTo32BitUIntOrInt(sampleSizes.length),
|
|
1711
|
+
...sampleSizes.map((size) => numberTo32BitUIntOrInt(size))
|
|
1712
|
+
]));
|
|
1713
|
+
};
|
|
1714
|
+
|
|
1715
|
+
// src/create/iso-base-media/trak/mdia/minf/stbl/create-stts.ts
|
|
1716
|
+
var makeEntry2 = (entry) => {
|
|
1717
|
+
return combineUint8Arrays([
|
|
1718
|
+
numberTo32BitUIntOrInt(entry.sampleCount),
|
|
1719
|
+
numberTo32BitUIntOrInt(entry.sampleOffset)
|
|
1720
|
+
]);
|
|
1721
|
+
};
|
|
1722
|
+
var createSttsAtom = (samplePositions) => {
|
|
1723
|
+
let lastDuration = null;
|
|
1724
|
+
const durations = samplePositions.map((_, i, a) => {
|
|
1725
|
+
if (a[i].duration === undefined || a[i].duration === 0) {
|
|
1726
|
+
return (a[i + 1]?.dts ?? a[i].dts) - a[i].dts;
|
|
1727
|
+
}
|
|
1728
|
+
return a[i].duration;
|
|
1729
|
+
});
|
|
1730
|
+
const entries = [];
|
|
1731
|
+
for (const duration2 of durations) {
|
|
1732
|
+
if (duration2 === lastDuration) {
|
|
1733
|
+
entries[entries.length - 1].sampleCount++;
|
|
1734
|
+
} else {
|
|
1735
|
+
entries.push({
|
|
1736
|
+
sampleCount: 1,
|
|
1737
|
+
sampleOffset: duration2
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
lastDuration = duration2;
|
|
1741
|
+
}
|
|
1742
|
+
return addSize(combineUint8Arrays([
|
|
1743
|
+
stringsToUint8Array("stts"),
|
|
1744
|
+
new Uint8Array([0]),
|
|
1745
|
+
new Uint8Array([0, 0, 0]),
|
|
1746
|
+
numberTo32BitUIntOrInt(entries.length),
|
|
1747
|
+
...entries.map((e) => makeEntry2(e))
|
|
1748
|
+
]));
|
|
1749
|
+
};
|
|
1750
|
+
|
|
1751
|
+
// src/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avc1.ts
|
|
1752
|
+
var createStsdData = (codecSpecificData) => {
|
|
1753
|
+
return addSize(combineUint8Arrays([
|
|
1754
|
+
stringsToUint8Array("stsd"),
|
|
1755
|
+
new Uint8Array([0]),
|
|
1756
|
+
new Uint8Array([0, 0, 0]),
|
|
1757
|
+
new Uint8Array([0, 0, 0, 1]),
|
|
1758
|
+
codecSpecificData
|
|
1759
|
+
]));
|
|
1760
|
+
};
|
|
1761
|
+
|
|
1762
|
+
// src/create/iso-base-media/trak/mdia/minf/create-stbl.ts
|
|
1763
|
+
var createStbl = ({
|
|
1764
|
+
samplePositions,
|
|
1765
|
+
codecSpecificData,
|
|
1766
|
+
isVideo
|
|
1767
|
+
}) => {
|
|
1768
|
+
return addSize(combineUint8Arrays([
|
|
1769
|
+
stringsToUint8Array("stbl"),
|
|
1770
|
+
createStsdData(codecSpecificData),
|
|
1771
|
+
createSttsAtom(samplePositions),
|
|
1772
|
+
isVideo ? createStss(samplePositions) : null,
|
|
1773
|
+
createCttsBox(samplePositions),
|
|
1774
|
+
createStsc(samplePositions),
|
|
1775
|
+
createStsz(samplePositions),
|
|
1776
|
+
createStcoAtom(samplePositions),
|
|
1777
|
+
isVideo ? null : new Uint8Array([
|
|
1778
|
+
0,
|
|
1779
|
+
0,
|
|
1780
|
+
0,
|
|
1781
|
+
26,
|
|
1782
|
+
115,
|
|
1783
|
+
103,
|
|
1784
|
+
112,
|
|
1785
|
+
100,
|
|
1786
|
+
1,
|
|
1787
|
+
0,
|
|
1788
|
+
0,
|
|
1789
|
+
0,
|
|
1790
|
+
114,
|
|
1791
|
+
111,
|
|
1792
|
+
108,
|
|
1793
|
+
108,
|
|
1794
|
+
0,
|
|
1795
|
+
0,
|
|
1796
|
+
0,
|
|
1797
|
+
2,
|
|
1798
|
+
0,
|
|
1799
|
+
0,
|
|
1800
|
+
0,
|
|
1801
|
+
1,
|
|
1802
|
+
255,
|
|
1803
|
+
255,
|
|
1804
|
+
0,
|
|
1805
|
+
0,
|
|
1806
|
+
0,
|
|
1807
|
+
28,
|
|
1808
|
+
115,
|
|
1809
|
+
98,
|
|
1810
|
+
103,
|
|
1811
|
+
112,
|
|
1812
|
+
0,
|
|
1813
|
+
0,
|
|
1814
|
+
0,
|
|
1815
|
+
0,
|
|
1816
|
+
114,
|
|
1817
|
+
111,
|
|
1818
|
+
108,
|
|
1819
|
+
108,
|
|
1820
|
+
0,
|
|
1821
|
+
0,
|
|
1822
|
+
0,
|
|
1823
|
+
1,
|
|
1824
|
+
0,
|
|
1825
|
+
0,
|
|
1826
|
+
10,
|
|
1827
|
+
25,
|
|
1828
|
+
0,
|
|
1829
|
+
0,
|
|
1830
|
+
0,
|
|
1831
|
+
1
|
|
1832
|
+
])
|
|
1833
|
+
].filter(truthy)));
|
|
1834
|
+
};
|
|
1835
|
+
|
|
1836
|
+
// src/create/iso-base-media/trak/mdia/minf/create-vmhd.ts
|
|
1837
|
+
var createVmhd = () => {
|
|
1838
|
+
return addSize(combineUint8Arrays([
|
|
1839
|
+
stringsToUint8Array("vmhd"),
|
|
1840
|
+
new Uint8Array([0]),
|
|
1841
|
+
new Uint8Array([0, 0, 1]),
|
|
1842
|
+
new Uint8Array([0, 0]),
|
|
1843
|
+
new Uint8Array([0, 0, 0, 0, 0, 0])
|
|
1844
|
+
]));
|
|
1845
|
+
};
|
|
1846
|
+
|
|
1847
|
+
// src/create/iso-base-media/udta/meta/create-hdlr.ts
|
|
1848
|
+
var createHdlr = (type) => {
|
|
1849
|
+
return addSize(combineUint8Arrays([
|
|
1850
|
+
stringsToUint8Array("hdlr"),
|
|
1851
|
+
new Uint8Array([0]),
|
|
1852
|
+
new Uint8Array([0, 0, 0]),
|
|
1853
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1854
|
+
stringsToUint8Array(type === "mdir" ? "mdir" : type === "video" ? "vide" : "soun"),
|
|
1855
|
+
type === "mdir" ? numberTo32BitUIntOrInt(1634758764) : new Uint8Array([0, 0, 0, 0]),
|
|
1856
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1857
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
1858
|
+
stringsToUint8Array(type === "mdir" ? "\0" : type === "video" ? "VideoHandler\0" : "SoundHandler\0")
|
|
1859
|
+
]));
|
|
1860
|
+
};
|
|
1861
|
+
|
|
1862
|
+
// src/create/iso-base-media/serialize-track.ts
|
|
1863
|
+
var serializeTrack = ({
|
|
1864
|
+
track,
|
|
1865
|
+
durationInUnits,
|
|
1866
|
+
samplePositions,
|
|
1867
|
+
timescale
|
|
1868
|
+
}) => {
|
|
1869
|
+
if (track.codec !== "h264" && track.codec !== "aac") {
|
|
1870
|
+
throw new Error("Currently only H.264 and AAC is supported");
|
|
1871
|
+
}
|
|
1872
|
+
return createTrak({
|
|
1873
|
+
tkhd: track.codec === "aac" ? createTkhdForAudio({
|
|
1874
|
+
creationTime: Date.now(),
|
|
1875
|
+
flags: TKHD_FLAGS.TRACK_ENABLED | TKHD_FLAGS.TRACK_IN_MOVIE,
|
|
1876
|
+
modificationTime: Date.now(),
|
|
1877
|
+
duration: durationInUnits,
|
|
1878
|
+
trackId: track.trackNumber,
|
|
1879
|
+
volume: 1,
|
|
1880
|
+
timescale
|
|
1881
|
+
}) : track.type === "video" ? createTkhdForVideo({
|
|
1882
|
+
creationTime: Date.now(),
|
|
1883
|
+
modificationTime: Date.now(),
|
|
1884
|
+
duration: durationInUnits,
|
|
1885
|
+
flags: TKHD_FLAGS.TRACK_ENABLED | TKHD_FLAGS.TRACK_IN_MOVIE,
|
|
1886
|
+
height: track.height,
|
|
1887
|
+
width: track.width,
|
|
1888
|
+
matrix: IDENTITY_MATRIX,
|
|
1889
|
+
trackId: track.trackNumber,
|
|
1890
|
+
volume: 0,
|
|
1891
|
+
timescale
|
|
1892
|
+
}) : new Uint8Array(stringsToUint8Array("wrong")),
|
|
1893
|
+
mdia: createMdia({
|
|
1894
|
+
mdhd: createMdhd({
|
|
1895
|
+
creationTime: null,
|
|
1896
|
+
modificationTime: null,
|
|
1897
|
+
duration: durationInUnits,
|
|
1898
|
+
timescale: track.timescale
|
|
1899
|
+
}),
|
|
1900
|
+
hdlr: track.type === "video" ? createHdlr("video") : createHdlr("audio"),
|
|
1901
|
+
minf: createMinf({
|
|
1902
|
+
stblAtom: createStbl({
|
|
1903
|
+
samplePositions,
|
|
1904
|
+
isVideo: track.type === "video",
|
|
1905
|
+
codecSpecificData: createCodecSpecificData(track)
|
|
1906
|
+
}),
|
|
1907
|
+
vmhdAtom: track.type === "audio" ? createSmhd() : createVmhd()
|
|
1908
|
+
})
|
|
1909
|
+
})
|
|
1910
|
+
});
|
|
1911
|
+
};
|
|
1912
|
+
|
|
1913
|
+
// src/create/iso-base-media/udta/create-meta.ts
|
|
1914
|
+
var createMeta = ({
|
|
1915
|
+
hdlr,
|
|
1916
|
+
ilst
|
|
1917
|
+
}) => {
|
|
1918
|
+
return addSize(combineUint8Arrays([
|
|
1919
|
+
stringsToUint8Array("meta"),
|
|
1920
|
+
new Uint8Array([0]),
|
|
1921
|
+
new Uint8Array([0, 0, 0]),
|
|
1922
|
+
hdlr,
|
|
1923
|
+
ilst
|
|
1924
|
+
]));
|
|
1925
|
+
};
|
|
1926
|
+
|
|
1927
|
+
// src/create/iso-base-media/mp4-header.ts
|
|
1928
|
+
var HEADER_LENGTH = 1024000;
|
|
1929
|
+
var createPaddedMoovAtom = ({
|
|
1930
|
+
durationInUnits,
|
|
1931
|
+
trackInfo,
|
|
1932
|
+
timescale
|
|
1933
|
+
}) => {
|
|
1934
|
+
return padIsoBaseMediaBytes(createMoov({
|
|
1935
|
+
mvhd: createMvhd({
|
|
1936
|
+
timescale,
|
|
1937
|
+
durationInUnits,
|
|
1938
|
+
matrix: IDENTITY_MATRIX,
|
|
1939
|
+
nextTrackId: trackInfo.map((t) => t.track.trackNumber).reduce((a, b) => Math.max(a, b), 0) + 1,
|
|
1940
|
+
rate: 1,
|
|
1941
|
+
volume: 1,
|
|
1942
|
+
creationTime: Date.now(),
|
|
1943
|
+
modificationTime: Date.now()
|
|
1944
|
+
}),
|
|
1945
|
+
traks: trackInfo.map((track) => {
|
|
1946
|
+
return serializeTrack({
|
|
1947
|
+
timescale,
|
|
1948
|
+
track: track.track,
|
|
1949
|
+
durationInUnits,
|
|
1950
|
+
samplePositions: track.samplePositions
|
|
1951
|
+
});
|
|
1952
|
+
}),
|
|
1953
|
+
udta: createUdta(createMeta({
|
|
1954
|
+
hdlr: createHdlr("mdir"),
|
|
1955
|
+
ilst: createIlst([
|
|
1956
|
+
createToo("WebCodecs"),
|
|
1957
|
+
createCmt("Made with @remotion/webcodecs")
|
|
1958
|
+
])
|
|
1959
|
+
}))
|
|
1960
|
+
}), HEADER_LENGTH);
|
|
1961
|
+
};
|
|
1962
|
+
|
|
1963
|
+
// src/create/iso-base-media/create-iso-base-media.ts
|
|
1964
|
+
var createIsoBaseMedia = async ({
|
|
1965
|
+
writer,
|
|
1966
|
+
onBytesProgress,
|
|
1967
|
+
onMillisecondsProgress,
|
|
1968
|
+
logLevel,
|
|
1969
|
+
filename
|
|
1970
|
+
}) => {
|
|
1971
|
+
const header = createIsoBaseMediaFtyp({
|
|
1972
|
+
compatibleBrands: ["isom", "iso2", "avc1", "mp42"],
|
|
1973
|
+
majorBrand: "isom",
|
|
1974
|
+
minorBrand: 512
|
|
1975
|
+
});
|
|
1976
|
+
const w = await writer.createContent({ filename, mimeType: "video/mp4" });
|
|
1977
|
+
await w.write(header);
|
|
1978
|
+
let durationInUnits = 0;
|
|
1979
|
+
const currentTracks = [];
|
|
1980
|
+
const samplePositions = [];
|
|
1981
|
+
const sampleChunkIndices = [];
|
|
1982
|
+
const moovOffset = w.getWrittenByteCount();
|
|
1983
|
+
const getPaddedMoovAtom = () => {
|
|
1984
|
+
return createPaddedMoovAtom({
|
|
1985
|
+
durationInUnits,
|
|
1986
|
+
trackInfo: currentTracks.map((track) => {
|
|
1987
|
+
return {
|
|
1988
|
+
track,
|
|
1989
|
+
durationInUnits,
|
|
1990
|
+
samplePositions: samplePositions[track.trackNumber] ?? [],
|
|
1991
|
+
timescale: track.timescale
|
|
1992
|
+
};
|
|
1993
|
+
}),
|
|
1994
|
+
timescale: 1000
|
|
1995
|
+
});
|
|
1996
|
+
};
|
|
1997
|
+
await w.write(getPaddedMoovAtom());
|
|
1998
|
+
let mdatSize = 8;
|
|
1999
|
+
const mdatSizeOffset = w.getWrittenByteCount();
|
|
2000
|
+
await w.write(combineUint8Arrays([
|
|
2001
|
+
numberTo32BitUIntOrInt(mdatSize),
|
|
2002
|
+
stringsToUint8Array("mdat")
|
|
2003
|
+
]));
|
|
2004
|
+
const updateMdatSize = async () => {
|
|
2005
|
+
await w.updateDataAt(mdatSizeOffset, numberTo32BitUIntOrInt(mdatSize));
|
|
2006
|
+
onBytesProgress(w.getWrittenByteCount());
|
|
2007
|
+
};
|
|
2008
|
+
const operationProm = { current: Promise.resolve() };
|
|
2009
|
+
const updateMoov = async () => {
|
|
2010
|
+
await w.updateDataAt(moovOffset, getPaddedMoovAtom());
|
|
2011
|
+
onBytesProgress(w.getWrittenByteCount());
|
|
2012
|
+
};
|
|
2013
|
+
const updateDuration = (newDuration) => {
|
|
2014
|
+
durationInUnits = newDuration;
|
|
2015
|
+
onMillisecondsProgress(newDuration);
|
|
2016
|
+
};
|
|
2017
|
+
const addCodecPrivateToTrack = ({
|
|
2018
|
+
trackNumber: trackNumber2,
|
|
2019
|
+
codecPrivate: codecPrivate2
|
|
2020
|
+
}) => {
|
|
2021
|
+
currentTracks.forEach((track) => {
|
|
2022
|
+
if (track.trackNumber === trackNumber2) {
|
|
2023
|
+
track.codecPrivate = codecPrivate2;
|
|
2024
|
+
}
|
|
2025
|
+
});
|
|
2026
|
+
};
|
|
2027
|
+
let lastChunkWasVideo = false;
|
|
2028
|
+
const addSample = async ({
|
|
2029
|
+
chunk,
|
|
2030
|
+
trackNumber: trackNumber2,
|
|
2031
|
+
isVideo,
|
|
2032
|
+
timescale,
|
|
2033
|
+
codecPrivate: codecPrivate2
|
|
2034
|
+
}) => {
|
|
2035
|
+
const position = w.getWrittenByteCount();
|
|
2036
|
+
await w.write(chunk.data);
|
|
2037
|
+
mdatSize += chunk.data.length;
|
|
2038
|
+
onBytesProgress(w.getWrittenByteCount());
|
|
2039
|
+
if (codecPrivate2) {
|
|
2040
|
+
addCodecPrivateToTrack({ trackNumber: trackNumber2, codecPrivate: codecPrivate2 });
|
|
2041
|
+
}
|
|
2042
|
+
const newDuration = Math.round((chunk.timestamp + (chunk.duration ?? 0)) / 1000);
|
|
2043
|
+
updateDuration(newDuration);
|
|
2044
|
+
if (!samplePositions[trackNumber2]) {
|
|
2045
|
+
samplePositions[trackNumber2] = [];
|
|
2046
|
+
}
|
|
2047
|
+
if (typeof sampleChunkIndices[trackNumber2] === "undefined") {
|
|
2048
|
+
sampleChunkIndices[trackNumber2] = 0;
|
|
2049
|
+
}
|
|
2050
|
+
if (isVideo && chunk.type === "key") {
|
|
2051
|
+
sampleChunkIndices[trackNumber2]++;
|
|
2052
|
+
} else if (!isVideo && samplePositions[trackNumber2].length % 22 === 0) {
|
|
2053
|
+
sampleChunkIndices[trackNumber2]++;
|
|
2054
|
+
} else if (lastChunkWasVideo !== isVideo) {
|
|
2055
|
+
sampleChunkIndices[trackNumber2]++;
|
|
2056
|
+
}
|
|
2057
|
+
const samplePositionToAdd = {
|
|
2058
|
+
isKeyframe: chunk.type === "key",
|
|
2059
|
+
offset: position,
|
|
2060
|
+
chunk: sampleChunkIndices[trackNumber2],
|
|
2061
|
+
cts: Math.round(chunk.cts / (1e6 / timescale)),
|
|
2062
|
+
dts: Math.round(chunk.dts / (1e6 / timescale)),
|
|
2063
|
+
duration: Math.round((chunk.duration ?? 0) / (1e6 / timescale)),
|
|
2064
|
+
size: chunk.data.length
|
|
2065
|
+
};
|
|
2066
|
+
lastChunkWasVideo = isVideo;
|
|
2067
|
+
samplePositions[trackNumber2].push(samplePositionToAdd);
|
|
2068
|
+
};
|
|
2069
|
+
const addTrack = (track) => {
|
|
2070
|
+
const trackNumber2 = currentTracks.length + 1;
|
|
2071
|
+
currentTracks.push({ ...track, trackNumber: trackNumber2 });
|
|
2072
|
+
return Promise.resolve({ trackNumber: trackNumber2 });
|
|
2073
|
+
};
|
|
2074
|
+
const waitForFinishPromises = [];
|
|
2075
|
+
return {
|
|
2076
|
+
save: () => {
|
|
2077
|
+
return w.save();
|
|
2078
|
+
},
|
|
2079
|
+
remove: async () => {
|
|
2080
|
+
await w.remove();
|
|
2081
|
+
},
|
|
2082
|
+
addSample: ({ chunk, trackNumber: trackNumber2, isVideo, timescale, codecPrivate: codecPrivate2 }) => {
|
|
2083
|
+
operationProm.current = operationProm.current.then(() => {
|
|
2084
|
+
return addSample({
|
|
2085
|
+
chunk,
|
|
2086
|
+
trackNumber: trackNumber2,
|
|
2087
|
+
isVideo,
|
|
2088
|
+
timescale,
|
|
2089
|
+
codecPrivate: codecPrivate2
|
|
2090
|
+
});
|
|
2091
|
+
});
|
|
2092
|
+
return operationProm.current;
|
|
2093
|
+
},
|
|
2094
|
+
addTrack: (track) => {
|
|
2095
|
+
operationProm.current = operationProm.current.then(() => addTrack(track));
|
|
2096
|
+
return operationProm.current;
|
|
2097
|
+
},
|
|
2098
|
+
updateTrackSampleRate: ({ sampleRate, trackNumber: trackNumber2 }) => {
|
|
2099
|
+
currentTracks.forEach((track) => {
|
|
2100
|
+
if (track.trackNumber === trackNumber2) {
|
|
2101
|
+
if (track.type !== "audio") {
|
|
2102
|
+
throw new Error(`Tried to update sample rate of track ${trackNumber2}, but it's not an audio track`);
|
|
2103
|
+
}
|
|
2104
|
+
track.sampleRate = sampleRate;
|
|
2105
|
+
}
|
|
2106
|
+
});
|
|
2107
|
+
},
|
|
2108
|
+
addWaitForFinishPromise: (promise) => {
|
|
2109
|
+
waitForFinishPromises.push(promise);
|
|
2110
|
+
},
|
|
2111
|
+
async waitForFinish() {
|
|
2112
|
+
Log.verbose(logLevel, "All write operations queued. Waiting for finish...");
|
|
2113
|
+
await Promise.all(waitForFinishPromises.map((p) => p()));
|
|
2114
|
+
Log.verbose(logLevel, "Cleanup tasks executed");
|
|
2115
|
+
await operationProm.current;
|
|
2116
|
+
await updateMoov();
|
|
2117
|
+
await updateMdatSize();
|
|
2118
|
+
Log.verbose(logLevel, "All write operations done. Waiting for finish...");
|
|
2119
|
+
await w.waitForFinish();
|
|
2120
|
+
},
|
|
2121
|
+
updateDuration: (duration2) => {
|
|
2122
|
+
operationProm.current = operationProm.current.then(() => updateDuration(duration2));
|
|
2123
|
+
return operationProm.current;
|
|
2124
|
+
}
|
|
2125
|
+
};
|
|
2126
|
+
};
|
|
2127
|
+
|
|
2128
|
+
// src/create/matroska/cluster-segment.ts
|
|
1025
2129
|
var CLUSTER_MIN_VINT_WIDTH = 8;
|
|
1026
2130
|
var createClusterSegment = (timestamp) => {
|
|
1027
2131
|
return makeMatroskaBytes({
|
|
@@ -1062,32 +2166,36 @@ var makeSimpleBlock = ({
|
|
|
1062
2166
|
]);
|
|
1063
2167
|
};
|
|
1064
2168
|
|
|
1065
|
-
// src/create/
|
|
1066
|
-
var CREATE_TIME_SCALE = 1e6;
|
|
1067
|
-
|
|
1068
|
-
// src/create/cluster.ts
|
|
2169
|
+
// src/create/matroska/cluster.ts
|
|
1069
2170
|
var maxClusterTimestamp = 2 ** 15;
|
|
1070
|
-
var timestampToClusterTimestamp = (timestamp) => {
|
|
1071
|
-
return Math.round(timestamp /
|
|
2171
|
+
var timestampToClusterTimestamp = (timestamp, timescale) => {
|
|
2172
|
+
return Math.round(timestamp / timescale * 1000);
|
|
1072
2173
|
};
|
|
1073
2174
|
var canFitInCluster = ({
|
|
1074
2175
|
clusterStartTimestamp,
|
|
1075
|
-
chunk
|
|
2176
|
+
chunk,
|
|
2177
|
+
timescale
|
|
1076
2178
|
}) => {
|
|
1077
|
-
const timecodeRelativeToCluster = timestampToClusterTimestamp(chunk.timestamp) - timestampToClusterTimestamp(clusterStartTimestamp);
|
|
2179
|
+
const timecodeRelativeToCluster = timestampToClusterTimestamp(chunk.timestamp, timescale) - timestampToClusterTimestamp(clusterStartTimestamp, timescale);
|
|
1078
2180
|
if (timecodeRelativeToCluster < 0) {
|
|
1079
2181
|
throw new Error(`timecodeRelativeToCluster is negative`);
|
|
1080
2182
|
}
|
|
1081
2183
|
return timecodeRelativeToCluster <= maxClusterTimestamp;
|
|
1082
2184
|
};
|
|
1083
|
-
var makeCluster = async (
|
|
1084
|
-
|
|
1085
|
-
|
|
2185
|
+
var makeCluster = async ({
|
|
2186
|
+
writer,
|
|
2187
|
+
clusterStartTimestamp,
|
|
2188
|
+
timescale,
|
|
2189
|
+
logLevel
|
|
2190
|
+
}) => {
|
|
2191
|
+
Log.verbose(logLevel, `Making new Matroska cluster with timestamp ${clusterStartTimestamp}`);
|
|
2192
|
+
const cluster = createClusterSegment(timestampToClusterTimestamp(clusterStartTimestamp, timescale));
|
|
2193
|
+
const clusterVIntPosition = writer.getWrittenByteCount() + cluster.offsets.offset + matroskaToHex(matroskaElements.Cluster).byteLength;
|
|
1086
2194
|
let clusterSize = cluster.bytes.byteLength - matroskaToHex(matroskaElements.Cluster).byteLength - CLUSTER_MIN_VINT_WIDTH;
|
|
1087
|
-
await
|
|
2195
|
+
await writer.write(cluster.bytes);
|
|
1088
2196
|
const addSample = async (chunk, trackNumber2) => {
|
|
1089
|
-
const timecodeRelativeToCluster = timestampToClusterTimestamp(chunk.timestamp) - timestampToClusterTimestamp(clusterStartTimestamp);
|
|
1090
|
-
if (!canFitInCluster({ clusterStartTimestamp, chunk })) {
|
|
2197
|
+
const timecodeRelativeToCluster = timestampToClusterTimestamp(chunk.timestamp, timescale) - timestampToClusterTimestamp(clusterStartTimestamp, timescale);
|
|
2198
|
+
if (!canFitInCluster({ clusterStartTimestamp, chunk, timescale })) {
|
|
1091
2199
|
throw new Error(`timecodeRelativeToCluster is too big: ${timecodeRelativeToCluster} > ${maxClusterTimestamp}`);
|
|
1092
2200
|
}
|
|
1093
2201
|
const keyframe = chunk.type === "key";
|
|
@@ -1100,8 +2208,8 @@ var makeCluster = async (w, clusterStartTimestamp) => {
|
|
|
1100
2208
|
timecodeRelativeToCluster
|
|
1101
2209
|
});
|
|
1102
2210
|
clusterSize += simpleBlock2.byteLength;
|
|
1103
|
-
await
|
|
1104
|
-
await
|
|
2211
|
+
await writer.updateDataAt(clusterVIntPosition, getVariableInt(clusterSize, CLUSTER_MIN_VINT_WIDTH));
|
|
2212
|
+
await writer.write(simpleBlock2);
|
|
1105
2213
|
return { timecodeRelativeToCluster };
|
|
1106
2214
|
};
|
|
1107
2215
|
const shouldMakeNewCluster = ({
|
|
@@ -1109,13 +2217,15 @@ var makeCluster = async (w, clusterStartTimestamp) => {
|
|
|
1109
2217
|
chunk,
|
|
1110
2218
|
newT
|
|
1111
2219
|
}) => {
|
|
1112
|
-
const newTimestamp = timestampToClusterTimestamp(newT);
|
|
1113
|
-
const oldTimestamp = timestampToClusterTimestamp(clusterStartTimestamp);
|
|
2220
|
+
const newTimestamp = timestampToClusterTimestamp(newT, timescale);
|
|
2221
|
+
const oldTimestamp = timestampToClusterTimestamp(clusterStartTimestamp, timescale);
|
|
1114
2222
|
const canFit = canFitInCluster({
|
|
1115
2223
|
chunk,
|
|
1116
|
-
clusterStartTimestamp
|
|
2224
|
+
clusterStartTimestamp,
|
|
2225
|
+
timescale
|
|
1117
2226
|
});
|
|
1118
2227
|
if (!canFit) {
|
|
2228
|
+
Log.verbose(logLevel, `Cannot fit ${chunk.timestamp} in cluster ${clusterStartTimestamp}. Creating new cluster`);
|
|
1119
2229
|
return true;
|
|
1120
2230
|
}
|
|
1121
2231
|
const keyframe = chunk.type === "key";
|
|
@@ -1128,7 +2238,7 @@ var makeCluster = async (w, clusterStartTimestamp) => {
|
|
|
1128
2238
|
};
|
|
1129
2239
|
};
|
|
1130
2240
|
|
|
1131
|
-
// src/create/make-duration-with-padding.ts
|
|
2241
|
+
// src/create/matroska/make-duration-with-padding.ts
|
|
1132
2242
|
var makeDurationWithPadding = (newDuration) => {
|
|
1133
2243
|
return makeMatroskaBytes({
|
|
1134
2244
|
type: "Duration",
|
|
@@ -1140,7 +2250,7 @@ var makeDurationWithPadding = (newDuration) => {
|
|
|
1140
2250
|
});
|
|
1141
2251
|
};
|
|
1142
2252
|
|
|
1143
|
-
// src/create/matroska-cues.ts
|
|
2253
|
+
// src/create/matroska/matroska-cues.ts
|
|
1144
2254
|
var createMatroskaCues = (cues) => {
|
|
1145
2255
|
return makeMatroskaBytes({
|
|
1146
2256
|
type: "Cues",
|
|
@@ -1186,7 +2296,7 @@ var createMatroskaCues = (cues) => {
|
|
|
1186
2296
|
});
|
|
1187
2297
|
};
|
|
1188
2298
|
|
|
1189
|
-
// src/create/matroska-header.ts
|
|
2299
|
+
// src/create/matroska/matroska-header.ts
|
|
1190
2300
|
var makeMatroskaHeader = () => {
|
|
1191
2301
|
return makeMatroskaBytes({
|
|
1192
2302
|
type: "Header",
|
|
@@ -1249,7 +2359,7 @@ var makeMatroskaHeader = () => {
|
|
|
1249
2359
|
});
|
|
1250
2360
|
};
|
|
1251
2361
|
|
|
1252
|
-
// src/create/matroska-info.ts
|
|
2362
|
+
// src/create/matroska/matroska-info.ts
|
|
1253
2363
|
var makeMatroskaInfo = ({ timescale }) => {
|
|
1254
2364
|
return makeMatroskaBytes({
|
|
1255
2365
|
type: "Info",
|
|
@@ -1278,7 +2388,7 @@ var makeMatroskaInfo = ({ timescale }) => {
|
|
|
1278
2388
|
});
|
|
1279
2389
|
};
|
|
1280
2390
|
|
|
1281
|
-
// src/create/matroska-seek.ts
|
|
2391
|
+
// src/create/matroska/matroska-seek.ts
|
|
1282
2392
|
var createMatroskaSeekHead = (seeks) => {
|
|
1283
2393
|
return padMatroskaBytes(makeMatroskaBytes({
|
|
1284
2394
|
type: "SeekHead",
|
|
@@ -1307,7 +2417,7 @@ var createMatroskaSeekHead = (seeks) => {
|
|
|
1307
2417
|
}), 200);
|
|
1308
2418
|
};
|
|
1309
2419
|
|
|
1310
|
-
// src/create/matroska-segment.ts
|
|
2420
|
+
// src/create/matroska/matroska-segment.ts
|
|
1311
2421
|
var MATROSKA_SEGMENT_MIN_VINT_WIDTH = 8;
|
|
1312
2422
|
var createMatroskaSegment = (children) => {
|
|
1313
2423
|
return makeMatroskaBytes({
|
|
@@ -1317,11 +2427,6 @@ var createMatroskaSegment = (children) => {
|
|
|
1317
2427
|
});
|
|
1318
2428
|
};
|
|
1319
2429
|
|
|
1320
|
-
// src/truthy.ts
|
|
1321
|
-
function truthy(value) {
|
|
1322
|
-
return Boolean(value);
|
|
1323
|
-
}
|
|
1324
|
-
|
|
1325
2430
|
// src/boxes/webm/traversal.ts
|
|
1326
2431
|
var getMainSegment = (segments) => {
|
|
1327
2432
|
return segments.find((s) => s.type === "Segment");
|
|
@@ -1584,7 +2689,7 @@ var makeMatroskaColorBytes = ({
|
|
|
1584
2689
|
});
|
|
1585
2690
|
};
|
|
1586
2691
|
|
|
1587
|
-
// src/create/matroska-trackentry.ts
|
|
2692
|
+
// src/create/matroska/matroska-trackentry.ts
|
|
1588
2693
|
var makeMatroskaVideoBytes = ({
|
|
1589
2694
|
color: color2,
|
|
1590
2695
|
width,
|
|
@@ -1824,24 +2929,31 @@ var makeMatroskaVideoTrackEntryBytes = ({
|
|
|
1824
2929
|
});
|
|
1825
2930
|
};
|
|
1826
2931
|
var makeMatroskaTracks = (tracks2) => {
|
|
2932
|
+
const bytesArr = tracks2.map((t) => {
|
|
2933
|
+
const bytes = t.type === "video" ? makeMatroskaVideoTrackEntryBytes(t) : makeMatroskaAudioTrackEntryBytes(t);
|
|
2934
|
+
return bytes;
|
|
2935
|
+
});
|
|
1827
2936
|
return padMatroskaBytes(makeMatroskaBytes({
|
|
1828
2937
|
type: "Tracks",
|
|
1829
|
-
value:
|
|
2938
|
+
value: bytesArr,
|
|
1830
2939
|
minVintWidth: null
|
|
1831
2940
|
}), 500);
|
|
1832
2941
|
};
|
|
1833
2942
|
|
|
1834
|
-
// src/create/create-media.ts
|
|
1835
|
-
var
|
|
2943
|
+
// src/create/matroska/create-matroska-media.ts
|
|
2944
|
+
var timescale = 1e6;
|
|
2945
|
+
var createMatroskaMedia = async ({
|
|
1836
2946
|
writer,
|
|
1837
2947
|
onBytesProgress,
|
|
1838
|
-
onMillisecondsProgress
|
|
2948
|
+
onMillisecondsProgress,
|
|
2949
|
+
filename,
|
|
2950
|
+
logLevel
|
|
1839
2951
|
}) => {
|
|
1840
2952
|
const header = makeMatroskaHeader();
|
|
1841
|
-
const w = await writer.createContent();
|
|
2953
|
+
const w = await writer.createContent({ filename, mimeType: "video/webm" });
|
|
1842
2954
|
await w.write(header.bytes);
|
|
1843
2955
|
const matroskaInfo = makeMatroskaInfo({
|
|
1844
|
-
timescale
|
|
2956
|
+
timescale
|
|
1845
2957
|
});
|
|
1846
2958
|
const currentTracks = [];
|
|
1847
2959
|
const seeks = [];
|
|
@@ -1890,7 +3002,12 @@ var createMedia = async ({
|
|
|
1890
3002
|
};
|
|
1891
3003
|
await w.write(matroskaSegment.bytes);
|
|
1892
3004
|
const clusterOffset = w.getWrittenByteCount();
|
|
1893
|
-
let currentCluster = await makeCluster(
|
|
3005
|
+
let currentCluster = await makeCluster({
|
|
3006
|
+
writer: w,
|
|
3007
|
+
clusterStartTimestamp: 0,
|
|
3008
|
+
timescale,
|
|
3009
|
+
logLevel
|
|
3010
|
+
});
|
|
1894
3011
|
seeks.push({
|
|
1895
3012
|
hexString: matroskaElements.Cluster,
|
|
1896
3013
|
byte: clusterOffset - seekHeadOffset
|
|
@@ -1898,9 +3015,14 @@ var createMedia = async ({
|
|
|
1898
3015
|
const trackNumberProgresses = {};
|
|
1899
3016
|
const getClusterOrMakeNew = async ({
|
|
1900
3017
|
chunk,
|
|
1901
|
-
isVideo
|
|
3018
|
+
isVideo,
|
|
3019
|
+
trackNumber: trackNumber2
|
|
1902
3020
|
}) => {
|
|
1903
|
-
const
|
|
3021
|
+
const trackProgressValues = Object.values(trackNumberProgresses);
|
|
3022
|
+
const smallestProgress = trackProgressValues.length === 0 ? 0 : Math.min(...trackProgressValues);
|
|
3023
|
+
if (chunk.type === "key") {
|
|
3024
|
+
trackNumberProgresses[trackNumber2] = chunk.timestamp;
|
|
3025
|
+
}
|
|
1904
3026
|
if (!currentCluster.shouldMakeNewCluster({
|
|
1905
3027
|
newT: smallestProgress,
|
|
1906
3028
|
isVideo,
|
|
@@ -1908,7 +3030,12 @@ var createMedia = async ({
|
|
|
1908
3030
|
})) {
|
|
1909
3031
|
return { cluster: currentCluster, isNew: false, smallestProgress };
|
|
1910
3032
|
}
|
|
1911
|
-
currentCluster = await makeCluster(
|
|
3033
|
+
currentCluster = await makeCluster({
|
|
3034
|
+
writer: w,
|
|
3035
|
+
clusterStartTimestamp: smallestProgress,
|
|
3036
|
+
timescale,
|
|
3037
|
+
logLevel
|
|
3038
|
+
});
|
|
1912
3039
|
return { cluster: currentCluster, isNew: true, smallestProgress };
|
|
1913
3040
|
};
|
|
1914
3041
|
const updateDuration = async (newDuration) => {
|
|
@@ -1916,11 +3043,15 @@ var createMedia = async ({
|
|
|
1916
3043
|
await w.updateDataAt(durationOffset, blocks.bytes);
|
|
1917
3044
|
onBytesProgress(w.getWrittenByteCount());
|
|
1918
3045
|
};
|
|
1919
|
-
const addSample = async (
|
|
1920
|
-
|
|
3046
|
+
const addSample = async ({
|
|
3047
|
+
chunk,
|
|
3048
|
+
trackNumber: trackNumber2,
|
|
3049
|
+
isVideo
|
|
3050
|
+
}) => {
|
|
1921
3051
|
const { cluster, isNew, smallestProgress } = await getClusterOrMakeNew({
|
|
1922
3052
|
chunk,
|
|
1923
|
-
isVideo
|
|
3053
|
+
isVideo,
|
|
3054
|
+
trackNumber: trackNumber2
|
|
1924
3055
|
});
|
|
1925
3056
|
const newDuration = Math.round((chunk.timestamp + (chunk.duration ?? 0)) / 1000);
|
|
1926
3057
|
await updateDuration(newDuration);
|
|
@@ -1928,7 +3059,7 @@ var createMedia = async ({
|
|
|
1928
3059
|
if (isNew) {
|
|
1929
3060
|
const newCluster = w.getWrittenByteCount();
|
|
1930
3061
|
cues.push({
|
|
1931
|
-
time: timestampToClusterTimestamp(smallestProgress) + timecodeRelativeToCluster,
|
|
3062
|
+
time: timestampToClusterTimestamp(smallestProgress, timescale) + timecodeRelativeToCluster,
|
|
1932
3063
|
clusterPosition: newCluster - seekHeadOffset,
|
|
1933
3064
|
trackNumber: trackNumber2
|
|
1934
3065
|
});
|
|
@@ -1944,79 +3075,53 @@ var createMedia = async ({
|
|
|
1944
3075
|
const operationProm = { current: Promise.resolve() };
|
|
1945
3076
|
const waitForFinishPromises = [];
|
|
1946
3077
|
return {
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
3078
|
+
updateTrackSampleRate: ({ sampleRate, trackNumber: trackNumber2 }) => {
|
|
3079
|
+
currentTracks.forEach((track) => {
|
|
3080
|
+
if (track.trackNumber === trackNumber2) {
|
|
3081
|
+
if (track.type !== "audio") {
|
|
3082
|
+
throw new Error("track is not audio");
|
|
3083
|
+
}
|
|
3084
|
+
track.sampleRate = sampleRate;
|
|
3085
|
+
}
|
|
3086
|
+
});
|
|
3087
|
+
},
|
|
3088
|
+
save: () => {
|
|
3089
|
+
return w.save();
|
|
1950
3090
|
},
|
|
1951
3091
|
remove: async () => {
|
|
1952
3092
|
await w.remove();
|
|
1953
3093
|
},
|
|
1954
|
-
addSample: (chunk, trackNumber2, isVideo) => {
|
|
1955
|
-
operationProm.current = operationProm.current.then(() => addSample(chunk, trackNumber2, isVideo));
|
|
3094
|
+
addSample: ({ chunk, trackNumber: trackNumber2, isVideo }) => {
|
|
3095
|
+
operationProm.current = operationProm.current.then(() => addSample({ chunk, trackNumber: trackNumber2, isVideo }));
|
|
1956
3096
|
return operationProm.current;
|
|
1957
3097
|
},
|
|
1958
3098
|
updateDuration: (duration2) => {
|
|
1959
3099
|
operationProm.current = operationProm.current.then(() => updateDuration(duration2));
|
|
1960
3100
|
return operationProm.current;
|
|
1961
|
-
},
|
|
1962
|
-
addTrack: (track) => {
|
|
1963
|
-
const trackNumber2 = currentTracks.length + 1;
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
await
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
await
|
|
1980
|
-
await w.
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
await updateSegmentSize(segmentSize);
|
|
1984
|
-
}
|
|
1985
|
-
};
|
|
1986
|
-
};
|
|
1987
|
-
|
|
1988
|
-
// src/log.ts
|
|
1989
|
-
var logLevels = ["trace", "verbose", "info", "warn", "error"];
|
|
1990
|
-
var getNumberForLogLevel = (level) => {
|
|
1991
|
-
return logLevels.indexOf(level);
|
|
1992
|
-
};
|
|
1993
|
-
var isEqualOrBelowLogLevel = (currentLevel, level) => {
|
|
1994
|
-
return getNumberForLogLevel(currentLevel) <= getNumberForLogLevel(level);
|
|
1995
|
-
};
|
|
1996
|
-
var Log = {
|
|
1997
|
-
trace: (logLevel, ...args) => {
|
|
1998
|
-
if (isEqualOrBelowLogLevel(logLevel, "trace")) {
|
|
1999
|
-
return console.log(...args);
|
|
2000
|
-
}
|
|
2001
|
-
},
|
|
2002
|
-
verbose: (logLevel, ...args) => {
|
|
2003
|
-
if (isEqualOrBelowLogLevel(logLevel, "verbose")) {
|
|
2004
|
-
return console.log(...args);
|
|
2005
|
-
}
|
|
2006
|
-
},
|
|
2007
|
-
info: (logLevel, ...args) => {
|
|
2008
|
-
if (isEqualOrBelowLogLevel(logLevel, "info")) {
|
|
2009
|
-
return console.log(...args);
|
|
2010
|
-
}
|
|
2011
|
-
},
|
|
2012
|
-
warn: (logLevel, ...args) => {
|
|
2013
|
-
if (isEqualOrBelowLogLevel(logLevel, "warn")) {
|
|
2014
|
-
return console.warn(...args);
|
|
3101
|
+
},
|
|
3102
|
+
addTrack: (track) => {
|
|
3103
|
+
const trackNumber2 = currentTracks.length + 1;
|
|
3104
|
+
operationProm.current = operationProm.current.then(() => addTrack({ ...track, trackNumber: trackNumber2 }));
|
|
3105
|
+
trackNumbers.push(trackNumber2);
|
|
3106
|
+
return operationProm.current.then(() => ({ trackNumber: trackNumber2 }));
|
|
3107
|
+
},
|
|
3108
|
+
addWaitForFinishPromise: (promise) => {
|
|
3109
|
+
waitForFinishPromises.push(promise);
|
|
3110
|
+
},
|
|
3111
|
+
async waitForFinish() {
|
|
3112
|
+
await Promise.all(waitForFinishPromises.map((p) => p()));
|
|
3113
|
+
await operationProm.current;
|
|
3114
|
+
seeks.push({
|
|
3115
|
+
hexString: matroskaElements.Cues,
|
|
3116
|
+
byte: w.getWrittenByteCount() - seekHeadOffset
|
|
3117
|
+
});
|
|
3118
|
+
await updateSeekWrite();
|
|
3119
|
+
await w.write(createMatroskaCues(cues).bytes);
|
|
3120
|
+
await w.waitForFinish();
|
|
3121
|
+
const segmentSize = w.getWrittenByteCount() - segmentOffset - matroskaToHex(matroskaElements.Segment).byteLength - MATROSKA_SEGMENT_MIN_VINT_WIDTH;
|
|
3122
|
+
await updateSegmentSize(segmentSize);
|
|
2015
3123
|
}
|
|
2016
|
-
}
|
|
2017
|
-
error: (...args) => {
|
|
2018
|
-
return console.error(...args);
|
|
2019
|
-
}
|
|
3124
|
+
};
|
|
2020
3125
|
};
|
|
2021
3126
|
|
|
2022
3127
|
// src/boxes/iso-base-media/traversal.ts
|
|
@@ -2053,135 +3158,373 @@ var getMdiaBox = (trakBox) => {
|
|
|
2053
3158
|
if (!mdiaBox || mdiaBox.type !== "regular-box") {
|
|
2054
3159
|
return null;
|
|
2055
3160
|
}
|
|
2056
|
-
return mdiaBox;
|
|
3161
|
+
return mdiaBox;
|
|
3162
|
+
};
|
|
3163
|
+
var getMdhdBox = (trakBox) => {
|
|
3164
|
+
const mdiaBox = getMdiaBox(trakBox);
|
|
3165
|
+
if (!mdiaBox) {
|
|
3166
|
+
return null;
|
|
3167
|
+
}
|
|
3168
|
+
const mdhdBox = mdiaBox.children.find((c) => c.type === "mdhd-box");
|
|
3169
|
+
return mdhdBox;
|
|
3170
|
+
};
|
|
3171
|
+
var getStblBox = (trakBox) => {
|
|
3172
|
+
const mdiaBox = getMdiaBox(trakBox);
|
|
3173
|
+
if (!mdiaBox) {
|
|
3174
|
+
return null;
|
|
3175
|
+
}
|
|
3176
|
+
const minfBox = mdiaBox.children.find((s) => s.type === "regular-box" && s.boxType === "minf");
|
|
3177
|
+
if (!minfBox || minfBox.type !== "regular-box") {
|
|
3178
|
+
return null;
|
|
3179
|
+
}
|
|
3180
|
+
const stblBox = minfBox.children.find((s) => s.type === "regular-box" && s.boxType === "stbl");
|
|
3181
|
+
if (!stblBox || stblBox.type !== "regular-box") {
|
|
3182
|
+
return null;
|
|
3183
|
+
}
|
|
3184
|
+
return stblBox;
|
|
3185
|
+
};
|
|
3186
|
+
var getStsdBox = (trakBox) => {
|
|
3187
|
+
const stblBox = getStblBox(trakBox);
|
|
3188
|
+
if (!stblBox || stblBox.type !== "regular-box") {
|
|
3189
|
+
return null;
|
|
3190
|
+
}
|
|
3191
|
+
const stsdBox = stblBox.children.find((s) => s.type === "stsd-box");
|
|
3192
|
+
return stsdBox;
|
|
3193
|
+
};
|
|
3194
|
+
var getVideoDescriptors = (trakBox) => {
|
|
3195
|
+
const stsdBox = getStsdBox(trakBox);
|
|
3196
|
+
if (!stsdBox) {
|
|
3197
|
+
return null;
|
|
3198
|
+
}
|
|
3199
|
+
const descriptors = stsdBox.samples.map((s) => {
|
|
3200
|
+
return s.type === "video" ? s.descriptors.map((d) => {
|
|
3201
|
+
return d.type === "avcc-box" ? d.privateData : d.type === "hvcc-box" ? d.privateData : null;
|
|
3202
|
+
}) : [];
|
|
3203
|
+
});
|
|
3204
|
+
return descriptors.flat(1).filter(Boolean)[0] ?? null;
|
|
3205
|
+
};
|
|
3206
|
+
var getStcoBox = (trakBox) => {
|
|
3207
|
+
const stblBox = getStblBox(trakBox);
|
|
3208
|
+
if (!stblBox || stblBox.type !== "regular-box") {
|
|
3209
|
+
return null;
|
|
3210
|
+
}
|
|
3211
|
+
const stcoBox = stblBox.children.find((s) => s.type === "stco-box");
|
|
3212
|
+
return stcoBox;
|
|
3213
|
+
};
|
|
3214
|
+
var getSttsBox = (trakBox) => {
|
|
3215
|
+
const stblBox = getStblBox(trakBox);
|
|
3216
|
+
if (!stblBox || stblBox.type !== "regular-box") {
|
|
3217
|
+
return null;
|
|
3218
|
+
}
|
|
3219
|
+
const sttsBox = stblBox.children.find((s) => s.type === "stts-box");
|
|
3220
|
+
return sttsBox;
|
|
3221
|
+
};
|
|
3222
|
+
var getCttsBox = (trakBox) => {
|
|
3223
|
+
const stblBox = getStblBox(trakBox);
|
|
3224
|
+
if (!stblBox || stblBox.type !== "regular-box") {
|
|
3225
|
+
return null;
|
|
3226
|
+
}
|
|
3227
|
+
const cttsBox = stblBox.children.find((s) => s.type === "ctts-box");
|
|
3228
|
+
return cttsBox;
|
|
3229
|
+
};
|
|
3230
|
+
var getStszBox = (trakBox) => {
|
|
3231
|
+
const stblBox = getStblBox(trakBox);
|
|
3232
|
+
if (!stblBox || stblBox.type !== "regular-box") {
|
|
3233
|
+
return null;
|
|
3234
|
+
}
|
|
3235
|
+
const stszBox = stblBox.children.find((s) => s.type === "stsz-box");
|
|
3236
|
+
return stszBox;
|
|
3237
|
+
};
|
|
3238
|
+
var getStscBox = (trakBox) => {
|
|
3239
|
+
const stblBox = getStblBox(trakBox);
|
|
3240
|
+
if (!stblBox || stblBox.type !== "regular-box") {
|
|
3241
|
+
return null;
|
|
3242
|
+
}
|
|
3243
|
+
const stcoBox = stblBox.children.find((b) => b.type === "stsc-box");
|
|
3244
|
+
return stcoBox;
|
|
3245
|
+
};
|
|
3246
|
+
var getStssBox = (trakBox) => {
|
|
3247
|
+
const stblBox = getStblBox(trakBox);
|
|
3248
|
+
if (!stblBox || stblBox.type !== "regular-box") {
|
|
3249
|
+
return null;
|
|
3250
|
+
}
|
|
3251
|
+
const stssBox = stblBox.children.find((b) => b.type === "stss-box");
|
|
3252
|
+
return stssBox;
|
|
3253
|
+
};
|
|
3254
|
+
var getTfdtBox = (segment) => {
|
|
3255
|
+
if (segment.type !== "regular-box" || segment.boxType !== "traf") {
|
|
3256
|
+
throw new Error("Expected traf-box");
|
|
3257
|
+
}
|
|
3258
|
+
const tfhdBox = segment.children.find((c) => c.type === "tfdt-box");
|
|
3259
|
+
if (!tfhdBox || tfhdBox.type !== "tfdt-box") {
|
|
3260
|
+
throw new Error("Expected tfhd-box");
|
|
3261
|
+
}
|
|
3262
|
+
return tfhdBox;
|
|
3263
|
+
};
|
|
3264
|
+
var getTfhdBox = (segment) => {
|
|
3265
|
+
if (segment.type !== "regular-box" || segment.boxType !== "traf") {
|
|
3266
|
+
throw new Error("Expected traf-box");
|
|
3267
|
+
}
|
|
3268
|
+
const tfhdBox = segment.children.find((c) => c.type === "tfhd-box");
|
|
3269
|
+
if (!tfhdBox || tfhdBox.type !== "tfhd-box") {
|
|
3270
|
+
throw new Error("Expected tfhd-box");
|
|
3271
|
+
}
|
|
3272
|
+
return tfhdBox;
|
|
3273
|
+
};
|
|
3274
|
+
var getTrunBoxes = (segment) => {
|
|
3275
|
+
if (segment.type !== "regular-box" || segment.boxType !== "traf") {
|
|
3276
|
+
throw new Error("Expected traf-box");
|
|
3277
|
+
}
|
|
3278
|
+
const trunBoxes = segment.children.filter((c) => c.type === "trun-box");
|
|
3279
|
+
return trunBoxes;
|
|
3280
|
+
};
|
|
3281
|
+
var getMdatBox = (anySegment) => {
|
|
3282
|
+
const mdat = anySegment.find((b) => b.type === "mdat-box");
|
|
3283
|
+
if (!mdat) {
|
|
3284
|
+
return null;
|
|
3285
|
+
}
|
|
3286
|
+
if (mdat.type !== "mdat-box") {
|
|
3287
|
+
throw new Error("Expected mdat-box");
|
|
3288
|
+
}
|
|
3289
|
+
return mdat;
|
|
3290
|
+
};
|
|
3291
|
+
|
|
3292
|
+
// src/get-sample-positions.ts
|
|
3293
|
+
var getSamplePositions = ({
|
|
3294
|
+
stcoBox,
|
|
3295
|
+
stszBox,
|
|
3296
|
+
stscBox,
|
|
3297
|
+
stssBox,
|
|
3298
|
+
sttsBox,
|
|
3299
|
+
cttsBox
|
|
3300
|
+
}) => {
|
|
3301
|
+
const sttsDeltas = [];
|
|
3302
|
+
for (const distribution of sttsBox.sampleDistribution) {
|
|
3303
|
+
for (let i = 0;i < distribution.sampleCount; i++) {
|
|
3304
|
+
sttsDeltas.push(distribution.sampleDelta);
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
const cttsEntries = [];
|
|
3308
|
+
for (const entry of cttsBox?.entries ?? [
|
|
3309
|
+
{ sampleCount: sttsDeltas.length, sampleOffset: 0 }
|
|
3310
|
+
]) {
|
|
3311
|
+
for (let i = 0;i < entry.sampleCount; i++) {
|
|
3312
|
+
cttsEntries.push(entry.sampleOffset);
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
let dts = 0;
|
|
3316
|
+
const chunks = stcoBox.entries;
|
|
3317
|
+
const samples = [];
|
|
3318
|
+
let samplesPerChunk = 1;
|
|
3319
|
+
for (let i = 0;i < chunks.length; i++) {
|
|
3320
|
+
const hasEntry = stscBox.entries.find((entry) => entry.firstChunk === i + 1);
|
|
3321
|
+
if (hasEntry) {
|
|
3322
|
+
samplesPerChunk = hasEntry.samplesPerChunk;
|
|
3323
|
+
}
|
|
3324
|
+
let offsetInThisChunk = 0;
|
|
3325
|
+
for (let j = 0;j < samplesPerChunk; j++) {
|
|
3326
|
+
const size = stszBox.countType === "fixed" ? stszBox.sampleSize : stszBox.entries[samples.length];
|
|
3327
|
+
const isKeyframe = stssBox ? stssBox.sampleNumber.includes(samples.length + 1) : true;
|
|
3328
|
+
const delta = sttsDeltas[samples.length];
|
|
3329
|
+
const ctsOffset = cttsEntries[samples.length];
|
|
3330
|
+
const cts = dts + ctsOffset;
|
|
3331
|
+
samples.push({
|
|
3332
|
+
offset: Number(chunks[i]) + offsetInThisChunk,
|
|
3333
|
+
size,
|
|
3334
|
+
isKeyframe,
|
|
3335
|
+
dts,
|
|
3336
|
+
cts,
|
|
3337
|
+
duration: delta,
|
|
3338
|
+
chunk: i
|
|
3339
|
+
});
|
|
3340
|
+
dts += delta;
|
|
3341
|
+
offsetInThisChunk += size;
|
|
3342
|
+
}
|
|
3343
|
+
}
|
|
3344
|
+
return samples;
|
|
3345
|
+
};
|
|
3346
|
+
|
|
3347
|
+
// src/samples-from-moof.ts
|
|
3348
|
+
var getSamplesFromTraf = (trafSegment, moofOffset) => {
|
|
3349
|
+
if (trafSegment.type !== "regular-box" || trafSegment.boxType !== "traf") {
|
|
3350
|
+
throw new Error("Expected traf-box");
|
|
3351
|
+
}
|
|
3352
|
+
const tfhdBox = getTfhdBox(trafSegment);
|
|
3353
|
+
const defaultSampleDuration = tfhdBox?.defaultSampleDuration ?? null;
|
|
3354
|
+
const defaultSampleSize = tfhdBox?.defaultSampleSize ?? null;
|
|
3355
|
+
const defaultSampleFlags = tfhdBox?.defaultSampleFlags ?? null;
|
|
3356
|
+
const tfdtBox = getTfdtBox(trafSegment);
|
|
3357
|
+
const trunBoxes = getTrunBoxes(trafSegment);
|
|
3358
|
+
let time = 0;
|
|
3359
|
+
let offset = 0;
|
|
3360
|
+
let dataOffset = 0;
|
|
3361
|
+
const samples = [];
|
|
3362
|
+
for (const trunBox of trunBoxes) {
|
|
3363
|
+
let i = -1;
|
|
3364
|
+
if (trunBox.dataOffset) {
|
|
3365
|
+
dataOffset = trunBox.dataOffset;
|
|
3366
|
+
offset = 0;
|
|
3367
|
+
}
|
|
3368
|
+
for (const sample of trunBox.samples) {
|
|
3369
|
+
i++;
|
|
3370
|
+
const duration2 = sample.sampleDuration ?? defaultSampleDuration;
|
|
3371
|
+
if (duration2 === null) {
|
|
3372
|
+
throw new Error("Expected duration");
|
|
3373
|
+
}
|
|
3374
|
+
const size = sample.sampleSize ?? defaultSampleSize;
|
|
3375
|
+
if (size === null) {
|
|
3376
|
+
throw new Error("Expected size");
|
|
3377
|
+
}
|
|
3378
|
+
const isFirstSample = i === 0;
|
|
3379
|
+
const sampleFlags = sample.sampleFlags ? sample.sampleFlags : isFirstSample && trunBox.firstSampleFlags !== null ? trunBox.firstSampleFlags : defaultSampleFlags;
|
|
3380
|
+
if (sampleFlags === null) {
|
|
3381
|
+
throw new Error("Expected sample flags");
|
|
3382
|
+
}
|
|
3383
|
+
const keyframe = !(sampleFlags >> 16 & 1);
|
|
3384
|
+
const dts = time + (tfdtBox?.baseMediaDecodeTime ?? 0);
|
|
3385
|
+
const samplePosition = {
|
|
3386
|
+
offset: offset + (moofOffset ?? 0) + (dataOffset ?? 0),
|
|
3387
|
+
dts,
|
|
3388
|
+
cts: dts,
|
|
3389
|
+
duration: duration2,
|
|
3390
|
+
isKeyframe: keyframe,
|
|
3391
|
+
size,
|
|
3392
|
+
chunk: 0
|
|
3393
|
+
};
|
|
3394
|
+
samples.push(samplePosition);
|
|
3395
|
+
offset += size;
|
|
3396
|
+
time += duration2;
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3399
|
+
return samples;
|
|
2057
3400
|
};
|
|
2058
|
-
var
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
3401
|
+
var getSamplesFromMoof = ({
|
|
3402
|
+
moofBox,
|
|
3403
|
+
trackId
|
|
3404
|
+
}) => {
|
|
3405
|
+
if (moofBox.type !== "regular-box") {
|
|
3406
|
+
throw new Error("Expected moof-box");
|
|
2062
3407
|
}
|
|
2063
|
-
const
|
|
2064
|
-
|
|
3408
|
+
const trafs = moofBox.children.filter((c) => c.type === "regular-box" && c.boxType === "traf");
|
|
3409
|
+
const mapped = trafs.map((traf) => {
|
|
3410
|
+
const tfhdBox = getTfhdBox(traf);
|
|
3411
|
+
return tfhdBox?.trackId === trackId ? getSamplesFromTraf(traf, moofBox.offset) : [];
|
|
3412
|
+
});
|
|
3413
|
+
return mapped.flat(1);
|
|
2065
3414
|
};
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
3415
|
+
|
|
3416
|
+
// src/boxes/iso-base-media/get-sample-positions-from-track.ts
|
|
3417
|
+
var getSamplePositionsFromTrack = (trakBox, moofBox) => {
|
|
3418
|
+
const stszBox = getStszBox(trakBox);
|
|
3419
|
+
const stcoBox = getStcoBox(trakBox);
|
|
3420
|
+
const stscBox = getStscBox(trakBox);
|
|
3421
|
+
const stssBox = getStssBox(trakBox);
|
|
3422
|
+
const sttsBox = getSttsBox(trakBox);
|
|
3423
|
+
const tkhdBox = getTkhdBox(trakBox);
|
|
3424
|
+
const cttsBox = getCttsBox(trakBox);
|
|
3425
|
+
const timescaleAndDuration = getTimescaleAndDuration(trakBox);
|
|
3426
|
+
if (!tkhdBox) {
|
|
3427
|
+
throw new Error("Expected tkhd box in trak box");
|
|
2070
3428
|
}
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
return null;
|
|
3429
|
+
if (!stszBox) {
|
|
3430
|
+
throw new Error("Expected stsz box in trak box");
|
|
2074
3431
|
}
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
return null;
|
|
3432
|
+
if (!stcoBox) {
|
|
3433
|
+
throw new Error("Expected stco box in trak box");
|
|
2078
3434
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
var getStsdBox = (trakBox) => {
|
|
2082
|
-
const stblBox = getStblBox(trakBox);
|
|
2083
|
-
if (!stblBox || stblBox.type !== "regular-box") {
|
|
2084
|
-
return null;
|
|
3435
|
+
if (!stscBox) {
|
|
3436
|
+
throw new Error("Expected stsc box in trak box");
|
|
2085
3437
|
}
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
};
|
|
2089
|
-
var getVideoDescriptors = (trakBox) => {
|
|
2090
|
-
const stsdBox = getStsdBox(trakBox);
|
|
2091
|
-
if (!stsdBox) {
|
|
2092
|
-
return null;
|
|
3438
|
+
if (!sttsBox) {
|
|
3439
|
+
throw new Error("Expected stts box in trak box");
|
|
2093
3440
|
}
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
3441
|
+
if (!timescaleAndDuration) {
|
|
3442
|
+
throw new Error("Expected timescale and duration in trak box");
|
|
3443
|
+
}
|
|
3444
|
+
let samplePositions = getSamplePositions({
|
|
3445
|
+
stcoBox,
|
|
3446
|
+
stscBox,
|
|
3447
|
+
stszBox,
|
|
3448
|
+
stssBox,
|
|
3449
|
+
sttsBox,
|
|
3450
|
+
cttsBox
|
|
2098
3451
|
});
|
|
2099
|
-
|
|
2100
|
-
};
|
|
2101
|
-
var getStcoBox = (trakBox) => {
|
|
2102
|
-
const stblBox = getStblBox(trakBox);
|
|
2103
|
-
if (!stblBox || stblBox.type !== "regular-box") {
|
|
2104
|
-
return null;
|
|
3452
|
+
if (samplePositions.length === 0 && moofBox) {
|
|
3453
|
+
samplePositions = getSamplesFromMoof({ moofBox, trackId: tkhdBox.trackId });
|
|
2105
3454
|
}
|
|
2106
|
-
|
|
2107
|
-
return stcoBox;
|
|
3455
|
+
return samplePositions;
|
|
2108
3456
|
};
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
3457
|
+
|
|
3458
|
+
// src/get-duration.ts
|
|
3459
|
+
var getDurationFromMatroska = (segments) => {
|
|
3460
|
+
const mainSegment = segments.find((s) => s.type === "Segment");
|
|
3461
|
+
if (!mainSegment || mainSegment.type !== "Segment") {
|
|
2112
3462
|
return null;
|
|
2113
3463
|
}
|
|
2114
|
-
const
|
|
2115
|
-
|
|
2116
|
-
};
|
|
2117
|
-
var getCttsBox = (trakBox) => {
|
|
2118
|
-
const stblBox = getStblBox(trakBox);
|
|
2119
|
-
if (!stblBox || stblBox.type !== "regular-box") {
|
|
3464
|
+
const { value: children } = mainSegment;
|
|
3465
|
+
if (!children) {
|
|
2120
3466
|
return null;
|
|
2121
3467
|
}
|
|
2122
|
-
const
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
3468
|
+
const infoSegment = children.find((s) => s.type === "Info");
|
|
3469
|
+
const relevantBoxes = [
|
|
3470
|
+
...mainSegment.value,
|
|
3471
|
+
...infoSegment && infoSegment.type === "Info" ? infoSegment.value : []
|
|
3472
|
+
];
|
|
3473
|
+
const timestampScale2 = relevantBoxes.find((s) => s.type === "TimestampScale");
|
|
3474
|
+
if (!timestampScale2 || timestampScale2.type !== "TimestampScale") {
|
|
2128
3475
|
return null;
|
|
2129
3476
|
}
|
|
2130
|
-
const
|
|
2131
|
-
|
|
2132
|
-
};
|
|
2133
|
-
var getStscBox = (trakBox) => {
|
|
2134
|
-
const stblBox = getStblBox(trakBox);
|
|
2135
|
-
if (!stblBox || stblBox.type !== "regular-box") {
|
|
3477
|
+
const duration2 = relevantBoxes.find((s) => s.type === "Duration");
|
|
3478
|
+
if (!duration2 || duration2.type !== "Duration") {
|
|
2136
3479
|
return null;
|
|
2137
3480
|
}
|
|
2138
|
-
|
|
2139
|
-
return stcoBox;
|
|
3481
|
+
return duration2.value.value / timestampScale2.value.value * 1000;
|
|
2140
3482
|
};
|
|
2141
|
-
var
|
|
2142
|
-
const
|
|
2143
|
-
|
|
2144
|
-
return null;
|
|
2145
|
-
}
|
|
2146
|
-
const stssBox = stblBox.children.find((b) => b.type === "stss-box");
|
|
2147
|
-
return stssBox;
|
|
3483
|
+
var isMatroska = (boxes) => {
|
|
3484
|
+
const matroskaBox = boxes.find((b) => b.type === "Segment");
|
|
3485
|
+
return matroskaBox;
|
|
2148
3486
|
};
|
|
2149
|
-
var
|
|
2150
|
-
if (
|
|
2151
|
-
|
|
3487
|
+
var getDuration = (boxes, parserState) => {
|
|
3488
|
+
if (isMatroska(boxes)) {
|
|
3489
|
+
return getDurationFromMatroska(boxes);
|
|
2152
3490
|
}
|
|
2153
|
-
const
|
|
2154
|
-
if (!
|
|
2155
|
-
|
|
3491
|
+
const moovBox = getMoovBox(boxes);
|
|
3492
|
+
if (!moovBox) {
|
|
3493
|
+
return null;
|
|
2156
3494
|
}
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
throw new Error("Expected traf-box");
|
|
3495
|
+
const moofBox = getMoofBox(boxes);
|
|
3496
|
+
const mvhdBox = getMvhdBox(moovBox);
|
|
3497
|
+
if (!mvhdBox) {
|
|
3498
|
+
return null;
|
|
2162
3499
|
}
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
throw new Error("Expected tfhd-box");
|
|
3500
|
+
if (mvhdBox.type !== "mvhd-box") {
|
|
3501
|
+
throw new Error("Expected mvhd-box");
|
|
2166
3502
|
}
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
var getTrunBoxes = (segment) => {
|
|
2170
|
-
if (segment.type !== "regular-box" || segment.boxType !== "traf") {
|
|
2171
|
-
throw new Error("Expected traf-box");
|
|
3503
|
+
if (mvhdBox.durationInSeconds > 0) {
|
|
3504
|
+
return mvhdBox.durationInSeconds;
|
|
2172
3505
|
}
|
|
2173
|
-
const
|
|
2174
|
-
|
|
3506
|
+
const tracks2 = getTracks(boxes, parserState);
|
|
3507
|
+
const allTracks = [
|
|
3508
|
+
...tracks2.videoTracks,
|
|
3509
|
+
...tracks2.audioTracks,
|
|
3510
|
+
...tracks2.otherTracks
|
|
3511
|
+
];
|
|
3512
|
+
const allSamples = allTracks.map((t) => {
|
|
3513
|
+
const { timescale: ts } = t;
|
|
3514
|
+
const samplePositions = getSamplePositionsFromTrack(t.trakBox, moofBox);
|
|
3515
|
+
const highest = samplePositions?.map((sp) => (sp.cts + sp.duration) / ts).reduce((a, b) => Math.max(a, b), 0);
|
|
3516
|
+
return highest ?? 0;
|
|
3517
|
+
});
|
|
3518
|
+
const highestTimestamp = Math.max(...allSamples);
|
|
3519
|
+
return highestTimestamp;
|
|
2175
3520
|
};
|
|
2176
|
-
var
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
return null;
|
|
2180
|
-
}
|
|
2181
|
-
|
|
2182
|
-
throw new Error("Expected mdat-box");
|
|
3521
|
+
var hasDuration = (boxes, parserState) => {
|
|
3522
|
+
try {
|
|
3523
|
+
const duration2 = getDuration(boxes, parserState);
|
|
3524
|
+
return getDuration(boxes, parserState) !== null && duration2 !== 0;
|
|
3525
|
+
} catch {
|
|
3526
|
+
return false;
|
|
2183
3527
|
}
|
|
2184
|
-
return mdat;
|
|
2185
3528
|
};
|
|
2186
3529
|
|
|
2187
3530
|
// src/get-fps.ts
|
|
@@ -2227,21 +3570,12 @@ var getTimescaleAndDuration = (trakBox) => {
|
|
|
2227
3570
|
}
|
|
2228
3571
|
return null;
|
|
2229
3572
|
};
|
|
2230
|
-
var
|
|
2231
|
-
const
|
|
2232
|
-
if (!moovBox) {
|
|
2233
|
-
return null;
|
|
2234
|
-
}
|
|
2235
|
-
const trackBoxes = getTraks(moovBox);
|
|
2236
|
-
const trackBox = trackBoxes.find(trakBoxContainsVideo);
|
|
2237
|
-
if (!trackBox) {
|
|
2238
|
-
return null;
|
|
2239
|
-
}
|
|
2240
|
-
const timescaleAndDuration = getTimescaleAndDuration(trackBox);
|
|
3573
|
+
var getFpsFromMp4TrakBox = (trakBox) => {
|
|
3574
|
+
const timescaleAndDuration = getTimescaleAndDuration(trakBox);
|
|
2241
3575
|
if (!timescaleAndDuration) {
|
|
2242
3576
|
return null;
|
|
2243
3577
|
}
|
|
2244
|
-
const sttsBox = getSttsBox(
|
|
3578
|
+
const sttsBox = getSttsBox(trakBox);
|
|
2245
3579
|
if (!sttsBox) {
|
|
2246
3580
|
return null;
|
|
2247
3581
|
}
|
|
@@ -2251,8 +3585,23 @@ var getFps = (segments) => {
|
|
|
2251
3585
|
durationInSamples: timescaleAndDuration.duration
|
|
2252
3586
|
});
|
|
2253
3587
|
};
|
|
3588
|
+
var getFps = (segments) => {
|
|
3589
|
+
const moovBox = getMoovBox(segments);
|
|
3590
|
+
if (!moovBox) {
|
|
3591
|
+
return null;
|
|
3592
|
+
}
|
|
3593
|
+
const trackBoxes = getTraks(moovBox);
|
|
3594
|
+
const trackBox = trackBoxes.find(trakBoxContainsVideo);
|
|
3595
|
+
if (!trackBox) {
|
|
3596
|
+
return null;
|
|
3597
|
+
}
|
|
3598
|
+
return getFpsFromMp4TrakBox(trackBox);
|
|
3599
|
+
};
|
|
2254
3600
|
var hasFps = (boxes) => {
|
|
2255
3601
|
try {
|
|
3602
|
+
if (isMatroska(boxes)) {
|
|
3603
|
+
return true;
|
|
3604
|
+
}
|
|
2256
3605
|
return getFps(boxes) !== null;
|
|
2257
3606
|
} catch {
|
|
2258
3607
|
return false;
|
|
@@ -2275,12 +3624,8 @@ var getAudioCodec = (boxes, parserState) => {
|
|
|
2275
3624
|
}
|
|
2276
3625
|
return null;
|
|
2277
3626
|
};
|
|
2278
|
-
var hasAudioCodec = (boxes
|
|
2279
|
-
|
|
2280
|
-
return getAudioCodec(boxes, state) !== null;
|
|
2281
|
-
} catch {
|
|
2282
|
-
return false;
|
|
2283
|
-
}
|
|
3627
|
+
var hasAudioCodec = (boxes) => {
|
|
3628
|
+
return hasTracks(boxes);
|
|
2284
3629
|
};
|
|
2285
3630
|
var getCodecSpecificatorFromEsdsBox = ({
|
|
2286
3631
|
child
|
|
@@ -2300,9 +3645,9 @@ var getCodecSpecificatorFromEsdsBox = ({
|
|
|
2300
3645
|
};
|
|
2301
3646
|
}
|
|
2302
3647
|
const audioSpecificConfig = descriptor.decoderSpecificConfigs.find((d) => {
|
|
2303
|
-
return d.type === "
|
|
3648
|
+
return d.type === "mp4a-specific-config" ? d : null;
|
|
2304
3649
|
});
|
|
2305
|
-
if (!audioSpecificConfig || audioSpecificConfig.type !== "
|
|
3650
|
+
if (!audioSpecificConfig || audioSpecificConfig.type !== "mp4a-specific-config") {
|
|
2306
3651
|
throw new Error("No audio-specific-config");
|
|
2307
3652
|
}
|
|
2308
3653
|
return {
|
|
@@ -2311,6 +3656,29 @@ var getCodecSpecificatorFromEsdsBox = ({
|
|
|
2311
3656
|
description: audioSpecificConfig.asBytes
|
|
2312
3657
|
};
|
|
2313
3658
|
};
|
|
3659
|
+
var getCodecPrivateFromTrak = (trakBox) => {
|
|
3660
|
+
const stsdBox = getStsdBox(trakBox);
|
|
3661
|
+
if (!stsdBox) {
|
|
3662
|
+
return null;
|
|
3663
|
+
}
|
|
3664
|
+
const audioSample = stsdBox.samples.find((s) => s.type === "audio");
|
|
3665
|
+
if (!audioSample || audioSample.type !== "audio") {
|
|
3666
|
+
return null;
|
|
3667
|
+
}
|
|
3668
|
+
const esds = audioSample.children.find((b) => b.type === "esds-box");
|
|
3669
|
+
if (!esds || esds.type !== "esds-box") {
|
|
3670
|
+
return null;
|
|
3671
|
+
}
|
|
3672
|
+
const decoderConfigDescriptor = esds.descriptors.find((d) => d.type === "decoder-config-descriptor");
|
|
3673
|
+
if (!decoderConfigDescriptor) {
|
|
3674
|
+
return null;
|
|
3675
|
+
}
|
|
3676
|
+
const mp4a = decoderConfigDescriptor.decoderSpecificConfigs.find((d) => d.type === "mp4a-specific-config");
|
|
3677
|
+
if (!mp4a) {
|
|
3678
|
+
return null;
|
|
3679
|
+
}
|
|
3680
|
+
return mp4a.asBytes;
|
|
3681
|
+
};
|
|
2314
3682
|
var onSample = (sample, children) => {
|
|
2315
3683
|
const child = children.find((c) => c.type === "esds-box");
|
|
2316
3684
|
if (child && child.type === "esds-box") {
|
|
@@ -2651,18 +4019,11 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
|
|
|
2651
4019
|
getUint8(),
|
|
2652
4020
|
getUint8(),
|
|
2653
4021
|
getUint8(),
|
|
2654
|
-
getUint8()
|
|
2655
|
-
]);
|
|
2656
|
-
return Number(bigInt);
|
|
2657
|
-
};
|
|
2658
|
-
const getFourByteNumber = (
|
|
2659
|
-
if (littleEndian) {
|
|
2660
|
-
const one = getUint8();
|
|
2661
|
-
const two = getUint8();
|
|
2662
|
-
const three = getUint8();
|
|
2663
|
-
const four = getUint8();
|
|
2664
|
-
return four << 24 | three << 16 | two << 8 | one;
|
|
2665
|
-
}
|
|
4022
|
+
getUint8()
|
|
4023
|
+
]);
|
|
4024
|
+
return Number(bigInt);
|
|
4025
|
+
};
|
|
4026
|
+
const getFourByteNumber = () => {
|
|
2666
4027
|
return getUint8() << 24 | getUint8() << 16 | getUint8() << 8 | getUint8();
|
|
2667
4028
|
};
|
|
2668
4029
|
const getPaddedFourByteNumber = () => {
|
|
@@ -3016,7 +4377,7 @@ var parseAv1PrivateData = (data, colrAtom) => {
|
|
|
3016
4377
|
const chroma_sample_position = iterator.getBits(2);
|
|
3017
4378
|
str += subsampling_x && subsampling_y ? chroma_sample_position === 1 ? "1" : "0" : "0";
|
|
3018
4379
|
str += ".";
|
|
3019
|
-
if (colrAtom) {
|
|
4380
|
+
if (colrAtom && colrAtom.colorType === "transfer-characteristics") {
|
|
3020
4381
|
str += colrAtom.primaries.toString().padStart(2, "0");
|
|
3021
4382
|
str += ".";
|
|
3022
4383
|
str += colrAtom.transfer.toString().padStart(2, "0");
|
|
@@ -3125,11 +4486,7 @@ var getVideoCodec = (boxes) => {
|
|
|
3125
4486
|
return null;
|
|
3126
4487
|
};
|
|
3127
4488
|
var hasVideoCodec = (boxes) => {
|
|
3128
|
-
|
|
3129
|
-
return getVideoCodec(boxes) !== null;
|
|
3130
|
-
} catch {
|
|
3131
|
-
return false;
|
|
3132
|
-
}
|
|
4489
|
+
return hasTracks(boxes);
|
|
3133
4490
|
};
|
|
3134
4491
|
var getVideoPrivateData = (trakBox) => {
|
|
3135
4492
|
const videoSample = getStsdVideoConfig(trakBox);
|
|
@@ -3159,6 +4516,9 @@ var getIsoBmColrConfig = (trakBox) => {
|
|
|
3159
4516
|
if (!colrAtom) {
|
|
3160
4517
|
return null;
|
|
3161
4518
|
}
|
|
4519
|
+
if (colrAtom.colorType !== "transfer-characteristics") {
|
|
4520
|
+
return null;
|
|
4521
|
+
}
|
|
3162
4522
|
return {
|
|
3163
4523
|
fullRange: colrAtom.fullRangeFlag,
|
|
3164
4524
|
matrixCoefficients: colrAtom.matrixIndex === 1 ? "bt709" : colrAtom.matrixIndex === 5 ? "bt470bg" : colrAtom.matrixIndex === 6 ? "smpte170m" : null,
|
|
@@ -3217,7 +4577,7 @@ var makeBaseMediaTrack = (trakBox) => {
|
|
|
3217
4577
|
sampleRate,
|
|
3218
4578
|
description,
|
|
3219
4579
|
trakBox,
|
|
3220
|
-
codecPrivate:
|
|
4580
|
+
codecPrivate: getCodecPrivateFromTrak(trakBox),
|
|
3221
4581
|
codecWithoutConfig: getAudioCodecFromTrack(trakBox)
|
|
3222
4582
|
};
|
|
3223
4583
|
}
|
|
@@ -3270,7 +4630,8 @@ var makeBaseMediaTrack = (trakBox) => {
|
|
|
3270
4630
|
primaries: null,
|
|
3271
4631
|
transferCharacteristics: null
|
|
3272
4632
|
},
|
|
3273
|
-
codecWithoutConfig: getVideoCodecFromIsoTrak(trakBox)
|
|
4633
|
+
codecWithoutConfig: getVideoCodecFromIsoTrak(trakBox),
|
|
4634
|
+
fps: getFpsFromMp4TrakBox(trakBox)
|
|
3274
4635
|
};
|
|
3275
4636
|
return track;
|
|
3276
4637
|
};
|
|
@@ -3534,7 +4895,7 @@ var getMatroskaAudioCodecString = (track) => {
|
|
|
3534
4895
|
throw new Error(`Unknown codec: ${codec.value}`);
|
|
3535
4896
|
};
|
|
3536
4897
|
var getTrack = ({
|
|
3537
|
-
timescale,
|
|
4898
|
+
timescale: timescale2,
|
|
3538
4899
|
track
|
|
3539
4900
|
}) => {
|
|
3540
4901
|
const trackType2 = getTrackTypeSegment(track);
|
|
@@ -3577,7 +4938,7 @@ var getTrack = ({
|
|
|
3577
4938
|
numerator: 1,
|
|
3578
4939
|
denominator: 1
|
|
3579
4940
|
},
|
|
3580
|
-
timescale,
|
|
4941
|
+
timescale: timescale2,
|
|
3581
4942
|
codedHeight: height.value.value,
|
|
3582
4943
|
codedWidth: width.value.value,
|
|
3583
4944
|
displayAspectHeight: displayHeight2 ? displayHeight2.value.value : height.value.value,
|
|
@@ -3593,7 +4954,8 @@ var getTrack = ({
|
|
|
3593
4954
|
},
|
|
3594
4955
|
codecWithoutConfig: getMatroskaVideoCodecWithoutConfigString({
|
|
3595
4956
|
codecSegment: codec
|
|
3596
|
-
})
|
|
4957
|
+
}),
|
|
4958
|
+
fps: null
|
|
3597
4959
|
};
|
|
3598
4960
|
}
|
|
3599
4961
|
if (trackTypeToString(trackType2.value.value) === "audio") {
|
|
@@ -3607,7 +4969,7 @@ var getTrack = ({
|
|
|
3607
4969
|
type: "audio",
|
|
3608
4970
|
trackId,
|
|
3609
4971
|
codec: getMatroskaAudioCodecString(track),
|
|
3610
|
-
timescale,
|
|
4972
|
+
timescale: timescale2,
|
|
3611
4973
|
numberOfChannels,
|
|
3612
4974
|
sampleRate,
|
|
3613
4975
|
description: getAudioDescription(track),
|
|
@@ -3622,7 +4984,7 @@ var getTrack = ({
|
|
|
3622
4984
|
};
|
|
3623
4985
|
|
|
3624
4986
|
// src/boxes/webm/get-ready-tracks.ts
|
|
3625
|
-
var getTracksFromMatroska = (segment,
|
|
4987
|
+
var getTracksFromMatroska = (segment, timescale2) => {
|
|
3626
4988
|
const tracksSegment = getTracksSegment(segment);
|
|
3627
4989
|
if (!tracksSegment) {
|
|
3628
4990
|
throw new Error("No tracks segment");
|
|
@@ -3637,7 +4999,7 @@ var getTracksFromMatroska = (segment, timescale) => {
|
|
|
3637
4999
|
}
|
|
3638
5000
|
const track = getTrack({
|
|
3639
5001
|
track: trackEntrySegment,
|
|
3640
|
-
timescale
|
|
5002
|
+
timescale: timescale2
|
|
3641
5003
|
});
|
|
3642
5004
|
if (track) {
|
|
3643
5005
|
tracks2.push(track);
|
|
@@ -3761,239 +5123,6 @@ var hasDimensions = (boxes, state) => {
|
|
|
3761
5123
|
}
|
|
3762
5124
|
};
|
|
3763
5125
|
|
|
3764
|
-
// src/get-sample-positions.ts
|
|
3765
|
-
var getSamplePositions = ({
|
|
3766
|
-
stcoBox,
|
|
3767
|
-
stszBox,
|
|
3768
|
-
stscBox,
|
|
3769
|
-
stssBox,
|
|
3770
|
-
sttsBox,
|
|
3771
|
-
cttsBox
|
|
3772
|
-
}) => {
|
|
3773
|
-
const sttsDeltas = [];
|
|
3774
|
-
for (const distribution of sttsBox.sampleDistribution) {
|
|
3775
|
-
for (let i = 0;i < distribution.sampleCount; i++) {
|
|
3776
|
-
sttsDeltas.push(distribution.sampleDelta);
|
|
3777
|
-
}
|
|
3778
|
-
}
|
|
3779
|
-
const cttsEntries = [];
|
|
3780
|
-
for (const entry of cttsBox?.entries ?? [
|
|
3781
|
-
{ sampleCount: sttsDeltas.length, sampleOffset: 0 }
|
|
3782
|
-
]) {
|
|
3783
|
-
for (let i = 0;i < entry.sampleCount; i++) {
|
|
3784
|
-
cttsEntries.push(entry.sampleOffset);
|
|
3785
|
-
}
|
|
3786
|
-
}
|
|
3787
|
-
let dts = 0;
|
|
3788
|
-
const chunks = stcoBox.entries;
|
|
3789
|
-
const samples = [];
|
|
3790
|
-
let samplesPerChunk = 1;
|
|
3791
|
-
for (let i = 0;i < chunks.length; i++) {
|
|
3792
|
-
const hasEntry = stscBox.entries.find((entry) => entry.firstChunk === i + 1);
|
|
3793
|
-
if (hasEntry) {
|
|
3794
|
-
samplesPerChunk = hasEntry.samplesPerChunk;
|
|
3795
|
-
}
|
|
3796
|
-
let offsetInThisChunk = 0;
|
|
3797
|
-
for (let j = 0;j < samplesPerChunk; j++) {
|
|
3798
|
-
const size = stszBox.countType === "fixed" ? stszBox.sampleSize : stszBox.entries[samples.length];
|
|
3799
|
-
const isKeyframe = stssBox ? stssBox.sampleNumber.includes(samples.length + 1) : true;
|
|
3800
|
-
const delta = sttsDeltas[samples.length];
|
|
3801
|
-
const ctsOffset = cttsEntries[samples.length];
|
|
3802
|
-
const cts = dts + ctsOffset;
|
|
3803
|
-
samples.push({
|
|
3804
|
-
offset: Number(chunks[i]) + offsetInThisChunk,
|
|
3805
|
-
size,
|
|
3806
|
-
isKeyframe,
|
|
3807
|
-
dts,
|
|
3808
|
-
cts,
|
|
3809
|
-
duration: delta
|
|
3810
|
-
});
|
|
3811
|
-
dts += delta;
|
|
3812
|
-
offsetInThisChunk += size;
|
|
3813
|
-
}
|
|
3814
|
-
}
|
|
3815
|
-
return samples;
|
|
3816
|
-
};
|
|
3817
|
-
|
|
3818
|
-
// src/samples-from-moof.ts
|
|
3819
|
-
var getSamplesFromTraf = (trafSegment, moofOffset) => {
|
|
3820
|
-
if (trafSegment.type !== "regular-box" || trafSegment.boxType !== "traf") {
|
|
3821
|
-
throw new Error("Expected traf-box");
|
|
3822
|
-
}
|
|
3823
|
-
const tfhdBox = getTfhdBox(trafSegment);
|
|
3824
|
-
const defaultSampleDuration = tfhdBox?.defaultSampleDuration ?? null;
|
|
3825
|
-
const defaultSampleSize = tfhdBox?.defaultSampleSize ?? null;
|
|
3826
|
-
const defaultSampleFlags = tfhdBox?.defaultSampleFlags ?? null;
|
|
3827
|
-
const tfdtBox = getTfdtBox(trafSegment);
|
|
3828
|
-
const trunBoxes = getTrunBoxes(trafSegment);
|
|
3829
|
-
let time = 0;
|
|
3830
|
-
let offset = 0;
|
|
3831
|
-
let dataOffset = 0;
|
|
3832
|
-
const samples = [];
|
|
3833
|
-
for (const trunBox of trunBoxes) {
|
|
3834
|
-
let i = -1;
|
|
3835
|
-
if (trunBox.dataOffset) {
|
|
3836
|
-
dataOffset = trunBox.dataOffset;
|
|
3837
|
-
offset = 0;
|
|
3838
|
-
}
|
|
3839
|
-
for (const sample of trunBox.samples) {
|
|
3840
|
-
i++;
|
|
3841
|
-
const duration2 = sample.sampleDuration ?? defaultSampleDuration;
|
|
3842
|
-
if (duration2 === null) {
|
|
3843
|
-
throw new Error("Expected duration");
|
|
3844
|
-
}
|
|
3845
|
-
const size = sample.sampleSize ?? defaultSampleSize;
|
|
3846
|
-
if (size === null) {
|
|
3847
|
-
throw new Error("Expected size");
|
|
3848
|
-
}
|
|
3849
|
-
const isFirstSample = i === 0;
|
|
3850
|
-
const sampleFlags = sample.sampleFlags ? sample.sampleFlags : isFirstSample && trunBox.firstSampleFlags !== null ? trunBox.firstSampleFlags : defaultSampleFlags;
|
|
3851
|
-
if (sampleFlags === null) {
|
|
3852
|
-
throw new Error("Expected sample flags");
|
|
3853
|
-
}
|
|
3854
|
-
const keyframe = !(sampleFlags >> 16 & 1);
|
|
3855
|
-
const dts = time + (tfdtBox?.baseMediaDecodeTime ?? 0);
|
|
3856
|
-
const samplePosition = {
|
|
3857
|
-
offset: offset + (moofOffset ?? 0) + (dataOffset ?? 0),
|
|
3858
|
-
dts,
|
|
3859
|
-
cts: dts,
|
|
3860
|
-
duration: duration2,
|
|
3861
|
-
isKeyframe: keyframe,
|
|
3862
|
-
size
|
|
3863
|
-
};
|
|
3864
|
-
samples.push(samplePosition);
|
|
3865
|
-
offset += size;
|
|
3866
|
-
time += duration2;
|
|
3867
|
-
}
|
|
3868
|
-
}
|
|
3869
|
-
return samples;
|
|
3870
|
-
};
|
|
3871
|
-
var getSamplesFromMoof = ({
|
|
3872
|
-
moofBox,
|
|
3873
|
-
trackId
|
|
3874
|
-
}) => {
|
|
3875
|
-
if (moofBox.type !== "regular-box") {
|
|
3876
|
-
throw new Error("Expected moof-box");
|
|
3877
|
-
}
|
|
3878
|
-
const trafs = moofBox.children.filter((c) => c.type === "regular-box" && c.boxType === "traf");
|
|
3879
|
-
const mapped = trafs.map((traf) => {
|
|
3880
|
-
const tfhdBox = getTfhdBox(traf);
|
|
3881
|
-
return tfhdBox?.trackId === trackId ? getSamplesFromTraf(traf, moofBox.offset) : [];
|
|
3882
|
-
});
|
|
3883
|
-
return mapped.flat(1);
|
|
3884
|
-
};
|
|
3885
|
-
|
|
3886
|
-
// src/boxes/iso-base-media/get-sample-positions-from-track.ts
|
|
3887
|
-
var getSamplePositionsFromTrack = (trakBox, moofBox) => {
|
|
3888
|
-
const stszBox = getStszBox(trakBox);
|
|
3889
|
-
const stcoBox = getStcoBox(trakBox);
|
|
3890
|
-
const stscBox = getStscBox(trakBox);
|
|
3891
|
-
const stssBox = getStssBox(trakBox);
|
|
3892
|
-
const sttsBox = getSttsBox(trakBox);
|
|
3893
|
-
const tkhdBox = getTkhdBox(trakBox);
|
|
3894
|
-
const cttsBox = getCttsBox(trakBox);
|
|
3895
|
-
const timescaleAndDuration = getTimescaleAndDuration(trakBox);
|
|
3896
|
-
if (!tkhdBox) {
|
|
3897
|
-
throw new Error("Expected tkhd box in trak box");
|
|
3898
|
-
}
|
|
3899
|
-
if (!stszBox) {
|
|
3900
|
-
throw new Error("Expected stsz box in trak box");
|
|
3901
|
-
}
|
|
3902
|
-
if (!stcoBox) {
|
|
3903
|
-
throw new Error("Expected stco box in trak box");
|
|
3904
|
-
}
|
|
3905
|
-
if (!stscBox) {
|
|
3906
|
-
throw new Error("Expected stsc box in trak box");
|
|
3907
|
-
}
|
|
3908
|
-
if (!sttsBox) {
|
|
3909
|
-
throw new Error("Expected stts box in trak box");
|
|
3910
|
-
}
|
|
3911
|
-
if (!timescaleAndDuration) {
|
|
3912
|
-
throw new Error("Expected timescale and duration in trak box");
|
|
3913
|
-
}
|
|
3914
|
-
let samplePositions = getSamplePositions({
|
|
3915
|
-
stcoBox,
|
|
3916
|
-
stscBox,
|
|
3917
|
-
stszBox,
|
|
3918
|
-
stssBox,
|
|
3919
|
-
sttsBox,
|
|
3920
|
-
cttsBox
|
|
3921
|
-
});
|
|
3922
|
-
if (samplePositions.length === 0 && moofBox) {
|
|
3923
|
-
samplePositions = getSamplesFromMoof({ moofBox, trackId: tkhdBox.trackId });
|
|
3924
|
-
}
|
|
3925
|
-
return samplePositions;
|
|
3926
|
-
};
|
|
3927
|
-
|
|
3928
|
-
// src/get-duration.ts
|
|
3929
|
-
var getDurationFromMatroska = (segments) => {
|
|
3930
|
-
const mainSegment = segments.find((s) => s.type === "Segment");
|
|
3931
|
-
if (!mainSegment || mainSegment.type !== "Segment") {
|
|
3932
|
-
return null;
|
|
3933
|
-
}
|
|
3934
|
-
const { value: children } = mainSegment;
|
|
3935
|
-
if (!children) {
|
|
3936
|
-
return null;
|
|
3937
|
-
}
|
|
3938
|
-
const infoSegment = children.find((s) => s.type === "Info");
|
|
3939
|
-
const relevantBoxes = [
|
|
3940
|
-
...mainSegment.value,
|
|
3941
|
-
...infoSegment && infoSegment.type === "Info" ? infoSegment.value : []
|
|
3942
|
-
];
|
|
3943
|
-
const timestampScale2 = relevantBoxes.find((s) => s.type === "TimestampScale");
|
|
3944
|
-
if (!timestampScale2 || timestampScale2.type !== "TimestampScale") {
|
|
3945
|
-
return null;
|
|
3946
|
-
}
|
|
3947
|
-
const duration2 = relevantBoxes.find((s) => s.type === "Duration");
|
|
3948
|
-
if (!duration2 || duration2.type !== "Duration") {
|
|
3949
|
-
return null;
|
|
3950
|
-
}
|
|
3951
|
-
return duration2.value.value / timestampScale2.value.value * 1000;
|
|
3952
|
-
};
|
|
3953
|
-
var getDuration = (boxes, parserState) => {
|
|
3954
|
-
const matroskaBox = boxes.find((b) => b.type === "Segment");
|
|
3955
|
-
if (matroskaBox) {
|
|
3956
|
-
return getDurationFromMatroska(boxes);
|
|
3957
|
-
}
|
|
3958
|
-
const moovBox = getMoovBox(boxes);
|
|
3959
|
-
if (!moovBox) {
|
|
3960
|
-
return null;
|
|
3961
|
-
}
|
|
3962
|
-
const moofBox = getMoofBox(boxes);
|
|
3963
|
-
const mvhdBox = getMvhdBox(moovBox);
|
|
3964
|
-
if (!mvhdBox) {
|
|
3965
|
-
return null;
|
|
3966
|
-
}
|
|
3967
|
-
if (mvhdBox.type !== "mvhd-box") {
|
|
3968
|
-
throw new Error("Expected mvhd-box");
|
|
3969
|
-
}
|
|
3970
|
-
if (mvhdBox.durationInSeconds > 0) {
|
|
3971
|
-
return mvhdBox.durationInSeconds;
|
|
3972
|
-
}
|
|
3973
|
-
const tracks2 = getTracks(boxes, parserState);
|
|
3974
|
-
const allTracks = [
|
|
3975
|
-
...tracks2.videoTracks,
|
|
3976
|
-
...tracks2.audioTracks,
|
|
3977
|
-
...tracks2.otherTracks
|
|
3978
|
-
];
|
|
3979
|
-
const allSamples = allTracks.map((t) => {
|
|
3980
|
-
const { timescale: ts } = t;
|
|
3981
|
-
const samplePositions = getSamplePositionsFromTrack(t.trakBox, moofBox);
|
|
3982
|
-
const highest = samplePositions?.map((sp) => (sp.cts + sp.duration) / ts).reduce((a, b) => Math.max(a, b), 0);
|
|
3983
|
-
return highest ?? 0;
|
|
3984
|
-
});
|
|
3985
|
-
const highestTimestamp = Math.max(...allSamples);
|
|
3986
|
-
return highestTimestamp;
|
|
3987
|
-
};
|
|
3988
|
-
var hasDuration = (boxes, parserState) => {
|
|
3989
|
-
try {
|
|
3990
|
-
const duration2 = getDuration(boxes, parserState);
|
|
3991
|
-
return getDuration(boxes, parserState) !== null && duration2 !== 0;
|
|
3992
|
-
} catch {
|
|
3993
|
-
return false;
|
|
3994
|
-
}
|
|
3995
|
-
};
|
|
3996
|
-
|
|
3997
5126
|
// src/emit-available-info.ts
|
|
3998
5127
|
var emitAvailableInfo = ({
|
|
3999
5128
|
hasInfo,
|
|
@@ -4007,14 +5136,14 @@ var emitAvailableInfo = ({
|
|
|
4007
5136
|
const keys = Object.keys(hasInfo);
|
|
4008
5137
|
for (const key of keys) {
|
|
4009
5138
|
if (key === "boxes") {
|
|
4010
|
-
if (hasInfo.boxes && returnValue.boxes === undefined) {
|
|
5139
|
+
if (parseResult && hasInfo.boxes && returnValue.boxes === undefined) {
|
|
4011
5140
|
moreFields.onBoxes?.(parseResult.segments);
|
|
4012
5141
|
returnValue.boxes = parseResult.segments;
|
|
4013
5142
|
}
|
|
4014
5143
|
continue;
|
|
4015
5144
|
}
|
|
4016
5145
|
if (key === "durationInSeconds") {
|
|
4017
|
-
if (hasInfo.durationInSeconds && returnValue.durationInSeconds === undefined) {
|
|
5146
|
+
if (hasInfo.durationInSeconds && returnValue.durationInSeconds === undefined && parseResult) {
|
|
4018
5147
|
const durationInSeconds = getDuration(parseResult.segments, state);
|
|
4019
5148
|
moreFields.onDurationInSeconds?.(durationInSeconds);
|
|
4020
5149
|
returnValue.durationInSeconds = durationInSeconds;
|
|
@@ -4022,7 +5151,7 @@ var emitAvailableInfo = ({
|
|
|
4022
5151
|
continue;
|
|
4023
5152
|
}
|
|
4024
5153
|
if (key === "dimensions") {
|
|
4025
|
-
if (hasInfo.dimensions && returnValue.dimensions === undefined) {
|
|
5154
|
+
if (hasInfo.dimensions && returnValue.dimensions === undefined && parseResult) {
|
|
4026
5155
|
const dimensionsQueried = getDimensions(parseResult.segments, state);
|
|
4027
5156
|
const dimensions = {
|
|
4028
5157
|
height: dimensionsQueried.height,
|
|
@@ -4034,7 +5163,7 @@ var emitAvailableInfo = ({
|
|
|
4034
5163
|
continue;
|
|
4035
5164
|
}
|
|
4036
5165
|
if (key === "unrotatedDimensions") {
|
|
4037
|
-
if (returnValue.unrotatedDimensions === undefined && hasInfo.unrotatedDimensions) {
|
|
5166
|
+
if (returnValue.unrotatedDimensions === undefined && hasInfo.unrotatedDimensions && parseResult) {
|
|
4038
5167
|
const dimensionsQueried = getDimensions(parseResult.segments, state);
|
|
4039
5168
|
const unrotatedDimensions = {
|
|
4040
5169
|
height: dimensionsQueried.unrotatedHeight,
|
|
@@ -4046,7 +5175,7 @@ var emitAvailableInfo = ({
|
|
|
4046
5175
|
continue;
|
|
4047
5176
|
}
|
|
4048
5177
|
if (key === "rotation") {
|
|
4049
|
-
if (returnValue.rotation === undefined && hasInfo.rotation) {
|
|
5178
|
+
if (returnValue.rotation === undefined && hasInfo.rotation && parseResult) {
|
|
4050
5179
|
const dimensionsQueried = getDimensions(parseResult.segments, state);
|
|
4051
5180
|
const { rotation } = dimensionsQueried;
|
|
4052
5181
|
moreFields.onRotation?.(rotation);
|
|
@@ -4055,7 +5184,7 @@ var emitAvailableInfo = ({
|
|
|
4055
5184
|
continue;
|
|
4056
5185
|
}
|
|
4057
5186
|
if (key === "fps") {
|
|
4058
|
-
if (returnValue.fps === undefined && hasInfo.fps) {
|
|
5187
|
+
if (returnValue.fps === undefined && hasInfo.fps && parseResult) {
|
|
4059
5188
|
const fps = getFps(parseResult.segments);
|
|
4060
5189
|
moreFields.onFps?.(fps);
|
|
4061
5190
|
returnValue.fps = fps;
|
|
@@ -4063,7 +5192,7 @@ var emitAvailableInfo = ({
|
|
|
4063
5192
|
continue;
|
|
4064
5193
|
}
|
|
4065
5194
|
if (key === "videoCodec") {
|
|
4066
|
-
if (returnValue.videoCodec === undefined && hasInfo.videoCodec) {
|
|
5195
|
+
if (returnValue.videoCodec === undefined && hasInfo.videoCodec && parseResult) {
|
|
4067
5196
|
const videoCodec = getVideoCodec(parseResult.segments);
|
|
4068
5197
|
moreFields.onVideoCodec?.(videoCodec);
|
|
4069
5198
|
returnValue.videoCodec = videoCodec;
|
|
@@ -4071,7 +5200,7 @@ var emitAvailableInfo = ({
|
|
|
4071
5200
|
continue;
|
|
4072
5201
|
}
|
|
4073
5202
|
if (key === "audioCodec") {
|
|
4074
|
-
if (returnValue.audioCodec === undefined && hasInfo.audioCodec) {
|
|
5203
|
+
if (returnValue.audioCodec === undefined && hasInfo.audioCodec && parseResult) {
|
|
4075
5204
|
const audioCodec = getAudioCodec(parseResult.segments, state);
|
|
4076
5205
|
moreFields.onAudioCodec?.(audioCodec);
|
|
4077
5206
|
returnValue.audioCodec = audioCodec;
|
|
@@ -4079,7 +5208,7 @@ var emitAvailableInfo = ({
|
|
|
4079
5208
|
continue;
|
|
4080
5209
|
}
|
|
4081
5210
|
if (key === "tracks") {
|
|
4082
|
-
if (hasInfo.tracks && returnValue.videoTracks === undefined && returnValue.audioTracks === undefined) {
|
|
5211
|
+
if (hasInfo.tracks && returnValue.videoTracks === undefined && returnValue.audioTracks === undefined && parseResult) {
|
|
4083
5212
|
const { videoTracks, audioTracks } = getTracks(parseResult.segments, state);
|
|
4084
5213
|
moreFields.onTracks?.({ videoTracks, audioTracks });
|
|
4085
5214
|
returnValue.videoTracks = videoTracks;
|
|
@@ -4110,7 +5239,7 @@ var emitAvailableInfo = ({
|
|
|
4110
5239
|
continue;
|
|
4111
5240
|
}
|
|
4112
5241
|
if (key === "container") {
|
|
4113
|
-
if (returnValue.container === undefined && hasInfo.container) {
|
|
5242
|
+
if (returnValue.container === undefined && hasInfo.container && parseResult) {
|
|
4114
5243
|
const container = getContainer(parseResult.segments);
|
|
4115
5244
|
moreFields.onContainer?.(container);
|
|
4116
5245
|
returnValue.container = container;
|
|
@@ -4126,25 +5255,25 @@ var getAvailableInfo = (options, parseResult, state) => {
|
|
|
4126
5255
|
const keys = Object.entries(options).filter(([, value]) => value);
|
|
4127
5256
|
const infos = keys.map(([key]) => {
|
|
4128
5257
|
if (key === "boxes") {
|
|
4129
|
-
return parseResult.status === "done";
|
|
5258
|
+
return Boolean(parseResult && parseResult.status === "done");
|
|
4130
5259
|
}
|
|
4131
5260
|
if (key === "durationInSeconds") {
|
|
4132
|
-
return hasDuration(parseResult.segments, state);
|
|
5261
|
+
return Boolean(parseResult && hasDuration(parseResult.segments, state));
|
|
4133
5262
|
}
|
|
4134
5263
|
if (key === "dimensions" || key === "rotation" || key === "unrotatedDimensions") {
|
|
4135
|
-
return hasDimensions(parseResult.segments, state);
|
|
5264
|
+
return Boolean(parseResult && hasDimensions(parseResult.segments, state));
|
|
4136
5265
|
}
|
|
4137
5266
|
if (key === "fps") {
|
|
4138
|
-
return hasFps(parseResult.segments);
|
|
5267
|
+
return Boolean(parseResult && hasFps(parseResult.segments));
|
|
4139
5268
|
}
|
|
4140
5269
|
if (key === "videoCodec") {
|
|
4141
|
-
return hasVideoCodec(parseResult.segments);
|
|
5270
|
+
return Boolean(parseResult && hasVideoCodec(parseResult.segments));
|
|
4142
5271
|
}
|
|
4143
5272
|
if (key === "audioCodec") {
|
|
4144
|
-
return hasAudioCodec(parseResult.segments
|
|
5273
|
+
return Boolean(parseResult && hasAudioCodec(parseResult.segments));
|
|
4145
5274
|
}
|
|
4146
5275
|
if (key === "tracks") {
|
|
4147
|
-
return hasTracks(parseResult.segments);
|
|
5276
|
+
return Boolean(parseResult && hasTracks(parseResult.segments));
|
|
4148
5277
|
}
|
|
4149
5278
|
if (key === "internalStats") {
|
|
4150
5279
|
return false;
|
|
@@ -4156,7 +5285,7 @@ var getAvailableInfo = (options, parseResult, state) => {
|
|
|
4156
5285
|
return true;
|
|
4157
5286
|
}
|
|
4158
5287
|
if (key === "container") {
|
|
4159
|
-
return hasContainer(parseResult.segments);
|
|
5288
|
+
return Boolean(parseResult && hasContainer(parseResult.segments));
|
|
4160
5289
|
}
|
|
4161
5290
|
throw new Error(`Unknown key: ${key}`);
|
|
4162
5291
|
});
|
|
@@ -4169,7 +5298,7 @@ var getAvailableInfo = (options, parseResult, state) => {
|
|
|
4169
5298
|
};
|
|
4170
5299
|
|
|
4171
5300
|
// src/boxes/iso-base-media/esds/decoder-specific-config.ts
|
|
4172
|
-
var parseDecoderSpecificConfig = (iterator) => {
|
|
5301
|
+
var parseDecoderSpecificConfig = (iterator, logLevel) => {
|
|
4173
5302
|
const layerTag = iterator.getUint8();
|
|
4174
5303
|
const layerSize = iterator.getPaddedFourByteNumber();
|
|
4175
5304
|
const start = iterator.counter.getOffset();
|
|
@@ -4193,13 +5322,15 @@ var parseDecoderSpecificConfig = (iterator) => {
|
|
|
4193
5322
|
if (read < layerSize) {
|
|
4194
5323
|
iterator.discard(layerSize - read);
|
|
4195
5324
|
}
|
|
4196
|
-
|
|
5325
|
+
if (bytes.byteLength === 2 && bytes[0] === 17 && bytes[1] === 136) {
|
|
5326
|
+
Log.warn(logLevel, "Chrome has a bug and might not be able to decode this audio. It will be fixed, see: https://issues.chromium.org/issues/360083330");
|
|
5327
|
+
}
|
|
4197
5328
|
return {
|
|
4198
|
-
type: "
|
|
5329
|
+
type: "mp4a-specific-config",
|
|
4199
5330
|
audioObjectType,
|
|
4200
5331
|
samplingFrequencyIndex,
|
|
4201
5332
|
channelConfiguration,
|
|
4202
|
-
asBytes:
|
|
5333
|
+
asBytes: bytes
|
|
4203
5334
|
};
|
|
4204
5335
|
};
|
|
4205
5336
|
|
|
@@ -4214,7 +5345,8 @@ var mapToObjectAudioIndicator = (num) => {
|
|
|
4214
5345
|
return "unknown";
|
|
4215
5346
|
};
|
|
4216
5347
|
var processDescriptor = ({
|
|
4217
|
-
iterator
|
|
5348
|
+
iterator,
|
|
5349
|
+
logLevel
|
|
4218
5350
|
}) => {
|
|
4219
5351
|
const tag = iterator.getUint8();
|
|
4220
5352
|
if (tag === 4) {
|
|
@@ -4230,8 +5362,8 @@ var processDescriptor = ({
|
|
|
4230
5362
|
const maxBitrate = iterator.getUint32();
|
|
4231
5363
|
const avgBitrate = iterator.getUint32();
|
|
4232
5364
|
const decoderSpecificConfigs = [];
|
|
4233
|
-
while (size - (iterator.counter.getOffset() - initialOffset)
|
|
4234
|
-
const decoderSpecificConfig = parseDecoderSpecificConfig(iterator);
|
|
5365
|
+
while (size - (iterator.counter.getOffset() - initialOffset) > 0) {
|
|
5366
|
+
const decoderSpecificConfig = parseDecoderSpecificConfig(iterator, logLevel);
|
|
4235
5367
|
decoderSpecificConfigs.push(decoderSpecificConfig);
|
|
4236
5368
|
}
|
|
4237
5369
|
return {
|
|
@@ -4261,12 +5393,13 @@ var processDescriptor = ({
|
|
|
4261
5393
|
descriptor: null
|
|
4262
5394
|
};
|
|
4263
5395
|
};
|
|
4264
|
-
var parseDescriptors = (iterator, maxBytes) => {
|
|
5396
|
+
var parseDescriptors = (iterator, maxBytes, logLevel) => {
|
|
4265
5397
|
const descriptors = [];
|
|
4266
5398
|
const initialOffset = iterator.counter.getOffset();
|
|
4267
5399
|
while (iterator.bytesRemaining() > 0 && iterator.counter.getOffset() - initialOffset < maxBytes) {
|
|
4268
5400
|
const { descriptor } = processDescriptor({
|
|
4269
|
-
iterator
|
|
5401
|
+
iterator,
|
|
5402
|
+
logLevel
|
|
4270
5403
|
});
|
|
4271
5404
|
if (descriptor) {
|
|
4272
5405
|
descriptors.push(descriptor);
|
|
@@ -4281,7 +5414,8 @@ var parseDescriptors = (iterator, maxBytes) => {
|
|
|
4281
5414
|
var parseEsds = ({
|
|
4282
5415
|
data,
|
|
4283
5416
|
size,
|
|
4284
|
-
fileOffset
|
|
5417
|
+
fileOffset,
|
|
5418
|
+
logLevel
|
|
4285
5419
|
}) => {
|
|
4286
5420
|
const version = data.getUint8();
|
|
4287
5421
|
data.discard(3);
|
|
@@ -4290,7 +5424,7 @@ var parseEsds = ({
|
|
|
4290
5424
|
const esId = data.getUint16();
|
|
4291
5425
|
data.discard(1);
|
|
4292
5426
|
const remaining = size - (data.counter.getOffset() - fileOffset);
|
|
4293
|
-
const descriptors = parseDescriptors(data, remaining);
|
|
5427
|
+
const descriptors = parseDescriptors(data, remaining, logLevel);
|
|
4294
5428
|
const remainingNow = size - (data.counter.getOffset() - fileOffset);
|
|
4295
5429
|
data.discard(remainingNow);
|
|
4296
5430
|
return {
|
|
@@ -4397,15 +5531,19 @@ var parseMdat = async ({
|
|
|
4397
5531
|
break;
|
|
4398
5532
|
}
|
|
4399
5533
|
const bytes = data.getSlice(samplesWithIndex.samplePosition.size);
|
|
4400
|
-
const timestamp =
|
|
4401
|
-
const duration2 =
|
|
5534
|
+
const timestamp = samplesWithIndex.samplePosition.cts * 1e6 / samplesWithIndex.track.timescale;
|
|
5535
|
+
const duration2 = samplesWithIndex.samplePosition.duration * 1e6 / samplesWithIndex.track.timescale;
|
|
5536
|
+
const cts = samplesWithIndex.samplePosition.cts * 1e6 / samplesWithIndex.track.timescale;
|
|
5537
|
+
const dts = samplesWithIndex.samplePosition.dts * 1e6 / samplesWithIndex.track.timescale;
|
|
4402
5538
|
if (samplesWithIndex.track.type === "audio") {
|
|
4403
5539
|
await options.parserState.onAudioSample(samplesWithIndex.track.trackId, {
|
|
4404
5540
|
data: bytes,
|
|
4405
5541
|
timestamp,
|
|
5542
|
+
duration: duration2,
|
|
5543
|
+
cts,
|
|
5544
|
+
dts,
|
|
4406
5545
|
trackId: samplesWithIndex.track.trackId,
|
|
4407
|
-
type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta"
|
|
4408
|
-
duration: duration2
|
|
5546
|
+
type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta"
|
|
4409
5547
|
});
|
|
4410
5548
|
}
|
|
4411
5549
|
if (samplesWithIndex.track.type === "video") {
|
|
@@ -4413,8 +5551,8 @@ var parseMdat = async ({
|
|
|
4413
5551
|
data: bytes,
|
|
4414
5552
|
timestamp,
|
|
4415
5553
|
duration: duration2,
|
|
4416
|
-
cts
|
|
4417
|
-
dts
|
|
5554
|
+
cts,
|
|
5555
|
+
dts,
|
|
4418
5556
|
trackId: samplesWithIndex.track.trackId,
|
|
4419
5557
|
type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta"
|
|
4420
5558
|
});
|
|
@@ -4443,7 +5581,7 @@ var parseMdhd = ({
|
|
|
4443
5581
|
data.discard(3);
|
|
4444
5582
|
const creationTime = version === 1 ? Number(data.getUint64()) : data.getUint32();
|
|
4445
5583
|
const modificationTime = version === 1 ? Number(data.getUint64()) : data.getUint32();
|
|
4446
|
-
const
|
|
5584
|
+
const timescale2 = data.getUint32();
|
|
4447
5585
|
const duration2 = version === 1 ? data.getUint64() : data.getUint32();
|
|
4448
5586
|
const language2 = data.getUint16();
|
|
4449
5587
|
const quality = data.getUint16();
|
|
@@ -4454,7 +5592,7 @@ var parseMdhd = ({
|
|
|
4454
5592
|
return {
|
|
4455
5593
|
type: "mdhd-box",
|
|
4456
5594
|
duration: Number(duration2),
|
|
4457
|
-
timescale,
|
|
5595
|
+
timescale: timescale2,
|
|
4458
5596
|
version,
|
|
4459
5597
|
language: language2,
|
|
4460
5598
|
quality,
|
|
@@ -4469,7 +5607,8 @@ var parseMoov = async ({
|
|
|
4469
5607
|
offset,
|
|
4470
5608
|
size,
|
|
4471
5609
|
options,
|
|
4472
|
-
signal
|
|
5610
|
+
signal,
|
|
5611
|
+
logLevel
|
|
4473
5612
|
}) => {
|
|
4474
5613
|
const children = await parseBoxes({
|
|
4475
5614
|
iterator,
|
|
@@ -4478,8 +5617,8 @@ var parseMoov = async ({
|
|
|
4478
5617
|
initialBoxes: [],
|
|
4479
5618
|
options,
|
|
4480
5619
|
continueMdat: false,
|
|
4481
|
-
|
|
4482
|
-
|
|
5620
|
+
signal,
|
|
5621
|
+
logLevel
|
|
4483
5622
|
});
|
|
4484
5623
|
if (children.status === "incomplete") {
|
|
4485
5624
|
throw new Error("Incomplete boxes are not allowed");
|
|
@@ -4492,15 +5631,6 @@ var parseMoov = async ({
|
|
|
4492
5631
|
};
|
|
4493
5632
|
};
|
|
4494
5633
|
|
|
4495
|
-
// src/boxes/iso-base-media/to-date.ts
|
|
4496
|
-
var toUnixTimestamp = (value) => {
|
|
4497
|
-
if (value === 0) {
|
|
4498
|
-
return null;
|
|
4499
|
-
}
|
|
4500
|
-
const baseDate = new Date("1904-01-01T00:00:00Z");
|
|
4501
|
-
return Math.floor(value + baseDate.getTime() / 1000) * 1000;
|
|
4502
|
-
};
|
|
4503
|
-
|
|
4504
5634
|
// src/boxes/iso-base-media/mvhd.ts
|
|
4505
5635
|
var parseMvhd = ({
|
|
4506
5636
|
iterator,
|
|
@@ -4523,14 +5653,17 @@ var parseMvhd = ({
|
|
|
4523
5653
|
iterator.discard(2);
|
|
4524
5654
|
iterator.discard(4);
|
|
4525
5655
|
iterator.discard(4);
|
|
4526
|
-
const matrix = [
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
5656
|
+
const matrix = [
|
|
5657
|
+
iterator.getFixedPointSigned1616Number(),
|
|
5658
|
+
iterator.getFixedPointSigned1616Number(),
|
|
5659
|
+
iterator.getFixedPointSigned230Number(),
|
|
5660
|
+
iterator.getFixedPointSigned1616Number(),
|
|
5661
|
+
iterator.getFixedPointSigned1616Number(),
|
|
5662
|
+
iterator.getFixedPointSigned230Number(),
|
|
5663
|
+
iterator.getFixedPointSigned1616Number(),
|
|
5664
|
+
iterator.getFixedPointSigned1616Number(),
|
|
5665
|
+
iterator.getFixedPointSigned230Number()
|
|
5666
|
+
];
|
|
4534
5667
|
iterator.discard(4 * 6);
|
|
4535
5668
|
const nextTrackId = iterator.getUint32();
|
|
4536
5669
|
volumeView.destroy();
|
|
@@ -4587,9 +5720,115 @@ var parseAvcc = ({
|
|
|
4587
5720
|
};
|
|
4588
5721
|
};
|
|
4589
5722
|
|
|
5723
|
+
// src/boxes/iso-base-media/parse-icc-profile.ts
|
|
5724
|
+
var parseIccProfile = (data) => {
|
|
5725
|
+
const iterator = getArrayBufferIterator(data, Infinity);
|
|
5726
|
+
const size = iterator.getUint32();
|
|
5727
|
+
if (size !== data.length) {
|
|
5728
|
+
throw new Error("Invalid ICC profile size");
|
|
5729
|
+
}
|
|
5730
|
+
const preferredCMMType = iterator.getByteString(4);
|
|
5731
|
+
const profileVersion = iterator.getByteString(4);
|
|
5732
|
+
const profileDeviceClass = iterator.getByteString(4);
|
|
5733
|
+
const colorSpace = iterator.getByteString(4);
|
|
5734
|
+
const pcs = iterator.getByteString(4);
|
|
5735
|
+
const dateTime = iterator.getSlice(12);
|
|
5736
|
+
const signature = iterator.getByteString(4);
|
|
5737
|
+
if (signature !== "acsp") {
|
|
5738
|
+
throw new Error("Invalid ICC profile signature");
|
|
5739
|
+
}
|
|
5740
|
+
const primaryPlatform = iterator.getByteString(4);
|
|
5741
|
+
const profileFlags = iterator.getUint32();
|
|
5742
|
+
const deviceManufacturer = iterator.getByteString(4);
|
|
5743
|
+
const deviceModel = iterator.getByteString(4);
|
|
5744
|
+
const deviceAttributes = iterator.getUint64();
|
|
5745
|
+
const renderingIntent = iterator.getUint32();
|
|
5746
|
+
const pcsIlluminant1 = iterator.getUint32();
|
|
5747
|
+
const pcsIlluminant2 = iterator.getUint32();
|
|
5748
|
+
const pcsIlluminant3 = iterator.getUint32();
|
|
5749
|
+
const profileCreator = iterator.getByteString(4);
|
|
5750
|
+
const profileId = iterator.getByteString(16);
|
|
5751
|
+
iterator.discard(28);
|
|
5752
|
+
const tagCount = iterator.getUint32();
|
|
5753
|
+
const entries = [];
|
|
5754
|
+
for (let i = 0;i < tagCount; i++) {
|
|
5755
|
+
const entry = {
|
|
5756
|
+
tag: iterator.getByteString(4),
|
|
5757
|
+
offset: iterator.getUint32(),
|
|
5758
|
+
size: iterator.getUint32()
|
|
5759
|
+
};
|
|
5760
|
+
entries.push(entry);
|
|
5761
|
+
}
|
|
5762
|
+
let lastOffset = -1;
|
|
5763
|
+
let rXYZ = null;
|
|
5764
|
+
let gXYZ = null;
|
|
5765
|
+
let bXYZ = null;
|
|
5766
|
+
let whitePoint = null;
|
|
5767
|
+
for (const entry of entries) {
|
|
5768
|
+
const found = data.slice(entry.offset, entry.offset + entry.size);
|
|
5769
|
+
if (entry.tag === "rXYZ" || entry.tag === "gXYZ" || entry.tag === "bXYZ" || entry.tag === "wtpt") {
|
|
5770
|
+
const it = getArrayBufferIterator(found, Infinity);
|
|
5771
|
+
it.discard(4);
|
|
5772
|
+
const x = it.getInt32() / 65536;
|
|
5773
|
+
const y = it.getInt32() / 65536;
|
|
5774
|
+
const z = it.getInt32() / 65536;
|
|
5775
|
+
it.destroy();
|
|
5776
|
+
const point = { x, y, z };
|
|
5777
|
+
if (entry.tag === "rXYZ") {
|
|
5778
|
+
rXYZ = point;
|
|
5779
|
+
} else if (entry.tag === "gXYZ") {
|
|
5780
|
+
gXYZ = point;
|
|
5781
|
+
} else if (entry.tag === "bXYZ") {
|
|
5782
|
+
bXYZ = point;
|
|
5783
|
+
} else if (entry.tag === "wtpt") {
|
|
5784
|
+
whitePoint = point;
|
|
5785
|
+
}
|
|
5786
|
+
}
|
|
5787
|
+
if (lastOffset !== -1) {
|
|
5788
|
+
const bytesToAdvance = entry.offset - lastOffset;
|
|
5789
|
+
const bytesToGoBackwards = entry.size - bytesToAdvance;
|
|
5790
|
+
if (bytesToGoBackwards > 0) {
|
|
5791
|
+
iterator.counter.decrement(bytesToGoBackwards);
|
|
5792
|
+
}
|
|
5793
|
+
}
|
|
5794
|
+
lastOffset = entry.offset;
|
|
5795
|
+
}
|
|
5796
|
+
const profile = {
|
|
5797
|
+
size,
|
|
5798
|
+
preferredCMMType,
|
|
5799
|
+
profileVersion,
|
|
5800
|
+
profileDeviceClass,
|
|
5801
|
+
colorSpace,
|
|
5802
|
+
pcs,
|
|
5803
|
+
dateTime,
|
|
5804
|
+
signature,
|
|
5805
|
+
primaryPlatform,
|
|
5806
|
+
profileFlags,
|
|
5807
|
+
deviceManufacturer,
|
|
5808
|
+
deviceModel,
|
|
5809
|
+
deviceAttributes,
|
|
5810
|
+
renderingIntent,
|
|
5811
|
+
pcsIlluminant: [
|
|
5812
|
+
pcsIlluminant1 / 65536,
|
|
5813
|
+
pcsIlluminant2 / 65536,
|
|
5814
|
+
pcsIlluminant3 / 65536
|
|
5815
|
+
],
|
|
5816
|
+
profileCreator,
|
|
5817
|
+
profileId,
|
|
5818
|
+
entries,
|
|
5819
|
+
bXYZ,
|
|
5820
|
+
gXYZ,
|
|
5821
|
+
rXYZ,
|
|
5822
|
+
whitePoint
|
|
5823
|
+
};
|
|
5824
|
+
iterator.destroy();
|
|
5825
|
+
return profile;
|
|
5826
|
+
};
|
|
5827
|
+
|
|
4590
5828
|
// src/boxes/iso-base-media/stsd/colr.ts
|
|
4591
5829
|
var parseColorParameterBox = ({
|
|
4592
|
-
iterator
|
|
5830
|
+
iterator,
|
|
5831
|
+
size
|
|
4593
5832
|
}) => {
|
|
4594
5833
|
const byteString = iterator.getByteString(4);
|
|
4595
5834
|
if (byteString === "nclx") {
|
|
@@ -4601,6 +5840,7 @@ var parseColorParameterBox = ({
|
|
|
4601
5840
|
iterator.stopReadingBits();
|
|
4602
5841
|
return {
|
|
4603
5842
|
type: "colr-box",
|
|
5843
|
+
colorType: "transfer-characteristics",
|
|
4604
5844
|
fullRangeFlag,
|
|
4605
5845
|
matrixIndex,
|
|
4606
5846
|
primaries: primaries2,
|
|
@@ -4613,12 +5853,22 @@ var parseColorParameterBox = ({
|
|
|
4613
5853
|
const matrixIndex = iterator.getUint16();
|
|
4614
5854
|
return {
|
|
4615
5855
|
type: "colr-box",
|
|
5856
|
+
colorType: "transfer-characteristics",
|
|
4616
5857
|
fullRangeFlag: false,
|
|
4617
5858
|
matrixIndex,
|
|
4618
5859
|
primaries: primaries2,
|
|
4619
5860
|
transfer
|
|
4620
5861
|
};
|
|
4621
5862
|
}
|
|
5863
|
+
if (byteString === "prof") {
|
|
5864
|
+
const profile = iterator.getSlice(size - 12);
|
|
5865
|
+
return {
|
|
5866
|
+
type: "colr-box",
|
|
5867
|
+
colorType: "icc-profile",
|
|
5868
|
+
profile,
|
|
5869
|
+
parsed: parseIccProfile(profile)
|
|
5870
|
+
};
|
|
5871
|
+
}
|
|
4622
5872
|
throw new Error("Unexpected box type " + byteString);
|
|
4623
5873
|
};
|
|
4624
5874
|
|
|
@@ -4678,7 +5928,6 @@ var parseMebx = async ({
|
|
|
4678
5928
|
offset,
|
|
4679
5929
|
size,
|
|
4680
5930
|
options,
|
|
4681
|
-
littleEndian,
|
|
4682
5931
|
signal
|
|
4683
5932
|
}) => {
|
|
4684
5933
|
iterator.discard(6);
|
|
@@ -4690,8 +5939,8 @@ var parseMebx = async ({
|
|
|
4690
5939
|
initialBoxes: [],
|
|
4691
5940
|
options,
|
|
4692
5941
|
continueMdat: false,
|
|
4693
|
-
|
|
4694
|
-
|
|
5942
|
+
signal,
|
|
5943
|
+
logLevel: "info"
|
|
4695
5944
|
});
|
|
4696
5945
|
if (children.status === "incomplete") {
|
|
4697
5946
|
throw new Error("Incomplete boxes are not allowed");
|
|
@@ -4855,7 +6104,8 @@ var audioTags = [
|
|
|
4855
6104
|
var processSample = async ({
|
|
4856
6105
|
iterator,
|
|
4857
6106
|
options,
|
|
4858
|
-
signal
|
|
6107
|
+
signal,
|
|
6108
|
+
logLevel
|
|
4859
6109
|
}) => {
|
|
4860
6110
|
const fileOffset = iterator.counter.getOffset();
|
|
4861
6111
|
const bytesRemaining = iterator.bytesRemaining();
|
|
@@ -4899,8 +6149,8 @@ var processSample = async ({
|
|
|
4899
6149
|
initialBoxes: [],
|
|
4900
6150
|
options,
|
|
4901
6151
|
continueMdat: false,
|
|
4902
|
-
|
|
4903
|
-
|
|
6152
|
+
signal,
|
|
6153
|
+
logLevel
|
|
4904
6154
|
});
|
|
4905
6155
|
if (children.status === "incomplete") {
|
|
4906
6156
|
throw new Error("Incomplete boxes are not allowed");
|
|
@@ -4946,8 +6196,8 @@ var processSample = async ({
|
|
|
4946
6196
|
initialBoxes: [],
|
|
4947
6197
|
options,
|
|
4948
6198
|
continueMdat: false,
|
|
4949
|
-
|
|
4950
|
-
|
|
6199
|
+
signal,
|
|
6200
|
+
logLevel
|
|
4951
6201
|
});
|
|
4952
6202
|
if (children.status === "incomplete") {
|
|
4953
6203
|
throw new Error("Incomplete boxes are not allowed");
|
|
@@ -4997,8 +6247,8 @@ var processSample = async ({
|
|
|
4997
6247
|
initialBoxes: [],
|
|
4998
6248
|
options,
|
|
4999
6249
|
continueMdat: false,
|
|
5000
|
-
|
|
5001
|
-
|
|
6250
|
+
signal,
|
|
6251
|
+
logLevel
|
|
5002
6252
|
});
|
|
5003
6253
|
if (children.status === "incomplete") {
|
|
5004
6254
|
throw new Error("Incomplete boxes are not allowed");
|
|
@@ -5051,8 +6301,8 @@ var processSample = async ({
|
|
|
5051
6301
|
initialBoxes: [],
|
|
5052
6302
|
options,
|
|
5053
6303
|
continueMdat: false,
|
|
5054
|
-
|
|
5055
|
-
|
|
6304
|
+
signal,
|
|
6305
|
+
logLevel
|
|
5056
6306
|
}) : (iterator.discard(bytesRemainingInBox), { status: "done", segments: [] });
|
|
5057
6307
|
if (children.status === "incomplete") {
|
|
5058
6308
|
throw new Error("Incomplete boxes are not allowed");
|
|
@@ -5088,7 +6338,8 @@ var parseSamples = async ({
|
|
|
5088
6338
|
iterator,
|
|
5089
6339
|
maxBytes,
|
|
5090
6340
|
options,
|
|
5091
|
-
signal
|
|
6341
|
+
signal,
|
|
6342
|
+
logLevel
|
|
5092
6343
|
}) => {
|
|
5093
6344
|
const samples = [];
|
|
5094
6345
|
const initialOffset = iterator.counter.getOffset();
|
|
@@ -5096,7 +6347,8 @@ var parseSamples = async ({
|
|
|
5096
6347
|
const { sample } = await processSample({
|
|
5097
6348
|
iterator,
|
|
5098
6349
|
options,
|
|
5099
|
-
signal
|
|
6350
|
+
signal,
|
|
6351
|
+
logLevel
|
|
5100
6352
|
});
|
|
5101
6353
|
if (sample) {
|
|
5102
6354
|
samples.push(sample);
|
|
@@ -5124,7 +6376,8 @@ var parseStsd = async ({
|
|
|
5124
6376
|
iterator,
|
|
5125
6377
|
maxBytes: bytesRemainingInBox,
|
|
5126
6378
|
options,
|
|
5127
|
-
signal
|
|
6379
|
+
signal,
|
|
6380
|
+
logLevel: "info"
|
|
5128
6381
|
});
|
|
5129
6382
|
if (boxes.length !== numberOfEntries) {
|
|
5130
6383
|
throw new Error(`Expected ${numberOfEntries} sample descriptions, got ${boxes.length}`);
|
|
@@ -5394,7 +6647,8 @@ var parseTrak = async ({
|
|
|
5394
6647
|
size,
|
|
5395
6648
|
offsetAtStart,
|
|
5396
6649
|
options,
|
|
5397
|
-
signal
|
|
6650
|
+
signal,
|
|
6651
|
+
logLevel
|
|
5398
6652
|
}) => {
|
|
5399
6653
|
const children = await parseBoxes({
|
|
5400
6654
|
iterator: data,
|
|
@@ -5403,8 +6657,8 @@ var parseTrak = async ({
|
|
|
5403
6657
|
initialBoxes: [],
|
|
5404
6658
|
options,
|
|
5405
6659
|
continueMdat: false,
|
|
5406
|
-
|
|
5407
|
-
|
|
6660
|
+
signal,
|
|
6661
|
+
logLevel
|
|
5408
6662
|
});
|
|
5409
6663
|
if (children.status === "incomplete") {
|
|
5410
6664
|
throw new Error("Incomplete boxes are not allowed");
|
|
@@ -5465,8 +6719,8 @@ var getChildren = async ({
|
|
|
5465
6719
|
iterator,
|
|
5466
6720
|
bytesRemainingInBox,
|
|
5467
6721
|
options,
|
|
5468
|
-
|
|
5469
|
-
|
|
6722
|
+
signal,
|
|
6723
|
+
logLevel
|
|
5470
6724
|
}) => {
|
|
5471
6725
|
const parseChildren = boxType === "mdia" || boxType === "minf" || boxType === "stbl" || boxType === "moof" || boxType === "dims" || boxType === "wave" || boxType === "traf" || boxType === "stsb";
|
|
5472
6726
|
if (parseChildren) {
|
|
@@ -5477,8 +6731,8 @@ var getChildren = async ({
|
|
|
5477
6731
|
initialBoxes: [],
|
|
5478
6732
|
options,
|
|
5479
6733
|
continueMdat: false,
|
|
5480
|
-
|
|
5481
|
-
|
|
6734
|
+
signal,
|
|
6735
|
+
logLevel
|
|
5482
6736
|
});
|
|
5483
6737
|
if (parsed.status === "incomplete") {
|
|
5484
6738
|
throw new Error("Incomplete boxes are not allowed");
|
|
@@ -5527,12 +6781,12 @@ var processBox = async ({
|
|
|
5527
6781
|
allowIncompleteBoxes,
|
|
5528
6782
|
parsedBoxes,
|
|
5529
6783
|
options,
|
|
5530
|
-
|
|
5531
|
-
|
|
6784
|
+
signal,
|
|
6785
|
+
logLevel
|
|
5532
6786
|
}) => {
|
|
5533
6787
|
const fileOffset = iterator.counter.getOffset();
|
|
5534
6788
|
const bytesRemaining = iterator.bytesRemaining();
|
|
5535
|
-
const boxSizeRaw = iterator.getFourByteNumber(
|
|
6789
|
+
const boxSizeRaw = iterator.getFourByteNumber();
|
|
5536
6790
|
if (boxSizeRaw === 1 && iterator.bytesRemaining() < 12 || iterator.bytesRemaining() < 4) {
|
|
5537
6791
|
iterator.counter.decrement(iterator.counter.getOffset() - fileOffset);
|
|
5538
6792
|
if (allowIncompleteBoxes) {
|
|
@@ -5554,7 +6808,7 @@ var processBox = async ({
|
|
|
5554
6808
|
};
|
|
5555
6809
|
}
|
|
5556
6810
|
const boxType = iterator.getByteString(4);
|
|
5557
|
-
const boxSize = boxSizeRaw === 1 ? iterator.getEightByteNumber(
|
|
6811
|
+
const boxSize = boxSizeRaw === 1 ? iterator.getEightByteNumber() : boxSizeRaw;
|
|
5558
6812
|
if (bytesRemaining < boxSize) {
|
|
5559
6813
|
if (boxType === "mdat") {
|
|
5560
6814
|
const shouldSkip = (options.canSkipVideoData || !hasTracks(parsedBoxes)) && options.supportsContentRange;
|
|
@@ -5604,7 +6858,8 @@ var processBox = async ({
|
|
|
5604
6858
|
}
|
|
5605
6859
|
if (boxType === "colr") {
|
|
5606
6860
|
const box = parseColorParameterBox({
|
|
5607
|
-
iterator
|
|
6861
|
+
iterator,
|
|
6862
|
+
size: boxSize
|
|
5608
6863
|
});
|
|
5609
6864
|
return {
|
|
5610
6865
|
type: "complete",
|
|
@@ -5749,7 +7004,6 @@ var processBox = async ({
|
|
|
5749
7004
|
offset: fileOffset,
|
|
5750
7005
|
size: boxSize,
|
|
5751
7006
|
options,
|
|
5752
|
-
littleEndian,
|
|
5753
7007
|
signal
|
|
5754
7008
|
});
|
|
5755
7009
|
return {
|
|
@@ -5765,7 +7019,8 @@ var processBox = async ({
|
|
|
5765
7019
|
offset: fileOffset,
|
|
5766
7020
|
size: boxSize,
|
|
5767
7021
|
options,
|
|
5768
|
-
signal
|
|
7022
|
+
signal,
|
|
7023
|
+
logLevel
|
|
5769
7024
|
});
|
|
5770
7025
|
return {
|
|
5771
7026
|
type: "complete",
|
|
@@ -5780,7 +7035,8 @@ var processBox = async ({
|
|
|
5780
7035
|
size: boxSize,
|
|
5781
7036
|
offsetAtStart: fileOffset,
|
|
5782
7037
|
options,
|
|
5783
|
-
signal
|
|
7038
|
+
signal,
|
|
7039
|
+
logLevel
|
|
5784
7040
|
});
|
|
5785
7041
|
const transformedTrack = makeBaseMediaTrack(box);
|
|
5786
7042
|
if (transformedTrack) {
|
|
@@ -5880,7 +7136,8 @@ var processBox = async ({
|
|
|
5880
7136
|
const box = parseEsds({
|
|
5881
7137
|
data: iterator,
|
|
5882
7138
|
size: boxSize,
|
|
5883
|
-
fileOffset
|
|
7139
|
+
fileOffset,
|
|
7140
|
+
logLevel
|
|
5884
7141
|
});
|
|
5885
7142
|
return {
|
|
5886
7143
|
type: "complete",
|
|
@@ -5915,8 +7172,8 @@ var processBox = async ({
|
|
|
5915
7172
|
iterator,
|
|
5916
7173
|
bytesRemainingInBox,
|
|
5917
7174
|
options,
|
|
5918
|
-
|
|
5919
|
-
|
|
7175
|
+
signal,
|
|
7176
|
+
logLevel
|
|
5920
7177
|
});
|
|
5921
7178
|
return {
|
|
5922
7179
|
type: "complete",
|
|
@@ -5938,8 +7195,8 @@ var parseBoxes = async ({
|
|
|
5938
7195
|
initialBoxes,
|
|
5939
7196
|
options,
|
|
5940
7197
|
continueMdat,
|
|
5941
|
-
|
|
5942
|
-
|
|
7198
|
+
signal,
|
|
7199
|
+
logLevel
|
|
5943
7200
|
}) => {
|
|
5944
7201
|
let boxes = initialBoxes;
|
|
5945
7202
|
const initialOffset = iterator.counter.getOffset();
|
|
@@ -5957,8 +7214,8 @@ var parseBoxes = async ({
|
|
|
5957
7214
|
allowIncompleteBoxes,
|
|
5958
7215
|
parsedBoxes: initialBoxes,
|
|
5959
7216
|
options,
|
|
5960
|
-
|
|
5961
|
-
|
|
7217
|
+
signal,
|
|
7218
|
+
logLevel
|
|
5962
7219
|
});
|
|
5963
7220
|
if (result.type === "incomplete") {
|
|
5964
7221
|
if (Number.isFinite(maxBytes)) {
|
|
@@ -5975,8 +7232,8 @@ var parseBoxes = async ({
|
|
|
5975
7232
|
initialBoxes: boxes,
|
|
5976
7233
|
options,
|
|
5977
7234
|
continueMdat: false,
|
|
5978
|
-
|
|
5979
|
-
|
|
7235
|
+
signal,
|
|
7236
|
+
logLevel
|
|
5980
7237
|
});
|
|
5981
7238
|
},
|
|
5982
7239
|
skipTo: null
|
|
@@ -5994,8 +7251,8 @@ var parseBoxes = async ({
|
|
|
5994
7251
|
initialBoxes: boxes,
|
|
5995
7252
|
options,
|
|
5996
7253
|
continueMdat: result,
|
|
5997
|
-
|
|
5998
|
-
|
|
7254
|
+
signal,
|
|
7255
|
+
logLevel
|
|
5999
7256
|
}));
|
|
6000
7257
|
},
|
|
6001
7258
|
skipTo: null
|
|
@@ -6027,8 +7284,8 @@ var parseBoxes = async ({
|
|
|
6027
7284
|
initialBoxes: boxes,
|
|
6028
7285
|
options,
|
|
6029
7286
|
continueMdat: false,
|
|
6030
|
-
|
|
6031
|
-
|
|
7287
|
+
signal,
|
|
7288
|
+
logLevel
|
|
6032
7289
|
});
|
|
6033
7290
|
},
|
|
6034
7291
|
skipTo: result.skipTo
|
|
@@ -6046,8 +7303,8 @@ var parseBoxes = async ({
|
|
|
6046
7303
|
initialBoxes: boxes,
|
|
6047
7304
|
options,
|
|
6048
7305
|
continueMdat: false,
|
|
6049
|
-
|
|
6050
|
-
|
|
7306
|
+
signal,
|
|
7307
|
+
logLevel
|
|
6051
7308
|
});
|
|
6052
7309
|
},
|
|
6053
7310
|
skipTo: null
|
|
@@ -6073,8 +7330,8 @@ var parseBoxes = async ({
|
|
|
6073
7330
|
initialBoxes: boxes,
|
|
6074
7331
|
options,
|
|
6075
7332
|
continueMdat: false,
|
|
6076
|
-
|
|
6077
|
-
|
|
7333
|
+
signal,
|
|
7334
|
+
logLevel
|
|
6078
7335
|
});
|
|
6079
7336
|
},
|
|
6080
7337
|
skipTo: skipped ? mdatState.fileOffset : null
|
|
@@ -6145,11 +7402,11 @@ var getSampleFromBlock = (ebml, parserContext, offset) => {
|
|
|
6145
7402
|
const { keyframe } = parseBlockFlags(iterator, ebml.type === "SimpleBlock" ? matroskaElements.SimpleBlock : matroskaElements.Block);
|
|
6146
7403
|
const { codec, trackTimescale } = parserContext.parserState.getTrackInfoByNumber(trackNumber2);
|
|
6147
7404
|
const clusterOffset = parserContext.parserState.getTimestampOffsetForByteOffset(offset);
|
|
6148
|
-
const
|
|
7405
|
+
const timescale2 = parserContext.parserState.getTimescale();
|
|
6149
7406
|
if (clusterOffset === undefined) {
|
|
6150
7407
|
throw new Error("Could not find offset for byte offset " + offset);
|
|
6151
7408
|
}
|
|
6152
|
-
const timecodeInNanoSeconds = (timecodeRelativeToCluster + clusterOffset) *
|
|
7409
|
+
const timecodeInNanoSeconds = (timecodeRelativeToCluster + clusterOffset) * timescale2 * (trackTimescale ?? 1);
|
|
6153
7410
|
const timecodeInMicroseconds = timecodeInNanoSeconds / 1000;
|
|
6154
7411
|
if (!codec) {
|
|
6155
7412
|
throw new Error(`Could not find codec for track ${trackNumber2}`);
|
|
@@ -6158,8 +7415,8 @@ var getSampleFromBlock = (ebml, parserContext, offset) => {
|
|
|
6158
7415
|
if (codec.startsWith("V_")) {
|
|
6159
7416
|
const partialVideoSample = {
|
|
6160
7417
|
data: iterator.getSlice(remainingNow),
|
|
6161
|
-
cts:
|
|
6162
|
-
dts:
|
|
7418
|
+
cts: timecodeInMicroseconds,
|
|
7419
|
+
dts: timecodeInMicroseconds,
|
|
6163
7420
|
duration: undefined,
|
|
6164
7421
|
trackId: trackNumber2,
|
|
6165
7422
|
timestamp: timecodeInMicroseconds
|
|
@@ -6187,7 +7444,9 @@ var getSampleFromBlock = (ebml, parserContext, offset) => {
|
|
|
6187
7444
|
trackId: trackNumber2,
|
|
6188
7445
|
timestamp: timecodeInMicroseconds,
|
|
6189
7446
|
type: "key",
|
|
6190
|
-
duration: undefined
|
|
7447
|
+
duration: undefined,
|
|
7448
|
+
cts: timecodeInMicroseconds,
|
|
7449
|
+
dts: timecodeInMicroseconds
|
|
6191
7450
|
};
|
|
6192
7451
|
iterator.destroy();
|
|
6193
7452
|
return {
|
|
@@ -6367,32 +7626,54 @@ var postprocessEbml = async ({
|
|
|
6367
7626
|
};
|
|
6368
7627
|
|
|
6369
7628
|
// src/boxes/webm/segments.ts
|
|
6370
|
-
var
|
|
6371
|
-
|
|
7629
|
+
var continueAfterMatroskaParseResult = async ({
|
|
7630
|
+
result,
|
|
6372
7631
|
iterator,
|
|
6373
|
-
length,
|
|
6374
7632
|
parserContext,
|
|
6375
|
-
|
|
7633
|
+
segment
|
|
6376
7634
|
}) => {
|
|
6377
|
-
if (
|
|
6378
|
-
throw new Error(
|
|
7635
|
+
if (result.status === "done") {
|
|
7636
|
+
throw new Error("Should not continue after done");
|
|
6379
7637
|
}
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
7638
|
+
const proceeded = await result.continueParsing();
|
|
7639
|
+
if (proceeded.status === "done") {
|
|
7640
|
+
return {
|
|
7641
|
+
status: "done",
|
|
7642
|
+
segment
|
|
7643
|
+
};
|
|
7644
|
+
}
|
|
7645
|
+
return {
|
|
7646
|
+
continueParsing() {
|
|
7647
|
+
return continueAfterMatroskaParseResult({
|
|
7648
|
+
result: proceeded,
|
|
7649
|
+
iterator,
|
|
7650
|
+
parserContext,
|
|
7651
|
+
segment
|
|
7652
|
+
});
|
|
7653
|
+
},
|
|
7654
|
+
segment: null,
|
|
7655
|
+
status: "incomplete"
|
|
7656
|
+
};
|
|
6385
7657
|
};
|
|
6386
|
-
var expectSegment = async (
|
|
6387
|
-
|
|
7658
|
+
var expectSegment = async ({
|
|
7659
|
+
iterator,
|
|
7660
|
+
parserContext,
|
|
7661
|
+
offset,
|
|
7662
|
+
children
|
|
7663
|
+
}) => {
|
|
7664
|
+
iterator.counter.decrement(iterator.counter.getOffset() - offset);
|
|
6388
7665
|
if (iterator.bytesRemaining() === 0) {
|
|
6389
7666
|
return {
|
|
6390
7667
|
status: "incomplete",
|
|
6391
|
-
segments: [],
|
|
6392
7668
|
continueParsing: () => {
|
|
6393
|
-
return
|
|
7669
|
+
return expectAndProcessSegment({
|
|
7670
|
+
iterator,
|
|
7671
|
+
parserContext,
|
|
7672
|
+
offset,
|
|
7673
|
+
children
|
|
7674
|
+
});
|
|
6394
7675
|
},
|
|
6395
|
-
|
|
7676
|
+
segment: null
|
|
6396
7677
|
};
|
|
6397
7678
|
}
|
|
6398
7679
|
const segmentId = iterator.getMatroskaSegmentId();
|
|
@@ -6400,11 +7681,15 @@ var expectSegment = async (iterator, parserContext) => {
|
|
|
6400
7681
|
iterator.counter.decrement(iterator.counter.getOffset() - offset);
|
|
6401
7682
|
return {
|
|
6402
7683
|
status: "incomplete",
|
|
6403
|
-
segments: [],
|
|
6404
7684
|
continueParsing: () => {
|
|
6405
|
-
return
|
|
7685
|
+
return expectAndProcessSegment({
|
|
7686
|
+
iterator,
|
|
7687
|
+
parserContext,
|
|
7688
|
+
offset,
|
|
7689
|
+
children
|
|
7690
|
+
});
|
|
6406
7691
|
},
|
|
6407
|
-
|
|
7692
|
+
segment: null
|
|
6408
7693
|
};
|
|
6409
7694
|
}
|
|
6410
7695
|
const offsetBeforeVInt = iterator.counter.getOffset();
|
|
@@ -6414,41 +7699,43 @@ var expectSegment = async (iterator, parserContext) => {
|
|
|
6414
7699
|
iterator.counter.decrement(iterator.counter.getOffset() - offset);
|
|
6415
7700
|
return {
|
|
6416
7701
|
status: "incomplete",
|
|
6417
|
-
segments: [],
|
|
6418
7702
|
continueParsing: () => {
|
|
6419
|
-
return
|
|
7703
|
+
return expectSegment({ iterator, parserContext, offset, children });
|
|
6420
7704
|
},
|
|
6421
|
-
|
|
7705
|
+
segment: null
|
|
6422
7706
|
};
|
|
6423
7707
|
}
|
|
6424
7708
|
const bytesRemainingNow = iterator.byteLength() - iterator.counter.getOffset();
|
|
6425
7709
|
if (segmentId === "0x18538067" || segmentId === "0x1f43b675") {
|
|
7710
|
+
const newSegment = {
|
|
7711
|
+
type: segmentId === "0x18538067" ? "Segment" : "Cluster",
|
|
7712
|
+
minVintWidth: offsetAfterVInt - offsetBeforeVInt,
|
|
7713
|
+
value: []
|
|
7714
|
+
};
|
|
6426
7715
|
const main = await expectChildren({
|
|
6427
7716
|
iterator,
|
|
6428
7717
|
length,
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
value: s,
|
|
6433
|
-
minVintWidth: offsetAfterVInt - offsetBeforeVInt
|
|
6434
|
-
}) : (s) => ({
|
|
6435
|
-
type: "Cluster",
|
|
6436
|
-
value: s,
|
|
6437
|
-
minVintWidth: offsetAfterVInt - offsetBeforeVInt
|
|
6438
|
-
}),
|
|
6439
|
-
parserContext
|
|
7718
|
+
children: newSegment.value,
|
|
7719
|
+
parserContext,
|
|
7720
|
+
startOffset: iterator.counter.getOffset()
|
|
6440
7721
|
});
|
|
6441
7722
|
if (main.status === "incomplete") {
|
|
6442
7723
|
return {
|
|
6443
7724
|
status: "incomplete",
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
7725
|
+
continueParsing: () => {
|
|
7726
|
+
return continueAfterMatroskaParseResult({
|
|
7727
|
+
iterator,
|
|
7728
|
+
parserContext,
|
|
7729
|
+
result: main,
|
|
7730
|
+
segment: newSegment
|
|
7731
|
+
});
|
|
7732
|
+
},
|
|
7733
|
+
segment: newSegment
|
|
6447
7734
|
};
|
|
6448
7735
|
}
|
|
6449
7736
|
return {
|
|
6450
7737
|
status: "done",
|
|
6451
|
-
|
|
7738
|
+
segment: newSegment
|
|
6452
7739
|
};
|
|
6453
7740
|
}
|
|
6454
7741
|
if (bytesRemainingNow < length) {
|
|
@@ -6456,11 +7743,10 @@ var expectSegment = async (iterator, parserContext) => {
|
|
|
6456
7743
|
iterator.counter.decrement(bytesRead);
|
|
6457
7744
|
return {
|
|
6458
7745
|
status: "incomplete",
|
|
6459
|
-
|
|
7746
|
+
segment: null,
|
|
6460
7747
|
continueParsing: () => {
|
|
6461
|
-
return
|
|
6462
|
-
}
|
|
6463
|
-
skipTo: null
|
|
7748
|
+
return expectSegment({ iterator, parserContext, offset, children });
|
|
7749
|
+
}
|
|
6464
7750
|
};
|
|
6465
7751
|
}
|
|
6466
7752
|
const segment = await parseSegment({
|
|
@@ -6472,138 +7758,187 @@ var expectSegment = async (iterator, parserContext) => {
|
|
|
6472
7758
|
});
|
|
6473
7759
|
return {
|
|
6474
7760
|
status: "done",
|
|
6475
|
-
|
|
7761
|
+
segment
|
|
6476
7762
|
};
|
|
6477
7763
|
};
|
|
7764
|
+
var parseSegment = async ({
|
|
7765
|
+
segmentId,
|
|
7766
|
+
iterator,
|
|
7767
|
+
length,
|
|
7768
|
+
parserContext,
|
|
7769
|
+
headerReadSoFar
|
|
7770
|
+
}) => {
|
|
7771
|
+
if (length < 0) {
|
|
7772
|
+
throw new Error(`Expected length of ${segmentId} to be greater or equal 0`);
|
|
7773
|
+
}
|
|
7774
|
+
iterator.counter.decrement(headerReadSoFar);
|
|
7775
|
+
const offset = iterator.counter.getOffset();
|
|
7776
|
+
const ebml = await parseEbml(iterator, parserContext);
|
|
7777
|
+
const remapped = await postprocessEbml({ offset, ebml, parserContext });
|
|
7778
|
+
return remapped;
|
|
7779
|
+
};
|
|
6478
7780
|
|
|
6479
7781
|
// src/boxes/webm/segments/parse-children.ts
|
|
6480
7782
|
var processParseResult = ({
|
|
6481
7783
|
parseResult,
|
|
6482
|
-
children
|
|
6483
|
-
wrap
|
|
7784
|
+
children
|
|
6484
7785
|
}) => {
|
|
7786
|
+
if (parseResult.segment && !children.includes(parseResult.segment)) {
|
|
7787
|
+
children.push(parseResult.segment);
|
|
7788
|
+
}
|
|
6485
7789
|
if (parseResult.status === "incomplete") {
|
|
6486
7790
|
return {
|
|
6487
7791
|
status: "incomplete",
|
|
6488
|
-
|
|
7792
|
+
segment: parseResult.segment,
|
|
6489
7793
|
continueParsing: async () => {
|
|
6490
7794
|
const newParseResult = await parseResult.continueParsing();
|
|
6491
7795
|
return processParseResult({
|
|
6492
7796
|
children,
|
|
6493
|
-
parseResult: newParseResult
|
|
6494
|
-
wrap
|
|
7797
|
+
parseResult: newParseResult
|
|
6495
7798
|
});
|
|
6496
|
-
}
|
|
6497
|
-
skipTo: null
|
|
7799
|
+
}
|
|
6498
7800
|
};
|
|
6499
7801
|
}
|
|
6500
|
-
for (const segment of parseResult.segments) {
|
|
6501
|
-
children.push(segment);
|
|
6502
|
-
}
|
|
6503
7802
|
return {
|
|
6504
7803
|
status: "done",
|
|
6505
|
-
|
|
7804
|
+
segment: parseResult.segment
|
|
6506
7805
|
};
|
|
6507
7806
|
};
|
|
6508
|
-
var
|
|
6509
|
-
result,
|
|
7807
|
+
var expectAndProcessSegment = async ({
|
|
6510
7808
|
iterator,
|
|
7809
|
+
parserContext,
|
|
7810
|
+
offset,
|
|
7811
|
+
children
|
|
7812
|
+
}) => {
|
|
7813
|
+
const segment = await expectSegment({
|
|
7814
|
+
iterator,
|
|
7815
|
+
parserContext,
|
|
7816
|
+
offset,
|
|
7817
|
+
children
|
|
7818
|
+
});
|
|
7819
|
+
return processParseResult({
|
|
7820
|
+
children,
|
|
7821
|
+
parseResult: segment
|
|
7822
|
+
});
|
|
7823
|
+
};
|
|
7824
|
+
var continueAfterSegmentResult = async ({
|
|
7825
|
+
result,
|
|
7826
|
+
length,
|
|
6511
7827
|
children,
|
|
6512
|
-
wrap,
|
|
6513
7828
|
parserContext,
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
7829
|
+
iterator,
|
|
7830
|
+
startOffset
|
|
7831
|
+
}) => {
|
|
7832
|
+
if (result.status === "done") {
|
|
7833
|
+
throw new Error("Should not continue after done");
|
|
6518
7834
|
}
|
|
6519
|
-
const
|
|
6520
|
-
|
|
6521
|
-
if (continued.status === "incomplete") {
|
|
6522
|
-
if (!parserContext.supportsContentRange) {
|
|
6523
|
-
throw new Error("Content-Range header is not supported by the reader, but was asked to seek");
|
|
6524
|
-
}
|
|
7835
|
+
const segmentResult = await result.continueParsing();
|
|
7836
|
+
if (segmentResult.status === "done") {
|
|
6525
7837
|
return {
|
|
6526
7838
|
status: "incomplete",
|
|
6527
|
-
continueParsing:
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
7839
|
+
continueParsing: () => {
|
|
7840
|
+
return expectChildren({
|
|
7841
|
+
children,
|
|
7842
|
+
iterator,
|
|
7843
|
+
length,
|
|
7844
|
+
parserContext,
|
|
7845
|
+
startOffset
|
|
7846
|
+
});
|
|
7847
|
+
},
|
|
7848
|
+
skipTo: null
|
|
6537
7849
|
};
|
|
6538
7850
|
}
|
|
6539
|
-
return
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
7851
|
+
return {
|
|
7852
|
+
status: "incomplete",
|
|
7853
|
+
continueParsing: () => {
|
|
7854
|
+
return continueAfterSegmentResult({
|
|
7855
|
+
result: segmentResult,
|
|
7856
|
+
children,
|
|
7857
|
+
iterator,
|
|
7858
|
+
length,
|
|
7859
|
+
parserContext,
|
|
7860
|
+
startOffset
|
|
7861
|
+
});
|
|
7862
|
+
},
|
|
7863
|
+
skipTo: null
|
|
7864
|
+
};
|
|
6546
7865
|
};
|
|
6547
7866
|
var expectChildren = async ({
|
|
6548
7867
|
iterator,
|
|
6549
7868
|
length,
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
7869
|
+
children,
|
|
7870
|
+
parserContext,
|
|
7871
|
+
startOffset
|
|
6553
7872
|
}) => {
|
|
6554
|
-
const children = [...initialChildren];
|
|
6555
|
-
const startOffset = iterator.counter.getOffset();
|
|
6556
7873
|
while (iterator.counter.getOffset() < startOffset + length) {
|
|
6557
7874
|
if (iterator.bytesRemaining() === 0) {
|
|
6558
7875
|
break;
|
|
6559
7876
|
}
|
|
6560
|
-
const
|
|
6561
|
-
const child =
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
7877
|
+
const currentOffset = iterator.counter.getOffset();
|
|
7878
|
+
const child = await expectAndProcessSegment({
|
|
7879
|
+
iterator,
|
|
7880
|
+
parserContext,
|
|
7881
|
+
offset: currentOffset,
|
|
7882
|
+
children
|
|
6565
7883
|
});
|
|
6566
7884
|
if (child.status === "incomplete") {
|
|
6567
|
-
if (!parserContext.supportsContentRange) {
|
|
6568
|
-
throw new Error("Content-Range header is not supported by the reader, but was asked to seek");
|
|
6569
|
-
}
|
|
6570
7885
|
return {
|
|
6571
7886
|
status: "incomplete",
|
|
6572
|
-
continueParsing:
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
7887
|
+
continueParsing: () => {
|
|
7888
|
+
return continueAfterSegmentResult({
|
|
7889
|
+
result: child,
|
|
7890
|
+
children,
|
|
7891
|
+
iterator,
|
|
7892
|
+
length: length - (currentOffset - startOffset),
|
|
7893
|
+
parserContext,
|
|
7894
|
+
startOffset: currentOffset
|
|
7895
|
+
});
|
|
7896
|
+
},
|
|
7897
|
+
skipTo: null
|
|
6582
7898
|
};
|
|
6583
7899
|
}
|
|
6584
7900
|
}
|
|
6585
7901
|
return {
|
|
6586
|
-
status: "done"
|
|
6587
|
-
segments: wrap ? [wrap(children)] : children
|
|
7902
|
+
status: "done"
|
|
6588
7903
|
};
|
|
6589
7904
|
};
|
|
6590
7905
|
|
|
6591
7906
|
// src/boxes/webm/parse-webm-header.ts
|
|
6592
|
-
var
|
|
6593
|
-
|
|
7907
|
+
var continueAfterMatroskaResult = (result, children) => {
|
|
7908
|
+
if (result.status === "done") {
|
|
7909
|
+
return {
|
|
7910
|
+
status: "done",
|
|
7911
|
+
segments: children
|
|
7912
|
+
};
|
|
7913
|
+
}
|
|
7914
|
+
return {
|
|
7915
|
+
status: "incomplete",
|
|
7916
|
+
segments: children,
|
|
7917
|
+
continueParsing: async () => {
|
|
7918
|
+
const newResult = await result.continueParsing();
|
|
7919
|
+
return continueAfterMatroskaResult(newResult, children);
|
|
7920
|
+
},
|
|
7921
|
+
skipTo: null
|
|
7922
|
+
};
|
|
7923
|
+
};
|
|
7924
|
+
var parseWebm = async (counter, parserContext) => {
|
|
7925
|
+
const children = [];
|
|
7926
|
+
const results = await expectChildren({
|
|
6594
7927
|
iterator: counter,
|
|
6595
7928
|
length: Infinity,
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
7929
|
+
children,
|
|
7930
|
+
parserContext,
|
|
7931
|
+
startOffset: counter.counter.getOffset()
|
|
6599
7932
|
});
|
|
7933
|
+
return continueAfterMatroskaResult(results, children);
|
|
6600
7934
|
};
|
|
6601
7935
|
|
|
6602
7936
|
// src/parse-video.ts
|
|
6603
7937
|
var parseVideo = ({
|
|
6604
7938
|
iterator,
|
|
6605
7939
|
options,
|
|
6606
|
-
signal
|
|
7940
|
+
signal,
|
|
7941
|
+
logLevel
|
|
6607
7942
|
}) => {
|
|
6608
7943
|
if (iterator.bytesRemaining() === 0) {
|
|
6609
7944
|
return Promise.resolve({
|
|
@@ -6613,7 +7948,8 @@ var parseVideo = ({
|
|
|
6613
7948
|
return parseVideo({
|
|
6614
7949
|
iterator,
|
|
6615
7950
|
options,
|
|
6616
|
-
signal
|
|
7951
|
+
signal,
|
|
7952
|
+
logLevel
|
|
6617
7953
|
});
|
|
6618
7954
|
},
|
|
6619
7955
|
skipTo: null
|
|
@@ -6623,6 +7959,7 @@ var parseVideo = ({
|
|
|
6623
7959
|
throw new Error("AVI files are not yet supported");
|
|
6624
7960
|
}
|
|
6625
7961
|
if (iterator.isIsoBaseMedia()) {
|
|
7962
|
+
Log.verbose(logLevel, "Detected ISO Base Media container");
|
|
6626
7963
|
return parseBoxes({
|
|
6627
7964
|
iterator,
|
|
6628
7965
|
maxBytes: Infinity,
|
|
@@ -6630,11 +7967,12 @@ var parseVideo = ({
|
|
|
6630
7967
|
initialBoxes: [],
|
|
6631
7968
|
options,
|
|
6632
7969
|
continueMdat: false,
|
|
6633
|
-
|
|
6634
|
-
|
|
7970
|
+
signal,
|
|
7971
|
+
logLevel
|
|
6635
7972
|
});
|
|
6636
7973
|
}
|
|
6637
7974
|
if (iterator.isWebm()) {
|
|
7975
|
+
Log.verbose(logLevel, "Detected Matroska container");
|
|
6638
7976
|
return Promise.resolve(parseWebm(iterator, options));
|
|
6639
7977
|
}
|
|
6640
7978
|
if (iterator.isMp3()) {
|
|
@@ -6673,15 +8011,15 @@ var makeParserState = ({
|
|
|
6673
8011
|
const queuedAudioSamples = {};
|
|
6674
8012
|
const queuedVideoSamples = {};
|
|
6675
8013
|
const declinedTrackNumbers = [];
|
|
6676
|
-
let
|
|
8014
|
+
let timescale2 = null;
|
|
6677
8015
|
const getTimescale = () => {
|
|
6678
|
-
if (
|
|
8016
|
+
if (timescale2 === null) {
|
|
6679
8017
|
return 1e6;
|
|
6680
8018
|
}
|
|
6681
|
-
return
|
|
8019
|
+
return timescale2;
|
|
6682
8020
|
};
|
|
6683
8021
|
const setTimescale = (newTimescale) => {
|
|
6684
|
-
|
|
8022
|
+
timescale2 = newTimescale;
|
|
6685
8023
|
};
|
|
6686
8024
|
const timestampMap = new Map;
|
|
6687
8025
|
const setTimestampOffset = (byteOffset, timestamp) => {
|
|
@@ -6775,6 +8113,8 @@ var parseMedia = async ({
|
|
|
6775
8113
|
onAudioTrack,
|
|
6776
8114
|
onVideoTrack,
|
|
6777
8115
|
signal,
|
|
8116
|
+
logLevel = "info",
|
|
8117
|
+
onParseProgress,
|
|
6778
8118
|
...more
|
|
6779
8119
|
}) => {
|
|
6780
8120
|
const state = makeParserState({
|
|
@@ -6794,14 +8134,40 @@ var parseMedia = async ({
|
|
|
6794
8134
|
const moreFields = more;
|
|
6795
8135
|
let iterator = null;
|
|
6796
8136
|
let parseResult = null;
|
|
8137
|
+
const canSkipVideoData = !onVideoTrack && !onAudioTrack;
|
|
8138
|
+
if (canSkipVideoData) {
|
|
8139
|
+
Log.verbose(logLevel, "Only parsing metadata, because no onVideoTrack and onAudioTrack callbacks were passed.");
|
|
8140
|
+
} else {
|
|
8141
|
+
Log.verbose(logLevel, "Parsing video data, because onVideoTrack/onAudioTrack callbacks were passed.");
|
|
8142
|
+
}
|
|
6797
8143
|
const options = {
|
|
6798
|
-
canSkipVideoData
|
|
8144
|
+
canSkipVideoData,
|
|
6799
8145
|
onAudioTrack: onAudioTrack ?? null,
|
|
6800
8146
|
onVideoTrack: onVideoTrack ?? null,
|
|
6801
8147
|
parserState: state,
|
|
6802
8148
|
nullifySamples: !(typeof process !== "undefined" && typeof process.env !== "undefined" && process.env.KEEP_SAMPLES === "true"),
|
|
6803
8149
|
supportsContentRange
|
|
6804
8150
|
};
|
|
8151
|
+
const hasAllInfo = () => {
|
|
8152
|
+
if (parseResult === null) {
|
|
8153
|
+
return false;
|
|
8154
|
+
}
|
|
8155
|
+
const availableInfo = getAvailableInfo(fields ?? {}, parseResult, state);
|
|
8156
|
+
return Object.values(availableInfo).every(Boolean);
|
|
8157
|
+
};
|
|
8158
|
+
const triggerInfoEmit = () => {
|
|
8159
|
+
const availableInfo = getAvailableInfo(fields ?? {}, parseResult, state);
|
|
8160
|
+
emitAvailableInfo({
|
|
8161
|
+
hasInfo: availableInfo,
|
|
8162
|
+
moreFields,
|
|
8163
|
+
parseResult,
|
|
8164
|
+
state,
|
|
8165
|
+
returnValue,
|
|
8166
|
+
contentLength,
|
|
8167
|
+
name
|
|
8168
|
+
});
|
|
8169
|
+
};
|
|
8170
|
+
triggerInfoEmit();
|
|
6805
8171
|
while (parseResult === null || parseResult.status === "incomplete") {
|
|
6806
8172
|
if (signal?.aborted) {
|
|
6807
8173
|
throw new Error("Aborted");
|
|
@@ -6828,27 +8194,24 @@ var parseMedia = async ({
|
|
|
6828
8194
|
if (!iterator) {
|
|
6829
8195
|
throw new Error("Unexpected null");
|
|
6830
8196
|
}
|
|
8197
|
+
await onParseProgress?.({
|
|
8198
|
+
bytes: iterator.counter.getOffset(),
|
|
8199
|
+
percentage: contentLength ? iterator.counter.getOffset() / contentLength : null,
|
|
8200
|
+
totalBytes: contentLength
|
|
8201
|
+
});
|
|
8202
|
+
triggerInfoEmit();
|
|
6831
8203
|
if (parseResult && parseResult.status === "incomplete") {
|
|
8204
|
+
Log.verbose(logLevel, "Continuing parsing of file, currently at position", iterator.counter.getOffset(), getAvailableInfo(fields ?? {}, parseResult, state));
|
|
6832
8205
|
parseResult = await parseResult.continueParsing();
|
|
6833
8206
|
} else {
|
|
6834
8207
|
parseResult = await parseVideo({
|
|
6835
8208
|
iterator,
|
|
6836
8209
|
options,
|
|
6837
|
-
signal: signal ?? null
|
|
8210
|
+
signal: signal ?? null,
|
|
8211
|
+
logLevel
|
|
6838
8212
|
});
|
|
6839
8213
|
}
|
|
6840
|
-
|
|
6841
|
-
const hasAllInfo = Object.values(availableInfo).every(Boolean);
|
|
6842
|
-
emitAvailableInfo({
|
|
6843
|
-
hasInfo: availableInfo,
|
|
6844
|
-
moreFields,
|
|
6845
|
-
parseResult,
|
|
6846
|
-
state,
|
|
6847
|
-
returnValue,
|
|
6848
|
-
contentLength,
|
|
6849
|
-
name
|
|
6850
|
-
});
|
|
6851
|
-
if (hasAllInfo && !onVideoTrack && !onAudioTrack) {
|
|
8214
|
+
if (hasAllInfo() && !onVideoTrack && !onAudioTrack) {
|
|
6852
8215
|
break;
|
|
6853
8216
|
}
|
|
6854
8217
|
if (parseResult && parseResult.status === "incomplete" && parseResult.skipTo !== null) {
|
|
@@ -6861,6 +8224,7 @@ var parseMedia = async ({
|
|
|
6861
8224
|
iterator.skipTo(parseResult.skipTo, true);
|
|
6862
8225
|
}
|
|
6863
8226
|
}
|
|
8227
|
+
Log.verbose(logLevel, "Finished parsing file");
|
|
6864
8228
|
emitAvailableInfo({
|
|
6865
8229
|
hasInfo: Object.keys(fields ?? {}).reduce((acc, key) => {
|
|
6866
8230
|
acc[key] = true;
|
|
@@ -6877,12 +8241,17 @@ var parseMedia = async ({
|
|
|
6877
8241
|
iterator?.destroy();
|
|
6878
8242
|
return returnValue;
|
|
6879
8243
|
};
|
|
8244
|
+
// src/version.ts
|
|
8245
|
+
var VERSION = "4.0.231";
|
|
8246
|
+
|
|
6880
8247
|
// src/index.ts
|
|
6881
8248
|
var MediaParserInternals = {
|
|
6882
|
-
|
|
8249
|
+
createMatroskaMedia,
|
|
8250
|
+
createIsoBaseMedia,
|
|
6883
8251
|
Log
|
|
6884
8252
|
};
|
|
6885
8253
|
export {
|
|
6886
8254
|
parseMedia,
|
|
8255
|
+
VERSION,
|
|
6887
8256
|
MediaParserInternals
|
|
6888
8257
|
};
|