@blockcast/mmt-container 0.5.0 → 1.0.0-main.3cb7359ea316
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/README.md +21 -16
- package/dist/browser-runtime.js +1024 -1078
- package/dist/browser-runtime.js.map +4 -4
- package/dist/carp-catalog.d.ts +33 -87
- package/dist/carp-catalog.d.ts.map +1 -1
- package/dist/carp-catalog.js +12 -434
- package/dist/carp-catalog.js.map +4 -4
- package/dist/catalog-fec-params.d.ts +48 -161
- package/dist/catalog-fec-params.d.ts.map +1 -1
- package/dist/catalog-fec-params.js +567 -592
- package/dist/catalog-fec-params.js.map +4 -4
- package/dist/catalog-network-source.js +6 -2
- package/dist/catalog-network-source.js.map +3 -3
- package/dist/delivery-catalog.js +12 -4
- package/dist/delivery-catalog.js.map +4 -4
- package/dist/delta-fallback-config.d.ts +21 -26
- package/dist/delta-fallback-config.d.ts.map +1 -1
- package/dist/delta-fallback-config.js +582 -24
- package/dist/delta-fallback-config.js.map +4 -4
- package/dist/fec-manager.js +6 -2
- package/dist/fec-manager.js.map +3 -3
- package/dist/fec-state.d.ts +5 -43
- package/dist/fec-state.d.ts.map +1 -1
- package/dist/fec-state.js +529 -34
- package/dist/fec-state.js.map +4 -4
- package/dist/fec-worker-setup.js +6 -2
- package/dist/fec-worker-setup.js.map +3 -3
- package/dist/held-layer-admission.js +6 -2
- package/dist/held-layer-admission.js.map +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -39
- package/dist/index.js.map +2 -2
- package/dist/iso-block-locator.js +6 -2
- package/dist/iso-block-locator.js.map +3 -3
- package/dist/mfu-reassembler.js +6 -2
- package/dist/mfu-reassembler.js.map +3 -3
- package/dist/mmtp-container-parser.js +6 -2
- package/dist/mmtp-container-parser.js.map +3 -3
- package/dist/mmtp-container-parser.no-modules.js +551 -452
- package/dist/mmtp-container-parser.no-modules.js.map +4 -4
- package/dist/mmtp-decode-pipeline.js +6 -2
- package/dist/mmtp-decode-pipeline.js.map +3 -3
- package/dist/mmtp-fec-session.d.ts +7 -6
- package/dist/mmtp-fec-session.d.ts.map +1 -1
- package/dist/mmtp-fec-session.js +13 -9
- package/dist/mmtp-fec-session.js.map +3 -3
- package/dist/mmtp-router.d.ts +7 -16
- package/dist/mmtp-router.d.ts.map +1 -1
- package/dist/mmtp-router.js +19 -29
- package/dist/mmtp-router.js.map +3 -3
- package/dist/multicast-auth-catalog.js +7 -3
- package/dist/multicast-auth-catalog.js.map +3 -3
- package/dist/multicast-input.js +7 -3
- package/dist/multicast-input.js.map +3 -3
- package/dist/multicast-manager.d.ts +29 -32
- package/dist/multicast-manager.d.ts.map +1 -1
- package/dist/multicast-manager.js +682 -253
- package/dist/multicast-manager.js.map +4 -4
- package/dist/multicast-transport.d.ts +23 -2
- package/dist/multicast-transport.d.ts.map +1 -1
- package/dist/multicast-transport.js +57 -16
- package/dist/multicast-transport.js.map +4 -4
- package/dist/multicast-unwrap.js +6 -2
- package/dist/multicast-unwrap.js.map +3 -3
- package/dist/no-modules.js +551 -452
- package/dist/no-modules.js.map +4 -4
- package/dist/phase14-catalog-override.d.ts +10 -5
- package/dist/phase14-catalog-override.d.ts.map +1 -1
- package/dist/phase14-catalog-override.js +35 -11
- package/dist/phase14-catalog-override.js.map +2 -2
- package/dist/repair-fetch.d.ts +3 -1
- package/dist/repair-fetch.d.ts.map +1 -1
- package/dist/repair-fetch.js +16 -3
- package/dist/repair-fetch.js.map +3 -3
- package/dist/repair-layers.d.ts +0 -123
- package/dist/repair-layers.d.ts.map +1 -1
- package/dist/repair-layers.js +1 -349
- package/dist/repair-layers.js.map +3 -3
- package/dist/signaling.js +6 -2
- package/dist/signaling.js.map +3 -3
- package/dist/timestamp-codec.js +6 -2
- package/dist/timestamp-codec.js.map +3 -3
- package/dist/wasm-mfu-reassembler.js +6 -2
- package/dist/wasm-mfu-reassembler.js.map +3 -3
- package/dist/wasm-mmtp-container-parser.js +6 -2
- package/dist/wasm-mmtp-container-parser.js.map +3 -3
- package/package.json +9 -5
- package/schemas/catalog.schema.json +53 -58
- package/src/carp-catalog.ts +39 -229
- package/src/catalog-fec-params.ts +130 -493
- package/src/delta-fallback-config.ts +63 -50
- package/src/fec-state.ts +7 -62
- package/src/index.ts +10 -30
- package/src/mmtp-fec-session.ts +11 -10
- package/src/mmtp-router.ts +14 -29
- package/src/multicast-manager.ts +89 -121
- package/src/multicast-transport.ts +65 -12
- package/src/phase14-catalog-override.ts +67 -16
- package/src/repair-fetch.ts +27 -3
- package/src/repair-layers.ts +7 -520
- package/test-vectors/catalog/README.md +39 -67
- package/test-vectors/catalog/fec-01-runtime/README.md +15 -0
- package/test-vectors/catalog/{negative/fec-block-profile-retired.json → fec-01-runtime/fec-iso-ssbg1.json} +1 -1
- package/test-vectors/catalog/fec-01-runtime/fec-layered-repair.json +106 -0
- package/test-vectors/catalog/{negative/fec-block-profile-unknown.json → fec-01-runtime/fec-multicast.json} +2 -1
- package/test-vectors/catalog/fec-01-runtime/multicast-native-ssm-no-network-source.json +44 -0
- package/test-vectors/catalog/negative/fec-block-profile-missing.json +24 -11
- package/test-vectors/catalog/negative/fec-iso-symbol-size-below-floor.json +13 -8
- package/test-vectors/catalog/negative/fec-reed-solomon-iso-symbol-size-13.json +13 -8
- package/test-vectors/catalog/negative/fec-repair-layer-geometry.json +20 -10
- package/test-vectors/catalog/negative/fec-repair-layer-missing-symbols.json +20 -10
- package/test-vectors/catalog/negative/fec-repair-overlay-source-symbols-zero.json +25 -17
- package/test-vectors/catalog/negative/fec-repair-symbols-zero.json +13 -8
- package/test-vectors/catalog/negative/fec-source-symbols-zero.json +13 -8
- package/test-vectors/catalog/negative/fec-symbol-size-zero.json +13 -8
- package/test-vectors/catalog/negative/raptorq-source-symbols-over-max.json +18 -9
- package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +13 -8
- package/test-vectors/catalog/positive/fec-algorithm-unimplemented.json +14 -9
- package/test-vectors/catalog/positive/fec-iso-ssbg1.json +25 -12
- package/test-vectors/catalog/positive/fec-layered-repair.json +79 -35
- package/test-vectors/catalog/positive/fec-multicast.json +26 -13
- package/test-vectors/catalog/positive/fec-reed-solomon-layered.json +29 -18
- package/test-vectors/catalog/positive/multicast-draft01-4-1-example.json +28 -20
- package/test-vectors/catalog/positive/multicast-draft01-7-2-6-example.json +14 -10
- package/test-vectors/catalog/positive/multicast-native-ssm-no-network-source.json +22 -12
- package/test-vectors/catalog/section-codes.json +13 -22
- package/test-vectors/catalog-timing.json +2 -2
- package/test-vectors/catalog-validation.json +30 -243
- package/test-vectors/catalog/negative/fec-enhancement-repair-removed.json +0 -28
- package/test-vectors/catalog/negative/fec-reed-solomon-k-plus-p-over-255.json +0 -39
- package/test-vectors/catalog/negative/fec-reed-solomon-overlay-over-255.json +0 -40
- package/test-vectors/catalog/negative/fec-repair-multiple-depends.json +0 -32
- package/test-vectors/catalog/negative/fec-repair-overlay-with-layer.json +0 -34
- package/test-vectors/catalog/negative/fec-repair-priority-out-of-band.json +0 -24
- package/test-vectors/catalog/negative/fec-repair-source-symbols-without-scope.json +0 -33
package/dist/fec-state.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { isoBlockSpanUsable } from '@blockcast/mmt-base';
|
|
2
|
-
/** The optional elapsed-span rule lives in mmt-base beside the other catalog FEC rules. */
|
|
3
|
-
export { isoBlockSpanUsable };
|
|
4
1
|
/** Smallest positive catalog elapsed span; zero/absence means no elapsed deadline. */
|
|
5
2
|
export declare const MIN_INTERLEAVE_DEPTH_MS = 1;
|
|
6
3
|
/** Why FEC is not protecting this session. */
|
|
@@ -54,47 +51,12 @@ export interface FecStateEvidence<S extends object> {
|
|
|
54
51
|
readonly multicastLegJoined: boolean;
|
|
55
52
|
}
|
|
56
53
|
/**
|
|
57
|
-
* Whether
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* (`fecAlgorithmUnimplemented`, draft-ramadan-moq-fec-01 4), `blockProfile` names the implemented profile
|
|
62
|
-
* `iso-ssbg1-v1` (BLO-35597), and the block carries that profile's usable
|
|
63
|
-
* span field (`isoBlockSpanUsable`); zero/absence still permits in-band FEC. Total: it never throws, and answers false for
|
|
64
|
-
* any other value.
|
|
65
|
-
*
|
|
66
|
-
* `resolveCatalogTrackFec` reads this predicate, so the players' parameters and
|
|
67
|
-
* this state never disagree. Of the blocks this rejects, it returns no FEC
|
|
68
|
-
* geometry only for `algorithm: "none"`. One with any other algorithm is a
|
|
69
|
-
* malformed catalog (`FecCatalogConfig` marks both fields REQUIRED; the MSF
|
|
70
|
-
* schema and `validateCmsfMmtpCatalog` enforce them on `tracks[]`, but the
|
|
71
|
-
* hang dialect's `renditions` schema is permissive, so this is where a hang
|
|
72
|
-
* block fails closed), and `resolveCatalogTrackFec` throws a `RepairContractError` for
|
|
73
|
-
* it (`track_fec` unless another repair-contract violation fires first),
|
|
74
|
-
* whether or not the source has repair layers, rather than silently dropping
|
|
75
|
-
* the track's repair subscription.
|
|
76
|
-
*
|
|
77
|
-
* The block profile is part of this predicate because the profile selects the
|
|
78
|
-
* block math and is never defaulted: draft-ramadan-moq-fec §5.1 defines one,
|
|
79
|
-
* `iso-ssbg1-v1`, and a receiver MUST NOT apply FEC under any other token. The
|
|
80
|
-
* retired `k-padded-v1` is simply not a known profile. `resolveCatalogTrackFec`
|
|
81
|
-
* and `MulticastManager.configureMultiTrack` resolve such a track to no FEC
|
|
82
|
-
* with a typed `TrackFecUnavailable` reason (`catalogFecUnavailable`: code
|
|
83
|
-
* `track_fec_block_profile_unimplemented` for an unimplemented token,
|
|
84
|
-
* `track_fec_block_profile` for an absent one), scoped to that track, so their
|
|
85
|
-
* parameters and this state still agree. The CMSF conformance validator
|
|
86
|
-
* (`validateCmsfMmtpCatalog`) rejects the catalog with the same code. An
|
|
87
|
-
* `iso-ssbg1-v1` instance with an invalid span is likewise unavailable for its
|
|
88
|
-
* track alone. Zero or absence supplies no elapsed deadline and uses bounded
|
|
89
|
-
* receiver-local state while decoding in-band FEC.
|
|
90
|
-
*
|
|
91
|
-
* The repair-contract resolvers (`resolveRepairLayers`) gate a `depends` target
|
|
92
|
-
* on `algorithm` alone and never read a source's `symbolSize`. They check its
|
|
93
|
-
* `sourceSymbols` for the RaptorQ K bound, and require a positive integer
|
|
94
|
-
* `sourceSymbols` and `repairSymbols` only when the source has repair layers or
|
|
95
|
-
* an overlay beyond layer 0.
|
|
54
|
+
* Whether the catalog gives the named source track FEC this receiver can run:
|
|
55
|
+
* its base instance is `ok` (`resolveFecBindings`, draft-ramadan-moq-fec-catalog-00).
|
|
56
|
+
* `resolveCatalogTrackFec` reads the same binding, so the players' parameters
|
|
57
|
+
* and this state never disagree. Total: never throws.
|
|
96
58
|
*/
|
|
97
|
-
export declare function catalogDeclaresFec(
|
|
59
|
+
export declare function catalogDeclaresFec(catalog: unknown, track: string): boolean;
|
|
98
60
|
/**
|
|
99
61
|
* Resolve a player's FEC state. First match wins:
|
|
100
62
|
*
|
package/dist/fec-state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fec-state.d.ts","sourceRoot":"","sources":["../src/fec-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fec-state.d.ts","sourceRoot":"","sources":["../src/fec-state.ts"],"names":[],"mappings":"AAiBA,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,8CAA8C;AAC9C,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG,cAAc,GAAG,qBAAqB,CAAA;AAEzF,kDAAkD;AAClD,eAAO,MAAM,oBAAoB,EAAE,SAAS,iBAAiB,EAIlD,CAAA;AAEX,4DAA4D;AAC5D,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,UAAU,GAAG,gBAAgB,CAAA;AAIvE,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAA;CACnC;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAA;AAE/E,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI,cAAc,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAA;AAE7E,sEAAsE;AACtE,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAEhD,uDAAuD;AACvD,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM;IAChD;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,CAAA;IACpC;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,eAAe,EAAE,kBAAkB,CAAA;IAC5C,gFAAgF;IAChF,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;IACjC;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAA;CACrC;AAcD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAE3E;AASD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;AACrH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,aAAa,CAAC,CAAA"}
|
package/dist/fec-state.js
CHANGED
|
@@ -12,36 +12,537 @@ var NTP_SHORT_HALF_RANGE = 2 ** (NTP_SHORT_BITS - 1);
|
|
|
12
12
|
var FEC_BLOCK_PROFILES = Object.freeze([
|
|
13
13
|
"iso-ssbg1-v1"
|
|
14
14
|
]);
|
|
15
|
-
function isFecBlockProfile(value) {
|
|
16
|
-
return value === "iso-ssbg1-v1";
|
|
17
|
-
}
|
|
18
15
|
|
|
19
|
-
// ../mmt-base/dist/
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
16
|
+
// ../mmt-base/dist/fec-catalog.js
|
|
17
|
+
var DEFAULT_SCHEMES = ["reed-solomon", "raptorq"];
|
|
18
|
+
var DEFAULT_PROFILES = ["moq-object-v1", "iso-ssbg1-v1"];
|
|
19
|
+
var RS_MAX_BLOCK = 255;
|
|
20
|
+
var RAPTORQ_MAX_K = 56403;
|
|
21
|
+
var MAX_24 = 16777215;
|
|
22
|
+
var ISO_MIN_T = 14;
|
|
23
|
+
var GEOMETRY_KEYS = [
|
|
24
|
+
"scheme",
|
|
25
|
+
"blockProfile",
|
|
26
|
+
"mmtpMode",
|
|
27
|
+
"timescale",
|
|
28
|
+
"symbolSize",
|
|
29
|
+
"interleaveDepthMs",
|
|
30
|
+
"reorderToleranceMs",
|
|
31
|
+
"sourceSymbols",
|
|
32
|
+
"fec"
|
|
33
|
+
];
|
|
34
|
+
var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
35
|
+
var has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
|
|
36
|
+
var isInt = (v) => typeof v === "number" && Number.isInteger(v);
|
|
37
|
+
var intIn = (v, lo, hi = Number.MAX_SAFE_INTEGER) => isInt(v) && v >= lo && v <= hi;
|
|
38
|
+
var profileAdmits = (profile, packaging) => profile !== "iso-ssbg1-v1" || packaging === "mmtp";
|
|
39
|
+
function validateFecCatalog(catalog, receiver = {}) {
|
|
40
|
+
const schemes = receiver.schemes ?? DEFAULT_SCHEMES;
|
|
41
|
+
const profiles = receiver.blockProfiles ?? DEFAULT_PROFILES;
|
|
42
|
+
const overlays = receiver.overlays ?? true;
|
|
43
|
+
const all = [];
|
|
44
|
+
const report = (code, path, inst) => {
|
|
45
|
+
const issue = { code, path };
|
|
46
|
+
all.push(issue);
|
|
47
|
+
inst?.issues.push(issue);
|
|
48
|
+
};
|
|
49
|
+
const tracks = isObj(catalog) && Array.isArray(catalog.tracks) ? catalog.tracks : [];
|
|
50
|
+
if (!isObj(catalog) || !Array.isArray(catalog.tracks))
|
|
51
|
+
report("fec_member", "/tracks");
|
|
52
|
+
let rejectAll = false;
|
|
53
|
+
tracks.forEach((t, ti) => {
|
|
54
|
+
if (!isObj(t))
|
|
55
|
+
return;
|
|
56
|
+
if (has(t, "enhancementRepair")) {
|
|
57
|
+
rejectAll = true;
|
|
58
|
+
report("fec_enhancement_repair", `/tracks/${ti}/enhancementRepair`);
|
|
59
|
+
}
|
|
60
|
+
if (Array.isArray(t.fec))
|
|
61
|
+
t.fec.forEach((o, ii) => {
|
|
62
|
+
if (isObj(o) && has(o, "enhancementRepair")) {
|
|
63
|
+
rejectAll = true;
|
|
64
|
+
report("fec_enhancement_repair", `/tracks/${ti}/fec/${ii}/enhancementRepair`);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
const key = (ns, name) => JSON.stringify([ns ?? null, name]);
|
|
69
|
+
const byName = /* @__PURE__ */ new Map();
|
|
70
|
+
tracks.forEach((t, ti) => {
|
|
71
|
+
if (isObj(t) && typeof t.name === "string") {
|
|
72
|
+
const k = key(t.namespace, t.name);
|
|
73
|
+
if (!byName.has(k))
|
|
74
|
+
byName.set(k, ti);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
const trackAt = (ti) => tracks[ti];
|
|
78
|
+
const insts = [];
|
|
79
|
+
tracks.forEach((t, ti) => {
|
|
80
|
+
if (!isObj(t) || !has(t, "fec") || t.packaging === "fec-repair" || t.packaging === "fec-source")
|
|
81
|
+
return;
|
|
82
|
+
if (!Array.isArray(t.fec)) {
|
|
83
|
+
report("fec_member", `/tracks/${ti}/fec`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
t.fec.forEach((o, ii) => {
|
|
87
|
+
const path = `/tracks/${ti}/fec/${ii}`;
|
|
88
|
+
const inst = {
|
|
89
|
+
path,
|
|
90
|
+
ti,
|
|
91
|
+
track: t,
|
|
92
|
+
obj: isObj(o) ? o : null,
|
|
93
|
+
id: null,
|
|
94
|
+
unavailable: false,
|
|
95
|
+
overlay: false,
|
|
96
|
+
issues: [],
|
|
97
|
+
layer0: null,
|
|
98
|
+
symbolNamed: null,
|
|
99
|
+
attached: []
|
|
100
|
+
};
|
|
101
|
+
insts.push(inst);
|
|
102
|
+
if (!inst.obj)
|
|
103
|
+
return report("fec_member", path, inst);
|
|
104
|
+
const o2 = inst.obj;
|
|
105
|
+
if (!has(o2, "instanceId"))
|
|
106
|
+
inst.id = 0;
|
|
107
|
+
else if (intIn(o2.instanceId, 0, 255))
|
|
108
|
+
inst.id = o2.instanceId;
|
|
109
|
+
else
|
|
110
|
+
report("fec_member", `${path}/instanceId`, inst);
|
|
111
|
+
inst.overlay = has(o2, "scope");
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
const declaresFec = insts.length > 0;
|
|
115
|
+
for (const inst of insts) {
|
|
116
|
+
const o = inst.obj;
|
|
117
|
+
if (!o)
|
|
118
|
+
continue;
|
|
119
|
+
const avail = (field, impl) => {
|
|
120
|
+
const p = `${inst.path}/${field}`;
|
|
121
|
+
const absent = field === "scheme" ? "fec_scheme_absent" : "fec_block_profile_absent";
|
|
122
|
+
const unimpl = field === "scheme" ? "fec_scheme_unimplemented" : "fec_block_profile_unimplemented";
|
|
123
|
+
if (!has(o, field))
|
|
124
|
+
return report(absent, p, inst), false;
|
|
125
|
+
if (typeof o[field] !== "string")
|
|
126
|
+
return report("fec_member", p, inst), true;
|
|
127
|
+
if (!impl.includes(o[field]))
|
|
128
|
+
return report(unimpl, p, inst), false;
|
|
129
|
+
return true;
|
|
130
|
+
};
|
|
131
|
+
if (!avail("scheme", schemes) || !avail("blockProfile", profiles))
|
|
132
|
+
inst.unavailable = true;
|
|
133
|
+
else if (typeof o.blockProfile === "string" && !profileAdmits(o.blockProfile, inst.track.packaging)) {
|
|
134
|
+
report("fec_block_profile_packaging", `${inst.path}/blockProfile`, inst);
|
|
135
|
+
inst.unavailable = true;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const live = (i) => !i.unavailable;
|
|
139
|
+
for (const inst of insts.filter(live)) {
|
|
140
|
+
const o = inst.obj;
|
|
141
|
+
if (!o)
|
|
142
|
+
continue;
|
|
143
|
+
const p = inst.path;
|
|
144
|
+
for (const m of ["sourceSymbols", "repairSymbols", "symbolSize"])
|
|
145
|
+
if (!intIn(o[m], 1))
|
|
146
|
+
report("fec_member", `${p}/${m}`, inst);
|
|
147
|
+
if (typeof o.repairTrack !== "string")
|
|
148
|
+
report("fec_member", `${p}/repairTrack`, inst);
|
|
149
|
+
if (has(o, "symbolTrack") && typeof o.symbolTrack !== "string")
|
|
150
|
+
report("fec_member", `${p}/symbolTrack`, inst);
|
|
151
|
+
if (has(o, "interleaveDepthMs")) {
|
|
152
|
+
const d = o.interleaveDepthMs;
|
|
153
|
+
if (!intIn(d, 0) || d === 0 && o.blockProfile !== "iso-ssbg1-v1")
|
|
154
|
+
report("fec_member", `${p}/interleaveDepthMs`, inst);
|
|
155
|
+
}
|
|
156
|
+
if (has(o, "reorderToleranceMs")) {
|
|
157
|
+
const r = o.reorderToleranceMs;
|
|
158
|
+
if (typeof r !== "number" || !Number.isFinite(r) || r < 0)
|
|
159
|
+
report("fec_member", `${p}/reorderToleranceMs`, inst);
|
|
160
|
+
}
|
|
161
|
+
if (has(o, "label") && typeof o.label !== "string")
|
|
162
|
+
report("fec_member", `${p}/label`, inst);
|
|
163
|
+
if (inst.overlay && o.scope !== "keyframe")
|
|
164
|
+
report("fec_member", `${p}/scope`, inst);
|
|
165
|
+
}
|
|
166
|
+
const idGroups = /* @__PURE__ */ new Map();
|
|
167
|
+
for (const inst of insts)
|
|
168
|
+
if (inst.id !== null) {
|
|
169
|
+
const k = `${inst.ti}:${inst.id}`;
|
|
170
|
+
idGroups.set(k, [...idGroups.get(k) ?? [], inst]);
|
|
171
|
+
}
|
|
172
|
+
for (const group of idGroups.values())
|
|
173
|
+
if (group.length > 1)
|
|
174
|
+
for (const inst of group.filter(live))
|
|
175
|
+
report("fec_instance_id", inst.obj && has(inst.obj, "instanceId") ? `${inst.path}/instanceId` : inst.path, inst);
|
|
176
|
+
const nameUses = /* @__PURE__ */ new Map();
|
|
177
|
+
for (const inst of insts)
|
|
178
|
+
for (const field of ["repairTrack", "symbolTrack"])
|
|
179
|
+
if (inst.obj && typeof inst.obj[field] === "string") {
|
|
180
|
+
const k = key(inst.track.namespace, inst.obj[field]);
|
|
181
|
+
nameUses.set(k, [...nameUses.get(k) ?? [], { inst, field }]);
|
|
182
|
+
}
|
|
183
|
+
const namedBy = /* @__PURE__ */ new Map();
|
|
184
|
+
for (const [k, uses] of nameUses) {
|
|
185
|
+
const tj = byName.get(k);
|
|
186
|
+
for (const { inst, field } of uses) {
|
|
187
|
+
const path = `${inst.path}/${field}`;
|
|
188
|
+
if (tj === void 0 || trackAt(tj).packaging !== (field === "repairTrack" ? "fec-repair" : "fec-source")) {
|
|
189
|
+
if (live(inst))
|
|
190
|
+
report("fec_naming", path, inst);
|
|
191
|
+
} else if (uses.length > 1) {
|
|
192
|
+
if (live(inst))
|
|
193
|
+
report("fec_naming", path, inst);
|
|
194
|
+
if (!namedBy.has(tj))
|
|
195
|
+
namedBy.set(tj, inst);
|
|
196
|
+
} else {
|
|
197
|
+
namedBy.set(tj, inst);
|
|
198
|
+
if (field === "repairTrack")
|
|
199
|
+
inst.layer0 = tj;
|
|
200
|
+
else
|
|
201
|
+
inst.symbolNamed = tj;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const owner = /* @__PURE__ */ new Map();
|
|
206
|
+
if (declaresFec)
|
|
207
|
+
tracks.forEach((t, tj) => {
|
|
208
|
+
if (!isObj(t) || t.packaging !== "fec-repair" && t.packaging !== "fec-source")
|
|
209
|
+
return;
|
|
210
|
+
const tp = `/tracks/${tj}`;
|
|
211
|
+
const named = namedBy.get(tj);
|
|
212
|
+
if (named) {
|
|
213
|
+
owner.set(tj, named);
|
|
214
|
+
if (!live(named))
|
|
215
|
+
return;
|
|
216
|
+
if (has(t, "source") && t.source !== named.track.name)
|
|
217
|
+
report("fec_resolution", `${tp}/source`, named);
|
|
218
|
+
if (has(t, "instanceId") && t.instanceId !== named.id)
|
|
219
|
+
report("fec_resolution", `${tp}/instanceId`, named);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (!has(t, "source"))
|
|
223
|
+
return report("fec_orphan", tp);
|
|
224
|
+
const id = has(t, "instanceId") ? t.instanceId : 0;
|
|
225
|
+
const src = typeof t.source === "string" ? byName.get(key(t.namespace, t.source)) : void 0;
|
|
226
|
+
const target = src === void 0 ? void 0 : insts.find((i) => i.ti === src && i.id === id);
|
|
227
|
+
if (!target)
|
|
228
|
+
return report("fec_naming", has(t, "instanceId") && src !== void 0 ? `${tp}/instanceId` : `${tp}/source`);
|
|
229
|
+
owner.set(tj, target);
|
|
230
|
+
target.attached.push(tj);
|
|
231
|
+
});
|
|
232
|
+
for (const [tj, inst] of owner) {
|
|
233
|
+
if (!live(inst))
|
|
234
|
+
continue;
|
|
235
|
+
const t = trackAt(tj);
|
|
236
|
+
const tp = `/tracks/${tj}`;
|
|
237
|
+
const symbol = t.packaging === "fec-source";
|
|
238
|
+
if (has(t, "source") && typeof t.source !== "string")
|
|
239
|
+
report("fec_member", `${tp}/source`, inst);
|
|
240
|
+
if (has(t, "instanceId") && !intIn(t.instanceId, 0, 255))
|
|
241
|
+
report("fec_member", `${tp}/instanceId`, inst);
|
|
242
|
+
for (const m of ["repairLayer", "repairSymbols"]) {
|
|
243
|
+
if (!has(t, m))
|
|
244
|
+
continue;
|
|
245
|
+
if (symbol || !intIn(t[m], m === "repairLayer" ? 0 : 1))
|
|
246
|
+
report("fec_member", `${tp}/${m}`, inst);
|
|
247
|
+
}
|
|
248
|
+
if (has(t, "priority") && !intIn(t.priority, symbol ? 0 : 192, 255))
|
|
249
|
+
report("fec_member", `${tp}/priority`, inst);
|
|
250
|
+
for (const k of Object.keys(t))
|
|
251
|
+
if (GEOMETRY_KEYS.includes(k) || k.startsWith("groupDuration"))
|
|
252
|
+
report("fec_track_geometry", `${tp}/${k.replace(/~/g, "~0").replace(/\//g, "~1")}`, inst);
|
|
253
|
+
}
|
|
254
|
+
for (const inst of insts.filter(live)) {
|
|
255
|
+
const o = inst.obj;
|
|
256
|
+
if (!o)
|
|
257
|
+
continue;
|
|
258
|
+
const repairs = inst.attached.filter((tj) => trackAt(tj).packaging === "fec-repair");
|
|
259
|
+
const symbols = inst.attached.filter((tj) => trackAt(tj).packaging === "fec-source");
|
|
260
|
+
if (symbols.length + (inst.symbolNamed !== null ? 1 : 0) > 1)
|
|
261
|
+
for (const tj of symbols)
|
|
262
|
+
report("fec_symbol_tracks", `/tracks/${tj}`, inst);
|
|
263
|
+
const l0 = inst.layer0 === null ? null : trackAt(inst.layer0);
|
|
264
|
+
const l0p = `/tracks/${inst.layer0}`;
|
|
265
|
+
if (inst.overlay) {
|
|
266
|
+
if (l0 && has(l0, "repairLayer"))
|
|
267
|
+
report("fec_overlay", `${l0p}/repairLayer`, inst);
|
|
268
|
+
for (const tj of repairs)
|
|
269
|
+
report("fec_overlay", has(trackAt(tj), "repairLayer") ? `/tracks/${tj}/repairLayer` : `/tracks/${tj}`, inst);
|
|
270
|
+
} else {
|
|
271
|
+
if (l0 && has(l0, "repairLayer") && l0.repairLayer !== 0)
|
|
272
|
+
report("fec_layers", `${l0p}/repairLayer`, inst);
|
|
273
|
+
if (l0 && has(l0, "repairSymbols") && intIn(o.repairSymbols, 1) && l0.repairSymbols !== o.repairSymbols)
|
|
274
|
+
report("fec_layer0", `${l0p}/repairSymbols`, inst);
|
|
275
|
+
const layers = [];
|
|
276
|
+
for (const tj of repairs) {
|
|
277
|
+
const t = trackAt(tj);
|
|
278
|
+
if (!has(t, "repairLayer"))
|
|
279
|
+
report("fec_member", `/tracks/${tj}/repairLayer`, inst);
|
|
280
|
+
else if (t.repairLayer === 0)
|
|
281
|
+
report("fec_layers", `/tracks/${tj}/repairLayer`, inst);
|
|
282
|
+
else if (intIn(t.repairLayer, 1))
|
|
283
|
+
layers.push({ tj, layer: t.repairLayer });
|
|
284
|
+
if (!has(t, "repairSymbols"))
|
|
285
|
+
report("fec_member", `/tracks/${tj}/repairSymbols`, inst);
|
|
286
|
+
}
|
|
287
|
+
const counts = /* @__PURE__ */ new Map();
|
|
288
|
+
for (const { layer } of layers)
|
|
289
|
+
counts.set(layer, (counts.get(layer) ?? 0) + 1);
|
|
290
|
+
let missing = 1;
|
|
291
|
+
while (counts.has(missing))
|
|
292
|
+
missing++;
|
|
293
|
+
for (const { tj, layer } of layers)
|
|
294
|
+
if (counts.get(layer) > 1 || layer > missing)
|
|
295
|
+
report("fec_layers", `/tracks/${tj}/repairLayer`, inst);
|
|
296
|
+
const chain = [
|
|
297
|
+
{ layer: 0, tj: inst.layer0, pri: l0 && intIn(l0.priority, 192, 255) ? l0.priority : l0 && has(l0, "priority") ? null : 240 },
|
|
298
|
+
...layers.map(({ tj, layer }) => {
|
|
299
|
+
const pr = trackAt(tj).priority;
|
|
300
|
+
return { layer, tj, pri: intIn(pr, 192, 255) ? pr : null };
|
|
301
|
+
})
|
|
302
|
+
].sort((a, b) => a.layer - b.layer);
|
|
303
|
+
let prev = null;
|
|
304
|
+
for (const c of chain) {
|
|
305
|
+
if (c.pri === null)
|
|
306
|
+
continue;
|
|
307
|
+
if (prev !== null && c.pri < prev)
|
|
308
|
+
report("fec_priority", `/tracks/${c.tj}/priority`, inst);
|
|
309
|
+
prev = Math.max(prev ?? c.pri, c.pri);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
const K = o.sourceSymbols;
|
|
313
|
+
const T = o.symbolSize;
|
|
314
|
+
const P0 = o.repairSymbols;
|
|
315
|
+
if (intIn(K, 1) && intIn(P0, 1)) {
|
|
316
|
+
let P = P0;
|
|
317
|
+
if (!inst.overlay)
|
|
318
|
+
for (const tj of repairs) {
|
|
319
|
+
const t = trackAt(tj);
|
|
320
|
+
if (intIn(t.repairLayer, 1) && intIn(t.repairSymbols, 1))
|
|
321
|
+
P += t.repairSymbols;
|
|
322
|
+
}
|
|
323
|
+
if (P > MAX_24 || K + P - 1 > MAX_24)
|
|
324
|
+
report("fec_bounds", inst.path, inst);
|
|
325
|
+
else if (o.scheme === "reed-solomon" && K + P > RS_MAX_BLOCK)
|
|
326
|
+
report("fec_bounds", inst.path, inst);
|
|
327
|
+
}
|
|
328
|
+
if (o.scheme === "raptorq" && intIn(K, 1) && K > RAPTORQ_MAX_K)
|
|
329
|
+
report("fec_bounds", `${inst.path}/sourceSymbols`, inst);
|
|
330
|
+
if (intIn(T, 1)) {
|
|
331
|
+
if (o.scheme === "raptorq" && T % 8 !== 0)
|
|
332
|
+
report("fec_bounds", `${inst.path}/symbolSize`, inst);
|
|
333
|
+
else if (o.blockProfile === "iso-ssbg1-v1" && T < ISO_MIN_T)
|
|
334
|
+
report("fec_bounds", `${inst.path}/symbolSize`, inst);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const overlayTracks = new Set(insts.filter((i) => live(i) && i.overlay).map((i) => i.ti));
|
|
338
|
+
for (const ti of overlayTracks) {
|
|
339
|
+
const ofTrack = insts.filter((i) => i.ti === ti && live(i));
|
|
340
|
+
const ovs = ofTrack.filter((i) => i.overlay);
|
|
341
|
+
if (!overlays) {
|
|
342
|
+
for (const ov of ovs)
|
|
343
|
+
report("fec_overlay_unsupported", `${ov.path}/scope`, ov);
|
|
344
|
+
for (const i of ofTrack)
|
|
345
|
+
i.issues.length === 0 && i.issues.push({ code: "fec_overlay_unsupported", path: `${ovs[0].path}/scope` });
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
if (ovs.length > 1)
|
|
349
|
+
for (const ov of ovs)
|
|
350
|
+
report("fec_overlay", `${ov.path}/scope`, ov);
|
|
351
|
+
for (const ov of ovs)
|
|
352
|
+
if (ov.obj?.blockProfile !== "iso-ssbg1-v1")
|
|
353
|
+
report("fec_overlay", `${ov.path}/blockProfile`, ov);
|
|
354
|
+
const cause = ovs.flatMap((ov) => ov.issues).find((x) => x.code === "fec_overlay");
|
|
355
|
+
if (cause) {
|
|
356
|
+
for (const ov of ovs)
|
|
357
|
+
if (ov.issues.length === 0)
|
|
358
|
+
ov.issues.push(cause);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
const rule4 = all.find((x) => x.code === "fec_enhancement_repair");
|
|
362
|
+
if (rejectAll && rule4) {
|
|
363
|
+
for (const i of insts)
|
|
364
|
+
if (i.issues.length === 0)
|
|
365
|
+
i.issues.push(rule4);
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
instances: insts.map((i) => ({
|
|
369
|
+
path: i.path,
|
|
370
|
+
track: typeof i.track.name === "string" ? i.track.name : null,
|
|
371
|
+
instanceId: i.id,
|
|
372
|
+
outcome: rejectAll || !i.unavailable && i.issues.length > 0 ? "violation" : i.unavailable ? "unavailable" : "ok",
|
|
373
|
+
issues: i.issues,
|
|
374
|
+
trackIndex: i.ti,
|
|
375
|
+
repairTrack: i.layer0,
|
|
376
|
+
boundRepairTracks: i.attached.filter((tj) => trackAt(tj).packaging === "fec-repair"),
|
|
377
|
+
symbolTrack: i.symbolNamed ?? i.attached.find((tj) => trackAt(tj).packaging === "fec-source") ?? null
|
|
378
|
+
})),
|
|
379
|
+
issues: all
|
|
380
|
+
};
|
|
30
381
|
}
|
|
31
|
-
|
|
32
|
-
|
|
382
|
+
|
|
383
|
+
// ../mmt-base/dist/fec-bindings.js
|
|
384
|
+
var RUNTIME_FEC_RECEIVER = Object.freeze({
|
|
385
|
+
schemes: Object.freeze(["raptorq", "reed-solomon"]),
|
|
386
|
+
blockProfiles: Object.freeze(["iso-ssbg1-v1"]),
|
|
387
|
+
overlays: true
|
|
388
|
+
});
|
|
389
|
+
var DEFAULT_FEC_REPAIR_PRIORITY = 240;
|
|
390
|
+
var recordOf = (v) => typeof v === "object" && v !== null && !Array.isArray(v) ? v : void 0;
|
|
391
|
+
var escape = (s) => s.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
392
|
+
function fecCatalogTracks(catalog) {
|
|
393
|
+
const root = recordOf(catalog) ?? {};
|
|
394
|
+
const tracks = [];
|
|
395
|
+
const pointers = [];
|
|
396
|
+
const hangNames = /* @__PURE__ */ new Set();
|
|
397
|
+
for (const role of ["video", "audio"]) {
|
|
398
|
+
for (const [name, r] of Object.entries(recordOf(recordOf(root[role])?.["renditions"]) ?? {})) {
|
|
399
|
+
const entry = recordOf(r);
|
|
400
|
+
if (!entry)
|
|
401
|
+
continue;
|
|
402
|
+
hangNames.add(name);
|
|
403
|
+
const kind = recordOf(entry["container"])?.["kind"];
|
|
404
|
+
const view = { name, packaging: kind === void 0 || kind === "mmtp-fec" ? "mmtp" : kind };
|
|
405
|
+
if (entry["fec"] !== void 0)
|
|
406
|
+
view["fec"] = entry["fec"];
|
|
407
|
+
tracks.push(view);
|
|
408
|
+
pointers.push(`/${role}/renditions/${escape(name)}`);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
const hangRenditions = tracks.length;
|
|
412
|
+
for (const [name, r] of Object.entries(recordOf(recordOf(root["repair"])?.["renditions"]) ?? {})) {
|
|
413
|
+
hangNames.add(name);
|
|
414
|
+
tracks.push({ packaging: "fec-repair", ...recordOf(r), name });
|
|
415
|
+
pointers.push(`/repair/renditions/${escape(name)}`);
|
|
416
|
+
}
|
|
417
|
+
const raw = Array.isArray(root["tracks"]) ? root["tracks"] : [];
|
|
418
|
+
const named = new Set(hangNames);
|
|
419
|
+
raw.forEach((t, i) => {
|
|
420
|
+
const name = recordOf(t)?.["name"];
|
|
421
|
+
if (typeof name === "string")
|
|
422
|
+
named.add(name);
|
|
423
|
+
if (typeof name === "string" && hangNames.has(name))
|
|
424
|
+
return;
|
|
425
|
+
tracks.push(t);
|
|
426
|
+
pointers.push(`/tracks/${i}`);
|
|
427
|
+
});
|
|
428
|
+
tracks.slice(0, hangRenditions).forEach((t, ti) => {
|
|
429
|
+
const view = t;
|
|
430
|
+
if (!Array.isArray(view["fec"]))
|
|
431
|
+
return;
|
|
432
|
+
view["fec"].forEach((o, ii) => {
|
|
433
|
+
const repairTrack = recordOf(o)?.["repairTrack"];
|
|
434
|
+
if (typeof repairTrack !== "string" || named.has(repairTrack))
|
|
435
|
+
return;
|
|
436
|
+
named.add(repairTrack);
|
|
437
|
+
const instanceId = recordOf(o)?.["instanceId"];
|
|
438
|
+
tracks.push({ name: repairTrack, packaging: "fec-repair", source: view["name"], ...instanceId === void 0 ? {} : { instanceId } });
|
|
439
|
+
pointers.push(`${pointers[ti]}/fec/${ii}/repairTrack`);
|
|
440
|
+
});
|
|
441
|
+
});
|
|
442
|
+
return { tracks, pointers };
|
|
33
443
|
}
|
|
34
|
-
function
|
|
35
|
-
|
|
444
|
+
function resolveFecBindings(catalog, receiver = RUNTIME_FEC_RECEIVER) {
|
|
445
|
+
const { tracks, pointers } = fecCatalogTracks(catalog);
|
|
446
|
+
const report = validateFecCatalog({ tracks }, receiver);
|
|
447
|
+
const at = (path) => {
|
|
448
|
+
const m = /^\/tracks\/(\d+)(.*)$/.exec(path);
|
|
449
|
+
return m ? pointers[Number(m[1])] + m[2] : path;
|
|
450
|
+
};
|
|
451
|
+
const trackAt = (i) => recordOf(tracks[i]) ?? {};
|
|
452
|
+
const nameAt = (i) => i === null ? void 0 : trackAt(i)["name"];
|
|
453
|
+
const why = (i) => Object.freeze({
|
|
454
|
+
code: i.issues[0]?.code ?? "fec_member",
|
|
455
|
+
path: at(i.issues[0]?.path ?? i.path),
|
|
456
|
+
outcome: i.outcome === "unavailable" ? "unavailable" : "violation"
|
|
457
|
+
});
|
|
458
|
+
const out = /* @__PURE__ */ new Map();
|
|
459
|
+
tracks.forEach((t, ti) => {
|
|
460
|
+
const track = recordOf(t);
|
|
461
|
+
const name = track?.["name"];
|
|
462
|
+
if (!track || typeof name !== "string" || out.has(name))
|
|
463
|
+
return;
|
|
464
|
+
if (track["packaging"] === "fec-repair" || track["packaging"] === "fec-source")
|
|
465
|
+
return;
|
|
466
|
+
const fec = track["fec"];
|
|
467
|
+
if (fec === void 0)
|
|
468
|
+
return;
|
|
469
|
+
if (!Array.isArray(fec)) {
|
|
470
|
+
const reason = { code: "fec_member", path: at(`/tracks/${ti}/fec`), outcome: "violation" };
|
|
471
|
+
out.set(name, Object.freeze({ status: "unavailable", track: name, pointer: pointers[ti], reason: Object.freeze(reason) }));
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
if (fec.length === 0)
|
|
475
|
+
return;
|
|
476
|
+
const insts = report.instances.filter((i) => i.trackIndex === ti);
|
|
477
|
+
const isOverlay = (i) => Object.hasOwn(recordOf(fec[Number(i.path.split("/").pop())]) ?? {}, "scope");
|
|
478
|
+
const bases = insts.filter((i) => !isOverlay(i));
|
|
479
|
+
const okBases = bases.filter((i) => i.outcome === "ok");
|
|
480
|
+
if (okBases.length !== 1) {
|
|
481
|
+
const reason = (
|
|
482
|
+
// No base instance at all (overlay-only `fec`) is a count of 0, not
|
|
483
|
+
// the overlay's own issue.
|
|
484
|
+
okBases.length > 1 || bases.length === 0 ? Object.freeze({ code: "fec_base_instances", path: at(`/tracks/${ti}/fec`), outcome: "violation" }) : why(bases[0] ?? insts[0])
|
|
485
|
+
);
|
|
486
|
+
out.set(name, Object.freeze({ status: "unavailable", track: name, pointer: pointers[ti], reason }));
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
const b = okBases[0];
|
|
490
|
+
const base = geometry(recordOf(fec[Number(b.path.split("/").pop())]), b.instanceId, nameAt(b.symbolTrack));
|
|
491
|
+
const priorityOf = (i) => {
|
|
492
|
+
const p = i === null ? void 0 : trackAt(i)["priority"];
|
|
493
|
+
return typeof p === "number" ? p : DEFAULT_FEC_REPAIR_PRIORITY;
|
|
494
|
+
};
|
|
495
|
+
const layers = [
|
|
496
|
+
{ layer: 0, repairTrackName: base.repairTrack, repairSymbols: base.repairSymbols, rsIdOffset: 0, priority: priorityOf(b.repairTrack) }
|
|
497
|
+
];
|
|
498
|
+
const more = b.boundRepairTracks.map((tj) => ({ tj, layer: trackAt(tj)["repairLayer"] })).sort((x, y) => x.layer - y.layer);
|
|
499
|
+
let offset = base.repairSymbols;
|
|
500
|
+
for (const { tj, layer } of more) {
|
|
501
|
+
const repairSymbols = trackAt(tj)["repairSymbols"];
|
|
502
|
+
layers.push({ layer, repairTrackName: nameAt(tj), repairSymbols, rsIdOffset: offset, priority: priorityOf(tj) });
|
|
503
|
+
offset += repairSymbols;
|
|
504
|
+
}
|
|
505
|
+
let overlay;
|
|
506
|
+
let overlayUnavailable;
|
|
507
|
+
const ov = insts.find(isOverlay);
|
|
508
|
+
if (ov?.outcome === "ok") {
|
|
509
|
+
const g = geometry(recordOf(fec[Number(ov.path.split("/").pop())]), ov.instanceId, nameAt(ov.symbolTrack));
|
|
510
|
+
overlay = Object.freeze({
|
|
511
|
+
repairTrackName: g.repairTrack,
|
|
512
|
+
scope: "keyframe",
|
|
513
|
+
sourceSymbols: g.sourceSymbols,
|
|
514
|
+
repairSymbols: g.repairSymbols,
|
|
515
|
+
priority: priorityOf(ov.repairTrack),
|
|
516
|
+
geometry: g
|
|
517
|
+
});
|
|
518
|
+
} else if (ov)
|
|
519
|
+
overlayUnavailable = why(ov);
|
|
520
|
+
out.set(name, Object.freeze({
|
|
521
|
+
status: "ok",
|
|
522
|
+
track: name,
|
|
523
|
+
pointer: pointers[ti],
|
|
524
|
+
base,
|
|
525
|
+
layers: Object.freeze(layers.map((l) => Object.freeze(l))),
|
|
526
|
+
totalBaseRepairSymbols: offset,
|
|
527
|
+
...overlay ? { overlay } : {},
|
|
528
|
+
...overlayUnavailable ? { overlayUnavailable } : {}
|
|
529
|
+
}));
|
|
530
|
+
});
|
|
531
|
+
return out;
|
|
36
532
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
533
|
+
function geometry(o, instanceId, symbolTrack) {
|
|
534
|
+
return Object.freeze({
|
|
535
|
+
instanceId,
|
|
536
|
+
scheme: o["scheme"],
|
|
537
|
+
blockProfile: o["blockProfile"],
|
|
538
|
+
sourceSymbols: o["sourceSymbols"],
|
|
539
|
+
repairSymbols: o["repairSymbols"],
|
|
540
|
+
symbolSize: o["symbolSize"],
|
|
541
|
+
...typeof o["interleaveDepthMs"] === "number" ? { interleaveDepthMs: o["interleaveDepthMs"] } : {},
|
|
542
|
+
...typeof o["reorderToleranceMs"] === "number" ? { reorderToleranceMs: o["reorderToleranceMs"] } : {},
|
|
543
|
+
repairTrack: o["repairTrack"],
|
|
544
|
+
...symbolTrack !== void 0 ? { symbolTrack } : {}
|
|
545
|
+
});
|
|
45
546
|
}
|
|
46
547
|
|
|
47
548
|
// src/fec-state.ts
|
|
@@ -60,13 +561,8 @@ var INACTIVE = Object.freeze({
|
|
|
60
561
|
function recordOf2(value) {
|
|
61
562
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
62
563
|
}
|
|
63
|
-
function
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
function catalogDeclaresFec(fec) {
|
|
67
|
-
const block = recordOf2(fec);
|
|
68
|
-
if (block === void 0 || block["algorithm"] === "none" || fecAlgorithmUnimplemented(block["algorithm"])) return false;
|
|
69
|
-
return isPositiveSafeInteger2(block["sourceSymbols"]) && isPositiveSafeInteger2(block["symbolSize"]) && isFecBlockProfile(block["blockProfile"]) && isoBlockSpanUsable(block) && !catalogFecDeclaresUnconfigurableInstance(block);
|
|
564
|
+
function catalogDeclaresFec(catalog, track) {
|
|
565
|
+
return resolveFecBindings(catalog).get(track)?.status === "ok";
|
|
70
566
|
}
|
|
71
567
|
function requireBoolean(value, field) {
|
|
72
568
|
if (typeof value !== "boolean") {
|
|
@@ -97,7 +593,6 @@ export {
|
|
|
97
593
|
FEC_INACTIVE_REASONS,
|
|
98
594
|
MIN_INTERLEAVE_DEPTH_MS,
|
|
99
595
|
catalogDeclaresFec,
|
|
100
|
-
isoBlockSpanUsable,
|
|
101
596
|
resolveFecState
|
|
102
597
|
};
|
|
103
598
|
//# sourceMappingURL=fec-state.js.map
|