@blockcast/mmt-container 0.1.0 → 0.3.0-main.ef68de90edb3
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 +524 -0
- package/dist/.build-stamp +0 -0
- package/dist/__tests__/test-utils.d.ts +71 -0
- package/dist/__tests__/test-utils.d.ts.map +1 -0
- package/dist/align.d.ts +152 -0
- package/dist/align.d.ts.map +1 -0
- package/dist/align.js +88 -0
- package/dist/align.js.map +7 -0
- package/dist/audio-init-parser.d.ts +66 -0
- package/dist/audio-init-parser.d.ts.map +1 -0
- package/dist/audio-init-parser.js +118 -0
- package/dist/audio-init-parser.js.map +7 -0
- package/dist/audio-ring-buffer.d.ts +50 -0
- package/dist/audio-ring-buffer.d.ts.map +1 -0
- package/dist/audio-ring-buffer.js +80 -0
- package/dist/audio-ring-buffer.js.map +7 -0
- package/dist/authored-timing.d.ts +32 -0
- package/dist/authored-timing.d.ts.map +1 -0
- package/dist/authored-timing.js +32 -0
- package/dist/authored-timing.js.map +7 -0
- package/dist/block-policy.d.ts +314 -0
- package/dist/block-policy.d.ts.map +1 -0
- package/dist/block-policy.js +466 -0
- package/dist/block-policy.js.map +7 -0
- package/dist/browser-runtime.js +26549 -0
- package/dist/browser-runtime.js.map +7 -0
- package/dist/carp-catalog.d.ts +429 -0
- package/dist/carp-catalog.d.ts.map +1 -0
- package/dist/carp-catalog.js +985 -0
- package/dist/carp-catalog.js.map +7 -0
- package/dist/catalog-fec-params.d.ts +275 -0
- package/dist/catalog-fec-params.d.ts.map +1 -0
- package/dist/catalog-fec-params.js +702 -0
- package/dist/catalog-fec-params.js.map +7 -0
- package/dist/catalog-network-source.d.ts +42 -0
- package/dist/catalog-network-source.d.ts.map +1 -0
- package/dist/catalog-network-source.js +47 -0
- package/dist/catalog-network-source.js.map +7 -0
- package/dist/catalog-validator.d.ts +18 -0
- package/dist/catalog-validator.d.ts.map +1 -0
- package/dist/catalog-validator.js +7747 -0
- package/dist/catalog-validator.js.map +7 -0
- package/dist/cmaf-block-assembler.d.ts +285 -0
- package/dist/cmaf-block-assembler.d.ts.map +1 -0
- package/dist/cmaf-block-assembler.js +1966 -0
- package/dist/cmaf-block-assembler.js.map +7 -0
- package/dist/cmaf-group-batcher.d.ts +38 -0
- package/dist/cmaf-group-batcher.d.ts.map +1 -0
- package/dist/cmaf-group-batcher.js +176 -0
- package/dist/cmaf-group-batcher.js.map +7 -0
- package/dist/cmcd-producer.d.ts +104 -0
- package/dist/cmcd-producer.d.ts.map +1 -0
- package/dist/cmcd-producer.js +183 -0
- package/dist/cmcd-producer.js.map +7 -0
- package/dist/codec-utils.d.ts +384 -0
- package/dist/codec-utils.d.ts.map +1 -0
- package/dist/codec-utils.js +1546 -0
- package/dist/codec-utils.js.map +7 -0
- package/dist/conceal-timeline.d.ts +146 -0
- package/dist/conceal-timeline.d.ts.map +1 -0
- package/dist/conceal-timeline.js +137 -0
- package/dist/conceal-timeline.js.map +7 -0
- package/dist/delivery-gap.d.ts +75 -0
- package/dist/delivery-gap.d.ts.map +1 -0
- package/dist/delivery-gap.js +88 -0
- package/dist/delivery-gap.js.map +7 -0
- package/dist/duplicate-ledger.d.ts +197 -0
- package/dist/duplicate-ledger.d.ts.map +1 -0
- package/dist/duplicate-ledger.js +226 -0
- package/dist/duplicate-ledger.js.map +7 -0
- package/dist/fec-codec.d.ts +32 -0
- package/dist/fec-codec.d.ts.map +1 -0
- package/dist/fec-codec.js +47 -0
- package/dist/fec-codec.js.map +7 -0
- package/dist/fec-manager.d.ts +583 -0
- package/dist/fec-manager.d.ts.map +1 -0
- package/dist/fec-manager.js +3899 -0
- package/dist/fec-manager.js.map +7 -0
- package/dist/fec-starvation-detector.d.ts +59 -0
- package/dist/fec-starvation-detector.d.ts.map +1 -0
- package/dist/fec-starvation-detector.js +60 -0
- package/dist/fec-starvation-detector.js.map +7 -0
- package/dist/fec-state.d.ts +131 -0
- package/dist/fec-state.d.ts.map +1 -0
- package/dist/fec-state.js +87 -0
- package/dist/fec-state.js.map +7 -0
- package/dist/fec-worker-setup.d.ts +94 -0
- package/dist/fec-worker-setup.d.ts.map +1 -0
- package/dist/fec-worker-setup.js +673 -0
- package/dist/fec-worker-setup.js.map +7 -0
- package/dist/fmp4-completion.d.ts +30 -0
- package/dist/fmp4-completion.d.ts.map +1 -0
- package/dist/fmp4-completion.js +21 -0
- package/dist/fmp4-completion.js.map +7 -0
- package/dist/fmp4-reader.d.ts +37 -0
- package/dist/fmp4-reader.d.ts.map +1 -0
- package/dist/fmp4-reader.js +100 -0
- package/dist/fmp4-reader.js.map +7 -0
- package/dist/index.d.ts +44 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +460 -14
- package/dist/index.js.map +7 -1
- package/dist/iso-block-locator.d.ts +118 -0
- package/dist/iso-block-locator.d.ts.map +1 -0
- package/dist/iso-block-locator.js +289 -0
- package/dist/iso-block-locator.js.map +7 -0
- package/dist/iso-bmff-timing.d.ts +78 -0
- package/dist/iso-bmff-timing.d.ts.map +1 -0
- package/dist/iso-bmff-timing.js +593 -0
- package/dist/iso-bmff-timing.js.map +7 -0
- package/dist/loc.d.ts +70 -75
- package/dist/loc.d.ts.map +1 -1
- package/dist/loc.js +106 -192
- package/dist/loc.js.map +7 -1
- package/dist/manifest-auth-plan.d.ts +30 -0
- package/dist/manifest-auth-plan.d.ts.map +1 -0
- package/dist/manifest-auth-plan.js +1266 -0
- package/dist/manifest-auth-plan.js.map +7 -0
- package/dist/media-router.d.ts +262 -0
- package/dist/media-router.d.ts.map +1 -0
- package/dist/media-router.js +584 -0
- package/dist/media-router.js.map +7 -0
- package/dist/mfu-reassembler.d.ts +313 -9
- package/dist/mfu-reassembler.d.ts.map +1 -1
- package/dist/mfu-reassembler.js +3051 -285
- package/dist/mfu-reassembler.js.map +7 -1
- package/dist/mfu-reassembly-policy.d.ts +24 -0
- package/dist/mfu-reassembly-policy.d.ts.map +1 -0
- package/dist/mfu-reassembly-policy.js +99 -0
- package/dist/mfu-reassembly-policy.js.map +7 -0
- package/dist/mmtp-container-parser.d.ts +568 -0
- package/dist/mmtp-container-parser.d.ts.map +1 -0
- package/dist/mmtp-container-parser.js +6580 -0
- package/dist/mmtp-container-parser.js.map +7 -0
- package/dist/mmtp-container-parser.no-modules.js +9616 -0
- package/dist/mmtp-container-parser.no-modules.js.map +7 -0
- package/dist/mmtp-decode-pipeline.d.ts +138 -0
- package/dist/mmtp-decode-pipeline.d.ts.map +1 -0
- package/dist/mmtp-decode-pipeline.js +6814 -0
- package/dist/mmtp-decode-pipeline.js.map +7 -0
- package/dist/mmtp-router.d.ts +679 -0
- package/dist/mmtp-router.d.ts.map +1 -0
- package/dist/mmtp-router.js +11278 -0
- package/dist/mmtp-router.js.map +7 -0
- package/dist/mmtp-to-cmaf.d.ts +187 -0
- package/dist/mmtp-to-cmaf.d.ts.map +1 -0
- package/dist/mmtp-to-cmaf.js +716 -0
- package/dist/mmtp-to-cmaf.js.map +7 -0
- package/dist/multicast-auth-catalog.d.ts +115 -0
- package/dist/multicast-auth-catalog.d.ts.map +1 -0
- package/dist/multicast-auth-catalog.js +202 -0
- package/dist/multicast-auth-catalog.js.map +7 -0
- package/dist/multicast-input.d.ts +141 -0
- package/dist/multicast-input.d.ts.map +1 -0
- package/dist/multicast-input.js +390 -0
- package/dist/multicast-input.js.map +7 -0
- package/dist/multicast-manager.d.ts +669 -0
- package/dist/multicast-manager.d.ts.map +1 -0
- package/dist/multicast-manager.js +19101 -0
- package/dist/multicast-manager.js.map +7 -0
- package/dist/multicast-transport.d.ts +271 -0
- package/dist/multicast-transport.d.ts.map +1 -0
- package/dist/multicast-transport.js +2264 -0
- package/dist/multicast-transport.js.map +7 -0
- package/dist/multicast-unwrap.d.ts +57 -0
- package/dist/multicast-unwrap.d.ts.map +1 -0
- package/dist/multicast-unwrap.js +418 -0
- package/dist/multicast-unwrap.js.map +7 -0
- package/dist/no-modules.d.ts +10 -0
- package/dist/no-modules.d.ts.map +1 -0
- package/dist/no-modules.js +9491 -0
- package/dist/no-modules.js.map +7 -0
- package/dist/phase14-catalog-override.d.ts +126 -0
- package/dist/phase14-catalog-override.d.ts.map +1 -0
- package/dist/phase14-catalog-override.js +155 -0
- package/dist/phase14-catalog-override.js.map +7 -0
- package/dist/repair-fetch.d.ts +270 -0
- package/dist/repair-fetch.d.ts.map +1 -0
- package/dist/repair-fetch.js +381 -0
- package/dist/repair-fetch.js.map +7 -0
- package/dist/repair-layers.d.ts +158 -0
- package/dist/repair-layers.d.ts.map +1 -0
- package/dist/repair-layers.js +344 -0
- package/dist/repair-layers.js.map +7 -0
- package/dist/sample-combiner.d.ts +212 -0
- package/dist/sample-combiner.d.ts.map +1 -0
- package/dist/sample-combiner.js +595 -0
- package/dist/sample-combiner.js.map +7 -0
- package/dist/signaling.d.ts +29 -0
- package/dist/signaling.d.ts.map +1 -0
- package/dist/signaling.js +572 -0
- package/dist/signaling.js.map +7 -0
- package/dist/source-auth.d.ts +2 -0
- package/dist/source-auth.d.ts.map +1 -0
- package/dist/source-auth.js +1209 -0
- package/dist/source-auth.js.map +7 -0
- package/dist/switching-set-alignment.d.ts +61 -0
- package/dist/switching-set-alignment.d.ts.map +1 -0
- package/dist/switching-set-alignment.js +70 -0
- package/dist/switching-set-alignment.js.map +7 -0
- package/dist/timestamp-codec.d.ts +34 -0
- package/dist/timestamp-codec.d.ts.map +1 -0
- package/dist/timestamp-codec.js +473 -0
- package/dist/timestamp-codec.js.map +7 -0
- package/dist/track-pipeline-setup.d.ts +83 -0
- package/dist/track-pipeline-setup.d.ts.map +1 -0
- package/dist/track-pipeline-setup.js +291 -0
- package/dist/track-pipeline-setup.js.map +7 -0
- package/dist/track-pipeline.d.ts +121 -0
- package/dist/track-pipeline.d.ts.map +1 -0
- package/dist/track-pipeline.js +209 -0
- package/dist/track-pipeline.js.map +7 -0
- package/dist/track-session.d.ts +414 -0
- package/dist/track-session.d.ts.map +1 -0
- package/dist/track-session.js +754 -0
- package/dist/track-session.js.map +7 -0
- package/dist/transport-pool.d.ts +69 -0
- package/dist/transport-pool.d.ts.map +1 -0
- package/dist/transport-pool.js +74 -0
- package/dist/transport-pool.js.map +7 -0
- package/dist/wasm-mfu-reassembler.d.ts +97 -0
- package/dist/wasm-mfu-reassembler.d.ts.map +1 -0
- package/dist/wasm-mfu-reassembler.js +2133 -0
- package/dist/wasm-mfu-reassembler.js.map +7 -0
- package/dist/wasm-mmtp-container-parser.d.ts +10 -0
- package/dist/wasm-mmtp-container-parser.d.ts.map +1 -0
- package/dist/wasm-mmtp-container-parser.js +6834 -0
- package/dist/wasm-mmtp-container-parser.js.map +7 -0
- package/node_modules/@blockcast/fec-worker/README.md +223 -0
- package/node_modules/@blockcast/fec-worker/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/fec-worker/dist/block-order.d.ts +38 -0
- package/node_modules/@blockcast/fec-worker/dist/block-order.d.ts.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/block-order.js +78 -0
- package/node_modules/@blockcast/fec-worker/dist/block-order.js.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts +93 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js +346 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts +380 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js +11 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts +14 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker.js +859 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker.js.map +7 -0
- package/node_modules/@blockcast/fec-worker/dist/index.d.ts +10 -0
- package/node_modules/@blockcast/fec-worker/dist/index.d.ts.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/index.js +8 -0
- package/node_modules/@blockcast/fec-worker/dist/index.js.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts +20 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js +370 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js.map +7 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts +104 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js +181 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts +194 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js +62 -0
- package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts +9 -0
- package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts.map +1 -0
- package/node_modules/@blockcast/fec-worker/dist/transfer.js +13 -0
- package/node_modules/@blockcast/fec-worker/dist/transfer.js.map +1 -0
- package/node_modules/@blockcast/fec-worker/package.json +59 -0
- package/node_modules/@blockcast/fec-worker/src/block-order.ts +93 -0
- package/node_modules/@blockcast/fec-worker/src/fec-worker-client.ts +392 -0
- package/node_modules/@blockcast/fec-worker/src/fec-worker-types.ts +399 -0
- package/node_modules/@blockcast/fec-worker/src/fec-worker.ts +1502 -0
- package/node_modules/@blockcast/fec-worker/src/index.ts +35 -0
- package/node_modules/@blockcast/fec-worker/src/shred-fec-worker.ts +589 -0
- package/node_modules/@blockcast/fec-worker/src/shred-worker-client.ts +222 -0
- package/node_modules/@blockcast/fec-worker/src/shred-worker-types.ts +209 -0
- package/node_modules/@blockcast/fec-worker/src/transfer.ts +12 -0
- package/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
- package/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
- package/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
- package/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
- package/node_modules/@blockcast/mmt-base/README.md +134 -0
- package/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts +55 -0
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +128 -0
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/index.d.ts +7 -0
- package/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/index.js +7 -0
- package/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +292 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.js +612 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +18 -0
- package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/net-constants.js +18 -0
- package/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +47 -0
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.js +54 -0
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +57 -0
- package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/serial-number.js +98 -0
- package/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +312 -0
- package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/signalling.js +637 -0
- package/node_modules/@blockcast/mmt-base/dist/signalling.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/package.json +49 -0
- package/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +145 -0
- package/node_modules/@blockcast/mmt-base/src/index.ts +6 -0
- package/node_modules/@blockcast/mmt-base/src/mmtp.ts +892 -0
- package/node_modules/@blockcast/mmt-base/src/net-constants.ts +17 -0
- package/node_modules/@blockcast/mmt-base/src/ntp-short.ts +67 -0
- package/node_modules/@blockcast/mmt-base/src/serial-number.ts +107 -0
- package/node_modules/@blockcast/mmt-base/src/signalling.ts +862 -0
- package/node_modules/@blockcast/mmt-fec/README.md +271 -0
- package/node_modules/@blockcast/mmt-fec/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts +82 -0
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.js +296 -0
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts +106 -0
- package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/block-processor.js +288 -0
- package/node_modules/@blockcast/mmt-fec/dist/block-processor.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts +46 -0
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js +96 -0
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts +33 -0
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js +57 -0
- package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts +205 -0
- package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js +240 -0
- package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/index.d.ts +28 -0
- package/node_modules/@blockcast/mmt-fec/dist/index.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/index.js +28 -0
- package/node_modules/@blockcast/mmt-fec/dist/index.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts +20 -0
- package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js +28 -0
- package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts +258 -0
- package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/oti.js +382 -0
- package/node_modules/@blockcast/mmt-fec/dist/oti.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts +41 -0
- package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js +81 -0
- package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/repair-group.d.ts +82 -0
- package/node_modules/@blockcast/mmt-fec/dist/repair-group.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/repair-group.js +170 -0
- package/node_modules/@blockcast/mmt-fec/dist/repair-group.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
- 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 +57 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/README.md +134 -0
- 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 +55 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +128 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts +7 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js +7 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +292 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js +612 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +18 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.js +18 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +47 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.js +54 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +57 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.js +98 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +312 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.js +637 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.js.map +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/package.json +49 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +145 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/index.ts +6 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/mmtp.ts +892 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/net-constants.ts +17 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/ntp-short.ts +67 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/serial-number.ts +107 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/signalling.ts +862 -0
- package/node_modules/@blockcast/mmt-fec/package.json +79 -0
- package/node_modules/@blockcast/mmt-fec/src/block-manager.ts +371 -0
- package/node_modules/@blockcast/mmt-fec/src/block-processor.ts +439 -0
- package/node_modules/@blockcast/mmt-fec/src/cmaf-recovery.ts +127 -0
- package/node_modules/@blockcast/mmt-fec/src/cmaf-symbols.ts +68 -0
- package/node_modules/@blockcast/mmt-fec/src/fec-block-mapper.ts +310 -0
- package/node_modules/@blockcast/mmt-fec/src/index.ts +94 -0
- package/node_modules/@blockcast/mmt-fec/src/loc-symbols.ts +34 -0
- package/node_modules/@blockcast/mmt-fec/src/oti.ts +463 -0
- package/node_modules/@blockcast/mmt-fec/src/reorder-buffer.ts +101 -0
- package/node_modules/@blockcast/mmt-fec/src/repair-group.ts +195 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts +28 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js +128 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js.map +1 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts +4 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js +4 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js.map +1 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts +37 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js +179 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js.map +1 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts +99 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js +492 -0
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js.map +1 -0
- package/node_modules/@blockcast/mmt-manifest-verify/package.json +45 -0
- package/node_modules/@blockcast/mmt-manifest-verify/src/admission.ts +171 -0
- package/node_modules/@blockcast/mmt-manifest-verify/src/index.ts +3 -0
- package/node_modules/@blockcast/mmt-manifest-verify/src/source-auth.ts +230 -0
- package/node_modules/@blockcast/mmt-manifest-verify/src/verifier.ts +669 -0
- package/node_modules/@noble/hashes/LICENSE +21 -0
- package/node_modules/@noble/hashes/README.md +521 -0
- package/node_modules/@noble/hashes/_assert.d.ts +17 -0
- package/node_modules/@noble/hashes/_assert.d.ts.map +1 -0
- package/node_modules/@noble/hashes/_assert.js +18 -0
- package/node_modules/@noble/hashes/_assert.js.map +1 -0
- package/node_modules/@noble/hashes/_blake.d.ts +14 -0
- package/node_modules/@noble/hashes/_blake.d.ts.map +1 -0
- package/node_modules/@noble/hashes/_blake.js +50 -0
- package/node_modules/@noble/hashes/_blake.js.map +1 -0
- package/node_modules/@noble/hashes/_md.d.ts +51 -0
- package/node_modules/@noble/hashes/_md.d.ts.map +1 -0
- package/node_modules/@noble/hashes/_md.js +162 -0
- package/node_modules/@noble/hashes/_md.js.map +1 -0
- package/node_modules/@noble/hashes/_u64.d.ts +55 -0
- package/node_modules/@noble/hashes/_u64.d.ts.map +1 -0
- package/node_modules/@noble/hashes/_u64.js +90 -0
- package/node_modules/@noble/hashes/_u64.js.map +1 -0
- package/node_modules/@noble/hashes/argon2.d.ts +32 -0
- package/node_modules/@noble/hashes/argon2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/argon2.js +401 -0
- package/node_modules/@noble/hashes/argon2.js.map +1 -0
- package/node_modules/@noble/hashes/blake1.d.ts +106 -0
- package/node_modules/@noble/hashes/blake1.d.ts.map +1 -0
- package/node_modules/@noble/hashes/blake1.js +459 -0
- package/node_modules/@noble/hashes/blake1.js.map +1 -0
- package/node_modules/@noble/hashes/blake2.d.ts +116 -0
- package/node_modules/@noble/hashes/blake2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/blake2.js +420 -0
- package/node_modules/@noble/hashes/blake2.js.map +1 -0
- package/node_modules/@noble/hashes/blake2b.d.ts +11 -0
- package/node_modules/@noble/hashes/blake2b.d.ts.map +1 -0
- package/node_modules/@noble/hashes/blake2b.js +14 -0
- package/node_modules/@noble/hashes/blake2b.js.map +1 -0
- package/node_modules/@noble/hashes/blake2s.d.ts +20 -0
- package/node_modules/@noble/hashes/blake2s.d.ts.map +1 -0
- package/node_modules/@noble/hashes/blake2s.js +24 -0
- package/node_modules/@noble/hashes/blake2s.js.map +1 -0
- package/node_modules/@noble/hashes/blake3.d.ts +54 -0
- package/node_modules/@noble/hashes/blake3.d.ts.map +1 -0
- package/node_modules/@noble/hashes/blake3.js +255 -0
- package/node_modules/@noble/hashes/blake3.js.map +1 -0
- package/node_modules/@noble/hashes/crypto.d.ts +2 -0
- package/node_modules/@noble/hashes/crypto.d.ts.map +1 -0
- package/node_modules/@noble/hashes/crypto.js +5 -0
- package/node_modules/@noble/hashes/crypto.js.map +1 -0
- package/node_modules/@noble/hashes/cryptoNode.d.ts +2 -0
- package/node_modules/@noble/hashes/cryptoNode.d.ts.map +1 -0
- package/node_modules/@noble/hashes/cryptoNode.js +18 -0
- package/node_modules/@noble/hashes/cryptoNode.js.map +1 -0
- package/node_modules/@noble/hashes/eskdf.d.ts +47 -0
- package/node_modules/@noble/hashes/eskdf.d.ts.map +1 -0
- package/node_modules/@noble/hashes/eskdf.js +166 -0
- package/node_modules/@noble/hashes/eskdf.js.map +1 -0
- package/node_modules/@noble/hashes/esm/_assert.d.ts +17 -0
- package/node_modules/@noble/hashes/esm/_assert.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/_assert.js +15 -0
- package/node_modules/@noble/hashes/esm/_assert.js.map +1 -0
- package/node_modules/@noble/hashes/esm/_blake.d.ts +14 -0
- package/node_modules/@noble/hashes/esm/_blake.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/_blake.js +45 -0
- package/node_modules/@noble/hashes/esm/_blake.js.map +1 -0
- package/node_modules/@noble/hashes/esm/_md.d.ts +51 -0
- package/node_modules/@noble/hashes/esm/_md.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/_md.js +155 -0
- package/node_modules/@noble/hashes/esm/_md.js.map +1 -0
- package/node_modules/@noble/hashes/esm/_u64.d.ts +55 -0
- package/node_modules/@noble/hashes/esm/_u64.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/_u64.js +67 -0
- package/node_modules/@noble/hashes/esm/_u64.js.map +1 -0
- package/node_modules/@noble/hashes/esm/argon2.d.ts +32 -0
- package/node_modules/@noble/hashes/esm/argon2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/argon2.js +392 -0
- package/node_modules/@noble/hashes/esm/argon2.js.map +1 -0
- package/node_modules/@noble/hashes/esm/blake1.d.ts +106 -0
- package/node_modules/@noble/hashes/esm/blake1.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/blake1.js +452 -0
- package/node_modules/@noble/hashes/esm/blake1.js.map +1 -0
- package/node_modules/@noble/hashes/esm/blake2.d.ts +116 -0
- package/node_modules/@noble/hashes/esm/blake2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/blake2.js +413 -0
- package/node_modules/@noble/hashes/esm/blake2.js.map +1 -0
- package/node_modules/@noble/hashes/esm/blake2b.d.ts +11 -0
- package/node_modules/@noble/hashes/esm/blake2b.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/blake2b.js +11 -0
- package/node_modules/@noble/hashes/esm/blake2b.js.map +1 -0
- package/node_modules/@noble/hashes/esm/blake2s.d.ts +20 -0
- package/node_modules/@noble/hashes/esm/blake2s.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/blake2s.js +21 -0
- package/node_modules/@noble/hashes/esm/blake2s.js.map +1 -0
- package/node_modules/@noble/hashes/esm/blake3.d.ts +54 -0
- package/node_modules/@noble/hashes/esm/blake3.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/blake3.js +251 -0
- package/node_modules/@noble/hashes/esm/blake3.js.map +1 -0
- package/node_modules/@noble/hashes/esm/crypto.d.ts +2 -0
- package/node_modules/@noble/hashes/esm/crypto.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/crypto.js +2 -0
- package/node_modules/@noble/hashes/esm/crypto.js.map +1 -0
- package/node_modules/@noble/hashes/esm/cryptoNode.d.ts +2 -0
- package/node_modules/@noble/hashes/esm/cryptoNode.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/cryptoNode.js +15 -0
- package/node_modules/@noble/hashes/esm/cryptoNode.js.map +1 -0
- package/node_modules/@noble/hashes/esm/eskdf.d.ts +47 -0
- package/node_modules/@noble/hashes/esm/eskdf.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/eskdf.js +160 -0
- package/node_modules/@noble/hashes/esm/eskdf.js.map +1 -0
- package/node_modules/@noble/hashes/esm/hkdf.d.ts +36 -0
- package/node_modules/@noble/hashes/esm/hkdf.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/hkdf.js +82 -0
- package/node_modules/@noble/hashes/esm/hkdf.js.map +1 -0
- package/node_modules/@noble/hashes/esm/hmac.d.ts +35 -0
- package/node_modules/@noble/hashes/esm/hmac.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/hmac.js +86 -0
- package/node_modules/@noble/hashes/esm/hmac.js.map +1 -0
- package/node_modules/@noble/hashes/esm/index.d.ts +2 -0
- package/node_modules/@noble/hashes/esm/index.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/index.js +33 -0
- package/node_modules/@noble/hashes/esm/index.js.map +1 -0
- package/node_modules/@noble/hashes/esm/legacy.d.ts +71 -0
- package/node_modules/@noble/hashes/esm/legacy.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/legacy.js +281 -0
- package/node_modules/@noble/hashes/esm/legacy.js.map +1 -0
- package/node_modules/@noble/hashes/esm/package.json +10 -0
- package/node_modules/@noble/hashes/esm/pbkdf2.d.ts +23 -0
- package/node_modules/@noble/hashes/esm/pbkdf2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/pbkdf2.js +97 -0
- package/node_modules/@noble/hashes/esm/pbkdf2.js.map +1 -0
- package/node_modules/@noble/hashes/esm/ripemd160.d.ts +13 -0
- package/node_modules/@noble/hashes/esm/ripemd160.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/ripemd160.js +13 -0
- package/node_modules/@noble/hashes/esm/ripemd160.js.map +1 -0
- package/node_modules/@noble/hashes/esm/scrypt.d.ts +34 -0
- package/node_modules/@noble/hashes/esm/scrypt.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/scrypt.js +228 -0
- package/node_modules/@noble/hashes/esm/scrypt.js.map +1 -0
- package/node_modules/@noble/hashes/esm/sha1.d.ts +11 -0
- package/node_modules/@noble/hashes/esm/sha1.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/sha1.js +11 -0
- package/node_modules/@noble/hashes/esm/sha1.js.map +1 -0
- package/node_modules/@noble/hashes/esm/sha2.d.ts +159 -0
- package/node_modules/@noble/hashes/esm/sha2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/sha2.js +375 -0
- package/node_modules/@noble/hashes/esm/sha2.js.map +1 -0
- package/node_modules/@noble/hashes/esm/sha256.d.ts +20 -0
- package/node_modules/@noble/hashes/esm/sha256.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/sha256.js +20 -0
- package/node_modules/@noble/hashes/esm/sha256.js.map +1 -0
- package/node_modules/@noble/hashes/esm/sha3-addons.d.ts +142 -0
- package/node_modules/@noble/hashes/esm/sha3-addons.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/sha3-addons.js +393 -0
- package/node_modules/@noble/hashes/esm/sha3-addons.js.map +1 -0
- package/node_modules/@noble/hashes/esm/sha3.d.ts +53 -0
- package/node_modules/@noble/hashes/esm/sha3.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/sha3.js +234 -0
- package/node_modules/@noble/hashes/esm/sha3.js.map +1 -0
- package/node_modules/@noble/hashes/esm/sha512.d.ts +26 -0
- package/node_modules/@noble/hashes/esm/sha512.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/sha512.js +26 -0
- package/node_modules/@noble/hashes/esm/sha512.js.map +1 -0
- package/node_modules/@noble/hashes/esm/utils.d.ts +161 -0
- package/node_modules/@noble/hashes/esm/utils.d.ts.map +1 -0
- package/node_modules/@noble/hashes/esm/utils.js +281 -0
- package/node_modules/@noble/hashes/esm/utils.js.map +1 -0
- package/node_modules/@noble/hashes/hkdf.d.ts +36 -0
- package/node_modules/@noble/hashes/hkdf.d.ts.map +1 -0
- package/node_modules/@noble/hashes/hkdf.js +88 -0
- package/node_modules/@noble/hashes/hkdf.js.map +1 -0
- package/node_modules/@noble/hashes/hmac.d.ts +35 -0
- package/node_modules/@noble/hashes/hmac.d.ts.map +1 -0
- package/node_modules/@noble/hashes/hmac.js +91 -0
- package/node_modules/@noble/hashes/hmac.js.map +1 -0
- package/node_modules/@noble/hashes/index.d.ts +1 -0
- package/node_modules/@noble/hashes/index.d.ts.map +1 -0
- package/node_modules/@noble/hashes/index.js +33 -0
- package/node_modules/@noble/hashes/index.js.map +1 -0
- package/node_modules/@noble/hashes/legacy.d.ts +71 -0
- package/node_modules/@noble/hashes/legacy.d.ts.map +1 -0
- package/node_modules/@noble/hashes/legacy.js +287 -0
- package/node_modules/@noble/hashes/legacy.js.map +1 -0
- package/node_modules/@noble/hashes/package.json +266 -0
- package/node_modules/@noble/hashes/pbkdf2.d.ts +23 -0
- package/node_modules/@noble/hashes/pbkdf2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/pbkdf2.js +101 -0
- package/node_modules/@noble/hashes/pbkdf2.js.map +1 -0
- package/node_modules/@noble/hashes/ripemd160.d.ts +13 -0
- package/node_modules/@noble/hashes/ripemd160.d.ts.map +1 -0
- package/node_modules/@noble/hashes/ripemd160.js +16 -0
- package/node_modules/@noble/hashes/ripemd160.js.map +1 -0
- package/node_modules/@noble/hashes/scrypt.d.ts +34 -0
- package/node_modules/@noble/hashes/scrypt.d.ts.map +1 -0
- package/node_modules/@noble/hashes/scrypt.js +232 -0
- package/node_modules/@noble/hashes/scrypt.js.map +1 -0
- package/node_modules/@noble/hashes/sha1.d.ts +11 -0
- package/node_modules/@noble/hashes/sha1.d.ts.map +1 -0
- package/node_modules/@noble/hashes/sha1.js +14 -0
- package/node_modules/@noble/hashes/sha1.js.map +1 -0
- package/node_modules/@noble/hashes/sha2.d.ts +159 -0
- package/node_modules/@noble/hashes/sha2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/sha2.js +384 -0
- package/node_modules/@noble/hashes/sha2.js.map +1 -0
- package/node_modules/@noble/hashes/sha256.d.ts +20 -0
- package/node_modules/@noble/hashes/sha256.d.ts.map +1 -0
- package/node_modules/@noble/hashes/sha256.js +23 -0
- package/node_modules/@noble/hashes/sha256.js.map +1 -0
- package/node_modules/@noble/hashes/sha3-addons.d.ts +142 -0
- package/node_modules/@noble/hashes/sha3-addons.d.ts.map +1 -0
- package/node_modules/@noble/hashes/sha3-addons.js +402 -0
- package/node_modules/@noble/hashes/sha3-addons.js.map +1 -0
- package/node_modules/@noble/hashes/sha3.d.ts +53 -0
- package/node_modules/@noble/hashes/sha3.d.ts.map +1 -0
- package/node_modules/@noble/hashes/sha3.js +239 -0
- package/node_modules/@noble/hashes/sha3.js.map +1 -0
- package/node_modules/@noble/hashes/sha512.d.ts +26 -0
- package/node_modules/@noble/hashes/sha512.d.ts.map +1 -0
- package/node_modules/@noble/hashes/sha512.js +29 -0
- package/node_modules/@noble/hashes/sha512.js.map +1 -0
- package/node_modules/@noble/hashes/src/_assert.ts +22 -0
- package/node_modules/@noble/hashes/src/_blake.ts +50 -0
- package/node_modules/@noble/hashes/src/_md.ts +176 -0
- package/node_modules/@noble/hashes/src/_u64.ts +91 -0
- package/node_modules/@noble/hashes/src/argon2.ts +497 -0
- package/node_modules/@noble/hashes/src/blake1.ts +534 -0
- package/node_modules/@noble/hashes/src/blake2.ts +486 -0
- package/node_modules/@noble/hashes/src/blake2b.ts +10 -0
- package/node_modules/@noble/hashes/src/blake2s.ts +20 -0
- package/node_modules/@noble/hashes/src/blake3.ts +272 -0
- package/node_modules/@noble/hashes/src/crypto.ts +9 -0
- package/node_modules/@noble/hashes/src/cryptoNode.ts +15 -0
- package/node_modules/@noble/hashes/src/eskdf.ts +187 -0
- package/node_modules/@noble/hashes/src/hkdf.ts +88 -0
- package/node_modules/@noble/hashes/src/hmac.ts +94 -0
- package/node_modules/@noble/hashes/src/index.ts +31 -0
- package/node_modules/@noble/hashes/src/legacy.ts +293 -0
- package/node_modules/@noble/hashes/src/pbkdf2.ts +122 -0
- package/node_modules/@noble/hashes/src/ripemd160.ts +12 -0
- package/node_modules/@noble/hashes/src/scrypt.ts +257 -0
- package/node_modules/@noble/hashes/src/sha1.ts +10 -0
- package/node_modules/@noble/hashes/src/sha2.ts +402 -0
- package/node_modules/@noble/hashes/src/sha256.ts +24 -0
- package/node_modules/@noble/hashes/src/sha3-addons.ts +499 -0
- package/node_modules/@noble/hashes/src/sha3.ts +258 -0
- package/node_modules/@noble/hashes/src/sha512.ts +34 -0
- package/node_modules/@noble/hashes/src/utils.ts +395 -0
- package/node_modules/@noble/hashes/utils.d.ts +161 -0
- package/node_modules/@noble/hashes/utils.d.ts.map +1 -0
- package/node_modules/@noble/hashes/utils.js +313 -0
- package/node_modules/@noble/hashes/utils.js.map +1 -0
- package/package.json +179 -8
- package/schemas/catalog.schema.json +357 -0
- package/src/align.ts +239 -0
- package/src/audio-init-parser.ts +189 -0
- package/src/audio-ring-buffer.ts +120 -0
- package/src/authored-timing.ts +63 -0
- package/src/block-policy.ts +903 -0
- package/src/carp-catalog.ts +1065 -0
- package/src/catalog-fec-params.ts +729 -0
- package/src/catalog-network-source.ts +74 -0
- package/src/catalog-validator.ts +34 -0
- package/src/cmaf-block-assembler.ts +1255 -0
- package/src/cmaf-group-batcher.ts +104 -0
- package/src/cmcd-producer.ts +329 -0
- package/src/codec-utils.ts +1984 -0
- package/src/conceal-timeline.ts +293 -0
- package/src/delivery-gap.ts +147 -0
- package/src/duplicate-ledger.ts +372 -0
- package/src/fec-codec.ts +61 -0
- package/src/fec-manager.ts +4298 -0
- package/src/fec-starvation-detector.ts +128 -0
- package/src/fec-state.ts +219 -0
- package/src/fec-worker-setup.ts +283 -0
- package/src/fmp4-completion.ts +47 -0
- package/src/fmp4-reader.ts +112 -0
- package/src/index.ts +590 -21
- package/src/iso-block-locator.ts +329 -0
- package/src/iso-bmff-timing.ts +813 -0
- package/src/loc.ts +128 -154
- package/src/manifest-auth-plan.ts +107 -0
- package/src/media-router.ts +841 -0
- package/src/mfu-reassembler.ts +3480 -155
- package/src/mfu-reassembly-policy.ts +134 -0
- package/src/mmtp-container-parser.ts +2380 -0
- package/src/mmtp-decode-pipeline.ts +406 -0
- package/src/mmtp-router.ts +4860 -0
- package/src/mmtp-to-cmaf.ts +977 -0
- package/src/multicast-auth-catalog.ts +340 -0
- package/src/multicast-input.ts +793 -0
- package/src/multicast-manager.ts +2783 -0
- package/src/multicast-transport.ts +1058 -0
- package/src/multicast-unwrap.ts +132 -0
- package/src/no-modules.ts +21 -0
- package/src/phase14-catalog-override.ts +336 -0
- package/src/repair-fetch.ts +772 -0
- package/src/repair-layers.ts +533 -0
- package/src/sample-combiner.ts +938 -0
- package/src/signaling.ts +78 -0
- package/src/source-auth.ts +1 -0
- package/src/switching-set-alignment.ts +109 -0
- package/src/timestamp-codec.ts +265 -0
- package/src/track-pipeline-setup.ts +205 -0
- package/src/track-pipeline.ts +332 -0
- package/src/track-session.ts +1010 -0
- package/src/transport-pool.ts +128 -0
- package/src/wasm-mfu-reassembler.ts +405 -0
- package/src/wasm-mmtp-container-parser.ts +23 -0
- package/test-vectors/align.json +199 -0
- package/test-vectors/catalog/README.md +106 -0
- package/test-vectors/catalog/negative/archive-origin-with-path.json +33 -0
- package/test-vectors/catalog/negative/archive-unknown-field.json +34 -0
- package/test-vectors/catalog/negative/fec-block-profile-missing.json +51 -0
- package/test-vectors/catalog/negative/fec-block-profile-unknown.json +52 -0
- package/test-vectors/catalog/negative/fec-enhancement-repair-removed.json +28 -0
- package/test-vectors/catalog/negative/fec-repair-layer-geometry.json +33 -0
- package/test-vectors/catalog/negative/fec-repair-layer-missing-symbols.json +31 -0
- package/test-vectors/catalog/negative/fec-repair-multiple-depends.json +32 -0
- package/test-vectors/catalog/negative/fec-repair-overlay-with-layer.json +34 -0
- package/test-vectors/catalog/negative/fec-repair-priority-out-of-band.json +24 -0
- package/test-vectors/catalog/negative/fec-repair-source-symbols-without-scope.json +33 -0
- package/test-vectors/catalog/negative/legacy-selection-params.json +15 -0
- package/test-vectors/catalog/negative/media-track-repair-layer.json +16 -0
- package/test-vectors/catalog/negative/missing-mmtp-fields.json +12 -0
- package/test-vectors/catalog/negative/multicast-auth-padded-key.json +37 -0
- package/test-vectors/catalog/negative/multicast-auth-reused-track-format.json +53 -0
- package/test-vectors/catalog/negative/multicast-auth-trailing-pad-bits.json +37 -0
- package/test-vectors/catalog/negative/multicast-endpoint-missing-protocol-and-source.json +24 -0
- package/test-vectors/catalog/negative/multicast-network-source-empty.json +44 -0
- package/test-vectors/catalog/negative/multicast-packet-id-signaling.json +26 -0
- package/test-vectors/catalog/negative/network-source-object.json +25 -0
- package/test-vectors/catalog/negative/raptorq-source-symbols-over-max.json +24 -0
- package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +27 -0
- package/test-vectors/catalog/negative/repair-track-legacy-shape.json +19 -0
- package/test-vectors/catalog/negative/track-role-empty.json +16 -0
- package/test-vectors/catalog/negative/track-role-non-string.json +16 -0
- package/test-vectors/catalog/positive/archive-origin.json +34 -0
- package/test-vectors/catalog/positive/fec-iso-ssbg1.json +52 -0
- package/test-vectors/catalog/positive/fec-layered-repair.json +106 -0
- package/test-vectors/catalog/positive/fec-multicast.json +52 -0
- package/test-vectors/catalog/positive/flat-av.json +30 -0
- package/test-vectors/catalog/positive/multicast-auth-rotation.json +55 -0
- package/test-vectors/catalog/positive/multicast-native-ssm-no-network-source.json +43 -0
- package/test-vectors/catalog/positive/ticks-and-mixed-timescales.json +39 -0
- package/test-vectors/catalog/positive/track-role.json +49 -0
- package/test-vectors/catalog/releases/moqcast-native-v16-v1/catalog.json +65 -0
- package/test-vectors/catalog/releases/moqcast-native-v16-v1.archive.sha256 +1 -0
- package/test-vectors/catalog-multicast-auth-v1.json +26 -0
- package/test-vectors/catalog-validation.json +732 -0
- package/test-vectors/catalog-validator-public-api.mjs +25 -0
- package/test-vectors/generate-source-auth-fixture.mjs +114 -0
- package/test-vectors/hevc-x265-repeat-headers-v1.json +40 -0
- package/test-vectors/source-auth-v1.json +61 -0
- package/test-vectors/source-contiguity-v1.json +131 -0
- package/test-vectors/subsample-placement-v1.json +230 -0
- package/dist/mmtp.d.ts +0 -73
- package/dist/mmtp.d.ts.map +0 -1
- package/dist/mmtp.js +0 -210
- package/dist/mmtp.js.map +0 -1
- package/src/mmtp.ts +0 -277
|
@@ -0,0 +1,1058 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin transport wrapper for SSM multicast — join, socket, watchdog,
|
|
3
|
+
* takeover/failback. Delegates raw packets to a callback (MmtpRouter
|
|
4
|
+
* or any direct consumer).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
isMulticastTrackPacketId,
|
|
9
|
+
subscriptionDeliversPacketBatches,
|
|
10
|
+
toWindowMulticastSubscribeConfig,
|
|
11
|
+
type WindowMulticastDelivery,
|
|
12
|
+
type WindowMulticastGateway,
|
|
13
|
+
type WindowMulticastSubscription,
|
|
14
|
+
} from '@blockcast/mmt-transport'
|
|
15
|
+
import {
|
|
16
|
+
MMTP_PACKET_ID_MAX,
|
|
17
|
+
MMTP_SIGNALING_PACKET_ID,
|
|
18
|
+
readMMTPPacketId,
|
|
19
|
+
} from '@blockcast/mmt-base'
|
|
20
|
+
|
|
21
|
+
export interface MulticastTransportConfig {
|
|
22
|
+
sourceAddress: string
|
|
23
|
+
groupAddress: string
|
|
24
|
+
port: number
|
|
25
|
+
mode?: 'auto' | 'native' | 'tunnel'
|
|
26
|
+
amtRelay?: string
|
|
27
|
+
amtRelayPort?: number
|
|
28
|
+
packetIds?: number[]
|
|
29
|
+
tracks?: { name: string; packetId: number }[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type ResolvedMulticastTransport = 'native' | 'amt'
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Why a joined transport handed control back to MoQ.
|
|
36
|
+
*
|
|
37
|
+
* - `silence`: the data plane was live (at least one accepted packet since the
|
|
38
|
+
* join) and then stayed silent for the catalog-derived failback window.
|
|
39
|
+
* - `subscription-error`: the provider reported the subscription failed. This
|
|
40
|
+
* is the provider's own explicit, typed outcome (a `MulticastError`, branch
|
|
41
|
+
* on its `code`), e.g. a bridge whose AMT tunnel it declared dead.
|
|
42
|
+
*/
|
|
43
|
+
export type MulticastFailbackReason =
|
|
44
|
+
| { readonly kind: 'silence'; readonly windowMs: number }
|
|
45
|
+
| { readonly kind: 'subscription-error'; readonly error: unknown }
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Why a join() resolved false, named by the step at which the join stopped,
|
|
49
|
+
* never by what an error message says.
|
|
50
|
+
*
|
|
51
|
+
* - `disposed`: the transport was disposed before the join started, or while
|
|
52
|
+
* the provider's subscribe() was pending.
|
|
53
|
+
* - `unavailable`: there is no window.multicast gateway with a subscribe().
|
|
54
|
+
* - `superseded`: a newer join() started while this join's subscribe() was
|
|
55
|
+
* pending; the newer join owns the transport.
|
|
56
|
+
* - `invalid-request`: the join config does not make a valid window.multicast
|
|
57
|
+
* request (toWindowMulticastSubscribeConfig refused it), so the provider was
|
|
58
|
+
* never asked.
|
|
59
|
+
* - `provider-rejected`: the provider's subscribe() rejected or threw. The only
|
|
60
|
+
* cause that carries the provider's own verdict (`providerError`).
|
|
61
|
+
* - `invalid-subscription`: subscribe() resolved something that is not a usable
|
|
62
|
+
* subscription: no event surface, a malformed `eventTypes`, an unknown
|
|
63
|
+
* `delivery`, or an `addEventListener` that threw.
|
|
64
|
+
* - `delivery-hook-failed`: the consumer's onDelivery hook threw for the
|
|
65
|
+
* delivery the subscription declared, e.g. 'ordered-relay' to FEC tracks
|
|
66
|
+
* configured without ordered geometry. A local configuration failure, not
|
|
67
|
+
* the provider's.
|
|
68
|
+
*/
|
|
69
|
+
export type MulticastJoinDeclineReason =
|
|
70
|
+
| 'disposed'
|
|
71
|
+
| 'unavailable'
|
|
72
|
+
| 'superseded'
|
|
73
|
+
| 'invalid-request'
|
|
74
|
+
| 'provider-rejected'
|
|
75
|
+
| 'invalid-subscription'
|
|
76
|
+
| 'delivery-hook-failed'
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The typed part of a provider's subscribe() rejection. `name` and `code` are
|
|
80
|
+
* the provider's own typed fields; the frozen multicast contract makes `code`
|
|
81
|
+
* the one to branch on (e.g. a bridge's `amt_relay_refused`). `message` is
|
|
82
|
+
* free text carried for humans only: never branch on it.
|
|
83
|
+
*/
|
|
84
|
+
export interface MulticastJoinProviderError {
|
|
85
|
+
readonly name: string
|
|
86
|
+
readonly message: string
|
|
87
|
+
/** Present only when the provider's error carries a string `code`. */
|
|
88
|
+
readonly code?: string
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* How a join() resolved: joined, or the typed reason it resolved false.
|
|
93
|
+
* `providerError` is present only for `provider-rejected`, and only when the
|
|
94
|
+
* provider's rejection value carries a string `name` and `message`.
|
|
95
|
+
*/
|
|
96
|
+
export type MulticastJoinOutcome =
|
|
97
|
+
| { readonly ok: true }
|
|
98
|
+
| {
|
|
99
|
+
readonly ok: false
|
|
100
|
+
readonly reason: MulticastJoinDeclineReason
|
|
101
|
+
readonly providerError?: MulticastJoinProviderError
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Receive counters plus the ingress-filter drop counters.
|
|
106
|
+
*
|
|
107
|
+
* `packetsReceived` / `bytesReceived` count only packets that passed the
|
|
108
|
+
* allow-list and were handed to the page — a rejected packet must never
|
|
109
|
+
* inflate them. The `dropped*` counters are the other half of that story:
|
|
110
|
+
* without them a filtered PID is indistinguishable from a PID that was never
|
|
111
|
+
* transmitted, which is exactly the ambiguity that makes an all-zero FEC
|
|
112
|
+
* repair count unreadable (a repair leg dropped here and a repair leg the
|
|
113
|
+
* publisher never sent produce byte-identical downstream telemetry).
|
|
114
|
+
*/
|
|
115
|
+
export interface MulticastTransportStats {
|
|
116
|
+
packetsReceived: number
|
|
117
|
+
bytesReceived: number
|
|
118
|
+
/** Parsed cleanly, but the packet ID is absent from the join's allow-list. */
|
|
119
|
+
packetsDroppedUnregisteredPid: number
|
|
120
|
+
/** MMTP header did not parse; the packet ID is unknown, so it cannot be attributed. */
|
|
121
|
+
packetsDroppedUnparseable: number
|
|
122
|
+
/**
|
|
123
|
+
* packet_id 0, the MMTP signaling flow. Expected traffic on a protected
|
|
124
|
+
* session (moq_mmt sends the AL-FEC message on it), so it is counted apart
|
|
125
|
+
* from the unregistered-PID fault counter and never takes a
|
|
126
|
+
* `droppedPacketIds` slot.
|
|
127
|
+
*/
|
|
128
|
+
packetsDroppedSignaling: number
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* join() calls by how they resolved, cumulative for the life of the transport:
|
|
133
|
+
* across rejoins, failed joins and dispose. `succeeded` plus every `declined`
|
|
134
|
+
* count is the number of join() calls that resolved, superseded ones
|
|
135
|
+
* included; a join() that rejects counts in none (see
|
|
136
|
+
* MulticastTransport.lastJoinOutcome).
|
|
137
|
+
*/
|
|
138
|
+
export interface MulticastJoinStats {
|
|
139
|
+
/** join() calls that resolved true. */
|
|
140
|
+
readonly succeeded: number
|
|
141
|
+
/** join() calls that resolved false, by the reason each one did. */
|
|
142
|
+
readonly declined: Readonly<Record<MulticastJoinDeclineReason, number>>
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const JOIN_SUCCEEDED: MulticastJoinOutcome = Object.freeze({ ok: true })
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The typed part of a provider's subscribe() rejection, or undefined when the
|
|
149
|
+
* rejection value is not an error with a string `name` and `message`. Nothing
|
|
150
|
+
* is filled in for a field the provider did not type, and the message is
|
|
151
|
+
* carried, never read.
|
|
152
|
+
*/
|
|
153
|
+
function providerErrorOf(error: unknown): MulticastJoinProviderError | undefined {
|
|
154
|
+
if (typeof error !== 'object' || error === null) return undefined
|
|
155
|
+
const fields = error as { readonly name?: unknown; readonly message?: unknown; readonly code?: unknown }
|
|
156
|
+
let name: unknown
|
|
157
|
+
let message: unknown
|
|
158
|
+
let code: unknown
|
|
159
|
+
try {
|
|
160
|
+
name = fields.name
|
|
161
|
+
message = fields.message
|
|
162
|
+
code = fields.code
|
|
163
|
+
} catch {
|
|
164
|
+
// A rejection value whose fields throw on read (a revoked Proxy) types
|
|
165
|
+
// nothing. Reading it must not turn a declined join into a rejected one.
|
|
166
|
+
return undefined
|
|
167
|
+
}
|
|
168
|
+
if (typeof name !== 'string' || typeof message !== 'string') return undefined
|
|
169
|
+
return Object.freeze(typeof code === 'string' ? { name, message, code } : { name, message })
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Distinct unregistered PIDs retained for diagnostics. A conformant catalog
|
|
174
|
+
* advertises a handful of PIDs per endpoint, so this only has to be large
|
|
175
|
+
* enough to name every leg of a mis-provisioned one; the cap exists so a
|
|
176
|
+
* malformed or hostile stream cycling the 16-bit PID space cannot grow the map
|
|
177
|
+
* without bound. Drops keep counting in aggregate after the cap.
|
|
178
|
+
*/
|
|
179
|
+
const MAX_TRACKED_DROPPED_PIDS = 16
|
|
180
|
+
|
|
181
|
+
type MulticastGlobals = typeof globalThis & {
|
|
182
|
+
multicast?: WindowMulticastGateway
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function getMulticastGlobals(): MulticastGlobals {
|
|
186
|
+
return globalThis as MulticastGlobals
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function hasMulticastGateway(): boolean {
|
|
190
|
+
return typeof getMulticastGlobals().multicast?.subscribe === 'function'
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* The packet one `bytes` event (or one element of a `packets` batch) carries,
|
|
195
|
+
* as a view of the provider's own bytes. A Uint8Array is used as it is; the
|
|
196
|
+
* bridge hands every packet over as one, so the common path builds nothing.
|
|
197
|
+
*/
|
|
198
|
+
function normalizeBytesEventDetail(detail: unknown): Uint8Array | null {
|
|
199
|
+
const value =
|
|
200
|
+
detail && typeof detail === 'object' && 'data' in detail
|
|
201
|
+
? (detail as { data?: unknown }).data
|
|
202
|
+
: detail
|
|
203
|
+
if (value instanceof Uint8Array) return value
|
|
204
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value)
|
|
205
|
+
if (ArrayBuffer.isView(value)) {
|
|
206
|
+
return new Uint8Array(value.buffer, value.byteOffset, value.byteLength)
|
|
207
|
+
}
|
|
208
|
+
return null
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* A provider that can replace a live subscription's MMTP packet-ID filter
|
|
213
|
+
* without rejoining its socket: the frozen multicast contract's
|
|
214
|
+
* `Subscription.setPacketIds` (pim `packages/multicast-contract`). It is not
|
|
215
|
+
* declared on every provider this transport meets, so it is detected, never
|
|
216
|
+
* assumed.
|
|
217
|
+
*/
|
|
218
|
+
interface PacketFilterUpdater {
|
|
219
|
+
setPacketIds(packetIds: readonly number[]): Promise<void> | void
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function packetFilterUpdater(
|
|
223
|
+
subscription: WindowMulticastSubscription,
|
|
224
|
+
): PacketFilterUpdater['setPacketIds'] | undefined {
|
|
225
|
+
const update = (subscription as Partial<PacketFilterUpdater>).setPacketIds
|
|
226
|
+
return typeof update === 'function' ? update.bind(subscription) : undefined
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function sameIds(a: ReadonlySet<number>, b: ReadonlySet<number>): boolean {
|
|
230
|
+
if (a.size !== b.size) return false
|
|
231
|
+
for (const id of a) if (!b.has(id)) return false
|
|
232
|
+
return true
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* The provider-side packet filter of one live join, and the in-place updates
|
|
237
|
+
* sent to it. It lives exactly as long as the join: a later join or release
|
|
238
|
+
* replaces it, and an acknowledgement for a replaced one is ignored.
|
|
239
|
+
*/
|
|
240
|
+
interface ProviderFilter {
|
|
241
|
+
/**
|
|
242
|
+
* The filter as the newest acknowledged update left it: the packet IDs the
|
|
243
|
+
* provider forwards, or null when it forwards every ID. Until an update is
|
|
244
|
+
* acknowledged it is the join's own filter.
|
|
245
|
+
*/
|
|
246
|
+
acknowledged: ReadonlySet<number> | null
|
|
247
|
+
/** Updates sent to the provider, numbered from 1 in send order. */
|
|
248
|
+
sent: number
|
|
249
|
+
/** The number of the newest acknowledged update; 0 for the join's own filter. */
|
|
250
|
+
acknowledgedUpdate: number
|
|
251
|
+
/** Updates sent and not yet settled. */
|
|
252
|
+
inFlight: number
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/** Which packet surface a join listens to, and its listener. */
|
|
256
|
+
type PacketListener =
|
|
257
|
+
| { readonly type: 'bytes'; readonly listener: (event: CustomEvent<unknown>) => void }
|
|
258
|
+
| { readonly type: 'packets'; readonly listener: (event: CustomEvent<readonly unknown[]>) => void }
|
|
259
|
+
|
|
260
|
+
export class MulticastTransport<TPacketContext = never> {
|
|
261
|
+
#onPacket: (packet: Uint8Array, context?: TPacketContext) => void
|
|
262
|
+
#subscription: WindowMulticastSubscription | null = null
|
|
263
|
+
#packetListener: PacketListener | null = null
|
|
264
|
+
#resolvedTransport: ResolvedMulticastTransport | undefined
|
|
265
|
+
#videoConfirmed = false
|
|
266
|
+
#audioConfirmed = false
|
|
267
|
+
// One armed no-packets timer per silence window (BLO-36599). Packets only
|
|
268
|
+
// record #lastPacketAtMs; the timer re-arms for the remainder when it wakes
|
|
269
|
+
// inside the window, instead of a clear+set pair on every packet.
|
|
270
|
+
#watchdog: ReturnType<typeof setTimeout> | null = null
|
|
271
|
+
#lastPacketAtMs = 0
|
|
272
|
+
#failbackWindowMs: number | null = null
|
|
273
|
+
#onTakeover: (() => void) | null = null
|
|
274
|
+
#onFailback: ((reason: MulticastFailbackReason) => void) | null = null
|
|
275
|
+
// Data-plane-live edge: the first packet this join accepted. Everything
|
|
276
|
+
// before it is join latency, not silence (see #resetWatchdog).
|
|
277
|
+
#dataPlaneLive = false
|
|
278
|
+
#onDataPlaneLive: (() => void) | null = null
|
|
279
|
+
#errorListener: ((event: CustomEvent<unknown>) => void) | null = null
|
|
280
|
+
#onDelivery: ((delivery: WindowMulticastDelivery) => void) | null = null
|
|
281
|
+
#delivery: WindowMulticastDelivery | undefined
|
|
282
|
+
#disposed = false
|
|
283
|
+
#stats: MulticastTransportStats = {
|
|
284
|
+
packetsReceived: 0,
|
|
285
|
+
bytesReceived: 0,
|
|
286
|
+
packetsDroppedUnregisteredPid: 0,
|
|
287
|
+
packetsDroppedUnparseable: 0,
|
|
288
|
+
packetsDroppedSignaling: 0,
|
|
289
|
+
}
|
|
290
|
+
// join() calls by how they resolved; see joinStats.
|
|
291
|
+
#joinsSucceeded = 0
|
|
292
|
+
readonly #joinsDeclined: Record<MulticastJoinDeclineReason, number> = {
|
|
293
|
+
disposed: 0,
|
|
294
|
+
unavailable: 0,
|
|
295
|
+
superseded: 0,
|
|
296
|
+
'invalid-request': 0,
|
|
297
|
+
'provider-rejected': 0,
|
|
298
|
+
'invalid-subscription': 0,
|
|
299
|
+
'delivery-hook-failed': 0,
|
|
300
|
+
}
|
|
301
|
+
// The newest resolved join's outcome (see lastJoinOutcome) and the join
|
|
302
|
+
// generation it belongs to. Generations are issued in start order, so a
|
|
303
|
+
// join that resolves after a newer join has recorded leaves it standing.
|
|
304
|
+
#lastJoinOutcome: MulticastJoinOutcome | undefined = undefined
|
|
305
|
+
#lastJoinOutcomeGeneration = 0
|
|
306
|
+
#droppedPidCounts = new Map<number, number>()
|
|
307
|
+
// Accepted bytes per MMTP packet_id; see bytesReceivedForPacketIds. Each
|
|
308
|
+
// value is a mutable cell, so the per-packet update is one lookup and an
|
|
309
|
+
// in-place add: no insertion once the key exists, and no re-boxed number
|
|
310
|
+
// per packet once a count outgrows the small-integer range.
|
|
311
|
+
readonly #acceptedBytesByPacketId = new Map<number, { bytes: number }>()
|
|
312
|
+
#packetIds: ReadonlySet<number> | null = null
|
|
313
|
+
// What the live join delivers with each accepted packet. A field, not a
|
|
314
|
+
// listener closure, so an in-place admission change (setContext) applies
|
|
315
|
+
// from the next packet on without rejoining.
|
|
316
|
+
#context: TPacketContext | undefined = undefined
|
|
317
|
+
// The live join's provider-side filter. An in-place widening must reach it,
|
|
318
|
+
// or the provider never delivers the new ID; null without a live join.
|
|
319
|
+
#providerFilter: ProviderFilter | null = null
|
|
320
|
+
// IDs an in-place update withdrew while the provider may still be
|
|
321
|
+
// delivering them. Their late packets are still counted as filtered, but
|
|
322
|
+
// they are the expected tail of a deliberate change, not a provisioning
|
|
323
|
+
// fault, so they are counted apart and do not raise the unadvertised-PID
|
|
324
|
+
// warning.
|
|
325
|
+
readonly #withdrawnPacketIds = new Set<number>()
|
|
326
|
+
#withdrawnPacketIdDrops = 0
|
|
327
|
+
// Distinct packet IDs dropped as provisioning faults: on the wire but in
|
|
328
|
+
// no allow-list the join or an in-place update declared. Capped with
|
|
329
|
+
// droppedPacketIds.
|
|
330
|
+
readonly #unadvertisedPacketIds = new Set<number>()
|
|
331
|
+
#joinGeneration = 0
|
|
332
|
+
|
|
333
|
+
constructor(onPacket: (packet: Uint8Array, context?: TPacketContext) => void) {
|
|
334
|
+
this.#onPacket = onPacket
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
static isAvailable(): boolean {
|
|
338
|
+
return hasMulticastGateway()
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
async join(config: MulticastTransportConfig, context?: TPacketContext): Promise<boolean> {
|
|
342
|
+
const generation = ++this.#joinGeneration
|
|
343
|
+
this.#releaseSubscription()
|
|
344
|
+
this.#dataPlaneLive = false
|
|
345
|
+
|
|
346
|
+
if (this.#disposed) return this.#declined(generation, 'disposed')
|
|
347
|
+
if (!MulticastTransport.isAvailable()) {
|
|
348
|
+
console.warn('[MulticastTransport] Multicast API not available')
|
|
349
|
+
return this.#declined(generation, 'unavailable')
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// What a throw from the step in progress means. Each step names its
|
|
353
|
+
// failure before it runs, so the catch classifies a decline by where the
|
|
354
|
+
// join stopped, never by what the error says.
|
|
355
|
+
let failure: MulticastJoinDeclineReason = 'invalid-request'
|
|
356
|
+
try {
|
|
357
|
+
const packetIds = config.packetIds?.length ? new Set(config.packetIds) : null
|
|
358
|
+
console.log(
|
|
359
|
+
`[MulticastTransport] window.multicast.subscribe(${config.sourceAddress}, ${config.groupAddress}, ${config.port})`,
|
|
360
|
+
)
|
|
361
|
+
const subscribeConfig = toWindowMulticastSubscribeConfig({
|
|
362
|
+
source: config.sourceAddress,
|
|
363
|
+
group: config.groupAddress,
|
|
364
|
+
port: config.port,
|
|
365
|
+
mode: config.mode,
|
|
366
|
+
amtRelay: config.amtRelay,
|
|
367
|
+
amtRelayPort: config.amtRelayPort,
|
|
368
|
+
packetIds: config.packetIds,
|
|
369
|
+
tracks: config.tracks,
|
|
370
|
+
})
|
|
371
|
+
failure = 'provider-rejected'
|
|
372
|
+
const subscription = await getMulticastGlobals().multicast!.subscribe!(subscribeConfig)
|
|
373
|
+
failure = 'invalid-subscription'
|
|
374
|
+
console.log(`[MulticastTransport] window.multicast.subscribe returned:`, !!subscription)
|
|
375
|
+
|
|
376
|
+
if (this.#disposed || generation !== this.#joinGeneration) {
|
|
377
|
+
void subscription.unsubscribe()
|
|
378
|
+
return this.#declined(generation, this.#displacedReason())
|
|
379
|
+
}
|
|
380
|
+
if (typeof subscription.addEventListener !== 'function') {
|
|
381
|
+
if (typeof subscription.unsubscribe === 'function') {
|
|
382
|
+
void subscription.unsubscribe()
|
|
383
|
+
}
|
|
384
|
+
throw new Error('window.multicast subscription does not support bytes events')
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Own the subscription before anything below can throw, so a failed
|
|
388
|
+
// join's release reaches unsubscribe() instead of leaking it.
|
|
389
|
+
this.#subscription = subscription
|
|
390
|
+
const live = () => !this.#disposed && generation === this.#joinGeneration
|
|
391
|
+
// Exactly one packet surface. A provider that advertises the `packets`
|
|
392
|
+
// extension delivers each reader batch as one event, so the page pays
|
|
393
|
+
// one DOM event and one liveness read per batch instead of per packet
|
|
394
|
+
// (BLO-36599). Every packet still goes through the same filter, counters
|
|
395
|
+
// and callback, in arrival order, as a view of the provider's bytes.
|
|
396
|
+
const packetListener: PacketListener = subscriptionDeliversPacketBatches(subscription)
|
|
397
|
+
? {
|
|
398
|
+
type: 'packets',
|
|
399
|
+
listener: (event) => {
|
|
400
|
+
if (!live()) return
|
|
401
|
+
this.#deliverBatch(event.detail, live)
|
|
402
|
+
},
|
|
403
|
+
}
|
|
404
|
+
: {
|
|
405
|
+
type: 'bytes',
|
|
406
|
+
listener: (event) => {
|
|
407
|
+
if (!live()) return
|
|
408
|
+
if (this.#deliver(event.detail)) this.#resetWatchdog()
|
|
409
|
+
},
|
|
410
|
+
}
|
|
411
|
+
this.#packetListener = packetListener
|
|
412
|
+
this.#packetIds = packetIds
|
|
413
|
+
this.#providerFilter = {
|
|
414
|
+
acknowledged: packetIds,
|
|
415
|
+
sent: 0,
|
|
416
|
+
acknowledgedUpdate: 0,
|
|
417
|
+
inFlight: 0,
|
|
418
|
+
}
|
|
419
|
+
this.#context = context
|
|
420
|
+
// Seed the allow-list's counters so accepted packets never insert. An
|
|
421
|
+
// id already counted by an earlier join keeps its count: the counters
|
|
422
|
+
// are cumulative across rejoins, as bytesReceived is.
|
|
423
|
+
if (packetIds) {
|
|
424
|
+
for (const packetId of packetIds) {
|
|
425
|
+
if (!this.#acceptedBytesByPacketId.has(packetId)) {
|
|
426
|
+
this.#acceptedBytesByPacketId.set(packetId, { bytes: 0 })
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
// The request origin is the accepted acquisition contract. The
|
|
431
|
+
// gateway no longer exposes a mutable transport/transportchange
|
|
432
|
+
// surface, so assign this only after subscribe() has resolved and the
|
|
433
|
+
// returned subscription has passed the event-surface check above.
|
|
434
|
+
this.#resolvedTransport = subscribeConfig.origin === 'amt' ? 'amt' : 'native'
|
|
435
|
+
// The provider alone knows whether its packets are independent
|
|
436
|
+
// datagrams or an ordered relay of one socket; undeclared promises no
|
|
437
|
+
// ordering. Announce it before the listener can deliver a packet. A
|
|
438
|
+
// rejected declaration fails the join and releases the subscription.
|
|
439
|
+
const delivery = subscription.delivery ?? 'datagram'
|
|
440
|
+
if (delivery !== 'datagram' && delivery !== 'ordered-relay') {
|
|
441
|
+
throw new Error(
|
|
442
|
+
`window.multicast subscription declared unknown delivery ${String(delivery)}`,
|
|
443
|
+
)
|
|
444
|
+
}
|
|
445
|
+
this.#delivery = delivery
|
|
446
|
+
failure = 'delivery-hook-failed'
|
|
447
|
+
this.#onDelivery?.(delivery)
|
|
448
|
+
failure = 'invalid-subscription'
|
|
449
|
+
// The provider's explicit, terminal subscription failure. Before the
|
|
450
|
+
// first packet this is the only signal that bounds a join, so it must
|
|
451
|
+
// reach the failback path rather than be dropped.
|
|
452
|
+
const onError = (event: CustomEvent<unknown>) => {
|
|
453
|
+
if (this.#disposed || generation !== this.#joinGeneration) return
|
|
454
|
+
this.#failBackOnSubscriptionError(event.detail)
|
|
455
|
+
}
|
|
456
|
+
this.#errorListener = onError
|
|
457
|
+
if (packetListener.type === 'packets') {
|
|
458
|
+
subscription.addEventListener('packets', packetListener.listener)
|
|
459
|
+
} else {
|
|
460
|
+
subscription.addEventListener('bytes', packetListener.listener)
|
|
461
|
+
}
|
|
462
|
+
subscription.addEventListener('error', onError)
|
|
463
|
+
// No watchdog here. A resolved subscribe() is the provider's join
|
|
464
|
+
// outcome, not proof that the data plane is live: over AMT it resolves
|
|
465
|
+
// once the gateway has sent its Membership Update, and the relay's
|
|
466
|
+
// upstream join plus one path RTT still precede the first packet. The
|
|
467
|
+
// silence window is a packet-gap clock for a stream that has flowed;
|
|
468
|
+
// charging join latency to it failed back joins that went on to play.
|
|
469
|
+
// The join phase is bounded by the provider's typed error or the host's
|
|
470
|
+
// takeover deadline (see SessionManager.joinActive). The window starts
|
|
471
|
+
// at the first accepted packet (#resetWatchdog).
|
|
472
|
+
console.log(
|
|
473
|
+
`[MulticastTransport] Joined ${config.groupAddress}:${config.port}`,
|
|
474
|
+
)
|
|
475
|
+
return this.#joined(generation)
|
|
476
|
+
} catch (err) {
|
|
477
|
+
if (this.#disposed || generation !== this.#joinGeneration) {
|
|
478
|
+
return this.#declined(generation, this.#displacedReason())
|
|
479
|
+
}
|
|
480
|
+
this.#releaseSubscription()
|
|
481
|
+
console.error('[MulticastTransport] Failed to join SSM group:', err)
|
|
482
|
+
return this.#declined(
|
|
483
|
+
generation,
|
|
484
|
+
failure,
|
|
485
|
+
failure === 'provider-rejected' ? providerErrorOf(err) : undefined,
|
|
486
|
+
)
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/** Record a join that resolved true; returns its result. */
|
|
491
|
+
#joined(generation: number): true {
|
|
492
|
+
this.#joinsSucceeded++
|
|
493
|
+
this.#recordJoinOutcome(generation, JOIN_SUCCEEDED)
|
|
494
|
+
return true
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/** Record a join that resolved false, and why; returns its result. */
|
|
498
|
+
#declined(
|
|
499
|
+
generation: number,
|
|
500
|
+
reason: MulticastJoinDeclineReason,
|
|
501
|
+
providerError?: MulticastJoinProviderError,
|
|
502
|
+
): false {
|
|
503
|
+
this.#joinsDeclined[reason]++
|
|
504
|
+
this.#recordJoinOutcome(
|
|
505
|
+
generation,
|
|
506
|
+
Object.freeze(
|
|
507
|
+
providerError === undefined ? { ok: false, reason } : { ok: false, reason, providerError },
|
|
508
|
+
),
|
|
509
|
+
)
|
|
510
|
+
return false
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Why a join that no longer owns the transport resolved false. dispose()
|
|
515
|
+
* advances the join generation too, so disposal is checked first.
|
|
516
|
+
*/
|
|
517
|
+
#displacedReason(): 'disposed' | 'superseded' {
|
|
518
|
+
return this.#disposed ? 'disposed' : 'superseded'
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
#recordJoinOutcome(generation: number, outcome: MulticastJoinOutcome): void {
|
|
522
|
+
if (generation <= this.#lastJoinOutcomeGeneration) return
|
|
523
|
+
this.#lastJoinOutcomeGeneration = generation
|
|
524
|
+
this.#lastJoinOutcome = outcome
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* One packet from the subscription: filter, count, and hand it to the
|
|
529
|
+
* callback. Returns whether it was delivered; the caller notes liveness.
|
|
530
|
+
*/
|
|
531
|
+
#deliver(detail: unknown): boolean {
|
|
532
|
+
const packet = normalizeBytesEventDetail(detail)
|
|
533
|
+
if (!packet) {
|
|
534
|
+
this.#stats.packetsDroppedUnparseable++
|
|
535
|
+
return false
|
|
536
|
+
}
|
|
537
|
+
if (!this.#acceptPacket(packet)) return false
|
|
538
|
+
// Read per packet: a callback that changes the admission (an in-place
|
|
539
|
+
// rendition switch committing on this very packet) takes effect from the
|
|
540
|
+
// next packet, including the rest of a batch.
|
|
541
|
+
this.#onPacket(packet, this.#context)
|
|
542
|
+
return true
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* One `packets` event. Each packet is delivered as a `bytes` event would
|
|
547
|
+
* have delivered it, including isolation: a packet whose callback throws
|
|
548
|
+
* does not cost the rest of its batch, as it would not have cost the next
|
|
549
|
+
* `bytes` event. The first failure is rethrown once the batch is done, so
|
|
550
|
+
* it reaches the event-listener error reporting a `bytes` listener's throw
|
|
551
|
+
* reached; any further one is rethrown from its own microtask, which the
|
|
552
|
+
* host reports the same way, so no failure is swallowed. A callback that
|
|
553
|
+
* disposes the transport or starts another join ends the batch there, as
|
|
554
|
+
* the per-packet guard would have ignored the remaining events.
|
|
555
|
+
*/
|
|
556
|
+
#deliverBatch(
|
|
557
|
+
batch: readonly unknown[],
|
|
558
|
+
live: () => boolean,
|
|
559
|
+
): void {
|
|
560
|
+
if (!Array.isArray(batch)) {
|
|
561
|
+
throw new TypeError('[MulticastTransport] packets event detail must be an array of packets')
|
|
562
|
+
}
|
|
563
|
+
let delivered = false
|
|
564
|
+
let failures: unknown[] | null = null
|
|
565
|
+
for (let i = 0; i < batch.length; i++) {
|
|
566
|
+
try {
|
|
567
|
+
if (this.#deliver(batch[i])) delivered = true
|
|
568
|
+
} catch (error) {
|
|
569
|
+
if (failures === null) failures = []
|
|
570
|
+
failures.push(error)
|
|
571
|
+
}
|
|
572
|
+
if (!live()) break
|
|
573
|
+
}
|
|
574
|
+
// One liveness read covers the batch: every packet in it arrived in the
|
|
575
|
+
// same provider task. A batch that delivered nothing, like a rejected
|
|
576
|
+
// bytes event, is not liveness.
|
|
577
|
+
if (delivered && live()) this.#resetWatchdog()
|
|
578
|
+
if (failures !== null) {
|
|
579
|
+
for (let i = 1; i < failures.length; i++) {
|
|
580
|
+
const failure = failures[i]
|
|
581
|
+
queueMicrotask(() => {
|
|
582
|
+
throw failure
|
|
583
|
+
})
|
|
584
|
+
}
|
|
585
|
+
throw failures[0]
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/** Feed a raw packet from an external source (e.g., AMT tunnel or ASM subscription). */
|
|
590
|
+
feedPacket(data: ArrayBuffer | Uint8Array, context?: TPacketContext): void {
|
|
591
|
+
if (this.#disposed) return
|
|
592
|
+
const packet = data instanceof Uint8Array ? data : new Uint8Array(data)
|
|
593
|
+
if (!this.#acceptPacket(packet)) return
|
|
594
|
+
this.#onPacket(packet, context)
|
|
595
|
+
this.#resetWatchdog()
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
confirmVideo(): void {
|
|
599
|
+
this.#videoConfirmed = true
|
|
600
|
+
this.#checkTakeover()
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
confirmAudio(): void {
|
|
604
|
+
this.#audioConfirmed = true
|
|
605
|
+
this.#checkTakeover()
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
onTakeover(cb: () => void): void {
|
|
609
|
+
this.#onTakeover = cb
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
onFailback(cb: (reason: MulticastFailbackReason) => void): void {
|
|
613
|
+
this.#onFailback = cb
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Called on every successful join, before the joined subscription can
|
|
618
|
+
* deliver a packet, with how that subscription delivers packets.
|
|
619
|
+
*/
|
|
620
|
+
onDelivery(cb: (delivery: WindowMulticastDelivery) => void): void {
|
|
621
|
+
this.#onDelivery = cb
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/** How the current subscription delivers packets, once joined. */
|
|
625
|
+
get delivery(): WindowMulticastDelivery | undefined {
|
|
626
|
+
return this.#delivery
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Fires once per join, at the first packet the join accepts (after the PID
|
|
631
|
+
* filter; a rejected packet is not liveness). This is the data-plane-live
|
|
632
|
+
* edge, where this transport's silence window starts. A join whose source
|
|
633
|
+
* never sends never reaches it, so a host may start a media-arrival budget
|
|
634
|
+
* here only if the provider bounds the join phase with a typed subscription
|
|
635
|
+
* error (see SessionManager.joinActive); otherwise the host starts it when
|
|
636
|
+
* the subscribe settles.
|
|
637
|
+
*/
|
|
638
|
+
onDataPlaneLive(cb: () => void): void {
|
|
639
|
+
this.#onDataPlaneLive = cb
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/** Whether the current join has accepted a packet (see onDataPlaneLive). */
|
|
643
|
+
get dataPlaneLive(): boolean {
|
|
644
|
+
return this.#dataPlaneLive
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
setFailbackWindowMs(windowMs: number): void {
|
|
648
|
+
if (!Number.isFinite(windowMs) || windowMs <= 0) {
|
|
649
|
+
throw new Error(
|
|
650
|
+
`[MulticastTransport] failbackWindowMs=${windowMs}. ` +
|
|
651
|
+
`Derive a positive failback window from the stream catalog.`,
|
|
652
|
+
)
|
|
653
|
+
}
|
|
654
|
+
this.#failbackWindowMs = windowMs
|
|
655
|
+
// An armed timer was scheduled against the previous window; re-derive its
|
|
656
|
+
// wake-up from the last packet so a narrower window is not enforced late.
|
|
657
|
+
if (this.#watchdog !== null) {
|
|
658
|
+
clearTimeout(this.#watchdog)
|
|
659
|
+
const silentMs = performance.now() - this.#lastPacketAtMs
|
|
660
|
+
this.#armWatchdog(Math.max(0, Math.ceil(windowMs - silentMs)))
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
get stats(): MulticastTransportStats {
|
|
665
|
+
return this.#stats
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* How the newest join() to resolve did: `{ ok: true }`, or `{ ok: false }`
|
|
670
|
+
* with the typed reason it resolved false (and, for `provider-rejected`, the
|
|
671
|
+
* provider's typed error fields). Undefined until a join resolves. Branch on
|
|
672
|
+
* `reason` and `providerError.code`, never on log text or
|
|
673
|
+
* `providerError.message`.
|
|
674
|
+
*
|
|
675
|
+
* Newest is by start order: a join that resolves after a newer join has
|
|
676
|
+
* recorded its outcome does not replace it, so once `await join()` resolves
|
|
677
|
+
* this names that join's outcome unless a newer join has already resolved.
|
|
678
|
+
* It records how a join resolved, not whether it is still joined (see
|
|
679
|
+
* `joined`); a join() that rejects instead of resolving records nothing,
|
|
680
|
+
* the rejection being its report. Frozen: a later outcome replaces the
|
|
681
|
+
* object, never changes it.
|
|
682
|
+
*/
|
|
683
|
+
get lastJoinOutcome(): MulticastJoinOutcome | undefined {
|
|
684
|
+
return this.#lastJoinOutcome
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* join() calls by how they resolved (see MulticastJoinStats). A fresh frozen
|
|
689
|
+
* snapshot on every read, so a later join never changes one already read.
|
|
690
|
+
* Kept apart from `stats`, which is the live counter object.
|
|
691
|
+
*/
|
|
692
|
+
get joinStats(): MulticastJoinStats {
|
|
693
|
+
return Object.freeze({
|
|
694
|
+
succeeded: this.#joinsSucceeded,
|
|
695
|
+
declined: Object.freeze({ ...this.#joinsDeclined }),
|
|
696
|
+
})
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Accepted bytes summed over `packetIds`: the `bytesReceived` share of those
|
|
701
|
+
* MMTP packet_ids. Counted by the same rule, on every path that counts
|
|
702
|
+
* `bytesReceived` (only packets that pass the ingress filter; packet_id 0
|
|
703
|
+
* signaling never), and cumulative for the life of the transport, across
|
|
704
|
+
* rejoins, as `bytesReceived` is. An id never accepted contributes 0. An
|
|
705
|
+
* unparseable packet admitted by a join without an allow-list has no
|
|
706
|
+
* packet_id, so it counts toward `bytesReceived` only.
|
|
707
|
+
*
|
|
708
|
+
* Use it to scope an ABR throughput sample to the active tier's source and
|
|
709
|
+
* repair packet_ids when the join admits more than the active tier (a
|
|
710
|
+
* shared group joined across rendition switches); `bytesReceived` is then
|
|
711
|
+
* the whole allow-list's arrival, not the active tier's. A Set, so an id
|
|
712
|
+
* shared by two tracks of the tier is counted once.
|
|
713
|
+
*
|
|
714
|
+
* Monotonic only for a fixed set: each id has counted since it was first
|
|
715
|
+
* admitted, so after a tier switch the new set's sum is not a continuation
|
|
716
|
+
* of the old one. A cumulative consumer takes a fresh baseline for the new
|
|
717
|
+
* set and never differences across sets.
|
|
718
|
+
*/
|
|
719
|
+
bytesReceivedForPacketIds(packetIds: ReadonlySet<number>): number {
|
|
720
|
+
let bytes = 0
|
|
721
|
+
for (const packetId of packetIds) {
|
|
722
|
+
bytes += this.#acceptedBytesByPacketId.get(packetId)?.bytes ?? 0
|
|
723
|
+
}
|
|
724
|
+
return bytes
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Per-PID drop breakdown, newest-capped at MAX_TRACKED_DROPPED_PIDS distinct
|
|
729
|
+
* PIDs. This is what names the offender: `packetsDroppedUnregisteredPid`
|
|
730
|
+
* says the ingress filter fired, this says it fired on 0x8001.
|
|
731
|
+
*/
|
|
732
|
+
get droppedPacketIds(): ReadonlyMap<number, number> {
|
|
733
|
+
return this.#droppedPidCounts
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Distinct packet IDs dropped as provisioning faults: arriving on the wire
|
|
738
|
+
* but in no allow-list the join or an in-place update (setPacketIds)
|
|
739
|
+
* declared, the drops that raise the unadvertised-PID warning. A packet ID
|
|
740
|
+
* an in-place update withdrew is not one (see withdrawnPacketIdDrops).
|
|
741
|
+
* Cumulative across rejoins and capped with droppedPacketIds.
|
|
742
|
+
*/
|
|
743
|
+
get unadvertisedPacketIds(): ReadonlySet<number> {
|
|
744
|
+
return this.#unadvertisedPacketIds
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Packets dropped because an in-place update (setPacketIds) withdrew their
|
|
749
|
+
* packet ID while the provider may still deliver it: the expected tail of
|
|
750
|
+
* a deliberate change. A subset of packetsDroppedUnregisteredPid,
|
|
751
|
+
* cumulative across rejoins.
|
|
752
|
+
*/
|
|
753
|
+
get withdrawnPacketIdDrops(): number {
|
|
754
|
+
return this.#withdrawnPacketIdDrops
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/** Whether a subscription is live: joined, and not yet released or replaced. */
|
|
758
|
+
get joined(): boolean {
|
|
759
|
+
return this.#subscription !== null
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* What the live join delivers with every accepted packet (the join's
|
|
764
|
+
* `context`, or the last setContext), or undefined without a live join.
|
|
765
|
+
*/
|
|
766
|
+
get context(): TPacketContext | undefined {
|
|
767
|
+
return this.#context
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* The live join's page-side packet-ID allow-list, or null when it admits
|
|
772
|
+
* every packet ID (a join that carried none, or no live join).
|
|
773
|
+
*/
|
|
774
|
+
get packetIds(): ReadonlySet<number> | null {
|
|
775
|
+
return this.#packetIds
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Replace what the live join delivers with each accepted packet, from the
|
|
780
|
+
* next packet on. The subscription (socket, group membership, AMT tunnel)
|
|
781
|
+
* is untouched: this is how an in-place rendition switch moves the router's
|
|
782
|
+
* ingress identities without leaving and re-joining the group.
|
|
783
|
+
*/
|
|
784
|
+
setContext(context: TPacketContext): void {
|
|
785
|
+
if (this.#subscription === null) {
|
|
786
|
+
throw new Error(
|
|
787
|
+
'[MulticastTransport] setContext needs a live join; join() carries the first context',
|
|
788
|
+
)
|
|
789
|
+
}
|
|
790
|
+
this.#context = context
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* Replace the live join's packet-ID allow-list in place, without rejoining.
|
|
795
|
+
*
|
|
796
|
+
* The page-side filter changes synchronously, before this returns: the
|
|
797
|
+
* next packet is admitted or dropped by the new list. The provider's own
|
|
798
|
+
* filter is updated through the subscription's `setPacketIds` when it has
|
|
799
|
+
* one; the returned promise settles with the provider's acknowledgement of
|
|
800
|
+
* this update. It resolves at once, telling the provider nothing, only
|
|
801
|
+
* when the provider cannot be told, or when no earlier update is still in
|
|
802
|
+
* flight and the provider already forwards exactly this list.
|
|
803
|
+
*
|
|
804
|
+
* While an update is in flight the provider's filter is not known, so every
|
|
805
|
+
* later update is sent: one skipped because it matched the last
|
|
806
|
+
* acknowledged filter would let the in-flight update land after it, and
|
|
807
|
+
* leave the provider forwarding a list nobody asked for last. Updates are
|
|
808
|
+
* numbered in send order and the newest acknowledged one describes the
|
|
809
|
+
* provider, so an acknowledgement that overtakes an older one is not undone
|
|
810
|
+
* by it.
|
|
811
|
+
*
|
|
812
|
+
* A provider without `setPacketIds` can still be narrowed: its wider filter
|
|
813
|
+
* keeps delivering the dropped IDs and the page-side filter discards them.
|
|
814
|
+
* It cannot be widened, since it would never deliver the added IDs; that is
|
|
815
|
+
* refused with a throw before anything changes. An ID this update withdraws
|
|
816
|
+
* may keep arriving until the provider applies the narrower list; those
|
|
817
|
+
* packets are counted as filtered like any other and in
|
|
818
|
+
* withdrawnPacketIdDrops, but are not unadvertised packet IDs: their
|
|
819
|
+
* arrival is the expected tail of this change rather than a provisioning
|
|
820
|
+
* fault.
|
|
821
|
+
*/
|
|
822
|
+
setPacketIds(packetIds: readonly number[]): Promise<void> {
|
|
823
|
+
const subscription = this.#subscription
|
|
824
|
+
const filter = this.#providerFilter
|
|
825
|
+
if (subscription === null || filter === null) {
|
|
826
|
+
throw new Error(
|
|
827
|
+
'[MulticastTransport] setPacketIds needs a live join; join() carries the first allow-list',
|
|
828
|
+
)
|
|
829
|
+
}
|
|
830
|
+
if (!Array.isArray(packetIds) || packetIds.length === 0) {
|
|
831
|
+
throw new RangeError(
|
|
832
|
+
'[MulticastTransport] setPacketIds needs a non-empty packet-ID list: ' +
|
|
833
|
+
'an in-place update names the packet IDs it admits',
|
|
834
|
+
)
|
|
835
|
+
}
|
|
836
|
+
if (!packetIds.every(isMulticastTrackPacketId)) {
|
|
837
|
+
throw new RangeError(
|
|
838
|
+
`[MulticastTransport] packetId must be an integer from 1 to ${MMTP_PACKET_ID_MAX}; ` +
|
|
839
|
+
"packetId 0 is the MMTP signaling flow and is never a track's",
|
|
840
|
+
)
|
|
841
|
+
}
|
|
842
|
+
const next: ReadonlySet<number> = new Set(packetIds)
|
|
843
|
+
const provider = filter.acknowledged
|
|
844
|
+
const update = packetFilterUpdater(subscription)
|
|
845
|
+
// Without an updater nothing is ever sent, so the join's filter is exact.
|
|
846
|
+
if (update === undefined && provider !== null) {
|
|
847
|
+
const missing = [...next].filter((id) => !provider.has(id))
|
|
848
|
+
if (missing.length > 0) {
|
|
849
|
+
throw new Error(
|
|
850
|
+
'[MulticastTransport] this subscription cannot widen its packet filter in place ' +
|
|
851
|
+
`(the provider exposes no setPacketIds); rejoin to admit ${missing.join(', ')}`,
|
|
852
|
+
)
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
const previous = this.#packetIds
|
|
856
|
+
this.#packetIds = next
|
|
857
|
+
for (const id of next) {
|
|
858
|
+
this.#withdrawnPacketIds.delete(id)
|
|
859
|
+
if (!this.#acceptedBytesByPacketId.has(id)) {
|
|
860
|
+
this.#acceptedBytesByPacketId.set(id, { bytes: 0 })
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
if (previous !== null) {
|
|
864
|
+
for (const id of previous) if (!next.has(id)) this.#withdrawnPacketIds.add(id)
|
|
865
|
+
}
|
|
866
|
+
if (update === undefined) return Promise.resolve()
|
|
867
|
+
if (filter.inFlight === 0 && provider !== null && sameIds(provider, next)) {
|
|
868
|
+
return Promise.resolve()
|
|
869
|
+
}
|
|
870
|
+
const number = ++filter.sent
|
|
871
|
+
filter.inFlight++
|
|
872
|
+
let applied: Promise<void>
|
|
873
|
+
try {
|
|
874
|
+
applied = Promise.resolve(update([...next]))
|
|
875
|
+
} catch (error) {
|
|
876
|
+
applied = Promise.reject(error)
|
|
877
|
+
}
|
|
878
|
+
return applied.then(
|
|
879
|
+
() => {
|
|
880
|
+
if (this.#providerFilter !== filter) return
|
|
881
|
+
filter.inFlight--
|
|
882
|
+
if (number > filter.acknowledgedUpdate) {
|
|
883
|
+
filter.acknowledgedUpdate = number
|
|
884
|
+
filter.acknowledged = next
|
|
885
|
+
}
|
|
886
|
+
},
|
|
887
|
+
(error: unknown) => {
|
|
888
|
+
// A refused update leaves the provider on the filter it had.
|
|
889
|
+
if (this.#providerFilter === filter) filter.inFlight--
|
|
890
|
+
throw error
|
|
891
|
+
},
|
|
892
|
+
)
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
get resolvedTransport(): ResolvedMulticastTransport | undefined {
|
|
896
|
+
return this.#resolvedTransport
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
dispose(): void {
|
|
900
|
+
++this.#joinGeneration
|
|
901
|
+
this.#disposed = true
|
|
902
|
+
this.#releaseSubscription()
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
#releaseSubscription(): void {
|
|
906
|
+
if (this.#watchdog) clearTimeout(this.#watchdog)
|
|
907
|
+
this.#watchdog = null
|
|
908
|
+
if (this.#subscription) {
|
|
909
|
+
const packetListener = this.#packetListener
|
|
910
|
+
if (packetListener?.type === 'packets') {
|
|
911
|
+
this.#subscription.removeEventListener('packets', packetListener.listener)
|
|
912
|
+
} else if (packetListener) {
|
|
913
|
+
this.#subscription.removeEventListener('bytes', packetListener.listener)
|
|
914
|
+
}
|
|
915
|
+
if (this.#errorListener) {
|
|
916
|
+
this.#subscription.removeEventListener('error', this.#errorListener)
|
|
917
|
+
}
|
|
918
|
+
void this.#subscription.unsubscribe()
|
|
919
|
+
}
|
|
920
|
+
this.#subscription = null
|
|
921
|
+
this.#packetListener = null
|
|
922
|
+
this.#errorListener = null
|
|
923
|
+
this.#resolvedTransport = undefined
|
|
924
|
+
this.#delivery = undefined
|
|
925
|
+
this.#packetIds = null
|
|
926
|
+
this.#providerFilter = null
|
|
927
|
+
this.#context = undefined
|
|
928
|
+
this.#withdrawnPacketIds.clear()
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/** The ingress filter; an accepted packet is counted here, once. */
|
|
932
|
+
#acceptPacket(packet: Uint8Array): boolean {
|
|
933
|
+
// This early read is intentional: rejected PIDs must not affect page
|
|
934
|
+
// delivery, receive statistics, or the failback liveness watchdog. It
|
|
935
|
+
// refuses exactly what parseMMTPHeader refuses but builds no header
|
|
936
|
+
// object; the router parses the header once, later (BLO-36599).
|
|
937
|
+
const packetId = readMMTPPacketId(packet)
|
|
938
|
+
if (packetId === null) {
|
|
939
|
+
// Without an allow-list there is no filter to enforce, so an unparseable
|
|
940
|
+
// packet keeps flowing to the router as before.
|
|
941
|
+
if (!this.#packetIds) {
|
|
942
|
+
this.#countAccepted(packet, null)
|
|
943
|
+
return true
|
|
944
|
+
}
|
|
945
|
+
this.#stats.packetsDroppedUnparseable++
|
|
946
|
+
return false
|
|
947
|
+
}
|
|
948
|
+
// packet_id 0 is the MMTP signaling flow and never a track's. Drop it even
|
|
949
|
+
// when the join carried no allow-list (a legacy catalog whose tracks omit
|
|
950
|
+
// packetId): the discard rule must not depend on how the catalog was written.
|
|
951
|
+
if (packetId === MMTP_SIGNALING_PACKET_ID) {
|
|
952
|
+
this.#stats.packetsDroppedSignaling++
|
|
953
|
+
return false
|
|
954
|
+
}
|
|
955
|
+
if (!this.#packetIds || this.#packetIds.has(packetId)) {
|
|
956
|
+
this.#countAccepted(packet, packetId)
|
|
957
|
+
return true
|
|
958
|
+
}
|
|
959
|
+
this.#recordUnregisteredPidDrop(packetId)
|
|
960
|
+
return false
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
/** Receive counters for one accepted packet; `packetId` is null when it has none. */
|
|
964
|
+
#countAccepted(packet: Uint8Array, packetId: number | null): void {
|
|
965
|
+
this.#stats.packetsReceived++
|
|
966
|
+
this.#stats.bytesReceived += packet.byteLength
|
|
967
|
+
if (packetId === null) return
|
|
968
|
+
const counter = this.#acceptedBytesByPacketId.get(packetId)
|
|
969
|
+
if (counter !== undefined) {
|
|
970
|
+
counter.bytes += packet.byteLength
|
|
971
|
+
} else {
|
|
972
|
+
// First sight of this id on a join with no allow-list (an allow-list's
|
|
973
|
+
// ids are seeded at join). Bounded by the 16-bit packet_id space.
|
|
974
|
+
this.#acceptedBytesByPacketId.set(packetId, { bytes: packet.byteLength })
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
#recordUnregisteredPidDrop(packetId: number): void {
|
|
979
|
+
this.#stats.packetsDroppedUnregisteredPid++
|
|
980
|
+
const withdrawn = this.#withdrawnPacketIds.has(packetId)
|
|
981
|
+
if (withdrawn) this.#withdrawnPacketIdDrops++
|
|
982
|
+
const seen = this.#droppedPidCounts.get(packetId)
|
|
983
|
+
if (seen !== undefined) {
|
|
984
|
+
this.#droppedPidCounts.set(packetId, seen + 1)
|
|
985
|
+
return
|
|
986
|
+
}
|
|
987
|
+
if (this.#droppedPidCounts.size >= MAX_TRACKED_DROPPED_PIDS) return
|
|
988
|
+
this.#droppedPidCounts.set(packetId, 1)
|
|
989
|
+
if (withdrawn) return
|
|
990
|
+
this.#unadvertisedPacketIds.add(packetId)
|
|
991
|
+
// Warn once per distinct PID. A PID arriving on the wire but missing from
|
|
992
|
+
// the catalog's advertised set is a provisioning fault, not stream noise,
|
|
993
|
+
// and it is silent in every downstream counter.
|
|
994
|
+
console.warn(
|
|
995
|
+
`[MulticastTransport] Dropping packetId=${packetId} (0x${packetId.toString(16)}): ` +
|
|
996
|
+
`not in the advertised set [${[...(this.#packetIds ?? [])].join(', ')}]. ` +
|
|
997
|
+
`If this is an FEC repair leg, the catalog is not advertising its packetId.`,
|
|
998
|
+
)
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
#checkTakeover(): void {
|
|
1002
|
+
if (this.#videoConfirmed && this.#audioConfirmed && this.#onTakeover) {
|
|
1003
|
+
const cb = this.#onTakeover
|
|
1004
|
+
this.#onTakeover = null // fire exactly once
|
|
1005
|
+
cb()
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
/**
|
|
1010
|
+
* Note liveness now; arm the no-packets timer if none is armed.
|
|
1011
|
+
*
|
|
1012
|
+
* Called only for accepted packets, so the first call of a join is the
|
|
1013
|
+
* data-plane-live edge and is what first arms the silence window: the window
|
|
1014
|
+
* measures silence of a flowing stream, which is undefined before the stream
|
|
1015
|
+
* has flowed.
|
|
1016
|
+
*/
|
|
1017
|
+
#resetWatchdog(): void {
|
|
1018
|
+
this.#lastPacketAtMs = performance.now()
|
|
1019
|
+
if (!this.#dataPlaneLive) {
|
|
1020
|
+
this.#dataPlaneLive = true
|
|
1021
|
+
this.#onDataPlaneLive?.()
|
|
1022
|
+
}
|
|
1023
|
+
if (this.#watchdog !== null) return
|
|
1024
|
+
if (!this.#onFailback) return
|
|
1025
|
+
if (this.#failbackWindowMs === null) {
|
|
1026
|
+
throw new Error(
|
|
1027
|
+
'[MulticastTransport] Failback watchdog requires a catalog-derived window',
|
|
1028
|
+
)
|
|
1029
|
+
}
|
|
1030
|
+
this.#armWatchdog(this.#failbackWindowMs)
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
#armWatchdog(delayMs: number): void {
|
|
1034
|
+
this.#watchdog = setTimeout(() => {
|
|
1035
|
+
this.#watchdog = null
|
|
1036
|
+
if (this.#disposed || !this.#onFailback || this.#failbackWindowMs === null) return
|
|
1037
|
+
const silentMs = performance.now() - this.#lastPacketAtMs
|
|
1038
|
+
if (silentMs < this.#failbackWindowMs) {
|
|
1039
|
+
this.#armWatchdog(Math.ceil(this.#failbackWindowMs - silentMs))
|
|
1040
|
+
return
|
|
1041
|
+
}
|
|
1042
|
+
console.warn(
|
|
1043
|
+
`[MulticastTransport] No packets for ${this.#failbackWindowMs}ms; failing back to MoQ`,
|
|
1044
|
+
)
|
|
1045
|
+
this.#onFailback({ kind: 'silence', windowMs: this.#failbackWindowMs })
|
|
1046
|
+
}, delayMs)
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/** Hand control back to MoQ for a provider-reported subscription failure. */
|
|
1050
|
+
#failBackOnSubscriptionError(error: unknown): void {
|
|
1051
|
+
// The subscription is dead; a silence timer armed against it would only
|
|
1052
|
+
// report the same failure a second time.
|
|
1053
|
+
if (this.#watchdog !== null) clearTimeout(this.#watchdog)
|
|
1054
|
+
this.#watchdog = null
|
|
1055
|
+
console.warn('[MulticastTransport] Subscription failed; failing back to MoQ:', error)
|
|
1056
|
+
this.#onFailback?.({ kind: 'subscription-error', error })
|
|
1057
|
+
}
|
|
1058
|
+
}
|