@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.
Files changed (136) hide show
  1. package/README.md +21 -16
  2. package/dist/browser-runtime.js +1024 -1078
  3. package/dist/browser-runtime.js.map +4 -4
  4. package/dist/carp-catalog.d.ts +33 -87
  5. package/dist/carp-catalog.d.ts.map +1 -1
  6. package/dist/carp-catalog.js +12 -434
  7. package/dist/carp-catalog.js.map +4 -4
  8. package/dist/catalog-fec-params.d.ts +48 -161
  9. package/dist/catalog-fec-params.d.ts.map +1 -1
  10. package/dist/catalog-fec-params.js +567 -592
  11. package/dist/catalog-fec-params.js.map +4 -4
  12. package/dist/catalog-network-source.js +6 -2
  13. package/dist/catalog-network-source.js.map +3 -3
  14. package/dist/delivery-catalog.js +12 -4
  15. package/dist/delivery-catalog.js.map +4 -4
  16. package/dist/delta-fallback-config.d.ts +21 -26
  17. package/dist/delta-fallback-config.d.ts.map +1 -1
  18. package/dist/delta-fallback-config.js +582 -24
  19. package/dist/delta-fallback-config.js.map +4 -4
  20. package/dist/fec-manager.js +6 -2
  21. package/dist/fec-manager.js.map +3 -3
  22. package/dist/fec-state.d.ts +5 -43
  23. package/dist/fec-state.d.ts.map +1 -1
  24. package/dist/fec-state.js +529 -34
  25. package/dist/fec-state.js.map +4 -4
  26. package/dist/fec-worker-setup.js +6 -2
  27. package/dist/fec-worker-setup.js.map +3 -3
  28. package/dist/held-layer-admission.js +6 -2
  29. package/dist/held-layer-admission.js.map +3 -3
  30. package/dist/index.d.ts +3 -3
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +5 -39
  33. package/dist/index.js.map +2 -2
  34. package/dist/iso-block-locator.js +6 -2
  35. package/dist/iso-block-locator.js.map +3 -3
  36. package/dist/mfu-reassembler.js +6 -2
  37. package/dist/mfu-reassembler.js.map +3 -3
  38. package/dist/mmtp-container-parser.js +6 -2
  39. package/dist/mmtp-container-parser.js.map +3 -3
  40. package/dist/mmtp-container-parser.no-modules.js +551 -452
  41. package/dist/mmtp-container-parser.no-modules.js.map +4 -4
  42. package/dist/mmtp-decode-pipeline.js +6 -2
  43. package/dist/mmtp-decode-pipeline.js.map +3 -3
  44. package/dist/mmtp-fec-session.d.ts +7 -6
  45. package/dist/mmtp-fec-session.d.ts.map +1 -1
  46. package/dist/mmtp-fec-session.js +13 -9
  47. package/dist/mmtp-fec-session.js.map +3 -3
  48. package/dist/mmtp-router.d.ts +7 -16
  49. package/dist/mmtp-router.d.ts.map +1 -1
  50. package/dist/mmtp-router.js +19 -29
  51. package/dist/mmtp-router.js.map +3 -3
  52. package/dist/multicast-auth-catalog.js +7 -3
  53. package/dist/multicast-auth-catalog.js.map +3 -3
  54. package/dist/multicast-input.js +7 -3
  55. package/dist/multicast-input.js.map +3 -3
  56. package/dist/multicast-manager.d.ts +29 -32
  57. package/dist/multicast-manager.d.ts.map +1 -1
  58. package/dist/multicast-manager.js +682 -253
  59. package/dist/multicast-manager.js.map +4 -4
  60. package/dist/multicast-transport.d.ts +23 -2
  61. package/dist/multicast-transport.d.ts.map +1 -1
  62. package/dist/multicast-transport.js +57 -16
  63. package/dist/multicast-transport.js.map +4 -4
  64. package/dist/multicast-unwrap.js +6 -2
  65. package/dist/multicast-unwrap.js.map +3 -3
  66. package/dist/no-modules.js +551 -452
  67. package/dist/no-modules.js.map +4 -4
  68. package/dist/phase14-catalog-override.d.ts +10 -5
  69. package/dist/phase14-catalog-override.d.ts.map +1 -1
  70. package/dist/phase14-catalog-override.js +35 -11
  71. package/dist/phase14-catalog-override.js.map +2 -2
  72. package/dist/repair-fetch.d.ts +3 -1
  73. package/dist/repair-fetch.d.ts.map +1 -1
  74. package/dist/repair-fetch.js +16 -3
  75. package/dist/repair-fetch.js.map +3 -3
  76. package/dist/repair-layers.d.ts +0 -123
  77. package/dist/repair-layers.d.ts.map +1 -1
  78. package/dist/repair-layers.js +1 -349
  79. package/dist/repair-layers.js.map +3 -3
  80. package/dist/signaling.js +6 -2
  81. package/dist/signaling.js.map +3 -3
  82. package/dist/timestamp-codec.js +6 -2
  83. package/dist/timestamp-codec.js.map +3 -3
  84. package/dist/wasm-mfu-reassembler.js +6 -2
  85. package/dist/wasm-mfu-reassembler.js.map +3 -3
  86. package/dist/wasm-mmtp-container-parser.js +6 -2
  87. package/dist/wasm-mmtp-container-parser.js.map +3 -3
  88. package/package.json +9 -5
  89. package/schemas/catalog.schema.json +53 -58
  90. package/src/carp-catalog.ts +39 -229
  91. package/src/catalog-fec-params.ts +130 -493
  92. package/src/delta-fallback-config.ts +63 -50
  93. package/src/fec-state.ts +7 -62
  94. package/src/index.ts +10 -30
  95. package/src/mmtp-fec-session.ts +11 -10
  96. package/src/mmtp-router.ts +14 -29
  97. package/src/multicast-manager.ts +89 -121
  98. package/src/multicast-transport.ts +65 -12
  99. package/src/phase14-catalog-override.ts +67 -16
  100. package/src/repair-fetch.ts +27 -3
  101. package/src/repair-layers.ts +7 -520
  102. package/test-vectors/catalog/README.md +39 -67
  103. package/test-vectors/catalog/fec-01-runtime/README.md +15 -0
  104. package/test-vectors/catalog/{negative/fec-block-profile-retired.json → fec-01-runtime/fec-iso-ssbg1.json} +1 -1
  105. package/test-vectors/catalog/fec-01-runtime/fec-layered-repair.json +106 -0
  106. package/test-vectors/catalog/{negative/fec-block-profile-unknown.json → fec-01-runtime/fec-multicast.json} +2 -1
  107. package/test-vectors/catalog/fec-01-runtime/multicast-native-ssm-no-network-source.json +44 -0
  108. package/test-vectors/catalog/negative/fec-block-profile-missing.json +24 -11
  109. package/test-vectors/catalog/negative/fec-iso-symbol-size-below-floor.json +13 -8
  110. package/test-vectors/catalog/negative/fec-reed-solomon-iso-symbol-size-13.json +13 -8
  111. package/test-vectors/catalog/negative/fec-repair-layer-geometry.json +20 -10
  112. package/test-vectors/catalog/negative/fec-repair-layer-missing-symbols.json +20 -10
  113. package/test-vectors/catalog/negative/fec-repair-overlay-source-symbols-zero.json +25 -17
  114. package/test-vectors/catalog/negative/fec-repair-symbols-zero.json +13 -8
  115. package/test-vectors/catalog/negative/fec-source-symbols-zero.json +13 -8
  116. package/test-vectors/catalog/negative/fec-symbol-size-zero.json +13 -8
  117. package/test-vectors/catalog/negative/raptorq-source-symbols-over-max.json +18 -9
  118. package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +13 -8
  119. package/test-vectors/catalog/positive/fec-algorithm-unimplemented.json +14 -9
  120. package/test-vectors/catalog/positive/fec-iso-ssbg1.json +25 -12
  121. package/test-vectors/catalog/positive/fec-layered-repair.json +79 -35
  122. package/test-vectors/catalog/positive/fec-multicast.json +26 -13
  123. package/test-vectors/catalog/positive/fec-reed-solomon-layered.json +29 -18
  124. package/test-vectors/catalog/positive/multicast-draft01-4-1-example.json +28 -20
  125. package/test-vectors/catalog/positive/multicast-draft01-7-2-6-example.json +14 -10
  126. package/test-vectors/catalog/positive/multicast-native-ssm-no-network-source.json +22 -12
  127. package/test-vectors/catalog/section-codes.json +13 -22
  128. package/test-vectors/catalog-timing.json +2 -2
  129. package/test-vectors/catalog-validation.json +30 -243
  130. package/test-vectors/catalog/negative/fec-enhancement-repair-removed.json +0 -28
  131. package/test-vectors/catalog/negative/fec-reed-solomon-k-plus-p-over-255.json +0 -39
  132. package/test-vectors/catalog/negative/fec-reed-solomon-overlay-over-255.json +0 -40
  133. package/test-vectors/catalog/negative/fec-repair-multiple-depends.json +0 -32
  134. package/test-vectors/catalog/negative/fec-repair-overlay-with-layer.json +0 -34
  135. package/test-vectors/catalog/negative/fec-repair-priority-out-of-band.json +0 -24
  136. package/test-vectors/catalog/negative/fec-repair-source-symbols-without-scope.json +0 -33
@@ -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 one catalog `fec` block (a hang rendition's `fec` or an MSF/CMSF
58
- * track's `fec`) declares an FEC instance a receiver can configure: source
59
- * symbols per block (K) and a symbol size (T) are both positive integers, the
60
- * algorithm is neither `none` nor a token this receiver does not implement
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(fec: unknown): boolean;
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
  *
@@ -1 +1 @@
1
- {"version":3,"file":"fec-state.d.ts","sourceRoot":"","sources":["../src/fec-state.ts"],"names":[],"mappings":"AAeA,OAAO,EAIL,kBAAkB,EACnB,MAAM,qBAAqB,CAAA;AAE5B,2FAA2F;AAC3F,OAAO,EAAE,kBAAkB,EAAE,CAAA;AAE7B,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;AAkBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAUxD;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"}
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/catalog-fec-source.js
20
- var ALL_ROLES = Object.freeze(["video", "audio"]);
21
- function recordOf(value) {
22
- return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
23
- }
24
- function isoBlockSpanUsable(fec) {
25
- const block = recordOf(fec);
26
- if (block === void 0 || block["blockProfile"] !== "iso-ssbg1-v1")
27
- return true;
28
- const ms = block["interleaveDepthMs"];
29
- return ms === void 0 || typeof ms === "number" && Number.isSafeInteger(ms) && ms >= 0;
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
- function fecAlgorithmUnimplemented(algorithm) {
32
- return typeof algorithm === "string" && algorithm !== "none" && algorithm !== "raptorq" && algorithm !== "reed-solomon";
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 isPositiveSafeInteger(value) {
35
- return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
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
- var ISO_SSBG1_MIN_SYMBOL_SIZE = 14;
38
- function catalogFecDeclaresUnconfigurableInstance(fec) {
39
- const block = recordOf(fec);
40
- if (block === void 0 || block["algorithm"] === "none" || fecAlgorithmUnimplemented(block["algorithm"]))
41
- return false;
42
- if (!(isPositiveSafeInteger(block["sourceSymbols"]) && isPositiveSafeInteger(block["symbolSize"])))
43
- return true;
44
- return block["blockProfile"] === "iso-ssbg1-v1" && block["symbolSize"] < ISO_SSBG1_MIN_SYMBOL_SIZE;
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 isPositiveSafeInteger2(value) {
64
- return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
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