@blockcast/mmt-container 0.3.0 → 0.4.0-main.1cd3cdea89da
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 +33 -16
- package/dist/browser-runtime.js +14814 -14255
- package/dist/browser-runtime.js.map +4 -4
- package/dist/carp-catalog.d.ts +24 -19
- package/dist/carp-catalog.d.ts.map +1 -1
- package/dist/carp-catalog.js +29 -14
- package/dist/carp-catalog.js.map +4 -4
- package/dist/catalog-fec-params.d.ts +88 -28
- package/dist/catalog-fec-params.d.ts.map +1 -1
- package/dist/catalog-fec-params.js +60 -23
- package/dist/catalog-fec-params.js.map +4 -4
- package/dist/catalog-network-source.js +1 -7
- package/dist/catalog-network-source.js.map +4 -4
- package/dist/cmaf-block-assembler.d.ts +0 -2
- package/dist/cmaf-block-assembler.d.ts.map +1 -1
- package/dist/cmaf-block-assembler.js +0 -1
- package/dist/cmaf-block-assembler.js.map +2 -2
- package/dist/cmcd-producer.d.ts.map +1 -1
- package/dist/cmcd-producer.js +0 -4
- package/dist/cmcd-producer.js.map +2 -2
- package/dist/delivery-catalog.d.ts +124 -0
- package/dist/delivery-catalog.d.ts.map +1 -0
- package/dist/delivery-catalog.js +1857 -0
- package/dist/delivery-catalog.js.map +7 -0
- package/dist/delta-fallback-config.d.ts +42 -0
- package/dist/delta-fallback-config.d.ts.map +1 -0
- package/dist/delta-fallback-config.js +59 -0
- package/dist/delta-fallback-config.js.map +7 -0
- package/dist/fec-manager.d.ts +52 -30
- package/dist/fec-manager.d.ts.map +1 -1
- package/dist/fec-manager.js +338 -293
- package/dist/fec-manager.js.map +4 -4
- package/dist/fec-state.d.ts +19 -31
- package/dist/fec-state.d.ts.map +1 -1
- package/dist/fec-state.js +4 -10
- package/dist/fec-state.js.map +4 -4
- package/dist/fec-worker-setup.d.ts +18 -14
- package/dist/fec-worker-setup.d.ts.map +1 -1
- package/dist/fec-worker-setup.js +81 -96
- package/dist/fec-worker-setup.js.map +4 -4
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -0
- package/dist/index.js.map +2 -2
- package/dist/iso-block-locator.js +1 -7
- package/dist/iso-block-locator.js.map +4 -4
- package/dist/media-router.d.ts +20 -8
- package/dist/media-router.d.ts.map +1 -1
- package/dist/media-router.js +46 -21
- package/dist/media-router.js.map +2 -2
- package/dist/mfu-reassembler.js +24 -30
- package/dist/mfu-reassembler.js.map +4 -4
- package/dist/mmtp-container-parser.d.ts +14 -11
- package/dist/mmtp-container-parser.d.ts.map +1 -1
- package/dist/mmtp-container-parser.js +126 -99
- package/dist/mmtp-container-parser.js.map +4 -4
- package/dist/mmtp-container-parser.no-modules.js +151 -108
- package/dist/mmtp-container-parser.no-modules.js.map +4 -4
- package/dist/mmtp-decode-pipeline.js +126 -99
- package/dist/mmtp-decode-pipeline.js.map +4 -4
- package/dist/mmtp-router.d.ts +51 -29
- package/dist/mmtp-router.d.ts.map +1 -1
- package/dist/mmtp-router.js +260 -326
- package/dist/mmtp-router.js.map +4 -4
- package/dist/multicast-input.js +1 -7
- package/dist/multicast-input.js.map +4 -4
- package/dist/multicast-manager.d.ts +72 -6
- package/dist/multicast-manager.d.ts.map +1 -1
- package/dist/multicast-manager.js +882 -673
- package/dist/multicast-manager.js.map +4 -4
- package/dist/multicast-transport.d.ts +1 -1
- package/dist/multicast-transport.d.ts.map +1 -1
- package/dist/multicast-transport.js +44 -26
- package/dist/multicast-transport.js.map +4 -4
- package/dist/multicast-unwrap.js +29 -35
- package/dist/multicast-unwrap.js.map +4 -4
- package/dist/no-modules.js +147 -106
- package/dist/no-modules.js.map +4 -4
- package/dist/repair-fetch.d.ts +116 -21
- package/dist/repair-fetch.d.ts.map +1 -1
- package/dist/repair-fetch.js +114 -34
- package/dist/repair-fetch.js.map +4 -4
- package/dist/repair-layers.d.ts +18 -7
- package/dist/repair-layers.d.ts.map +1 -1
- package/dist/repair-layers.js +12 -10
- package/dist/repair-layers.js.map +4 -4
- package/dist/signaling.js +2 -11
- package/dist/signaling.js.map +4 -4
- package/dist/timestamp-codec.js +24 -30
- package/dist/timestamp-codec.js.map +4 -4
- package/dist/track-session.d.ts +7 -0
- package/dist/track-session.d.ts.map +1 -1
- package/dist/track-session.js +15 -8
- package/dist/track-session.js.map +2 -2
- package/dist/wasm-mfu-reassembler.js +1 -7
- package/dist/wasm-mfu-reassembler.js.map +4 -4
- package/dist/wasm-mmtp-container-parser.js +126 -99
- package/dist/wasm-mmtp-container-parser.js.map +4 -4
- package/package.json +7 -14
- package/schemas/catalog.schema.json +3 -3
- package/src/carp-catalog.ts +46 -24
- package/src/catalog-fec-params.ts +173 -64
- package/src/cmaf-block-assembler.ts +1 -4
- package/src/cmcd-producer.ts +0 -6
- package/src/delivery-catalog.ts +498 -0
- package/src/delta-fallback-config.ts +72 -0
- package/src/fec-manager.ts +457 -334
- package/src/fec-state.ts +20 -32
- package/src/fec-worker-setup.ts +109 -90
- package/src/index.ts +32 -0
- package/src/media-router.ts +59 -21
- package/src/mmtp-container-parser.ts +106 -20
- package/src/mmtp-router.ts +189 -330
- package/src/multicast-manager.ts +265 -86
- package/src/multicast-transport.ts +16 -9
- package/src/repair-fetch.ts +273 -43
- package/src/repair-layers.ts +28 -8
- package/src/track-session.ts +28 -9
- package/test-vectors/catalog/README.md +37 -17
- package/test-vectors/catalog/negative/fec-block-profile-retired.json +52 -0
- package/test-vectors/catalog/negative/fec-enhancement-repair-removed.json +1 -1
- package/test-vectors/catalog/negative/fec-repair-layer-geometry.json +1 -1
- package/test-vectors/catalog/negative/fec-repair-layer-missing-symbols.json +1 -1
- package/test-vectors/catalog/negative/fec-repair-multiple-depends.json +1 -1
- package/test-vectors/catalog/negative/fec-repair-overlay-with-layer.json +1 -1
- package/test-vectors/catalog/negative/fec-repair-priority-out-of-band.json +1 -1
- package/test-vectors/catalog/negative/fec-repair-source-symbols-without-scope.json +1 -1
- package/test-vectors/catalog/negative/multicast-endpoint-relay-address.json +39 -0
- package/test-vectors/catalog/negative/multicast-network-source-empty.json +1 -1
- package/test-vectors/catalog/negative/raptorq-source-symbols-over-max.json +1 -1
- package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +1 -1
- package/test-vectors/catalog/positive/fec-layered-repair.json +2 -2
- package/test-vectors/catalog/positive/fec-multicast.json +2 -1
- package/test-vectors/catalog/positive/multicast-amt-manual-relay.json +38 -0
- package/test-vectors/catalog/positive/multicast-native-ssm-no-network-source.json +2 -1
- package/test-vectors/catalog-timing.json +356 -0
- package/test-vectors/catalog-validation.json +40 -5
- package/test-vectors/delivery-catalog/README.md +11 -0
- package/test-vectors/delivery-catalog/negative/missing-block-profile.json +58 -0
- package/test-vectors/delivery-catalog/negative/packet-id-signaling.json +59 -0
- package/test-vectors/delivery-catalog/negative/retired-k-padded-block-profile.json +59 -0
- package/test-vectors/delivery-catalog/positive/dash.json +56 -0
- package/test-vectors/delivery-catalog/positive/mmtp-source-only.json +43 -0
- package/node_modules/@blockcast/fec-worker/README.md +0 -223
- package/node_modules/@blockcast/fec-worker/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/fec-worker/dist/block-order.d.ts +0 -38
- package/node_modules/@blockcast/fec-worker/dist/block-order.d.ts.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/block-order.js +0 -78
- package/node_modules/@blockcast/fec-worker/dist/block-order.js.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts +0 -93
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js +0 -346
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts +0 -380
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js +0 -11
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts +0 -14
- package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/fec-worker.js +0 -859
- package/node_modules/@blockcast/fec-worker/dist/fec-worker.js.map +0 -7
- package/node_modules/@blockcast/fec-worker/dist/index.d.ts +0 -10
- package/node_modules/@blockcast/fec-worker/dist/index.d.ts.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/index.js +0 -8
- package/node_modules/@blockcast/fec-worker/dist/index.js.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts +0 -20
- package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js +0 -370
- package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js.map +0 -7
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts +0 -104
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js +0 -181
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts +0 -194
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js +0 -62
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts +0 -9
- package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts.map +0 -1
- package/node_modules/@blockcast/fec-worker/dist/transfer.js +0 -13
- package/node_modules/@blockcast/fec-worker/dist/transfer.js.map +0 -1
- package/node_modules/@blockcast/fec-worker/package.json +0 -59
- package/node_modules/@blockcast/fec-worker/src/block-order.ts +0 -93
- package/node_modules/@blockcast/fec-worker/src/fec-worker-client.ts +0 -392
- package/node_modules/@blockcast/fec-worker/src/fec-worker-types.ts +0 -399
- package/node_modules/@blockcast/fec-worker/src/fec-worker.ts +0 -1502
- package/node_modules/@blockcast/fec-worker/src/index.ts +0 -35
- package/node_modules/@blockcast/fec-worker/src/shred-fec-worker.ts +0 -589
- package/node_modules/@blockcast/fec-worker/src/shred-worker-client.ts +0 -222
- package/node_modules/@blockcast/fec-worker/src/shred-worker-types.ts +0 -209
- package/node_modules/@blockcast/fec-worker/src/transfer.ts +0 -12
- package/node_modules/@blockcast/mmt-alta-parse/README.md +0 -181
- package/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +0 -57
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.js +0 -115
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +0 -1
- package/node_modules/@blockcast/mmt-alta-parse/package.json +0 -50
- package/node_modules/@blockcast/mmt-alta-parse/src/index.ts +0 -136
- package/node_modules/@blockcast/mmt-base/README.md +0 -134
- package/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts +0 -55
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +0 -128
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/index.d.ts +0 -7
- package/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/index.js +0 -7
- package/node_modules/@blockcast/mmt-base/dist/index.js.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +0 -292
- package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/mmtp.js +0 -612
- package/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +0 -18
- package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/net-constants.js +0 -18
- package/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +0 -47
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.js +0 -54
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +0 -57
- package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/serial-number.js +0 -98
- package/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +0 -312
- package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-base/dist/signalling.js +0 -637
- package/node_modules/@blockcast/mmt-base/dist/signalling.js.map +0 -1
- package/node_modules/@blockcast/mmt-base/package.json +0 -49
- package/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +0 -145
- package/node_modules/@blockcast/mmt-base/src/index.ts +0 -6
- package/node_modules/@blockcast/mmt-base/src/mmtp.ts +0 -892
- package/node_modules/@blockcast/mmt-base/src/net-constants.ts +0 -17
- package/node_modules/@blockcast/mmt-base/src/ntp-short.ts +0 -67
- package/node_modules/@blockcast/mmt-base/src/serial-number.ts +0 -107
- package/node_modules/@blockcast/mmt-base/src/signalling.ts +0 -862
- package/node_modules/@blockcast/mmt-fec/README.md +0 -271
- package/node_modules/@blockcast/mmt-fec/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts +0 -82
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.js +0 -296
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts +0 -106
- package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/block-processor.js +0 -288
- package/node_modules/@blockcast/mmt-fec/dist/block-processor.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts +0 -46
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js +0 -96
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts +0 -33
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js +0 -57
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts +0 -205
- package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js +0 -240
- package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/index.d.ts +0 -28
- package/node_modules/@blockcast/mmt-fec/dist/index.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/index.js +0 -28
- package/node_modules/@blockcast/mmt-fec/dist/index.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts +0 -20
- package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js +0 -28
- package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts +0 -258
- package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/oti.js +0 -382
- package/node_modules/@blockcast/mmt-fec/dist/oti.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts +0 -41
- package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js +0 -81
- package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/repair-group.d.ts +0 -82
- package/node_modules/@blockcast/mmt-fec/dist/repair-group.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/dist/repair-group.js +0 -170
- package/node_modules/@blockcast/mmt-fec/dist/repair-group.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/README.md +0 -181
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +0 -57
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js +0 -115
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/package.json +0 -50
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/src/index.ts +0 -136
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/README.md +0 -134
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts +0 -55
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +0 -128
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts +0 -7
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js +0 -7
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +0 -292
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js +0 -612
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +0 -18
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.js +0 -18
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +0 -47
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.js +0 -54
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +0 -57
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.js +0 -98
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +0 -312
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.js +0 -637
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.js.map +0 -1
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/package.json +0 -49
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +0 -145
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/index.ts +0 -6
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/mmtp.ts +0 -892
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/net-constants.ts +0 -17
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/ntp-short.ts +0 -67
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/serial-number.ts +0 -107
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/signalling.ts +0 -862
- package/node_modules/@blockcast/mmt-fec/package.json +0 -79
- package/node_modules/@blockcast/mmt-fec/src/block-manager.ts +0 -371
- package/node_modules/@blockcast/mmt-fec/src/block-processor.ts +0 -439
- package/node_modules/@blockcast/mmt-fec/src/cmaf-recovery.ts +0 -127
- package/node_modules/@blockcast/mmt-fec/src/cmaf-symbols.ts +0 -68
- package/node_modules/@blockcast/mmt-fec/src/fec-block-mapper.ts +0 -310
- package/node_modules/@blockcast/mmt-fec/src/index.ts +0 -94
- package/node_modules/@blockcast/mmt-fec/src/loc-symbols.ts +0 -34
- package/node_modules/@blockcast/mmt-fec/src/oti.ts +0 -463
- package/node_modules/@blockcast/mmt-fec/src/reorder-buffer.ts +0 -101
- package/node_modules/@blockcast/mmt-fec/src/repair-group.ts +0 -195
- package/node_modules/@blockcast/mmt-manifest-verify/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts +0 -28
- package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js +0 -128
- package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js.map +0 -1
- package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts +0 -4
- package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js +0 -4
- package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js.map +0 -1
- package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts +0 -37
- package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js +0 -179
- package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js.map +0 -1
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts +0 -99
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts.map +0 -1
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js +0 -492
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js.map +0 -1
- package/node_modules/@blockcast/mmt-manifest-verify/package.json +0 -45
- package/node_modules/@blockcast/mmt-manifest-verify/src/admission.ts +0 -171
- package/node_modules/@blockcast/mmt-manifest-verify/src/index.ts +0 -3
- package/node_modules/@blockcast/mmt-manifest-verify/src/source-auth.ts +0 -230
- package/node_modules/@blockcast/mmt-manifest-verify/src/verifier.ts +0 -669
- package/node_modules/@noble/hashes/LICENSE +0 -21
- package/node_modules/@noble/hashes/README.md +0 -521
- package/node_modules/@noble/hashes/_assert.d.ts +0 -17
- package/node_modules/@noble/hashes/_assert.d.ts.map +0 -1
- package/node_modules/@noble/hashes/_assert.js +0 -18
- package/node_modules/@noble/hashes/_assert.js.map +0 -1
- package/node_modules/@noble/hashes/_blake.d.ts +0 -14
- package/node_modules/@noble/hashes/_blake.d.ts.map +0 -1
- package/node_modules/@noble/hashes/_blake.js +0 -50
- package/node_modules/@noble/hashes/_blake.js.map +0 -1
- package/node_modules/@noble/hashes/_md.d.ts +0 -51
- package/node_modules/@noble/hashes/_md.d.ts.map +0 -1
- package/node_modules/@noble/hashes/_md.js +0 -162
- package/node_modules/@noble/hashes/_md.js.map +0 -1
- package/node_modules/@noble/hashes/_u64.d.ts +0 -55
- package/node_modules/@noble/hashes/_u64.d.ts.map +0 -1
- package/node_modules/@noble/hashes/_u64.js +0 -90
- package/node_modules/@noble/hashes/_u64.js.map +0 -1
- package/node_modules/@noble/hashes/argon2.d.ts +0 -32
- package/node_modules/@noble/hashes/argon2.d.ts.map +0 -1
- package/node_modules/@noble/hashes/argon2.js +0 -401
- package/node_modules/@noble/hashes/argon2.js.map +0 -1
- package/node_modules/@noble/hashes/blake1.d.ts +0 -106
- package/node_modules/@noble/hashes/blake1.d.ts.map +0 -1
- package/node_modules/@noble/hashes/blake1.js +0 -459
- package/node_modules/@noble/hashes/blake1.js.map +0 -1
- package/node_modules/@noble/hashes/blake2.d.ts +0 -116
- package/node_modules/@noble/hashes/blake2.d.ts.map +0 -1
- package/node_modules/@noble/hashes/blake2.js +0 -420
- package/node_modules/@noble/hashes/blake2.js.map +0 -1
- package/node_modules/@noble/hashes/blake2b.d.ts +0 -11
- package/node_modules/@noble/hashes/blake2b.d.ts.map +0 -1
- package/node_modules/@noble/hashes/blake2b.js +0 -14
- package/node_modules/@noble/hashes/blake2b.js.map +0 -1
- package/node_modules/@noble/hashes/blake2s.d.ts +0 -20
- package/node_modules/@noble/hashes/blake2s.d.ts.map +0 -1
- package/node_modules/@noble/hashes/blake2s.js +0 -24
- package/node_modules/@noble/hashes/blake2s.js.map +0 -1
- package/node_modules/@noble/hashes/blake3.d.ts +0 -54
- package/node_modules/@noble/hashes/blake3.d.ts.map +0 -1
- package/node_modules/@noble/hashes/blake3.js +0 -255
- package/node_modules/@noble/hashes/blake3.js.map +0 -1
- package/node_modules/@noble/hashes/crypto.d.ts +0 -2
- package/node_modules/@noble/hashes/crypto.d.ts.map +0 -1
- package/node_modules/@noble/hashes/crypto.js +0 -5
- package/node_modules/@noble/hashes/crypto.js.map +0 -1
- package/node_modules/@noble/hashes/cryptoNode.d.ts +0 -2
- package/node_modules/@noble/hashes/cryptoNode.d.ts.map +0 -1
- package/node_modules/@noble/hashes/cryptoNode.js +0 -18
- package/node_modules/@noble/hashes/cryptoNode.js.map +0 -1
- package/node_modules/@noble/hashes/eskdf.d.ts +0 -47
- package/node_modules/@noble/hashes/eskdf.d.ts.map +0 -1
- package/node_modules/@noble/hashes/eskdf.js +0 -166
- package/node_modules/@noble/hashes/eskdf.js.map +0 -1
- package/node_modules/@noble/hashes/esm/_assert.d.ts +0 -17
- package/node_modules/@noble/hashes/esm/_assert.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/_assert.js +0 -15
- package/node_modules/@noble/hashes/esm/_assert.js.map +0 -1
- package/node_modules/@noble/hashes/esm/_blake.d.ts +0 -14
- package/node_modules/@noble/hashes/esm/_blake.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/_blake.js +0 -45
- package/node_modules/@noble/hashes/esm/_blake.js.map +0 -1
- package/node_modules/@noble/hashes/esm/_md.d.ts +0 -51
- package/node_modules/@noble/hashes/esm/_md.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/_md.js +0 -155
- package/node_modules/@noble/hashes/esm/_md.js.map +0 -1
- package/node_modules/@noble/hashes/esm/_u64.d.ts +0 -55
- package/node_modules/@noble/hashes/esm/_u64.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/_u64.js +0 -67
- package/node_modules/@noble/hashes/esm/_u64.js.map +0 -1
- package/node_modules/@noble/hashes/esm/argon2.d.ts +0 -32
- package/node_modules/@noble/hashes/esm/argon2.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/argon2.js +0 -392
- package/node_modules/@noble/hashes/esm/argon2.js.map +0 -1
- package/node_modules/@noble/hashes/esm/blake1.d.ts +0 -106
- package/node_modules/@noble/hashes/esm/blake1.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/blake1.js +0 -452
- package/node_modules/@noble/hashes/esm/blake1.js.map +0 -1
- package/node_modules/@noble/hashes/esm/blake2.d.ts +0 -116
- package/node_modules/@noble/hashes/esm/blake2.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/blake2.js +0 -413
- package/node_modules/@noble/hashes/esm/blake2.js.map +0 -1
- package/node_modules/@noble/hashes/esm/blake2b.d.ts +0 -11
- package/node_modules/@noble/hashes/esm/blake2b.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/blake2b.js +0 -11
- package/node_modules/@noble/hashes/esm/blake2b.js.map +0 -1
- package/node_modules/@noble/hashes/esm/blake2s.d.ts +0 -20
- package/node_modules/@noble/hashes/esm/blake2s.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/blake2s.js +0 -21
- package/node_modules/@noble/hashes/esm/blake2s.js.map +0 -1
- package/node_modules/@noble/hashes/esm/blake3.d.ts +0 -54
- package/node_modules/@noble/hashes/esm/blake3.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/blake3.js +0 -251
- package/node_modules/@noble/hashes/esm/blake3.js.map +0 -1
- package/node_modules/@noble/hashes/esm/crypto.d.ts +0 -2
- package/node_modules/@noble/hashes/esm/crypto.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/crypto.js +0 -2
- package/node_modules/@noble/hashes/esm/crypto.js.map +0 -1
- package/node_modules/@noble/hashes/esm/cryptoNode.d.ts +0 -2
- package/node_modules/@noble/hashes/esm/cryptoNode.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/cryptoNode.js +0 -15
- package/node_modules/@noble/hashes/esm/cryptoNode.js.map +0 -1
- package/node_modules/@noble/hashes/esm/eskdf.d.ts +0 -47
- package/node_modules/@noble/hashes/esm/eskdf.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/eskdf.js +0 -160
- package/node_modules/@noble/hashes/esm/eskdf.js.map +0 -1
- package/node_modules/@noble/hashes/esm/hkdf.d.ts +0 -36
- package/node_modules/@noble/hashes/esm/hkdf.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/hkdf.js +0 -82
- package/node_modules/@noble/hashes/esm/hkdf.js.map +0 -1
- package/node_modules/@noble/hashes/esm/hmac.d.ts +0 -35
- package/node_modules/@noble/hashes/esm/hmac.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/hmac.js +0 -86
- package/node_modules/@noble/hashes/esm/hmac.js.map +0 -1
- package/node_modules/@noble/hashes/esm/index.d.ts +0 -2
- package/node_modules/@noble/hashes/esm/index.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/index.js +0 -33
- package/node_modules/@noble/hashes/esm/index.js.map +0 -1
- package/node_modules/@noble/hashes/esm/legacy.d.ts +0 -71
- package/node_modules/@noble/hashes/esm/legacy.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/legacy.js +0 -281
- package/node_modules/@noble/hashes/esm/legacy.js.map +0 -1
- package/node_modules/@noble/hashes/esm/package.json +0 -10
- package/node_modules/@noble/hashes/esm/pbkdf2.d.ts +0 -23
- package/node_modules/@noble/hashes/esm/pbkdf2.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/pbkdf2.js +0 -97
- package/node_modules/@noble/hashes/esm/pbkdf2.js.map +0 -1
- package/node_modules/@noble/hashes/esm/ripemd160.d.ts +0 -13
- package/node_modules/@noble/hashes/esm/ripemd160.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/ripemd160.js +0 -13
- package/node_modules/@noble/hashes/esm/ripemd160.js.map +0 -1
- package/node_modules/@noble/hashes/esm/scrypt.d.ts +0 -34
- package/node_modules/@noble/hashes/esm/scrypt.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/scrypt.js +0 -228
- package/node_modules/@noble/hashes/esm/scrypt.js.map +0 -1
- package/node_modules/@noble/hashes/esm/sha1.d.ts +0 -11
- package/node_modules/@noble/hashes/esm/sha1.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/sha1.js +0 -11
- package/node_modules/@noble/hashes/esm/sha1.js.map +0 -1
- package/node_modules/@noble/hashes/esm/sha2.d.ts +0 -159
- package/node_modules/@noble/hashes/esm/sha2.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/sha2.js +0 -375
- package/node_modules/@noble/hashes/esm/sha2.js.map +0 -1
- package/node_modules/@noble/hashes/esm/sha256.d.ts +0 -20
- package/node_modules/@noble/hashes/esm/sha256.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/sha256.js +0 -20
- package/node_modules/@noble/hashes/esm/sha256.js.map +0 -1
- package/node_modules/@noble/hashes/esm/sha3-addons.d.ts +0 -142
- package/node_modules/@noble/hashes/esm/sha3-addons.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/sha3-addons.js +0 -393
- package/node_modules/@noble/hashes/esm/sha3-addons.js.map +0 -1
- package/node_modules/@noble/hashes/esm/sha3.d.ts +0 -53
- package/node_modules/@noble/hashes/esm/sha3.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/sha3.js +0 -234
- package/node_modules/@noble/hashes/esm/sha3.js.map +0 -1
- package/node_modules/@noble/hashes/esm/sha512.d.ts +0 -26
- package/node_modules/@noble/hashes/esm/sha512.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/sha512.js +0 -26
- package/node_modules/@noble/hashes/esm/sha512.js.map +0 -1
- package/node_modules/@noble/hashes/esm/utils.d.ts +0 -161
- package/node_modules/@noble/hashes/esm/utils.d.ts.map +0 -1
- package/node_modules/@noble/hashes/esm/utils.js +0 -281
- package/node_modules/@noble/hashes/esm/utils.js.map +0 -1
- package/node_modules/@noble/hashes/hkdf.d.ts +0 -36
- package/node_modules/@noble/hashes/hkdf.d.ts.map +0 -1
- package/node_modules/@noble/hashes/hkdf.js +0 -88
- package/node_modules/@noble/hashes/hkdf.js.map +0 -1
- package/node_modules/@noble/hashes/hmac.d.ts +0 -35
- package/node_modules/@noble/hashes/hmac.d.ts.map +0 -1
- package/node_modules/@noble/hashes/hmac.js +0 -91
- package/node_modules/@noble/hashes/hmac.js.map +0 -1
- package/node_modules/@noble/hashes/index.d.ts +0 -1
- package/node_modules/@noble/hashes/index.d.ts.map +0 -1
- package/node_modules/@noble/hashes/index.js +0 -33
- package/node_modules/@noble/hashes/index.js.map +0 -1
- package/node_modules/@noble/hashes/legacy.d.ts +0 -71
- package/node_modules/@noble/hashes/legacy.d.ts.map +0 -1
- package/node_modules/@noble/hashes/legacy.js +0 -287
- package/node_modules/@noble/hashes/legacy.js.map +0 -1
- package/node_modules/@noble/hashes/package.json +0 -266
- package/node_modules/@noble/hashes/pbkdf2.d.ts +0 -23
- package/node_modules/@noble/hashes/pbkdf2.d.ts.map +0 -1
- package/node_modules/@noble/hashes/pbkdf2.js +0 -101
- package/node_modules/@noble/hashes/pbkdf2.js.map +0 -1
- package/node_modules/@noble/hashes/ripemd160.d.ts +0 -13
- package/node_modules/@noble/hashes/ripemd160.d.ts.map +0 -1
- package/node_modules/@noble/hashes/ripemd160.js +0 -16
- package/node_modules/@noble/hashes/ripemd160.js.map +0 -1
- package/node_modules/@noble/hashes/scrypt.d.ts +0 -34
- package/node_modules/@noble/hashes/scrypt.d.ts.map +0 -1
- package/node_modules/@noble/hashes/scrypt.js +0 -232
- package/node_modules/@noble/hashes/scrypt.js.map +0 -1
- package/node_modules/@noble/hashes/sha1.d.ts +0 -11
- package/node_modules/@noble/hashes/sha1.d.ts.map +0 -1
- package/node_modules/@noble/hashes/sha1.js +0 -14
- package/node_modules/@noble/hashes/sha1.js.map +0 -1
- package/node_modules/@noble/hashes/sha2.d.ts +0 -159
- package/node_modules/@noble/hashes/sha2.d.ts.map +0 -1
- package/node_modules/@noble/hashes/sha2.js +0 -384
- package/node_modules/@noble/hashes/sha2.js.map +0 -1
- package/node_modules/@noble/hashes/sha256.d.ts +0 -20
- package/node_modules/@noble/hashes/sha256.d.ts.map +0 -1
- package/node_modules/@noble/hashes/sha256.js +0 -23
- package/node_modules/@noble/hashes/sha256.js.map +0 -1
- package/node_modules/@noble/hashes/sha3-addons.d.ts +0 -142
- package/node_modules/@noble/hashes/sha3-addons.d.ts.map +0 -1
- package/node_modules/@noble/hashes/sha3-addons.js +0 -402
- package/node_modules/@noble/hashes/sha3-addons.js.map +0 -1
- package/node_modules/@noble/hashes/sha3.d.ts +0 -53
- package/node_modules/@noble/hashes/sha3.d.ts.map +0 -1
- package/node_modules/@noble/hashes/sha3.js +0 -239
- package/node_modules/@noble/hashes/sha3.js.map +0 -1
- package/node_modules/@noble/hashes/sha512.d.ts +0 -26
- package/node_modules/@noble/hashes/sha512.d.ts.map +0 -1
- package/node_modules/@noble/hashes/sha512.js +0 -29
- package/node_modules/@noble/hashes/sha512.js.map +0 -1
- package/node_modules/@noble/hashes/src/_assert.ts +0 -22
- package/node_modules/@noble/hashes/src/_blake.ts +0 -50
- package/node_modules/@noble/hashes/src/_md.ts +0 -176
- package/node_modules/@noble/hashes/src/_u64.ts +0 -91
- package/node_modules/@noble/hashes/src/argon2.ts +0 -497
- package/node_modules/@noble/hashes/src/blake1.ts +0 -534
- package/node_modules/@noble/hashes/src/blake2.ts +0 -486
- package/node_modules/@noble/hashes/src/blake2b.ts +0 -10
- package/node_modules/@noble/hashes/src/blake2s.ts +0 -20
- package/node_modules/@noble/hashes/src/blake3.ts +0 -272
- package/node_modules/@noble/hashes/src/crypto.ts +0 -9
- package/node_modules/@noble/hashes/src/cryptoNode.ts +0 -15
- package/node_modules/@noble/hashes/src/eskdf.ts +0 -187
- package/node_modules/@noble/hashes/src/hkdf.ts +0 -88
- package/node_modules/@noble/hashes/src/hmac.ts +0 -94
- package/node_modules/@noble/hashes/src/index.ts +0 -31
- package/node_modules/@noble/hashes/src/legacy.ts +0 -293
- package/node_modules/@noble/hashes/src/pbkdf2.ts +0 -122
- package/node_modules/@noble/hashes/src/ripemd160.ts +0 -12
- package/node_modules/@noble/hashes/src/scrypt.ts +0 -257
- package/node_modules/@noble/hashes/src/sha1.ts +0 -10
- package/node_modules/@noble/hashes/src/sha2.ts +0 -402
- package/node_modules/@noble/hashes/src/sha256.ts +0 -24
- package/node_modules/@noble/hashes/src/sha3-addons.ts +0 -499
- package/node_modules/@noble/hashes/src/sha3.ts +0 -258
- package/node_modules/@noble/hashes/src/sha512.ts +0 -34
- package/node_modules/@noble/hashes/src/utils.ts +0 -395
- package/node_modules/@noble/hashes/utils.d.ts +0 -161
- package/node_modules/@noble/hashes/utils.d.ts.map +0 -1
- package/node_modules/@noble/hashes/utils.js +0 -313
- package/node_modules/@noble/hashes/utils.js.map +0 -1
package/dist/fec-manager.js
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
// src/track-session.ts
|
|
2
2
|
import { fecBlockBudgetMs } from "@blockcast/mmt-fec";
|
|
3
3
|
function computeFecDeliveryWindowMs(config) {
|
|
4
|
-
const fecInterleaveMs = config.interleaveDepthMs;
|
|
5
4
|
const fecK = config.sourceSymbols;
|
|
6
|
-
if (!Number.isFinite(
|
|
5
|
+
if (!Number.isFinite(fecK) || fecK <= 0) {
|
|
7
6
|
throw new Error(
|
|
8
|
-
`[TrackSession]
|
|
7
|
+
`[TrackSession] fecK=${fecK}. Derive a positive FEC source-symbol count from the stream catalog.`
|
|
9
8
|
);
|
|
10
9
|
}
|
|
11
|
-
|
|
10
|
+
return fecSpanDeliveryWindowMs(config.interleaveDepthMs, config.jitterBufferMs);
|
|
11
|
+
}
|
|
12
|
+
function fecSpanDeliveryWindowMs(interleaveDepthMs, jitterBufferMs) {
|
|
13
|
+
if (!Number.isFinite(interleaveDepthMs) || interleaveDepthMs <= 0) {
|
|
12
14
|
throw new Error(
|
|
13
|
-
`[TrackSession]
|
|
15
|
+
`[TrackSession] fecInterleaveMs=${interleaveDepthMs}. Derive a positive FEC interleave window from the stream catalog.`
|
|
14
16
|
);
|
|
15
17
|
}
|
|
16
|
-
if (
|
|
17
|
-
return fecBlockBudgetMs(
|
|
18
|
+
if (jitterBufferMs === void 0) return Math.ceil(interleaveDepthMs);
|
|
19
|
+
return fecBlockBudgetMs(interleaveDepthMs, jitterBufferMs);
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
// src/delivery-gap.ts
|
|
@@ -106,19 +108,16 @@ var DeliveryGapEstimator = class {
|
|
|
106
108
|
import {
|
|
107
109
|
deriveFecInterleaveDepth as deriveFecInterleaveDepth2,
|
|
108
110
|
deriveFecRetentionBlocks,
|
|
109
|
-
tryDeriveFecRetentionBlocks
|
|
111
|
+
tryDeriveFecRetentionBlocks,
|
|
112
|
+
LOCAL_FEC_RETENTION_BLOCKS,
|
|
113
|
+
LOCAL_FEC_TIMEOUT_MS
|
|
110
114
|
} from "@blockcast/mmt-fec";
|
|
111
115
|
|
|
112
|
-
// ../mmt-
|
|
116
|
+
// ../mmt-base/dist/mmtp.js
|
|
113
117
|
var MPU_HEADER_SIZE = 8;
|
|
114
118
|
var MPU_LENGTH_FIELD_SIZE = 2;
|
|
115
119
|
var MPU_HEADER_REMAINDER_SIZE = MPU_HEADER_SIZE - MPU_LENGTH_FIELD_SIZE;
|
|
116
120
|
|
|
117
|
-
// ../mmt-base/dist/mmtp.js
|
|
118
|
-
var MPU_HEADER_SIZE2 = 8;
|
|
119
|
-
var MPU_LENGTH_FIELD_SIZE2 = 2;
|
|
120
|
-
var MPU_HEADER_REMAINDER_SIZE2 = MPU_HEADER_SIZE2 - MPU_LENGTH_FIELD_SIZE2;
|
|
121
|
-
|
|
122
121
|
// ../mmt-base/dist/ntp-short.js
|
|
123
122
|
var NTP_SHORT_BITS = 32;
|
|
124
123
|
var NTP_SHORT_MODULUS = 2 ** NTP_SHORT_BITS;
|
|
@@ -146,49 +145,21 @@ function serial32Precedes(a, b) {
|
|
|
146
145
|
const distance = serial32Distance(a, b);
|
|
147
146
|
return distance !== 0 && distance < SERIAL32_HALF;
|
|
148
147
|
}
|
|
149
|
-
function kStrideBlockStart(sbn, k) {
|
|
150
|
-
assertUint32(sbn, "sbn");
|
|
151
|
-
if (!Number.isInteger(k) || k < 1 || k >= SERIAL32_HALF) {
|
|
152
|
-
throw new RangeError(`k must be a positive integer below 2^31 (got ${k})`);
|
|
153
|
-
}
|
|
154
|
-
const high = Math.floor(sbn / 65536);
|
|
155
|
-
const low = sbn % 65536;
|
|
156
|
-
return (high * k % SERIAL32_SPAN * 65536 + low * k) % SERIAL32_SPAN;
|
|
157
|
-
}
|
|
158
|
-
function kStrideBlockPrecedes(a, b, k) {
|
|
159
|
-
return serial32Precedes(kStrideBlockStart(a, k), kStrideBlockStart(b, k));
|
|
160
|
-
}
|
|
161
|
-
function kStrideBlocksBehind(a, b, k) {
|
|
162
|
-
const from = kStrideBlockStart(a, k);
|
|
163
|
-
const to = kStrideBlockStart(b, k);
|
|
164
|
-
if (!serial32Precedes(from, to))
|
|
165
|
-
return 0;
|
|
166
|
-
return Math.ceil(serial32Distance(from, to) / k);
|
|
167
|
-
}
|
|
168
|
-
function isKStrideBlock(sbn, k) {
|
|
169
|
-
return Number.isInteger(sbn) && sbn >= 0 && sbn < SERIAL32_SPAN && Number.isInteger(k) && k >= 1 && k < SERIAL32_HALF;
|
|
170
|
-
}
|
|
171
|
-
function kStrideNextBlock(sbn, k) {
|
|
172
|
-
assertUint32(sbn, "sbn");
|
|
173
|
-
kStrideBlockStart(sbn, k);
|
|
174
|
-
return (sbn + 1) * k >= SERIAL32_SPAN ? 0 : sbn + 1;
|
|
175
|
-
}
|
|
176
148
|
|
|
177
149
|
// ../mmt-base/dist/fec-block-profile.js
|
|
178
150
|
var FEC_BLOCK_PROFILES = Object.freeze([
|
|
179
|
-
"k-padded-v1",
|
|
180
151
|
"iso-ssbg1-v1"
|
|
181
152
|
]);
|
|
182
153
|
function isFecBlockProfile(value) {
|
|
183
|
-
return value === "
|
|
154
|
+
return value === "iso-ssbg1-v1";
|
|
184
155
|
}
|
|
185
156
|
function parseFecBlockProfile(value, where) {
|
|
186
157
|
if (isFecBlockProfile(value))
|
|
187
158
|
return value;
|
|
188
159
|
if (value === void 0) {
|
|
189
|
-
throw new Error(`${where} is required: name the FEC block profile ("
|
|
160
|
+
throw new Error(`${where} is required: name the FEC block profile ("iso-ssbg1-v1")`);
|
|
190
161
|
}
|
|
191
|
-
throw new Error(`${where} must be "
|
|
162
|
+
throw new Error(`${where} must be "iso-ssbg1-v1" (got ${JSON.stringify(value)})`);
|
|
192
163
|
}
|
|
193
164
|
var SSBG1_LENGTH_FIELD_BYTES = 2;
|
|
194
165
|
function ssbg1MaxPacketLength(symbolSize) {
|
|
@@ -441,7 +412,7 @@ var IsoBlockLocator = class _IsoBlockLocator {
|
|
|
441
412
|
};
|
|
442
413
|
|
|
443
414
|
// src/fec-state.ts
|
|
444
|
-
var MIN_INTERLEAVE_DEPTH_MS =
|
|
415
|
+
var MIN_INTERLEAVE_DEPTH_MS = 1;
|
|
445
416
|
var FEC_INACTIVE_REASONS = Object.freeze([
|
|
446
417
|
"no-catalog-fec",
|
|
447
418
|
"reliable-moq",
|
|
@@ -836,7 +807,6 @@ var FECManager = class _FECManager {
|
|
|
836
807
|
constructor() {
|
|
837
808
|
// Per-track WASM RaptorQ decoders, keyed by physical stream identity.
|
|
838
809
|
this.#fecDecoders = /* @__PURE__ */ new Map();
|
|
839
|
-
/** @deprecated Use setFecDecoder(packetId, ...). Backwards-compat shim. */
|
|
840
810
|
// Per-track Worker-backed FEC decoders, keyed by physical stream identity.
|
|
841
811
|
// Worker-backed tracks use async decode — recovered frames arrive via onFrame callback,
|
|
842
812
|
// not synchronous return from feedSourceSymbol/feedRepairSymbol.
|
|
@@ -851,10 +821,9 @@ var FECManager = class _FECManager {
|
|
|
851
821
|
// source/repair symbols do not split across two RaptorQ states.
|
|
852
822
|
this.#syncDecoderBlockOwners = /* @__PURE__ */ new Map();
|
|
853
823
|
this.#decoderBlockOwners = /* @__PURE__ */ new WeakMap();
|
|
854
|
-
this.#fecK = 4;
|
|
855
824
|
this.#fecSymbolSize = 0;
|
|
856
|
-
this.#fecTimeoutMs =
|
|
857
|
-
// default
|
|
825
|
+
this.#fecTimeoutMs = LOCAL_FEC_TIMEOUT_MS;
|
|
826
|
+
// local default; refined by setFramerate() when fps known
|
|
858
827
|
this.#trackConfigs = /* @__PURE__ */ new Map();
|
|
859
828
|
this.#fecStats = newFecCounters();
|
|
860
829
|
this.#fecTrackStats = /* @__PURE__ */ new Map();
|
|
@@ -894,14 +863,17 @@ var FECManager = class _FECManager {
|
|
|
894
863
|
this.#blockSourceEsis = /* @__PURE__ */ new Map();
|
|
895
864
|
// Authored SSB_length per block (ISO/IEC 23008-1 §C.5.3), learned from the
|
|
896
865
|
// first repair symbol. The FFmpeg moq_mmt publisher closes a block every D
|
|
897
|
-
// media units, usually before it holds K symbols
|
|
898
|
-
//
|
|
899
|
-
// SSB_length
|
|
900
|
-
//
|
|
866
|
+
// media units, usually before it holds K symbols; under iso-ssbg1-v1
|
|
867
|
+
// (ssbg_mode1) that block is K' = SSB_length symbols, its repair ESIs start
|
|
868
|
+
// at SSB_length, and K is only the maximum. Such a block is clean at
|
|
869
|
+
// SSB_length source arrivals and recoverable from SSB_length received
|
|
901
870
|
// symbols; waiting for K fails every one of them.
|
|
902
871
|
this.#blockAuthoredLengths = /* @__PURE__ */ new Map();
|
|
903
872
|
this.#ssbLengthConflictCount = 0;
|
|
904
873
|
this.#blockRepairRsIds = /* @__PURE__ */ new Map();
|
|
874
|
+
// RSB_length per block (C.5.3 Repair FEC Payload ID): how many repair
|
|
875
|
+
// symbols its repair group carries. Same lifecycle as #blockRepairRsIds.
|
|
876
|
+
this.#blockRsbLengths = /* @__PURE__ */ new Map();
|
|
905
877
|
// Blocks already recovered — prevents late source symbols from restarting timeouts.
|
|
906
878
|
// WASM removes blocks after recovery; late symbols create empty blocks returning null,
|
|
907
879
|
// which would falsely start new timeouts without this guard.
|
|
@@ -1014,14 +986,16 @@ var FECManager = class _FECManager {
|
|
|
1014
986
|
this.#resolvedBlockClasses = /* @__PURE__ */ new Map();
|
|
1015
987
|
// Blocks already reported through onBlockRepaired (once per block).
|
|
1016
988
|
this.#repairedBlocks = /* @__PURE__ */ new Set();
|
|
1017
|
-
// Blocks created
|
|
989
|
+
// Blocks created before any symbol of theirs was tracked: the repair-less
|
|
990
|
+
// spans placeIsoRepair materializes (onBlockVanished).
|
|
1018
991
|
this.#materializedBlocks = /* @__PURE__ */ new Set();
|
|
1019
992
|
// packetIds whose ordered-relay horizon became underivable and fell back to
|
|
1020
993
|
// the datagram deadline. Bounds the warn in #derivableOrderedHorizon to once
|
|
1021
994
|
// per stream. Not only throws: the ordinary out-of-range case is detected by
|
|
1022
995
|
// arithmetic and never throws at all.
|
|
1023
996
|
this.#orderedHorizonWarnedFor = /* @__PURE__ */ new Set();
|
|
1024
|
-
//
|
|
997
|
+
// Newest block start (SS_Start) seen per stream and when: the frontier for
|
|
998
|
+
// source-discontinuity detection and isoSpanResolution.
|
|
1025
999
|
this.#highestSbn = /* @__PURE__ */ new Map();
|
|
1026
1000
|
// iso-ssbg1-v1 block location per stream (streamKey). A source belongs to a
|
|
1027
1001
|
// block only once a repair symbol stated the block's (SS_Start, SSB_length).
|
|
@@ -1115,7 +1089,10 @@ var FECManager = class _FECManager {
|
|
|
1115
1089
|
#releasedWorkerClients;
|
|
1116
1090
|
#syncDecoderBlockOwners;
|
|
1117
1091
|
#decoderBlockOwners;
|
|
1118
|
-
|
|
1092
|
+
// The stream-global K a configure() call stated, reported as fecStats.k.
|
|
1093
|
+
// It never resolves a packetId: a packetId has only its own track config
|
|
1094
|
+
// (BLO-45953), and K does not feed the delivery-window math.
|
|
1095
|
+
#streamK;
|
|
1119
1096
|
#fecSymbolSize;
|
|
1120
1097
|
#fecTimeoutMs;
|
|
1121
1098
|
#trackConfigs;
|
|
@@ -1137,6 +1114,7 @@ var FECManager = class _FECManager {
|
|
|
1137
1114
|
#blockAuthoredLengths;
|
|
1138
1115
|
#ssbLengthConflictCount;
|
|
1139
1116
|
#blockRepairRsIds;
|
|
1117
|
+
#blockRsbLengths;
|
|
1140
1118
|
#completedBlocks;
|
|
1141
1119
|
#terminalExpiryMs;
|
|
1142
1120
|
#terminalQueues;
|
|
@@ -1277,7 +1255,8 @@ var FECManager = class _FECManager {
|
|
|
1277
1255
|
this.#completedBlocks.add(key);
|
|
1278
1256
|
if (clean) this.#cleanlyCompletedBlocks.add(key);
|
|
1279
1257
|
this.#indexBlockKey(key, sbn, packetId);
|
|
1280
|
-
const
|
|
1258
|
+
const config = this.#trackConfig(packetId);
|
|
1259
|
+
const expiresAtMs = nowMs + config.interleaveDepthMs + 2 * this.#blockLifetimeMs(config);
|
|
1281
1260
|
this.#terminalExpiryMs.set(key, expiresAtMs);
|
|
1282
1261
|
let queue = this.#terminalQueues.get(packetId);
|
|
1283
1262
|
if (!queue) {
|
|
@@ -1313,8 +1292,9 @@ var FECManager = class _FECManager {
|
|
|
1313
1292
|
* retention the Worker and the WASM decoder are configured with, because it
|
|
1314
1293
|
* comes from the same function they do (`deriveFecRetentionBlocks`, over the
|
|
1315
1294
|
* block's delivery window and its span). The decoder retires every block
|
|
1316
|
-
* more than this many
|
|
1317
|
-
*
|
|
1295
|
+
* more than this many blocks behind the newest SS_Start it saw, counted
|
|
1296
|
+
* from below by `isoBlocksBehindLowerBound` (`cleanup_by_ss_start`), so
|
|
1297
|
+
* settling earlier than this would decide a block the decoder would still
|
|
1318
1298
|
* have recovered.
|
|
1319
1299
|
*
|
|
1320
1300
|
* This used to call `deriveFecInterleaveDepth`, which returns D -- MEDIA
|
|
@@ -1327,6 +1307,14 @@ var FECManager = class _FECManager {
|
|
|
1327
1307
|
* derivation; do not re-derive a horizon at either call site.
|
|
1328
1308
|
*/
|
|
1329
1309
|
#orderedHorizonBlocksFor(packetId, config) {
|
|
1310
|
+
if (config.interleaveDepthMs === 0) {
|
|
1311
|
+
if (Number.isFinite(config.timeoutMs) && config.timeoutMs > 0) {
|
|
1312
|
+
return LOCAL_FEC_RETENTION_BLOCKS;
|
|
1313
|
+
}
|
|
1314
|
+
throw new Error(
|
|
1315
|
+
`[FECManager] packetId=${packetId}: local FEC cleanup requires a positive timeout (got ${config.timeoutMs})`
|
|
1316
|
+
);
|
|
1317
|
+
}
|
|
1330
1318
|
if (!_FECManager.#hasOrderedGeometry(config)) {
|
|
1331
1319
|
throw new Error(
|
|
1332
1320
|
`[FECManager] packetId=${packetId}: ordered-relay settlement derives the decoder's interleave horizon from the catalog interleaveDepthMs (>= ${MIN_INTERLEAVE_DEPTH_MS}ms), the media-unit rate and the block delivery window; got interleaveDepthMs=${config.interleaveDepthMs} fps=${String(config.fps)} timeoutMs=${config.timeoutMs}.`
|
|
@@ -1340,7 +1328,7 @@ var FECManager = class _FECManager {
|
|
|
1340
1328
|
* two can never disagree about which streams settle by stream order.
|
|
1341
1329
|
*/
|
|
1342
1330
|
static #hasOrderedGeometry(config) {
|
|
1343
|
-
return config
|
|
1331
|
+
return _FECManager.#hasCatalogTiming(config) && // `fps` is no longer an input to the horizon, but it still gates WHICH
|
|
1344
1332
|
// streams settle by stream order at all: a track with no usable
|
|
1345
1333
|
// media-unit rate fell back to datagram semantics before this and must
|
|
1346
1334
|
// keep doing so. Removing this widens ordered-relay settlement to streams
|
|
@@ -1380,6 +1368,9 @@ var FECManager = class _FECManager {
|
|
|
1380
1368
|
* argument: narrower IS the failing direction.
|
|
1381
1369
|
*/
|
|
1382
1370
|
#derivableOrderedHorizon(config, packetId) {
|
|
1371
|
+
if (config.interleaveDepthMs === 0) {
|
|
1372
|
+
return Number.isFinite(config.timeoutMs) && config.timeoutMs > 0 ? LOCAL_FEC_RETENTION_BLOCKS : void 0;
|
|
1373
|
+
}
|
|
1383
1374
|
if (!_FECManager.#hasOrderedGeometry(config)) return void 0;
|
|
1384
1375
|
try {
|
|
1385
1376
|
const blocks = tryDeriveFecRetentionBlocks(config.timeoutMs, config.interleaveDepthMs);
|
|
@@ -1412,19 +1403,20 @@ var FECManager = class _FECManager {
|
|
|
1412
1403
|
/**
|
|
1413
1404
|
* The stream's interleave horizon, or undefined when its geometry cannot
|
|
1414
1405
|
* define one. Two different streams reach that case, with different causes:
|
|
1415
|
-
* a packetId that was never configured,
|
|
1416
|
-
*
|
|
1406
|
+
* a packetId that was never configured, which has no geometry at all
|
|
1407
|
+
* (explicitly configured tracks are refused an underivable geometry
|
|
1417
1408
|
* at config time — #upsertTrackConfig, setMulticastSymbolDelivery); or a
|
|
1418
1409
|
* configured track whose timeoutMs was later widened past the 255-block
|
|
1419
1410
|
* ceiling without re-validating, which #derivableOrderedHorizon catches
|
|
1420
1411
|
* rather than throwing from the packet-feed path. Either way the stream
|
|
1421
|
-
* keeps datagram semantics instead of throwing.
|
|
1412
|
+
* keeps datagram semantics instead of throwing. A track's configuration can
|
|
1422
1413
|
* also change under a stream that already holds blocks, so a caller cannot
|
|
1423
1414
|
* assume a horizon that was defined when a block was held is still defined
|
|
1424
1415
|
* (see #advanceOrderedFrontier).
|
|
1425
1416
|
*/
|
|
1426
1417
|
#orderedHorizonBlocks(packetId) {
|
|
1427
|
-
|
|
1418
|
+
const config = this.#trackConfigs.get(packetId);
|
|
1419
|
+
return config === void 0 ? void 0 : this.#derivableOrderedHorizon(config, packetId);
|
|
1428
1420
|
}
|
|
1429
1421
|
/** True while a block of an ordered-relay stream can still receive symbols. */
|
|
1430
1422
|
#withinOrderedHorizon(key) {
|
|
@@ -1458,7 +1450,7 @@ var FECManager = class _FECManager {
|
|
|
1458
1450
|
*/
|
|
1459
1451
|
#advanceOrderedFrontier(streamKey, sbn, packetId, catalogTrackName) {
|
|
1460
1452
|
const previous = this.#orderedFrontiers.get(streamKey);
|
|
1461
|
-
const frontier = previous === void 0 || this.#blockPrecedes(previous, sbn
|
|
1453
|
+
const frontier = previous === void 0 || this.#blockPrecedes(previous, sbn) ? sbn : previous;
|
|
1462
1454
|
if (frontier !== previous) this.#orderedFrontiers.set(streamKey, frontier);
|
|
1463
1455
|
const pending = this.#orderedPendingBlocks.get(streamKey);
|
|
1464
1456
|
if (!pending) return;
|
|
@@ -1493,7 +1485,7 @@ var FECManager = class _FECManager {
|
|
|
1493
1485
|
if (this.#completedBlocks.has(key) || this.#pendingWorkerCleanups.has(key) || this.#repairRequestedBlocks.has(key)) return;
|
|
1494
1486
|
const authoredLength = this.#blockAuthoredLengths.get(key);
|
|
1495
1487
|
const received = (this.#blockSourceCounts.get(key) ?? 0) + (this.#blockRepairRsIds.get(key)?.size ?? 0);
|
|
1496
|
-
if (this.onRepairNeeded && (authoredLength === void 0 || received < authoredLength)) {
|
|
1488
|
+
if (this.#hasCatalogTimingForPacket(packetId) && this.onRepairNeeded && (authoredLength === void 0 || received < authoredLength)) {
|
|
1497
1489
|
this.#requestRepair(sbn, packetId, catalogTrackName, true);
|
|
1498
1490
|
return;
|
|
1499
1491
|
}
|
|
@@ -1649,7 +1641,7 @@ var FECManager = class _FECManager {
|
|
|
1649
1641
|
}
|
|
1650
1642
|
#requestRepair(sbn, packetId, catalogTrackName, settledByOrder = false) {
|
|
1651
1643
|
const key = this.#blockKey(sbn, packetId, catalogTrackName);
|
|
1652
|
-
if (this.#completedBlocks.has(key) || !this.onRepairNeeded || this.#repairRequestedBlocks.has(key)) return;
|
|
1644
|
+
if (this.#completedBlocks.has(key) || !this.#hasCatalogTimingForPacket(packetId) || !this.onRepairNeeded || this.#repairRequestedBlocks.has(key)) return;
|
|
1653
1645
|
const deadline = this.#repairDeadlines.get(key);
|
|
1654
1646
|
if (deadline?.handle != null) clearTimeout(deadline.handle);
|
|
1655
1647
|
this.#repairDeadlines.set(key, null);
|
|
@@ -1729,6 +1721,7 @@ var FECManager = class _FECManager {
|
|
|
1729
1721
|
}
|
|
1730
1722
|
/** A block's live class without creating classifier state for the stream. */
|
|
1731
1723
|
#peekClass(sbn, packetId, catalogTrackName) {
|
|
1724
|
+
if (!this.#hasCatalogTimingForPacket(packetId)) return "unknown";
|
|
1732
1725
|
const classifier = this.#classifiers.get(this.#streamKey(packetId, catalogTrackName));
|
|
1733
1726
|
if (classifier) return classifier.classOf(sbn);
|
|
1734
1727
|
return this.#geometryFor(packetId, catalogTrackName).trackKind === "audio" ? "audio" : "unknown";
|
|
@@ -1750,8 +1743,8 @@ var FECManager = class _FECManager {
|
|
|
1750
1743
|
// Deliberately one block tighter than deriveFecRetentionBlocks over the same
|
|
1751
1744
|
// inputs (that function's `+ 1`). Different question: the retention horizon
|
|
1752
1745
|
// asks how long the decoder still ACCEPTS symbols for a block, this asks how
|
|
1753
|
-
//
|
|
1754
|
-
// #noteSbnSeen).
|
|
1746
|
+
// many blocks a stream can live behind (or ahead of) its frontier before a
|
|
1747
|
+
// source symbol there is a discontinuity rather than loss (see #noteSbnSeen).
|
|
1755
1748
|
// The extra block of retention is slack for a block still being fed; a block
|
|
1756
1749
|
// nothing has been heard from does not get it. Not the units defect — but it
|
|
1757
1750
|
// is the next place the two can drift, so change both or neither.
|
|
@@ -1760,27 +1753,28 @@ var FECManager = class _FECManager {
|
|
|
1760
1753
|
return Math.ceil(config.timeoutMs / config.interleaveDepthMs);
|
|
1761
1754
|
}
|
|
1762
1755
|
/**
|
|
1763
|
-
* Record that a symbol for block `sbn`
|
|
1764
|
-
*
|
|
1756
|
+
* Record that a symbol for block `sbn` (the block's SS_Start) arrived and
|
|
1757
|
+
* advance the stream's frontier, the newest block start seen.
|
|
1765
1758
|
*
|
|
1766
|
-
*
|
|
1767
|
-
*
|
|
1768
|
-
*
|
|
1769
|
-
*
|
|
1770
|
-
*
|
|
1771
|
-
* its last symbol, is a source discontinuity, not loss. A repair symbol can
|
|
1772
|
-
* only advance the frontier: a D-28 fetch legitimately answers for an old
|
|
1773
|
-
* block, so it never signals a discontinuity.
|
|
1759
|
+
* A SOURCE symbol whose block goes back further than one live window, or
|
|
1760
|
+
* jumps further than the stream could have produced since its last symbol,
|
|
1761
|
+
* is a source discontinuity, not loss. A repair symbol can only advance the
|
|
1762
|
+
* frontier: a D-28 fetch legitimately answers for an old block, so it never
|
|
1763
|
+
* signals a discontinuity.
|
|
1774
1764
|
*
|
|
1775
1765
|
* The producer closes a block at its Dth media-unit boundary OR when K
|
|
1776
|
-
* source symbols filled it, so one interleave span can start several
|
|
1777
|
-
*
|
|
1778
|
-
*
|
|
1779
|
-
*
|
|
1780
|
-
*
|
|
1781
|
-
*
|
|
1782
|
-
*
|
|
1783
|
-
*
|
|
1766
|
+
* source symbols filled it, so one interleave span can start several blocks
|
|
1767
|
+
* (every large keyframe does). What bounds a forward jump is therefore
|
|
1768
|
+
* packet evidence, not a block rate: SS_ID advances by one per FEC source
|
|
1769
|
+
* packet (ISO/IEC 23008-1 C.5.2) and the MMTP packet_sequence_number by one
|
|
1770
|
+
* per packet of the packet_id, so with both source symbols'
|
|
1771
|
+
* packet_sequence_number a block start can move at most the packets sent
|
|
1772
|
+
* between them plus the anchor's own offset into its block (< K). Without
|
|
1773
|
+
* it, only the D-close rate is known.
|
|
1774
|
+
*
|
|
1775
|
+
* Vanished blocks are not enumerated here: their starts are unknown until a
|
|
1776
|
+
* repair states them. The SS_IDs between two stated blocks become one
|
|
1777
|
+
* repair-less span when the later block's repair arrives (placeIsoRepair).
|
|
1784
1778
|
*/
|
|
1785
1779
|
#noteSbnSeen(sbn, packetId, catalogTrackName, symbol, packetSequenceNumber) {
|
|
1786
1780
|
const streamKey = this.#streamKey(packetId, catalogTrackName);
|
|
@@ -1789,7 +1783,7 @@ var FECManager = class _FECManager {
|
|
|
1789
1783
|
const anchor = this.#sourceAnchors.get(streamKey);
|
|
1790
1784
|
const psn = symbol === "source" && packetSequenceNumber !== void 0 && Number.isSafeInteger(packetSequenceNumber) && packetSequenceNumber >= 0 && packetSequenceNumber <= 4294967295 ? packetSequenceNumber : void 0;
|
|
1791
1785
|
const anchorHere = () => {
|
|
1792
|
-
if (psn !== void 0 && (anchor === void 0 || !this.#blockPrecedes(sbn, anchor.sbn
|
|
1786
|
+
if (psn !== void 0 && (anchor === void 0 || !this.#blockPrecedes(sbn, anchor.sbn))) {
|
|
1793
1787
|
this.#sourceAnchors.set(streamKey, { sbn, psn, atMs: now });
|
|
1794
1788
|
}
|
|
1795
1789
|
};
|
|
@@ -1805,9 +1799,9 @@ var FECManager = class _FECManager {
|
|
|
1805
1799
|
anchorHere();
|
|
1806
1800
|
return;
|
|
1807
1801
|
}
|
|
1808
|
-
const config = this.#
|
|
1802
|
+
const config = this.#trackConfig(packetId);
|
|
1809
1803
|
const window = this.#liveWindowBlocks(config);
|
|
1810
|
-
if (!this.#blockPrecedes(previous.sbn, sbn
|
|
1804
|
+
if (!this.#blockPrecedes(previous.sbn, sbn)) {
|
|
1811
1805
|
if (symbol === "source" && window !== null && this.#blocksBehind(sbn, previous.sbn, packetId) > window) {
|
|
1812
1806
|
discontinuity();
|
|
1813
1807
|
return;
|
|
@@ -1818,15 +1812,9 @@ var FECManager = class _FECManager {
|
|
|
1818
1812
|
const missing = this.#blocksBehind(previous.sbn, sbn, packetId) - 1;
|
|
1819
1813
|
let plausible = true;
|
|
1820
1814
|
if (window !== null) {
|
|
1821
|
-
if (
|
|
1815
|
+
if (psn !== void 0 && anchor !== void 0 && this.#blockPrecedes(anchor.sbn, sbn) && psn !== anchor.psn) {
|
|
1822
1816
|
const sent = psn - anchor.psn >>> 0;
|
|
1823
1817
|
plausible = sent <= 2147483647 && serial32Distance(anchor.sbn, sbn) <= sent + config.k;
|
|
1824
|
-
} else if (psn !== void 0 && anchor !== void 0 && this.#blockPrecedes(anchor.sbn, sbn, packetId) && psn !== anchor.psn) {
|
|
1825
|
-
const sent = psn - anchor.psn >>> 0;
|
|
1826
|
-
const between = this.#blocksBehind(anchor.sbn, sbn, packetId) - 1;
|
|
1827
|
-
const dCloses = window + Math.ceil((now - anchor.atMs) / config.interleaveDepthMs);
|
|
1828
|
-
const kCloses = config.k > 0 ? Math.ceil(sent / config.k) : sent;
|
|
1829
|
-
plausible = sent <= 2147483647 && between <= sent - 1 && between <= dCloses + kCloses;
|
|
1830
1818
|
} else {
|
|
1831
1819
|
plausible = missing <= window + Math.ceil((now - previous.atMs) / config.interleaveDepthMs);
|
|
1832
1820
|
}
|
|
@@ -1838,48 +1826,31 @@ var FECManager = class _FECManager {
|
|
|
1838
1826
|
}
|
|
1839
1827
|
this.#highestSbn.set(streamKey, { sbn, atMs: now });
|
|
1840
1828
|
anchorHere();
|
|
1841
|
-
if (this.#isIso(packetId)) return;
|
|
1842
|
-
if (missing <= 0 || window === null) return;
|
|
1843
|
-
let vanished = previous.sbn;
|
|
1844
|
-
for (let i = 0; i < missing; i++) {
|
|
1845
|
-
vanished = this.#nextBlock(vanished, packetId);
|
|
1846
|
-
this.#materializeBlock(
|
|
1847
|
-
vanished,
|
|
1848
|
-
packetId,
|
|
1849
|
-
catalogTrackName,
|
|
1850
|
-
this.#blocksBehind(vanished, sbn, packetId) <= window
|
|
1851
|
-
);
|
|
1852
|
-
}
|
|
1853
1829
|
}
|
|
1854
1830
|
/*
|
|
1855
|
-
* Block order for one stream (BLO-35597 iso:5).
|
|
1856
|
-
* number (ISO/IEC 23008-1 C.5.2), so
|
|
1857
|
-
*
|
|
1858
|
-
*
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
#blockPrecedes(a, b, packetId) {
|
|
1863
|
-
if (this.#isIso(packetId)) return serial32Precedes(a, b);
|
|
1864
|
-
const k = this.kForPacket(packetId);
|
|
1865
|
-
return isKStrideBlock(a, k) && isKStrideBlock(b, k) ? kStrideBlockPrecedes(a, b, k) : a < b;
|
|
1866
|
-
}
|
|
1867
|
-
/** Blocks `a` lies behind `b` (0 when it does not precede it). */
|
|
1868
|
-
#blocksBehind(a, b, packetId) {
|
|
1869
|
-
if (this.#isIso(packetId)) return isoBlocksBehindLowerBound(a, b, this.kForPacket(packetId));
|
|
1870
|
-
const k = this.kForPacket(packetId);
|
|
1871
|
-
return isKStrideBlock(a, k) && isKStrideBlock(b, k) ? kStrideBlocksBehind(a, b, k) : Math.max(0, b - a);
|
|
1831
|
+
* Block order for one stream (BLO-35597 iso:5). A block is keyed by its
|
|
1832
|
+
* SS_Start and SS_ID is a 32-bit serial number (ISO/IEC 23008-1 C.5.2), so
|
|
1833
|
+
* blocks are ordered by RFC 1982 comparison of their starts. Only configured
|
|
1834
|
+
* streams hold blocks: every entry point refuses an unconfigured packetId.
|
|
1835
|
+
*/
|
|
1836
|
+
#blockPrecedes(a, b) {
|
|
1837
|
+
return serial32Precedes(a, b);
|
|
1872
1838
|
}
|
|
1873
|
-
/**
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1839
|
+
/**
|
|
1840
|
+
* Blocks `a` lies behind `b` (0 when it does not precede it). Blocks vary
|
|
1841
|
+
* in length (K' = SSB_length <= K), so only a lower bound is known: the one
|
|
1842
|
+
* metric the decoder and the worker retire by too.
|
|
1843
|
+
*/
|
|
1844
|
+
#blocksBehind(a, b, packetId) {
|
|
1845
|
+
return isoBlocksBehindLowerBound(a, b, this.#trackConfig(packetId).k);
|
|
1877
1846
|
}
|
|
1878
1847
|
#materializeBlock(sbn, packetId, catalogTrackName, repairable) {
|
|
1879
1848
|
const key = this.#blockKey(sbn, packetId, catalogTrackName);
|
|
1880
1849
|
if (this.#blockResolutionFor(key) !== "untracked") return;
|
|
1881
1850
|
this.#materializedBlocks.add(key);
|
|
1882
|
-
this.#
|
|
1851
|
+
if (this.#hasCatalogTimingForPacket(packetId)) {
|
|
1852
|
+
this.#classifierFor(packetId, catalogTrackName).touch(sbn);
|
|
1853
|
+
}
|
|
1883
1854
|
this.onBlockVanished?.(sbn, packetId, catalogTrackName);
|
|
1884
1855
|
if (repairable) {
|
|
1885
1856
|
this.noteBlockActivity(sbn, packetId, catalogTrackName, true);
|
|
@@ -1918,21 +1889,39 @@ var FECManager = class _FECManager {
|
|
|
1918
1889
|
});
|
|
1919
1890
|
if (this.#lifecycleTrace.length > 64) this.#lifecycleTrace.splice(0, 32);
|
|
1920
1891
|
}
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1892
|
+
/**
|
|
1893
|
+
* A configured packetId's track config. There is no manager-wide default
|
|
1894
|
+
* (BLO-45953): an unconfigured packetId does no FEC work, so every caller
|
|
1895
|
+
* here is reached only behind a configuration gate and this throw marks a
|
|
1896
|
+
* broken invariant, never a packet-path outcome.
|
|
1897
|
+
*/
|
|
1898
|
+
#trackConfig(packetId) {
|
|
1899
|
+
const config = this.#trackConfigs.get(packetId);
|
|
1900
|
+
if (config === void 0) {
|
|
1901
|
+
throw new Error(
|
|
1902
|
+
`[FECManager] packetId=${packetId} was never configured; configure the track from its catalog (configureTrack/setFecWorker/setFecDecoder) first`
|
|
1903
|
+
);
|
|
1904
|
+
}
|
|
1905
|
+
return config;
|
|
1929
1906
|
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1907
|
+
/**
|
|
1908
|
+
* Whether this track has the catalog's elapsed-time FEC policy. A zero span
|
|
1909
|
+
* is a deliberate no-deadline signal; it still leaves the wire geometry
|
|
1910
|
+
* usable for in-band decode, but it cannot drive classification, repair
|
|
1911
|
+
* fetches or layer adaptation.
|
|
1912
|
+
*/
|
|
1913
|
+
static #hasCatalogTiming(config) {
|
|
1914
|
+
return Number.isSafeInteger(config.interleaveDepthMs) && config.interleaveDepthMs >= MIN_INTERLEAVE_DEPTH_MS;
|
|
1915
|
+
}
|
|
1916
|
+
#hasCatalogTimingForPacket(packetId) {
|
|
1917
|
+
const config = this.#trackConfigs.get(packetId);
|
|
1918
|
+
return config !== void 0 && _FECManager.#hasCatalogTiming(config);
|
|
1932
1919
|
}
|
|
1933
1920
|
#computeTimeout(config) {
|
|
1934
|
-
if (config.timeoutMs && config.timeoutMs > 0)
|
|
1935
|
-
|
|
1921
|
+
if (typeof config.timeoutMs === "number" && Number.isFinite(config.timeoutMs) && config.timeoutMs > 0) {
|
|
1922
|
+
return config.timeoutMs;
|
|
1923
|
+
}
|
|
1924
|
+
if (Number.isSafeInteger(config.interleaveDepthMs) && config.interleaveDepthMs >= MIN_INTERLEAVE_DEPTH_MS) {
|
|
1936
1925
|
return Math.max(
|
|
1937
1926
|
this.#fecTimeoutMs,
|
|
1938
1927
|
computeFecDeliveryWindowMs({
|
|
@@ -1957,14 +1946,17 @@ var FECManager = class _FECManager {
|
|
|
1957
1946
|
*/
|
|
1958
1947
|
#refreshDeliveryGapWindow() {
|
|
1959
1948
|
let windowMs;
|
|
1960
|
-
const consider = (geometry) => {
|
|
1949
|
+
const consider = (geometry, packetId) => {
|
|
1950
|
+
if (!this.#hasCatalogTimingForPacket(packetId)) return;
|
|
1961
1951
|
if (geometry?.trackKind !== "video" || geometry.mode !== "classifying") return;
|
|
1962
1952
|
const { ticks, timescale } = geometry.keyframeInterval;
|
|
1963
1953
|
const ms = ticks / timescale * 1e3;
|
|
1964
1954
|
if (Number.isFinite(ms) && ms > 0 && (windowMs === void 0 || ms > windowMs)) windowMs = ms;
|
|
1965
1955
|
};
|
|
1966
|
-
for (const geometry of this.#streamGeometries
|
|
1967
|
-
|
|
1956
|
+
for (const [streamKey, geometry] of this.#streamGeometries) {
|
|
1957
|
+
consider(geometry, this.#parseStreamKey(streamKey).packetId);
|
|
1958
|
+
}
|
|
1959
|
+
for (const [packetId, config] of this.#trackConfigs) consider(config.geometry, packetId);
|
|
1968
1960
|
this.#deliveryGaps.setWindowMs(windowMs);
|
|
1969
1961
|
}
|
|
1970
1962
|
/**
|
|
@@ -1992,6 +1984,7 @@ var FECManager = class _FECManager {
|
|
|
1992
1984
|
return Math.max(config.timeoutMs, Math.ceil(config.interleaveDepthMs + gapMs));
|
|
1993
1985
|
}
|
|
1994
1986
|
#repairDeadlineMs(config, waitMs = this.#multicastWaitMs(config)) {
|
|
1987
|
+
if (!_FECManager.#hasCatalogTiming(config)) return waitMs;
|
|
1995
1988
|
const halfFailBoundMs = Math.ceil(waitMs / 2);
|
|
1996
1989
|
if (config.k > 0 && config.interleaveDepthMs >= MIN_INTERLEAVE_DEPTH_MS && config.fps !== void 0 && Number.isFinite(config.fps) && config.fps > 0) {
|
|
1997
1990
|
const mediaUnitMs = 1e3 / config.fps;
|
|
@@ -2006,10 +1999,12 @@ var FECManager = class _FECManager {
|
|
|
2006
1999
|
}
|
|
2007
2000
|
/**
|
|
2008
2001
|
* One block lifetime: the inactivity fail bound plus the D-28 repair grace,
|
|
2009
|
-
* at the widest wait the catalog allows (#maxMulticastWaitMs).
|
|
2010
|
-
*
|
|
2011
|
-
*
|
|
2012
|
-
*
|
|
2002
|
+
* at the widest wait the catalog allows (#maxMulticastWaitMs). For a track
|
|
2003
|
+
* without a catalog span this is receiver-local cleanup time only; no repair
|
|
2004
|
+
* grace is added. Everything derived from it (terminal retention, the
|
|
2005
|
+
* release gate's hold ceiling, the duplicate ledgers, the owed-cleanup
|
|
2006
|
+
* bound) is compared across time, so it must not follow the live
|
|
2007
|
+
* measurement.
|
|
2013
2008
|
*/
|
|
2014
2009
|
#blockLifetimeMs(config) {
|
|
2015
2010
|
const waitMs = this.#maxMulticastWaitMs(config);
|
|
@@ -2025,6 +2020,7 @@ var FECManager = class _FECManager {
|
|
|
2025
2020
|
return Math.min(waitMs + this.#repairGraceMs(config, waitMs), this.#blockLifetimeMs(config));
|
|
2026
2021
|
}
|
|
2027
2022
|
#repairGraceMs(config, waitMs) {
|
|
2023
|
+
if (!_FECManager.#hasCatalogTiming(config)) return 0;
|
|
2028
2024
|
return Math.max(1, waitMs - this.#repairDeadlineMs(config, waitMs));
|
|
2029
2025
|
}
|
|
2030
2026
|
#armBlockTimeout(sbn, packetId, catalogTrackName, delayMs) {
|
|
@@ -2111,51 +2107,72 @@ var FECManager = class _FECManager {
|
|
|
2111
2107
|
* stream; every other field stays per packetId.
|
|
2112
2108
|
*/
|
|
2113
2109
|
#upsertTrackConfig(packetId, config, catalogTrackName) {
|
|
2114
|
-
const
|
|
2110
|
+
const previousTrack = this.#trackConfigs.get(packetId);
|
|
2111
|
+
const k = config.k ?? previousTrack?.k;
|
|
2112
|
+
if (k === void 0 || !Number.isSafeInteger(k) || k <= 0) {
|
|
2113
|
+
throw new Error(
|
|
2114
|
+
`[FECManager] packetId=${packetId}: fec.k=${String(k)} must be a positive integer; configure the track from its catalog`
|
|
2115
|
+
);
|
|
2116
|
+
}
|
|
2117
|
+
const previous = previousTrack ?? {};
|
|
2115
2118
|
const streamScopedGeometry = catalogTrackName !== void 0 && config.geometry !== void 0 ? config.geometry : void 0;
|
|
2116
2119
|
if (streamScopedGeometry !== void 0) {
|
|
2117
2120
|
const { geometry: _streamGeometry, ...packetLevel } = config;
|
|
2118
2121
|
config = packetLevel;
|
|
2119
2122
|
}
|
|
2120
2123
|
const timingChanged = config.k !== void 0 || config.interleaveDepthMs !== void 0 || config.fps !== void 0;
|
|
2124
|
+
if (config.timeoutMs !== void 0 && (!Number.isFinite(config.timeoutMs) || config.timeoutMs < 0)) {
|
|
2125
|
+
throw new Error(
|
|
2126
|
+
`[FECManager] packetId=${packetId}: timeoutMs=${config.timeoutMs} must be a finite non-negative cleanup budget`
|
|
2127
|
+
);
|
|
2128
|
+
}
|
|
2121
2129
|
if (config.blockProfile !== void 0) {
|
|
2122
2130
|
parseFecBlockProfile(config.blockProfile, `packetId=${packetId} fec.blockProfile`);
|
|
2123
2131
|
}
|
|
2124
2132
|
const blockProfile = config.blockProfile ?? previous.blockProfile;
|
|
2125
2133
|
if (blockProfile === void 0) {
|
|
2126
2134
|
throw new Error(
|
|
2127
|
-
`[FECManager] packetId=${packetId}: fec.blockProfile is required ("
|
|
2135
|
+
`[FECManager] packetId=${packetId}: fec.blockProfile is required ("iso-ssbg1-v1"); configure the track from its catalog`
|
|
2128
2136
|
);
|
|
2129
2137
|
}
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
);
|
|
2136
|
-
}
|
|
2138
|
+
const ownInterleaveDepthMs = config.interleaveDepthMs ?? previousTrack?.interleaveDepthMs ?? 0;
|
|
2139
|
+
if (!Number.isSafeInteger(ownInterleaveDepthMs) || ownInterleaveDepthMs !== 0 && ownInterleaveDepthMs < MIN_INTERLEAVE_DEPTH_MS) {
|
|
2140
|
+
throw new Error(
|
|
2141
|
+
`[FECManager] packetId=${packetId}: fec.interleaveDepthMs must be absent, 0, or a finite value >= ${MIN_INTERLEAVE_DEPTH_MS} ms (got ${String(ownInterleaveDepthMs)})`
|
|
2142
|
+
);
|
|
2137
2143
|
}
|
|
2144
|
+
const hasCatalogTiming = _FECManager.#hasCatalogTiming({ interleaveDepthMs: ownInterleaveDepthMs });
|
|
2138
2145
|
const next = {
|
|
2139
2146
|
blockProfile,
|
|
2140
|
-
k
|
|
2141
|
-
symbolSize: config.symbolSize != null && config.symbolSize > 0 ? config.symbolSize :
|
|
2142
|
-
interleaveDepthMs:
|
|
2143
|
-
fps: config.fps ?? previous.fps,
|
|
2144
|
-
timeoutMs: config.timeoutMs ?? (timingChanged ? 0 : previous.timeoutMs),
|
|
2147
|
+
k,
|
|
2148
|
+
symbolSize: config.symbolSize != null && config.symbolSize > 0 ? config.symbolSize : previousTrack?.symbolSize ?? 0,
|
|
2149
|
+
interleaveDepthMs: ownInterleaveDepthMs,
|
|
2150
|
+
fps: config.fps ?? previous.fps ?? this.#fecFps,
|
|
2151
|
+
timeoutMs: config.timeoutMs ?? (timingChanged ? 0 : previous.timeoutMs ?? 0),
|
|
2145
2152
|
...(config.trackKind ?? previous.trackKind) === void 0 ? {} : { trackKind: config.trackKind ?? previous.trackKind },
|
|
2146
2153
|
...(config.codec ?? previous.codec) === void 0 ? {} : { codec: config.codec ?? previous.codec },
|
|
2147
2154
|
...(config.geometry ?? previous.geometry) === void 0 ? {} : { geometry: config.geometry ?? previous.geometry }
|
|
2148
2155
|
};
|
|
2149
|
-
|
|
2156
|
+
if (!hasCatalogTiming) {
|
|
2157
|
+
next.timeoutMs = config.timeoutMs !== void 0 && config.timeoutMs > 0 ? config.timeoutMs : previousTrack !== void 0 && previousTrack.interleaveDepthMs === 0 ? previousTrack.timeoutMs : LOCAL_FEC_TIMEOUT_MS;
|
|
2158
|
+
} else {
|
|
2159
|
+
next.timeoutMs = this.#computeTimeout(next);
|
|
2160
|
+
}
|
|
2150
2161
|
if (this.#multicastSymbolDelivery === "ordered-relay") {
|
|
2151
2162
|
this.#orderedHorizonBlocksFor(packetId, next);
|
|
2152
2163
|
}
|
|
2153
|
-
|
|
2164
|
+
const timingPolicyChanged = _FECManager.#hasCatalogTiming({ interleaveDepthMs: previous.interleaveDepthMs ?? 0 }) !== hasCatalogTiming;
|
|
2165
|
+
if (timingPolicyChanged && !hasCatalogTiming) {
|
|
2166
|
+
for (const key of [...this.#repairDeadlines.keys()]) {
|
|
2167
|
+
if (this.#belongsToPacket(key, packetId)) this.#clearRepairDeadline(key);
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
if (previous.blockProfile !== void 0 && previous.k !== next.k) {
|
|
2154
2171
|
this.#dropIsoLocators(packetId);
|
|
2155
2172
|
}
|
|
2156
2173
|
this.#trackConfigs.set(packetId, next);
|
|
2157
2174
|
this.#refreshDeliveryGapWindow();
|
|
2158
|
-
let policyChanged = config.geometry !== void 0 && JSON.stringify(config.geometry) !== JSON.stringify(previous.geometry) || config.trackKind !== void 0 && config.trackKind !== previous.trackKind;
|
|
2175
|
+
let policyChanged = timingPolicyChanged || config.geometry !== void 0 && JSON.stringify(config.geometry) !== JSON.stringify(previous.geometry) || config.trackKind !== void 0 && config.trackKind !== previous.trackKind;
|
|
2159
2176
|
if (streamScopedGeometry !== void 0) {
|
|
2160
2177
|
const streamKey = this.#streamKey(packetId, catalogTrackName);
|
|
2161
2178
|
if (JSON.stringify(streamScopedGeometry) !== JSON.stringify(this.#streamGeometries.get(streamKey))) {
|
|
@@ -2170,20 +2187,14 @@ var FECManager = class _FECManager {
|
|
|
2170
2187
|
if (!this.#belongsToPacket(key, packetId)) continue;
|
|
2171
2188
|
const stream = this.#parseStreamKey(key);
|
|
2172
2189
|
const geometry = this.#geometryFor(stream.packetId, stream.catalogTrackName);
|
|
2173
|
-
if (JSON.stringify(geometry) === JSON.stringify(classifier.geometry)) continue;
|
|
2190
|
+
if (hasCatalogTiming && JSON.stringify(geometry) === JSON.stringify(classifier.geometry)) continue;
|
|
2174
2191
|
this.#classifiers.delete(key);
|
|
2192
|
+
if (!hasCatalogTiming) continue;
|
|
2175
2193
|
this.#applyClassifierChanges(stream.packetId, stream.catalogTrackName, classifier.retire());
|
|
2176
2194
|
}
|
|
2177
2195
|
}
|
|
2178
2196
|
return next;
|
|
2179
2197
|
}
|
|
2180
|
-
#normalizeSymbolData(packetId, data) {
|
|
2181
|
-
const symbolSize = this.symbolSizeForPacket(packetId);
|
|
2182
|
-
if (symbolSize <= 0 || data.byteLength === symbolSize) return data;
|
|
2183
|
-
const normalized = new Uint8Array(symbolSize);
|
|
2184
|
-
normalized.set(data.subarray(0, symbolSize));
|
|
2185
|
-
return normalized;
|
|
2186
|
-
}
|
|
2187
2198
|
#blockKeysFor(sbn, packetId, catalogTrackName) {
|
|
2188
2199
|
if (packetId != null && catalogTrackName !== void 0) {
|
|
2189
2200
|
return [this.#blockKey(sbn, packetId, catalogTrackName)];
|
|
@@ -2244,7 +2255,7 @@ var FECManager = class _FECManager {
|
|
|
2244
2255
|
...stats,
|
|
2245
2256
|
packetId,
|
|
2246
2257
|
blocksComplete: trackTotal,
|
|
2247
|
-
k: this.#
|
|
2258
|
+
k: this.#trackConfigs.get(packetId)?.k,
|
|
2248
2259
|
recoveryRate: trackAffected > 0 ? stats.blocksRecovered / trackAffected * 100 : 100,
|
|
2249
2260
|
packetLossRate: trackTotal > 0 ? trackAffected / trackTotal * 100 : 0
|
|
2250
2261
|
};
|
|
@@ -2256,7 +2267,7 @@ var FECManager = class _FECManager {
|
|
|
2256
2267
|
(block) => block.multicastSymbols > 0 && block.moqSymbols > 0
|
|
2257
2268
|
).length,
|
|
2258
2269
|
recentBlockPathCounts: Array.from(this.#blockPathCounts.values()).slice(-24),
|
|
2259
|
-
k: this.#
|
|
2270
|
+
k: this.#streamK,
|
|
2260
2271
|
// True recovery rate: of blocks that HAD loss, how many were recovered?
|
|
2261
2272
|
recoveryRate: affected > 0 ? s.blocksRecovered / affected * 100 : 100,
|
|
2262
2273
|
packetLossRate: total > 0 ? affected / total * 100 : 0,
|
|
@@ -2269,7 +2280,6 @@ var FECManager = class _FECManager {
|
|
|
2269
2280
|
},
|
|
2270
2281
|
blocks: stats.blocks.map((block) => ({ ...block })),
|
|
2271
2282
|
decoder: stats.decoder ? { ...stats.decoder } : void 0,
|
|
2272
|
-
altaFailedDetails: stats.altaFailedDetails?.map((detail) => ({ ...detail })),
|
|
2273
2283
|
packetId
|
|
2274
2284
|
})),
|
|
2275
2285
|
repairSymbolSizeMismatches: this.#repairSymbolSizeMismatchCount,
|
|
@@ -2376,6 +2386,7 @@ var FECManager = class _FECManager {
|
|
|
2376
2386
|
resetMap(this.#blockSourceEsis);
|
|
2377
2387
|
resetMap(this.#blockAuthoredLengths);
|
|
2378
2388
|
resetMap(this.#blockRepairRsIds);
|
|
2389
|
+
resetMap(this.#blockRsbLengths);
|
|
2379
2390
|
resetMap(this.#blockPathCounts);
|
|
2380
2391
|
resetMap(this.#blockAnchorsMs);
|
|
2381
2392
|
resetMap(this.#blockCatalogTrackNames);
|
|
@@ -2493,6 +2504,7 @@ var FECManager = class _FECManager {
|
|
|
2493
2504
|
dropMap(this.#blockSourceEsis);
|
|
2494
2505
|
dropMap(this.#blockAuthoredLengths);
|
|
2495
2506
|
dropMap(this.#blockRepairRsIds);
|
|
2507
|
+
dropMap(this.#blockRsbLengths);
|
|
2496
2508
|
dropMap(this.#blockPathCounts);
|
|
2497
2509
|
dropMap(this.#blockAnchorsMs);
|
|
2498
2510
|
dropMap(this.#blockCatalogTrackNames);
|
|
@@ -2551,15 +2563,20 @@ var FECManager = class _FECManager {
|
|
|
2551
2563
|
}
|
|
2552
2564
|
}
|
|
2553
2565
|
}
|
|
2554
|
-
/**
|
|
2566
|
+
/**
|
|
2567
|
+
* Record a transport symbol and reject later duplicates of the same
|
|
2568
|
+
* packetId/SBN/ESI. `sbn` is the block's SS_Start. A packetId with no
|
|
2569
|
+
* configured block profile has no block geometry: its symbol is refused
|
|
2570
|
+
* (false) and no block state is created for it.
|
|
2571
|
+
*/
|
|
2555
2572
|
feedSymbolFromSource(packetId, sbn, esi, _data, source, catalogTrackName) {
|
|
2573
|
+
if (!this.#hasBlockProfile(packetId)) return false;
|
|
2556
2574
|
const blockKey = this.#blockKey(sbn, packetId, catalogTrackName);
|
|
2557
2575
|
const streamKey = this.#streamKey(packetId, catalogTrackName);
|
|
2558
2576
|
if (source === "multicast" && this.#multicastSymbolDelivery === "ordered-relay") {
|
|
2559
2577
|
this.#advanceOrderedFrontier(streamKey, sbn, packetId, catalogTrackName);
|
|
2560
2578
|
}
|
|
2561
|
-
const
|
|
2562
|
-
const sourceSymbols = this.#isIso(packetId) ? this.#isoLocatorFor(packetId, catalogTrackName).blockAt(sbn)?.length ?? k : k;
|
|
2579
|
+
const sourceSymbols = this.#isoLocatorFor(packetId, catalogTrackName).blockAt(sbn)?.length ?? this.#trackConfig(packetId).k;
|
|
2563
2580
|
const isSourceSymbol = esi >= 0 && esi < sourceSymbols;
|
|
2564
2581
|
const isStartupPartial = this.#startupPartialBlocks.has(blockKey);
|
|
2565
2582
|
const isReadyMulticastRepair = this.#startupRequireRepairReady && source === "multicast" && !isSourceSymbol && this.#startupRepairReadyPackets.has(streamKey);
|
|
@@ -2677,14 +2694,14 @@ var FECManager = class _FECManager {
|
|
|
2677
2694
|
for (const [key] of this.#activeBlocks) {
|
|
2678
2695
|
const { packetId, sbn } = this.#parseBlockKey(key);
|
|
2679
2696
|
const count = this.#blockSourceCounts.get(key) ?? 0;
|
|
2680
|
-
const k = this.#blockAuthoredLengths.get(key) ?? this
|
|
2697
|
+
const k = this.#blockAuthoredLengths.get(key) ?? this.#trackConfig(packetId).k;
|
|
2681
2698
|
blocks.push({ sbn, packetId, state: "collecting", sourceCount: count, k, progress: k > 0 ? Math.min(count / k, 1) : 0 });
|
|
2682
2699
|
}
|
|
2683
2700
|
const completed = [...this.#completedBlocks].slice(-16);
|
|
2684
2701
|
for (const key of completed) {
|
|
2685
2702
|
const { packetId, sbn } = this.#parseBlockKey(key);
|
|
2686
2703
|
if (!this.#activeBlocks.has(key)) {
|
|
2687
|
-
const k = this
|
|
2704
|
+
const k = this.#trackConfig(packetId).k;
|
|
2688
2705
|
blocks.push({ sbn, packetId, state: "complete", sourceCount: k, k, progress: 1 });
|
|
2689
2706
|
}
|
|
2690
2707
|
}
|
|
@@ -2695,25 +2712,23 @@ var FECManager = class _FECManager {
|
|
|
2695
2712
|
get wasmDecoder() {
|
|
2696
2713
|
return this.#fecDecoders.values().next().value?.client ?? null;
|
|
2697
2714
|
}
|
|
2698
|
-
|
|
2699
|
-
return this.#fecK;
|
|
2700
|
-
}
|
|
2715
|
+
/** A configured packetId's K; undefined for an unconfigured one (no FEC work). */
|
|
2701
2716
|
kForPacket(packetId) {
|
|
2702
|
-
return this.#
|
|
2717
|
+
return this.#trackConfigs.get(packetId)?.k;
|
|
2703
2718
|
}
|
|
2704
2719
|
/** FEC symbol size in bytes. */
|
|
2705
2720
|
get symbolSize() {
|
|
2706
2721
|
return this.#fecSymbolSize;
|
|
2707
2722
|
}
|
|
2708
2723
|
symbolSizeForPacket(packetId) {
|
|
2709
|
-
return this.#
|
|
2724
|
+
return this.#trackConfigs.get(packetId)?.symbolSize;
|
|
2710
2725
|
}
|
|
2711
2726
|
/** FEC block span in milliseconds (0 = no interleaving). */
|
|
2712
2727
|
get interleaveDepthMs() {
|
|
2713
2728
|
return this.#fecInterleaveDepthMs;
|
|
2714
2729
|
}
|
|
2715
2730
|
interleaveDepthMsForPacket(packetId) {
|
|
2716
|
-
return this.#
|
|
2731
|
+
return this.#trackConfigs.get(packetId)?.interleaveDepthMs;
|
|
2717
2732
|
}
|
|
2718
2733
|
/**
|
|
2719
2734
|
* Record one multicast MMTP packet arrival (every packet of the leg, FEC
|
|
@@ -2731,7 +2746,8 @@ var FECManager = class _FECManager {
|
|
|
2731
2746
|
* plus the larger of the catalog tolerance and the measured delivery gap.
|
|
2732
2747
|
*/
|
|
2733
2748
|
timeoutMsForPacket(packetId) {
|
|
2734
|
-
|
|
2749
|
+
const config = this.#trackConfigs.get(packetId);
|
|
2750
|
+
return config === void 0 ? void 0 : this.#multicastWaitMs(config);
|
|
2735
2751
|
}
|
|
2736
2752
|
/**
|
|
2737
2753
|
* Largest multicast delivery gap measured over the current window (ms), and
|
|
@@ -2743,6 +2759,31 @@ var FECManager = class _FECManager {
|
|
|
2743
2759
|
windowMs: this.#deliveryGaps.windowMs
|
|
2744
2760
|
};
|
|
2745
2761
|
}
|
|
2762
|
+
/**
|
|
2763
|
+
* An open block's accepted sources, distinct repair RS_IDs, authored K'
|
|
2764
|
+
* (SSB_length) and RSB_length (each undefined until a repair stated it).
|
|
2765
|
+
* Undefined for a block that is not open.
|
|
2766
|
+
*/
|
|
2767
|
+
blockSymbolCounts(sbn, packetId, catalogTrackName) {
|
|
2768
|
+
const key = this.#blockKey(sbn, packetId, catalogTrackName);
|
|
2769
|
+
if (!this.#activeBlocks.has(key)) return void 0;
|
|
2770
|
+
return {
|
|
2771
|
+
sources: this.#blockSourceCounts.get(key) ?? 0,
|
|
2772
|
+
repairs: this.#blockRepairRsIds.get(key)?.size ?? 0,
|
|
2773
|
+
authoredLength: this.#blockAuthoredLengths.get(key),
|
|
2774
|
+
repairGroupLength: this.#blockRsbLengths.get(key)
|
|
2775
|
+
};
|
|
2776
|
+
}
|
|
2777
|
+
/**
|
|
2778
|
+
* Record a block's RSB_length from one of its repair symbols (the router
|
|
2779
|
+
* parses it from the Repair FEC Payload ID). The largest stated value wins.
|
|
2780
|
+
*/
|
|
2781
|
+
noteRepairGroupLength(sbn, packetId, rsbLength, catalogTrackName) {
|
|
2782
|
+
if (!Number.isSafeInteger(rsbLength) || rsbLength <= 0) return;
|
|
2783
|
+
const key = this.#blockKey(sbn, packetId, catalogTrackName);
|
|
2784
|
+
if (!this.#activeBlocks.has(key)) return;
|
|
2785
|
+
if ((this.#blockRsbLengths.get(key) ?? 0) < rsbLength) this.#blockRsbLengths.set(key, rsbLength);
|
|
2786
|
+
}
|
|
2746
2787
|
/**
|
|
2747
2788
|
* Receiver-local time of a block's first accepted symbol, or undefined for
|
|
2748
2789
|
* a block no symbol reached (one materialized because a later SBN arrived).
|
|
@@ -2787,27 +2828,31 @@ var FECManager = class _FECManager {
|
|
|
2787
2828
|
}
|
|
2788
2829
|
/** Resolved per-track D-28 repair request deadline in milliseconds. */
|
|
2789
2830
|
repairDeadlineMsForPacket(packetId) {
|
|
2790
|
-
|
|
2831
|
+
const config = this.#trackConfigs.get(packetId);
|
|
2832
|
+
return config === void 0 ? void 0 : this.#repairDeadlineMs(config);
|
|
2791
2833
|
}
|
|
2792
2834
|
/**
|
|
2793
2835
|
* One block lifetime: the longest a block stays open after its last symbol
|
|
2794
2836
|
* (inactivity fail bound plus D-28 repair grace).
|
|
2795
2837
|
*/
|
|
2796
2838
|
blockLifetimeMsForPacket(packetId) {
|
|
2797
|
-
|
|
2839
|
+
const config = this.#trackConfigs.get(packetId);
|
|
2840
|
+
return config === void 0 ? void 0 : this.#blockLifetimeMs(config);
|
|
2798
2841
|
}
|
|
2799
2842
|
/**
|
|
2800
2843
|
* How long a terminal (clean, recovered or failed) block stays authoritative,
|
|
2801
2844
|
* for late symbols and for the in-order release gate. It is also the gate's
|
|
2802
2845
|
* hold ceiling (MmtpRouter's holdLimitMs): a retired block reads back as
|
|
2803
2846
|
* untracked, which the gate counts as lost, so no frame may still be waiting
|
|
2804
|
-
* on a block that can retire.
|
|
2805
|
-
*
|
|
2806
|
-
*
|
|
2807
|
-
*
|
|
2847
|
+
* on a block that can retire. With a positive catalog span the window is one
|
|
2848
|
+
* interleave depth for a gap's last block to finish arriving, one block
|
|
2849
|
+
* lifetime to fail it, and one more for an owed Worker cleanup. With an
|
|
2850
|
+
* absent/zero span it is a receiver-local cleanup bound only; it creates no
|
|
2851
|
+
* catalog FEC deadline.
|
|
2808
2852
|
*/
|
|
2809
2853
|
terminalRetentionMsForPacket(packetId) {
|
|
2810
|
-
const config = this.#
|
|
2854
|
+
const config = this.#trackConfigs.get(packetId);
|
|
2855
|
+
if (config === void 0) return void 0;
|
|
2811
2856
|
return config.interleaveDepthMs + 2 * this.#blockLifetimeMs(config);
|
|
2812
2857
|
}
|
|
2813
2858
|
/** Remaining fetch budget for a specific repair-requested block. */
|
|
@@ -2818,7 +2863,8 @@ var FECManager = class _FECManager {
|
|
|
2818
2863
|
if (deadlineMs !== void 0) {
|
|
2819
2864
|
return Math.max(1, Math.ceil(deadlineMs - performance.now()));
|
|
2820
2865
|
}
|
|
2821
|
-
const trackConfig = this.#
|
|
2866
|
+
const trackConfig = this.#trackConfigs.get(packetId);
|
|
2867
|
+
if (trackConfig === void 0) return void 0;
|
|
2822
2868
|
return Math.max(1, trackConfig.timeoutMs - this.#repairDeadlineMs(trackConfig));
|
|
2823
2869
|
}
|
|
2824
2870
|
/** True once configureTrack/setFecDecoder/setFecWorker configured this packetId. */
|
|
@@ -2829,14 +2875,19 @@ var FECManager = class _FECManager {
|
|
|
2829
2875
|
blockProfileForPacket(packetId) {
|
|
2830
2876
|
return this.#trackConfigs.get(packetId)?.blockProfile;
|
|
2831
2877
|
}
|
|
2832
|
-
|
|
2833
|
-
|
|
2878
|
+
/**
|
|
2879
|
+
* Whether a packetId has a configured block geometry. iso-ssbg1-v1 is the
|
|
2880
|
+
* only profile, so every configured track has it; a packetId never
|
|
2881
|
+
* configured (or released) has none and gets no FEC block tracking.
|
|
2882
|
+
*/
|
|
2883
|
+
#hasBlockProfile(packetId) {
|
|
2884
|
+
return this.#trackConfigs.get(packetId)?.blockProfile !== void 0;
|
|
2834
2885
|
}
|
|
2835
2886
|
#isoLocatorFor(packetId, catalogTrackName) {
|
|
2836
2887
|
const streamKey = this.#streamKey(packetId, catalogTrackName);
|
|
2837
2888
|
let locator = this.#isoLocators.get(streamKey);
|
|
2838
2889
|
if (!locator) {
|
|
2839
|
-
locator = new IsoBlockLocator(this
|
|
2890
|
+
locator = new IsoBlockLocator(this.#trackConfig(packetId).k, this.#isoRetentionBlocks(packetId));
|
|
2840
2891
|
this.#isoLocators.set(streamKey, locator);
|
|
2841
2892
|
}
|
|
2842
2893
|
return locator;
|
|
@@ -2867,12 +2918,14 @@ var FECManager = class _FECManager {
|
|
|
2867
2918
|
*/
|
|
2868
2919
|
#isoRetentionBlocks(packetId) {
|
|
2869
2920
|
const config = this.#trackConfigs.get(packetId);
|
|
2870
|
-
if (config?.blockProfile
|
|
2921
|
+
if (config?.blockProfile === void 0) {
|
|
2871
2922
|
throw new Error(
|
|
2872
|
-
`[FECManager] packetId=${packetId} has no iso-ssbg1-v1 block
|
|
2923
|
+
`[FECManager] packetId=${packetId} has no configured iso-ssbg1-v1 block profile`
|
|
2873
2924
|
);
|
|
2874
2925
|
}
|
|
2875
|
-
|
|
2926
|
+
if (!_FECManager.#hasCatalogTiming(config)) return LOCAL_FEC_RETENTION_BLOCKS;
|
|
2927
|
+
const terminalRetentionMs = config.interleaveDepthMs + 2 * this.#blockLifetimeMs(config);
|
|
2928
|
+
const blocks = Math.ceil(terminalRetentionMs / config.interleaveDepthMs) + 1;
|
|
2876
2929
|
if (!Number.isSafeInteger(blocks) || blocks <= 0) {
|
|
2877
2930
|
throw new Error(`[FECManager] packetId=${packetId} iso-ssbg1-v1 retention of ${blocks} blocks is not derivable`);
|
|
2878
2931
|
}
|
|
@@ -2880,7 +2933,8 @@ var FECManager = class _FECManager {
|
|
|
2880
2933
|
}
|
|
2881
2934
|
/** Whether an iso-ssbg1-v1 protected packet fits one ssbg_mode1 symbol (len + 2 <= T). */
|
|
2882
2935
|
isoSourceFits(packetId, packetLength) {
|
|
2883
|
-
|
|
2936
|
+
const symbolSize = this.#trackConfigs.get(packetId)?.symbolSize;
|
|
2937
|
+
return symbolSize !== void 0 && ssbg1FitsSymbol(packetLength, symbolSize);
|
|
2884
2938
|
}
|
|
2885
2939
|
/**
|
|
2886
2940
|
* Locate an iso-ssbg1-v1 source by range membership in a block a repair
|
|
@@ -2941,11 +2995,11 @@ var FECManager = class _FECManager {
|
|
|
2941
2995
|
* that could hold them is pending or not yet stated by a repair, else the
|
|
2942
2996
|
* starts of the blocks that failed or vanished.
|
|
2943
2997
|
*
|
|
2944
|
-
* `untracked` reads
|
|
2945
|
-
*
|
|
2946
|
-
*
|
|
2947
|
-
*
|
|
2948
|
-
* an SS_Start
|
|
2998
|
+
* `untracked` reads as the release gate reads it (MmtpRouter
|
|
2999
|
+
* #createFecReleaseGate): a block holding either released frame's SS_ID
|
|
3000
|
+
* (`fromSsId` or `toSsId`) delivered that frame, so untracked there means it
|
|
3001
|
+
* resolved and retired; a block starting after the stream's frontier
|
|
3002
|
+
* (`highestSbn`, an SS_Start) may still be heard from; a block at or behind the
|
|
2949
3003
|
* frontier that no symbol of this manager ever reached vanished, and its
|
|
2950
3004
|
* media is lost.
|
|
2951
3005
|
*/
|
|
@@ -3013,6 +3067,7 @@ var FECManager = class _FECManager {
|
|
|
3013
3067
|
}
|
|
3014
3068
|
/** Current classifier mode of a stream. */
|
|
3015
3069
|
classifierModeFor(packetId, catalogTrackName) {
|
|
3070
|
+
if (!this.#hasCatalogTimingForPacket(packetId)) return { mode: "all-protected", reason: null };
|
|
3016
3071
|
const classifier = this.#classifierFor(packetId, catalogTrackName);
|
|
3017
3072
|
return { mode: classifier.mode, reason: classifier.reason };
|
|
3018
3073
|
}
|
|
@@ -3022,10 +3077,12 @@ var FECManager = class _FECManager {
|
|
|
3022
3077
|
* it does not. A stream with no classifier yet has shown nothing against it.
|
|
3023
3078
|
*/
|
|
3024
3079
|
mpuBoundsRapsFor(packetId, catalogTrackName) {
|
|
3080
|
+
if (!this.#hasCatalogTimingForPacket(packetId)) return false;
|
|
3025
3081
|
return this.#classifiers.get(this.#streamKey(packetId, catalogTrackName))?.mpuBoundsRaps ?? true;
|
|
3026
3082
|
}
|
|
3027
3083
|
/** A block's class now, or frozen at its resolution. */
|
|
3028
3084
|
blockClassFor(sbn, packetId, catalogTrackName) {
|
|
3085
|
+
if (!this.#hasCatalogTimingForPacket(packetId)) return "unknown";
|
|
3029
3086
|
const frozen = this.#resolvedBlockClasses.get(this.#blockKey(sbn, packetId, catalogTrackName));
|
|
3030
3087
|
if (frozen !== void 0) return frozen;
|
|
3031
3088
|
return this.#peekClass(sbn, packetId, catalogTrackName);
|
|
@@ -3047,7 +3104,7 @@ var FECManager = class _FECManager {
|
|
|
3047
3104
|
* invariant (consecutive MPUs exactly one keyframe interval apart).
|
|
3048
3105
|
*/
|
|
3049
3106
|
noteReleasedRap(packetId, catalogTrackName, mpu, presentationTime, mediaTimescale) {
|
|
3050
|
-
if (!this.#trackConfigs.has(packetId)) return;
|
|
3107
|
+
if (!this.#trackConfigs.has(packetId) || !this.#hasCatalogTimingForPacket(packetId)) return;
|
|
3051
3108
|
this.#applyClassifierChanges(
|
|
3052
3109
|
packetId,
|
|
3053
3110
|
catalogTrackName,
|
|
@@ -3063,27 +3120,34 @@ var FECManager = class _FECManager {
|
|
|
3063
3120
|
// -----------------------------------------------------------------------
|
|
3064
3121
|
/** Configure FEC parameters. */
|
|
3065
3122
|
configure(config) {
|
|
3066
|
-
if (config.
|
|
3123
|
+
if (config.interleaveDepthMs != null && (!Number.isSafeInteger(config.interleaveDepthMs) || config.interleaveDepthMs < 0)) {
|
|
3124
|
+
throw new Error(
|
|
3125
|
+
`[FECManager] interleaveDepthMs=${config.interleaveDepthMs} must be a non-negative safe integer in milliseconds`
|
|
3126
|
+
);
|
|
3127
|
+
}
|
|
3128
|
+
if (config.timeoutMs != null && (!Number.isFinite(config.timeoutMs) || config.timeoutMs < 0)) {
|
|
3129
|
+
throw new Error(
|
|
3130
|
+
`[FECManager] timeoutMs=${config.timeoutMs} must be a finite non-negative cleanup budget`
|
|
3131
|
+
);
|
|
3132
|
+
}
|
|
3133
|
+
if (config.k != null && (!Number.isSafeInteger(config.k) || config.k <= 0)) {
|
|
3134
|
+
throw new Error(`[FECManager] k=${config.k} must be a positive integer`);
|
|
3135
|
+
}
|
|
3136
|
+
if (config.k != null) this.#streamK = config.k;
|
|
3067
3137
|
if (config.symbolSize != null && config.symbolSize > 0) this.#fecSymbolSize = config.symbolSize;
|
|
3068
3138
|
if (config.interleaveDepthMs != null) this.#fecInterleaveDepthMs = config.interleaveDepthMs;
|
|
3069
3139
|
if (config.fps != null && Number.isFinite(config.fps) && config.fps > 0) {
|
|
3070
3140
|
this.#fecFps = config.fps;
|
|
3071
3141
|
}
|
|
3072
|
-
if (config.interleaveDepthMs != null && config.interleaveDepthMs > 0 && config.interleaveDepthMs < MIN_INTERLEAVE_DEPTH_MS) {
|
|
3073
|
-
console.warn(`[FECManager] interleaveDepthMs=${config.interleaveDepthMs} looks like frame count, not milliseconds (\xA75.1 requires ms). Expected range: ${MIN_INTERLEAVE_DEPTH_MS}-10000ms.`);
|
|
3074
|
-
}
|
|
3075
3142
|
if (config.timeoutMs != null && config.timeoutMs > 0) {
|
|
3076
3143
|
this.#fecTimeoutMs = config.timeoutMs;
|
|
3077
|
-
} else if (config.interleaveDepthMs
|
|
3078
|
-
this.#fecTimeoutMs =
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
symbolSize: this.#fecSymbolSize,
|
|
3082
|
-
mediaUnitsPerSecond: config.fps
|
|
3083
|
-
});
|
|
3144
|
+
} else if (config.interleaveDepthMs === 0) {
|
|
3145
|
+
this.#fecTimeoutMs = LOCAL_FEC_TIMEOUT_MS;
|
|
3146
|
+
} else if (config.interleaveDepthMs != null && Number.isSafeInteger(config.interleaveDepthMs) && config.interleaveDepthMs >= MIN_INTERLEAVE_DEPTH_MS) {
|
|
3147
|
+
this.#fecTimeoutMs = fecSpanDeliveryWindowMs(config.interleaveDepthMs);
|
|
3084
3148
|
}
|
|
3085
3149
|
for (const [packetId, track] of this.#trackConfigs) {
|
|
3086
|
-
if (track.timeoutMs < this.#fecTimeoutMs) {
|
|
3150
|
+
if (_FECManager.#hasCatalogTiming(track) && track.timeoutMs < this.#fecTimeoutMs) {
|
|
3087
3151
|
this.#trackConfigs.set(packetId, { ...track, timeoutMs: this.#fecTimeoutMs });
|
|
3088
3152
|
}
|
|
3089
3153
|
}
|
|
@@ -3142,7 +3206,7 @@ var FECManager = class _FECManager {
|
|
|
3142
3206
|
);
|
|
3143
3207
|
}
|
|
3144
3208
|
if (config) this.#upsertTrackConfig(packetId, config, catalogTrackName);
|
|
3145
|
-
const workerK = this.#
|
|
3209
|
+
const workerK = this.#trackConfig(packetId).k;
|
|
3146
3210
|
this.#workerClients.set(streamKey, client);
|
|
3147
3211
|
this.#releasedWorkerClients.delete(client);
|
|
3148
3212
|
client.onFrame((data, meta) => {
|
|
@@ -3322,7 +3386,7 @@ var FECManager = class _FECManager {
|
|
|
3322
3386
|
return;
|
|
3323
3387
|
}
|
|
3324
3388
|
this.#settleOwedCleanup(key, "cleanup-ack-timeout");
|
|
3325
|
-
}, Math.ceil(this.#liveBlockLifetimeMs(this.#
|
|
3389
|
+
}, Math.ceil(this.#liveBlockLifetimeMs(this.#trackConfig(packetId))))
|
|
3326
3390
|
};
|
|
3327
3391
|
this.#pendingWorkerCleanupBounds.set(key, bound);
|
|
3328
3392
|
}
|
|
@@ -3363,16 +3427,11 @@ var FECManager = class _FECManager {
|
|
|
3363
3427
|
if (this.#fpsDetected || fps <= 0) return;
|
|
3364
3428
|
this.#fpsDetected = true;
|
|
3365
3429
|
this.#fecFps = fps;
|
|
3366
|
-
if (this.#fecInterleaveDepthMs >= MIN_INTERLEAVE_DEPTH_MS) {
|
|
3367
|
-
this.#fecTimeoutMs =
|
|
3368
|
-
interleaveDepthMs: this.#fecInterleaveDepthMs,
|
|
3369
|
-
sourceSymbols: this.#fecK,
|
|
3370
|
-
symbolSize: this.#fecSymbolSize,
|
|
3371
|
-
mediaUnitsPerSecond: fps
|
|
3372
|
-
});
|
|
3430
|
+
if (Number.isSafeInteger(this.#fecInterleaveDepthMs) && this.#fecInterleaveDepthMs >= MIN_INTERLEAVE_DEPTH_MS) {
|
|
3431
|
+
this.#fecTimeoutMs = fecSpanDeliveryWindowMs(this.#fecInterleaveDepthMs);
|
|
3373
3432
|
}
|
|
3374
3433
|
for (const [packetId, config] of this.#trackConfigs) {
|
|
3375
|
-
if (config.fps !== void 0 || config.interleaveDepthMs < MIN_INTERLEAVE_DEPTH_MS) continue;
|
|
3434
|
+
if (config.fps !== void 0 || !Number.isSafeInteger(config.interleaveDepthMs) || config.interleaveDepthMs < MIN_INTERLEAVE_DEPTH_MS) continue;
|
|
3376
3435
|
this.#trackConfigs.set(packetId, {
|
|
3377
3436
|
...config,
|
|
3378
3437
|
fps,
|
|
@@ -3401,51 +3460,33 @@ var FECManager = class _FECManager {
|
|
|
3401
3460
|
* Caller is responsible for routing recovered data and updating
|
|
3402
3461
|
* block completion state via `markBlockCompleted()`.
|
|
3403
3462
|
*/
|
|
3404
|
-
feedSourceSymbol(packetId, ssId, symbolData,
|
|
3463
|
+
feedSourceSymbol(packetId, ssId, symbolData, catalogTrackName) {
|
|
3405
3464
|
this.#fecStats.sourcePackets++;
|
|
3406
3465
|
this.#statsForPacket(packetId).sourcePackets++;
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
this.#isoSourceOversizeCount++;
|
|
3420
|
-
return null;
|
|
3421
|
-
}
|
|
3422
|
-
sbn = located.block.start;
|
|
3423
|
-
fecData = symbolData;
|
|
3424
|
-
} else {
|
|
3425
|
-
fecData = this.#normalizeSymbolData(packetId, symbolData);
|
|
3426
|
-
sbn = Math.floor(ssId / this.kForPacket(packetId));
|
|
3466
|
+
if (!this.#hasBlockProfile(packetId)) return null;
|
|
3467
|
+
const locator = this.#isoLocatorFor(packetId, catalogTrackName);
|
|
3468
|
+
const located = locator.locate(ssId);
|
|
3469
|
+
if (located === null) {
|
|
3470
|
+
throw new Error(
|
|
3471
|
+
`[FECManager] iso-ssbg1-v1 source SS_ID=${ssId} (packetId=${packetId}) has no stated block; hold it until a repair places it (placeIsoRepair)`
|
|
3472
|
+
);
|
|
3473
|
+
}
|
|
3474
|
+
locator.observe(ssId);
|
|
3475
|
+
if (!ssbg1FitsSymbol(symbolData.byteLength, this.#trackConfig(packetId).symbolSize)) {
|
|
3476
|
+
this.#isoSourceOversizeCount++;
|
|
3477
|
+
return null;
|
|
3427
3478
|
}
|
|
3479
|
+
const sbn = located.block.start;
|
|
3428
3480
|
const blockKey = this.#blockKey(sbn, packetId, catalogTrackName);
|
|
3429
3481
|
const syncBlockOwner = this.#syncDecoderBlockOwners.get(blockKey);
|
|
3430
3482
|
const workerClient = this.#routableWorkerForPacket(packetId, catalogTrackName);
|
|
3431
3483
|
if (workerClient && !syncBlockOwner) {
|
|
3432
3484
|
if (!this.#claimDecoderBlock(workerClient, sbn, catalogTrackName)) return null;
|
|
3433
|
-
const buf =
|
|
3434
|
-
|
|
3435
|
-
|
|
3485
|
+
const buf = symbolData.buffer.slice(
|
|
3486
|
+
symbolData.byteOffset,
|
|
3487
|
+
symbolData.byteOffset + symbolData.byteLength
|
|
3436
3488
|
);
|
|
3437
|
-
|
|
3438
|
-
const authBuf = alta.auth.buffer.slice(
|
|
3439
|
-
alta.auth.byteOffset,
|
|
3440
|
-
alta.auth.byteOffset + alta.auth.byteLength
|
|
3441
|
-
);
|
|
3442
|
-
workerClient.feedSource(ssId, buf, performance.now(), {
|
|
3443
|
-
auth: authBuf,
|
|
3444
|
-
payloadEnd: alta.payloadEnd
|
|
3445
|
-
});
|
|
3446
|
-
} else {
|
|
3447
|
-
workerClient.feedSource(ssId, buf, performance.now());
|
|
3448
|
-
}
|
|
3489
|
+
workerClient.feedSource(ssId, buf, performance.now());
|
|
3449
3490
|
return null;
|
|
3450
3491
|
}
|
|
3451
3492
|
const entry = this.#decoderForPacket(packetId, catalogTrackName);
|
|
@@ -3455,7 +3496,7 @@ var FECManager = class _FECManager {
|
|
|
3455
3496
|
this.#syncDecoderBlockOwners.set(blockKey, client);
|
|
3456
3497
|
let recovered = null;
|
|
3457
3498
|
try {
|
|
3458
|
-
recovered = client.add_source(ssId,
|
|
3499
|
+
recovered = client.add_source(ssId, symbolData, performance.now());
|
|
3459
3500
|
} catch {
|
|
3460
3501
|
}
|
|
3461
3502
|
this.#retireIsoUnplaced(client, packetId, catalogTrackName);
|
|
@@ -3474,7 +3515,8 @@ var FECManager = class _FECManager {
|
|
|
3474
3515
|
feedRepairSymbol(packetId, ssStart, ssbLength, rsId, repairData, catalogTrackName) {
|
|
3475
3516
|
this.#fecStats.repairPackets++;
|
|
3476
3517
|
this.#statsForPacket(packetId).repairPackets++;
|
|
3477
|
-
|
|
3518
|
+
if (!this.#hasBlockProfile(packetId)) return null;
|
|
3519
|
+
const symbolSize = this.#trackConfig(packetId).symbolSize;
|
|
3478
3520
|
if (symbolSize > 0 && repairData.byteLength !== symbolSize) {
|
|
3479
3521
|
this.#repairSymbolSizeMismatchCount++;
|
|
3480
3522
|
if (this.#repairSymbolSizeMismatchCount <= 5 || this.#repairSymbolSizeMismatchCount % 100 === 0) {
|
|
@@ -3485,18 +3527,12 @@ var FECManager = class _FECManager {
|
|
|
3485
3527
|
return null;
|
|
3486
3528
|
}
|
|
3487
3529
|
const fecData = repairData;
|
|
3488
|
-
const k = this
|
|
3489
|
-
|
|
3490
|
-
if (
|
|
3491
|
-
|
|
3492
|
-
if (ssbLength <= 0 || ssbLength > k || block === void 0 || block.span || block.length !== ssbLength) {
|
|
3493
|
-
return null;
|
|
3494
|
-
}
|
|
3495
|
-
sbn = ssStart;
|
|
3496
|
-
} else {
|
|
3497
|
-
if (ssbLength <= 0 || ssbLength > k || ssStart % k !== 0) return null;
|
|
3498
|
-
sbn = Math.floor(ssStart / k);
|
|
3530
|
+
const k = this.#trackConfig(packetId).k;
|
|
3531
|
+
const block = this.#isoLocatorFor(packetId, catalogTrackName).blockAt(ssStart);
|
|
3532
|
+
if (ssbLength <= 0 || ssbLength > k || block === void 0 || block.span || block.length !== ssbLength) {
|
|
3533
|
+
return null;
|
|
3499
3534
|
}
|
|
3535
|
+
const sbn = ssStart;
|
|
3500
3536
|
this.#noteSbnSeen(sbn, packetId, catalogTrackName, "repair");
|
|
3501
3537
|
this.noteBlockActivity(sbn, packetId, catalogTrackName);
|
|
3502
3538
|
const blockKey = this.#blockKey(sbn, packetId, catalogTrackName);
|
|
@@ -3534,8 +3570,9 @@ var FECManager = class _FECManager {
|
|
|
3534
3570
|
* Record a block's authored SSB_length from a repair symbol. Returns false,
|
|
3535
3571
|
* leaving the block unchanged, when the symbol contradicts the block: a
|
|
3536
3572
|
* different SSB_length than an earlier repair symbol declared is dropped,
|
|
3537
|
-
* and an SSB_length that places an already-received source ESI
|
|
3538
|
-
*
|
|
3573
|
+
* and an SSB_length that places an already-received source ESI at or past
|
|
3574
|
+
* the block's end fails the block, since its geometry can no longer be
|
|
3575
|
+
* trusted.
|
|
3539
3576
|
*/
|
|
3540
3577
|
#noteAuthoredLength(blockKey, sbn, packetId, ssbLength, catalogTrackName) {
|
|
3541
3578
|
const known = this.#blockAuthoredLengths.get(blockKey);
|
|
@@ -3602,7 +3639,7 @@ var FECManager = class _FECManager {
|
|
|
3602
3639
|
* a sweep tied to expiry alone would never run there.
|
|
3603
3640
|
*/
|
|
3604
3641
|
#retireIsoUnplaced(decoder, packetId, catalogTrackName) {
|
|
3605
|
-
if (!this.#
|
|
3642
|
+
if (!this.#hasBlockProfile(packetId)) return;
|
|
3606
3643
|
const newest = this.#isoLocators.get(this.#streamKey(packetId, catalogTrackName))?.newest;
|
|
3607
3644
|
if (newest === void 0) return;
|
|
3608
3645
|
try {
|
|
@@ -3647,11 +3684,13 @@ var FECManager = class _FECManager {
|
|
|
3647
3684
|
this.#failBlock(sbn, packetId, catalogTrackName);
|
|
3648
3685
|
return;
|
|
3649
3686
|
}
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3687
|
+
if (_FECManager.#hasCatalogTiming(trackConfig)) {
|
|
3688
|
+
this.#applyClassifierChanges(
|
|
3689
|
+
packetId,
|
|
3690
|
+
catalogTrackName,
|
|
3691
|
+
this.#classifierFor(packetId, catalogTrackName).observe(sbn, evidence)
|
|
3692
|
+
);
|
|
3693
|
+
}
|
|
3655
3694
|
const count = (this.#blockSourceCounts.get(key) ?? 0) + 1;
|
|
3656
3695
|
this.#blockSourceCounts.set(key, count);
|
|
3657
3696
|
if (count === 1) this.#indexBlockKey(key, sbn, packetId);
|
|
@@ -3684,6 +3723,7 @@ var FECManager = class _FECManager {
|
|
|
3684
3723
|
this.#blockSourceEsis.delete(key);
|
|
3685
3724
|
this.#blockAuthoredLengths.delete(key);
|
|
3686
3725
|
this.#blockRepairRsIds.delete(key);
|
|
3726
|
+
this.#blockRsbLengths.delete(key);
|
|
3687
3727
|
this.#markTerminal(key, sbn, packetId, true);
|
|
3688
3728
|
this.#markPathBlockComplete(sbn, packetId, catalogTrackName);
|
|
3689
3729
|
if (catalogTrackName === void 0) {
|
|
@@ -3695,6 +3735,7 @@ var FECManager = class _FECManager {
|
|
|
3695
3735
|
}
|
|
3696
3736
|
/** Refresh deadlines after accepted block activity. */
|
|
3697
3737
|
noteBlockActivity(sbn, packetId, catalogTrackName, sourceProgress = false) {
|
|
3738
|
+
if (!this.#trackConfigs.has(packetId)) return;
|
|
3698
3739
|
const key = this.#blockKey(sbn, packetId, catalogTrackName);
|
|
3699
3740
|
if (this.#completedBlocks.has(key)) return;
|
|
3700
3741
|
if (this.#pendingWorkerCleanups.has(key)) return;
|
|
@@ -3704,13 +3745,13 @@ var FECManager = class _FECManager {
|
|
|
3704
3745
|
this.#holdForOrderedSettlement(key, sbn, packetId, catalogTrackName);
|
|
3705
3746
|
return;
|
|
3706
3747
|
}
|
|
3707
|
-
const trackConfig = this.#
|
|
3748
|
+
const trackConfig = this.#trackConfig(packetId);
|
|
3708
3749
|
const timeoutMs = this.#multicastWaitMs(trackConfig);
|
|
3709
3750
|
if (!(timeoutMs > 0)) {
|
|
3710
3751
|
throw new Error(`[FECManager] packetId=${packetId} has no positive fail bound (timeoutMs=${timeoutMs})`);
|
|
3711
3752
|
}
|
|
3712
3753
|
const repairDeadline = this.#repairDeadlines.get(key);
|
|
3713
|
-
if (this.onRepairNeeded && !repairRequested && (repairDeadline === void 0 || sourceProgress)) {
|
|
3754
|
+
if (this.#hasCatalogTimingForPacket(packetId) && this.onRepairNeeded && !repairRequested && (repairDeadline === void 0 || sourceProgress)) {
|
|
3714
3755
|
this.#armRepairDeadline(
|
|
3715
3756
|
key,
|
|
3716
3757
|
sbn,
|
|
@@ -3734,6 +3775,7 @@ var FECManager = class _FECManager {
|
|
|
3734
3775
|
this.#blockSourceEsis.delete(key);
|
|
3735
3776
|
this.#blockAuthoredLengths.delete(key);
|
|
3736
3777
|
this.#blockRepairRsIds.delete(key);
|
|
3778
|
+
this.#blockRsbLengths.delete(key);
|
|
3737
3779
|
this.#syncDecoderBlockOwners.delete(key);
|
|
3738
3780
|
this.#markTerminal(key, sbn, packetId, false);
|
|
3739
3781
|
this.#failedBlocks.add(key);
|
|
@@ -3771,6 +3813,7 @@ var FECManager = class _FECManager {
|
|
|
3771
3813
|
this.#blockSourceEsis.delete(key);
|
|
3772
3814
|
this.#blockAuthoredLengths.delete(key);
|
|
3773
3815
|
this.#blockRepairRsIds.delete(key);
|
|
3816
|
+
this.#blockRsbLengths.delete(key);
|
|
3774
3817
|
this.#clearBlockTimer(key);
|
|
3775
3818
|
this.onBlockResolved?.(block.sbn, block.packetId, block.catalogTrackName);
|
|
3776
3819
|
}
|
|
@@ -3780,6 +3823,7 @@ var FECManager = class _FECManager {
|
|
|
3780
3823
|
}
|
|
3781
3824
|
/** Mark a block as completed externally (e.g., after routing recovered data). */
|
|
3782
3825
|
markBlockCompleted(sbn, packetId, catalogTrackName) {
|
|
3826
|
+
if (packetId != null && !this.#trackConfigs.has(packetId)) return;
|
|
3783
3827
|
for (const key of this.#blockKeysFor(sbn, packetId, catalogTrackName)) {
|
|
3784
3828
|
this.#resolveCompleted(key);
|
|
3785
3829
|
}
|
|
@@ -3860,6 +3904,7 @@ var FECManager = class _FECManager {
|
|
|
3860
3904
|
this.#blockSourceEsis.clear();
|
|
3861
3905
|
this.#blockAuthoredLengths.clear();
|
|
3862
3906
|
this.#blockRepairRsIds.clear();
|
|
3907
|
+
this.#blockRsbLengths.clear();
|
|
3863
3908
|
this.#completedBlocks.clear();
|
|
3864
3909
|
this.#cleanlyCompletedBlocks.clear();
|
|
3865
3910
|
this.#repairRequestedBlocks.clear();
|