@blockcast/mmt-container 0.1.0-main.0399efef1f07
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 +432 -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 +93 -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/browser-runtime.js +20087 -0
- package/dist/browser-runtime.js.map +7 -0
- package/dist/carp-catalog.d.ts +318 -0
- package/dist/carp-catalog.d.ts.map +1 -0
- package/dist/carp-catalog.js +873 -0
- package/dist/carp-catalog.js.map +7 -0
- package/dist/catalog-fec-params.d.ts +202 -0
- package/dist/catalog-fec-params.d.ts.map +1 -0
- package/dist/catalog-fec-params.js +568 -0
- package/dist/catalog-fec-params.js.map +7 -0
- package/dist/catalog-network-source.d.ts +19 -0
- package/dist/catalog-network-source.d.ts.map +1 -0
- package/dist/catalog-network-source.js +22 -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 +217 -0
- package/dist/cmaf-block-assembler.d.ts.map +1 -0
- package/dist/cmaf-block-assembler.js +1769 -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 +195 -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 +207 -0
- package/dist/cmcd-producer.js.map +7 -0
- package/dist/codec-utils.d.ts +248 -0
- package/dist/codec-utils.d.ts.map +1 -0
- package/dist/codec-utils.js +1268 -0
- package/dist/codec-utils.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 +307 -0
- package/dist/fec-manager.d.ts.map +1 -0
- package/dist/fec-manager.js +1530 -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 +75 -0
- package/dist/fec-starvation-detector.js.map +7 -0
- package/dist/fec-worker-setup.d.ts +88 -0
- package/dist/fec-worker-setup.d.ts.map +1 -0
- package/dist/fec-worker-setup.js +614 -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 +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +380 -0
- package/dist/index.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 +618 -0
- package/dist/iso-bmff-timing.js.map +7 -0
- package/dist/loc.d.ts +68 -0
- package/dist/loc.d.ts.map +1 -0
- package/dist/loc.js +143 -0
- package/dist/loc.js.map +7 -0
- 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 +1285 -0
- package/dist/manifest-auth-plan.js.map +7 -0
- package/dist/media-router.d.ts +251 -0
- package/dist/media-router.d.ts.map +1 -0
- package/dist/media-router.js +624 -0
- package/dist/media-router.js.map +7 -0
- package/dist/mfu-reassembler.d.ts +396 -0
- package/dist/mfu-reassembler.d.ts.map +1 -0
- package/dist/mfu-reassembler.js +3085 -0
- package/dist/mfu-reassembler.js.map +7 -0
- 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 +434 -0
- package/dist/mmtp-container-parser.d.ts.map +1 -0
- package/dist/mmtp-container-parser.js +6164 -0
- package/dist/mmtp-container-parser.js.map +7 -0
- package/dist/mmtp-container-parser.no-modules.js +8999 -0
- package/dist/mmtp-container-parser.no-modules.js.map +7 -0
- package/dist/mmtp-decode-pipeline.d.ts +132 -0
- package/dist/mmtp-decode-pipeline.d.ts.map +1 -0
- package/dist/mmtp-decode-pipeline.js +6413 -0
- package/dist/mmtp-decode-pipeline.js.map +7 -0
- package/dist/mmtp-router.d.ts +390 -0
- package/dist/mmtp-router.d.ts.map +1 -0
- package/dist/mmtp-router.js +9242 -0
- package/dist/mmtp-router.js.map +7 -0
- package/dist/mmtp-to-cmaf.d.ts +181 -0
- package/dist/mmtp-to-cmaf.d.ts.map +1 -0
- package/dist/mmtp-to-cmaf.js +802 -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 +107 -0
- package/dist/multicast-input.d.ts.map +1 -0
- package/dist/multicast-input.js +256 -0
- package/dist/multicast-input.js.map +7 -0
- package/dist/multicast-manager.d.ts +369 -0
- package/dist/multicast-manager.d.ts.map +1 -0
- package/dist/multicast-manager.js +13400 -0
- package/dist/multicast-manager.js.map +7 -0
- package/dist/multicast-transport.d.ts +61 -0
- package/dist/multicast-transport.d.ts.map +1 -0
- package/dist/multicast-transport.js +1665 -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 +384 -0
- package/dist/multicast-unwrap.js.map +7 -0
- package/dist/no-modules.d.ts +9 -0
- package/dist/no-modules.d.ts.map +1 -0
- package/dist/no-modules.js +8965 -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 +58 -0
- package/dist/repair-fetch.d.ts.map +1 -0
- package/dist/repair-fetch.js +127 -0
- package/dist/repair-fetch.js.map +7 -0
- package/dist/repair-layers.d.ts +141 -0
- package/dist/repair-layers.d.ts.map +1 -0
- package/dist/repair-layers.js +303 -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 +616 -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 +232 -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 +1238 -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 +85 -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 +456 -0
- package/dist/timestamp-codec.js.map +7 -0
- package/dist/track-pipeline-setup.d.ts +72 -0
- package/dist/track-pipeline-setup.d.ts.map +1 -0
- package/dist/track-pipeline-setup.js +306 -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 +229 -0
- package/dist/track-pipeline.js.map +7 -0
- package/dist/track-session.d.ts +398 -0
- package/dist/track-session.d.ts.map +1 -0
- package/dist/track-session.js +767 -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 +88 -0
- package/dist/transport-pool.js.map +7 -0
- package/dist/wasm-mfu-reassembler.d.ts +92 -0
- package/dist/wasm-mfu-reassembler.d.ts.map +1 -0
- package/dist/wasm-mfu-reassembler.js +2139 -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 +6418 -0
- package/dist/wasm-mmtp-container-parser.js.map +7 -0
- package/node_modules/@blockcast/fec-worker/README.md +213 -0
- package/node_modules/@blockcast/fec-worker/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts +87 -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 +279 -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 +252 -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 +565 -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 +349 -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 +179 -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 +47 -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/fec-worker-client.ts +319 -0
- package/node_modules/@blockcast/fec-worker/src/fec-worker-types.ts +268 -0
- package/node_modules/@blockcast/fec-worker/src/fec-worker.ts +1048 -0
- package/node_modules/@blockcast/fec-worker/src/index.ts +32 -0
- package/node_modules/@blockcast/fec-worker/src/shred-fec-worker.ts +558 -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 +194 -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 +120 -0
- package/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-base/dist/index.d.ts +2 -0
- package/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/index.js +2 -0
- package/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +276 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.js +645 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/package.json +49 -0
- package/node_modules/@blockcast/mmt-base/src/index.ts +1 -0
- package/node_modules/@blockcast/mmt-base/src/mmtp.ts +899 -0
- package/node_modules/@blockcast/mmt-fec/README.md +270 -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 +72 -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 +192 -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 +185 -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 +273 -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 +22 -0
- package/node_modules/@blockcast/mmt-fec/dist/index.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/index.js +22 -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 +172 -0
- package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/oti.js +254 -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/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 +120 -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/index.d.ts +2 -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 +2 -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 +276 -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 +645 -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/package.json +49 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/index.ts +1 -0
- package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/mmtp.ts +899 -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 +277 -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 +332 -0
- package/node_modules/@blockcast/mmt-fec/src/index.ts +77 -0
- package/node_modules/@blockcast/mmt-fec/src/loc-symbols.ts +34 -0
- package/node_modules/@blockcast/mmt-fec/src/oti.ts +317 -0
- package/node_modules/@blockcast/mmt-fec/src/reorder-buffer.ts +101 -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 +203 -0
- package/schemas/catalog.schema.json +360 -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/carp-catalog.ts +845 -0
- package/src/catalog-fec-params.ts +535 -0
- package/src/catalog-network-source.ts +49 -0
- package/src/catalog-validator.ts +34 -0
- package/src/cmaf-block-assembler.ts +1167 -0
- package/src/cmaf-group-batcher.ts +104 -0
- package/src/cmcd-producer.ts +334 -0
- package/src/codec-utils.ts +1611 -0
- package/src/fec-codec.ts +61 -0
- package/src/fec-manager.ts +2081 -0
- package/src/fec-starvation-detector.ts +128 -0
- package/src/fec-worker-setup.ts +213 -0
- package/src/fmp4-completion.ts +47 -0
- package/src/fmp4-reader.ts +112 -0
- package/src/index.ts +486 -0
- package/src/iso-bmff-timing.ts +813 -0
- package/src/loc.ts +181 -0
- package/src/manifest-auth-plan.ts +107 -0
- package/src/media-router.ts +795 -0
- package/src/mfu-reassembler.ts +3741 -0
- package/src/mfu-reassembly-policy.ts +134 -0
- package/src/mmtp-container-parser.ts +1836 -0
- package/src/mmtp-decode-pipeline.ts +389 -0
- package/src/mmtp-router.ts +3136 -0
- package/src/mmtp-to-cmaf.ts +1024 -0
- package/src/multicast-auth-catalog.ts +340 -0
- package/src/multicast-input.ts +439 -0
- package/src/multicast-manager.ts +1720 -0
- package/src/multicast-transport.ts +321 -0
- package/src/multicast-unwrap.ts +132 -0
- package/src/no-modules.ts +20 -0
- package/src/phase14-catalog-override.ts +336 -0
- package/src/repair-fetch.ts +238 -0
- package/src/repair-layers.ts +490 -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 +189 -0
- package/src/track-pipeline.ts +332 -0
- package/src/track-session.ts +994 -0
- package/src/transport-pool.ts +128 -0
- package/src/wasm-mfu-reassembler.ts +389 -0
- package/src/wasm-mmtp-container-parser.ts +23 -0
- package/test-vectors/align.json +199 -0
- package/test-vectors/catalog/README.md +40 -0
- package/test-vectors/catalog/negative/fec-enhancement-repair-removed.json +27 -0
- package/test-vectors/catalog/negative/fec-repair-layer-geometry.json +32 -0
- package/test-vectors/catalog/negative/fec-repair-layer-missing-symbols.json +30 -0
- package/test-vectors/catalog/negative/fec-repair-multiple-depends.json +31 -0
- package/test-vectors/catalog/negative/fec-repair-overlay-with-layer.json +33 -0
- package/test-vectors/catalog/negative/fec-repair-priority-out-of-band.json +23 -0
- package/test-vectors/catalog/negative/fec-repair-source-symbols-without-scope.json +32 -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/network-source-object.json +25 -0
- package/test-vectors/catalog/negative/raptorq-source-symbols-over-max.json +23 -0
- package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +26 -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/fec-layered-repair.json +104 -0
- package/test-vectors/catalog/positive/fec-multicast.json +51 -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/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 +148 -0
- package/test-vectors/catalog-validator-public-api.mjs +25 -0
- package/test-vectors/generate-source-auth-fixture.mjs +114 -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
|
@@ -0,0 +1,813 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strict ISO-BMFF timing extraction for the timed-MFU browser path.
|
|
3
|
+
*
|
|
4
|
+
* This intentionally implements only the current single-track MMT profile:
|
|
5
|
+
* one media track in FT=0, and one matching traf/trun in each FT=1. It does
|
|
6
|
+
* not infer timing from packet arrival, MMTP send timestamps, or cadence.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const U64_MAX = 0xffff_ffff_ffff_ffffn
|
|
10
|
+
const I64_MIN = -0x8000_0000_0000_0000n
|
|
11
|
+
const I64_MAX = 0x7fff_ffff_ffff_ffffn
|
|
12
|
+
const MICROSECONDS_PER_SECOND = 1_000_000n
|
|
13
|
+
|
|
14
|
+
const TFHD_BASE_DATA_OFFSET_PRESENT = 0x000001
|
|
15
|
+
const TFHD_SAMPLE_DESCRIPTION_INDEX_PRESENT = 0x000002
|
|
16
|
+
const TFHD_DEFAULT_SAMPLE_DURATION_PRESENT = 0x000008
|
|
17
|
+
const TFHD_DEFAULT_SAMPLE_SIZE_PRESENT = 0x000010
|
|
18
|
+
const TFHD_DEFAULT_SAMPLE_FLAGS_PRESENT = 0x000020
|
|
19
|
+
const TFHD_DURATION_IS_EMPTY = 0x010000
|
|
20
|
+
const TFHD_DEFAULT_BASE_IS_MOOF = 0x020000
|
|
21
|
+
const TFHD_KNOWN_FLAGS =
|
|
22
|
+
TFHD_BASE_DATA_OFFSET_PRESENT |
|
|
23
|
+
TFHD_SAMPLE_DESCRIPTION_INDEX_PRESENT |
|
|
24
|
+
TFHD_DEFAULT_SAMPLE_DURATION_PRESENT |
|
|
25
|
+
TFHD_DEFAULT_SAMPLE_SIZE_PRESENT |
|
|
26
|
+
TFHD_DEFAULT_SAMPLE_FLAGS_PRESENT |
|
|
27
|
+
TFHD_DURATION_IS_EMPTY |
|
|
28
|
+
TFHD_DEFAULT_BASE_IS_MOOF
|
|
29
|
+
|
|
30
|
+
const TRUN_DATA_OFFSET_PRESENT = 0x000001
|
|
31
|
+
const TRUN_FIRST_SAMPLE_FLAGS_PRESENT = 0x000004
|
|
32
|
+
const TRUN_SAMPLE_DURATION_PRESENT = 0x000100
|
|
33
|
+
const TRUN_SAMPLE_SIZE_PRESENT = 0x000200
|
|
34
|
+
const TRUN_SAMPLE_FLAGS_PRESENT = 0x000400
|
|
35
|
+
const TRUN_SAMPLE_CTS_OFFSET_PRESENT = 0x000800
|
|
36
|
+
const TRUN_KNOWN_FLAGS =
|
|
37
|
+
TRUN_DATA_OFFSET_PRESENT |
|
|
38
|
+
TRUN_FIRST_SAMPLE_FLAGS_PRESENT |
|
|
39
|
+
TRUN_SAMPLE_DURATION_PRESENT |
|
|
40
|
+
TRUN_SAMPLE_SIZE_PRESENT |
|
|
41
|
+
TRUN_SAMPLE_FLAGS_PRESENT |
|
|
42
|
+
TRUN_SAMPLE_CTS_OFFSET_PRESENT
|
|
43
|
+
|
|
44
|
+
export interface IsoBmffTrackTiming {
|
|
45
|
+
trackId: number
|
|
46
|
+
timescale: number
|
|
47
|
+
defaultSampleDuration?: number
|
|
48
|
+
defaultSampleSize?: number
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface IsoBmffSampleTiming {
|
|
52
|
+
/** Exact decode time in mdhd timescale units. */
|
|
53
|
+
decodeTime: bigint
|
|
54
|
+
/** Exact presentation time in mdhd timescale units, including signed CTS. */
|
|
55
|
+
presentationTime: bigint
|
|
56
|
+
/** Exact authored duration in mdhd timescale units. */
|
|
57
|
+
duration: number
|
|
58
|
+
timescale: number
|
|
59
|
+
/** Exact elementary-stream sample size declared by trun/tfhd/trex. */
|
|
60
|
+
size: number
|
|
61
|
+
/** Byte position of the sample relative to the beginning of the moof. */
|
|
62
|
+
bytePosition: bigint
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface IsoBmffMovieFragmentTiming {
|
|
66
|
+
movieFragmentSequenceNumber: number
|
|
67
|
+
samples: readonly IsoBmffSampleTiming[]
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type IsoBmffMovieFragmentRejection = 'invalid' | 'budget'
|
|
71
|
+
|
|
72
|
+
interface IsoBox {
|
|
73
|
+
type: string
|
|
74
|
+
start: number
|
|
75
|
+
bodyStart: number
|
|
76
|
+
end: number
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
interface FullBox {
|
|
80
|
+
version: number
|
|
81
|
+
flags: number
|
|
82
|
+
bodyStart: number
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface ParsedTrack {
|
|
86
|
+
trackId: number
|
|
87
|
+
handlerType: string
|
|
88
|
+
timescale: number
|
|
89
|
+
hasEdits: boolean
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface ParsedTfhd {
|
|
93
|
+
trackId: number
|
|
94
|
+
defaultSampleDuration?: number
|
|
95
|
+
defaultSampleSize?: number
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface MdatLayout {
|
|
99
|
+
dataStart: bigint
|
|
100
|
+
declaredEnd: bigint
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function view(data: Uint8Array): DataView {
|
|
104
|
+
return new DataView(data.buffer, data.byteOffset, data.byteLength)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function boxType(data: Uint8Array, offset: number): string {
|
|
108
|
+
return String.fromCharCode(
|
|
109
|
+
data[offset]!,
|
|
110
|
+
data[offset + 1]!,
|
|
111
|
+
data[offset + 2]!,
|
|
112
|
+
data[offset + 3]!,
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function readU64(data: Uint8Array, offset: number): bigint | null {
|
|
117
|
+
if (offset < 0 || offset + 8 > data.length) return null
|
|
118
|
+
const dataView = view(data)
|
|
119
|
+
return (BigInt(dataView.getUint32(offset, false)) << 32n) |
|
|
120
|
+
BigInt(dataView.getUint32(offset + 4, false))
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function parseBox(data: Uint8Array, start: number, limit: number): IsoBox | null {
|
|
124
|
+
if (start < 0 || limit > data.length || start + 8 > limit) return null
|
|
125
|
+
const dataView = view(data)
|
|
126
|
+
const shortSize = dataView.getUint32(start, false)
|
|
127
|
+
let headerSize = 8
|
|
128
|
+
let size: number
|
|
129
|
+
if (shortSize === 0) {
|
|
130
|
+
size = limit - start
|
|
131
|
+
} else if (shortSize === 1) {
|
|
132
|
+
if (start + 16 > limit) return null
|
|
133
|
+
const extendedSize = readU64(data, start + 8)
|
|
134
|
+
if (extendedSize === null || extendedSize > BigInt(Number.MAX_SAFE_INTEGER)) return null
|
|
135
|
+
headerSize = 16
|
|
136
|
+
size = Number(extendedSize)
|
|
137
|
+
} else {
|
|
138
|
+
size = shortSize
|
|
139
|
+
}
|
|
140
|
+
if (size < headerSize || start + size > limit) return null
|
|
141
|
+
return {
|
|
142
|
+
type: boxType(data, start + 4),
|
|
143
|
+
start,
|
|
144
|
+
bodyStart: start + headerSize,
|
|
145
|
+
end: start + size,
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function parseBoxes(data: Uint8Array, start: number, end: number): IsoBox[] | null {
|
|
150
|
+
if (start < 0 || end < start || end > data.length) return null
|
|
151
|
+
const boxes: IsoBox[] = []
|
|
152
|
+
let offset = start
|
|
153
|
+
while (offset < end) {
|
|
154
|
+
const box = parseBox(data, offset, end)
|
|
155
|
+
if (!box || box.end <= offset) return null
|
|
156
|
+
boxes.push(box)
|
|
157
|
+
offset = box.end
|
|
158
|
+
}
|
|
159
|
+
return offset === end ? boxes : null
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function children(data: Uint8Array, parent: IsoBox): IsoBox[] | null {
|
|
163
|
+
return parseBoxes(data, parent.bodyStart, parent.end)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function exactlyOne(boxes: readonly IsoBox[], type: string): IsoBox | null {
|
|
167
|
+
const matches = boxes.filter(box => box.type === type)
|
|
168
|
+
return matches.length === 1 ? matches[0]! : null
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function parseFullBox(data: Uint8Array, box: IsoBox): FullBox | null {
|
|
172
|
+
if (box.bodyStart + 4 > box.end) return null
|
|
173
|
+
const versionAndFlags = view(data).getUint32(box.bodyStart, false)
|
|
174
|
+
return {
|
|
175
|
+
version: versionAndFlags >>> 24,
|
|
176
|
+
flags: versionAndFlags & 0x00ff_ffff,
|
|
177
|
+
bodyStart: box.bodyStart + 4,
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function parseTkhdTrackId(data: Uint8Array, box: IsoBox): number | null {
|
|
182
|
+
const full = parseFullBox(data, box)
|
|
183
|
+
if (!full || full.flags & ~0x00000f) return null
|
|
184
|
+
const bodyLength = box.end - full.bodyStart
|
|
185
|
+
const trackIdOffset = full.version === 0
|
|
186
|
+
? full.bodyStart + 8
|
|
187
|
+
: full.version === 1
|
|
188
|
+
? full.bodyStart + 16
|
|
189
|
+
: -1
|
|
190
|
+
const expectedBodyLength = full.version === 0 ? 80 : full.version === 1 ? 92 : -1
|
|
191
|
+
if (trackIdOffset < 0 || bodyLength !== expectedBodyLength) return null
|
|
192
|
+
return view(data).getUint32(trackIdOffset, false)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function parseMdhdTimescale(data: Uint8Array, box: IsoBox): number | null {
|
|
196
|
+
const full = parseFullBox(data, box)
|
|
197
|
+
if (!full || full.flags !== 0) return null
|
|
198
|
+
const bodyLength = box.end - full.bodyStart
|
|
199
|
+
const timescaleOffset = full.version === 0
|
|
200
|
+
? full.bodyStart + 8
|
|
201
|
+
: full.version === 1
|
|
202
|
+
? full.bodyStart + 16
|
|
203
|
+
: -1
|
|
204
|
+
const expectedBodyLength = full.version === 0 ? 20 : full.version === 1 ? 32 : -1
|
|
205
|
+
if (timescaleOffset < 0 || bodyLength !== expectedBodyLength) return null
|
|
206
|
+
return view(data).getUint32(timescaleOffset, false)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function parseHandlerType(data: Uint8Array, box: IsoBox): string | null {
|
|
210
|
+
const full = parseFullBox(data, box)
|
|
211
|
+
if (!full || full.version !== 0 || full.flags !== 0 || full.bodyStart + 20 > box.end) {
|
|
212
|
+
return null
|
|
213
|
+
}
|
|
214
|
+
return boxType(data, full.bodyStart + 4)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function editListHasEntries(data: Uint8Array, box: IsoBox): boolean | null {
|
|
218
|
+
const full = parseFullBox(data, box)
|
|
219
|
+
if (!full || full.flags !== 0 || (full.version !== 0 && full.version !== 1)) return null
|
|
220
|
+
if (full.bodyStart + 4 > box.end) return null
|
|
221
|
+
const entryCount = view(data).getUint32(full.bodyStart, false)
|
|
222
|
+
const entrySize = full.version === 0 ? 12 : 20
|
|
223
|
+
const expectedEnd = full.bodyStart + 4 + entryCount * entrySize
|
|
224
|
+
if (!Number.isSafeInteger(expectedEnd) || expectedEnd !== box.end) return null
|
|
225
|
+
return entryCount !== 0
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function parseTrack(data: Uint8Array, trak: IsoBox): ParsedTrack | null {
|
|
229
|
+
const trakChildren = children(data, trak)
|
|
230
|
+
if (!trakChildren) return null
|
|
231
|
+
const tkhd = exactlyOne(trakChildren, 'tkhd')
|
|
232
|
+
const mdia = exactlyOne(trakChildren, 'mdia')
|
|
233
|
+
if (!tkhd || !mdia) return null
|
|
234
|
+
const trackId = parseTkhdTrackId(data, tkhd)
|
|
235
|
+
if (trackId === null || trackId === 0) return null
|
|
236
|
+
|
|
237
|
+
const mdiaChildren = children(data, mdia)
|
|
238
|
+
if (!mdiaChildren) return null
|
|
239
|
+
const mdhd = exactlyOne(mdiaChildren, 'mdhd')
|
|
240
|
+
const hdlr = exactlyOne(mdiaChildren, 'hdlr')
|
|
241
|
+
if (!mdhd || !hdlr) return null
|
|
242
|
+
const timescale = parseMdhdTimescale(data, mdhd)
|
|
243
|
+
const handlerType = parseHandlerType(data, hdlr)
|
|
244
|
+
if (timescale === null || timescale === 0 || handlerType === null) return null
|
|
245
|
+
|
|
246
|
+
const edtsBoxes = trakChildren.filter(box => box.type === 'edts')
|
|
247
|
+
if (edtsBoxes.length > 1) return null
|
|
248
|
+
let hasEdits = false
|
|
249
|
+
if (edtsBoxes.length === 1) {
|
|
250
|
+
const edtsChildren = children(data, edtsBoxes[0]!)
|
|
251
|
+
if (!edtsChildren) return null
|
|
252
|
+
const editLists = edtsChildren.filter(box => box.type === 'elst')
|
|
253
|
+
if (editLists.length > 1) return null
|
|
254
|
+
if (editLists.length === 1) {
|
|
255
|
+
const result = editListHasEntries(data, editLists[0]!)
|
|
256
|
+
if (result === null) return null
|
|
257
|
+
hasEdits = result
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return { trackId, handlerType, timescale, hasEdits }
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function parseTrex(data: Uint8Array, box: IsoBox): IsoBmffTrackTiming | null {
|
|
265
|
+
const full = parseFullBox(data, box)
|
|
266
|
+
if (!full || full.version !== 0 || full.flags !== 0 || box.end - full.bodyStart !== 20) {
|
|
267
|
+
return null
|
|
268
|
+
}
|
|
269
|
+
const dataView = view(data)
|
|
270
|
+
const trackId = dataView.getUint32(full.bodyStart, false)
|
|
271
|
+
const defaultSampleDuration = dataView.getUint32(full.bodyStart + 8, false)
|
|
272
|
+
const defaultSampleSize = dataView.getUint32(full.bodyStart + 12, false)
|
|
273
|
+
return {
|
|
274
|
+
trackId,
|
|
275
|
+
timescale: 0,
|
|
276
|
+
...(defaultSampleDuration === 0 ? {} : { defaultSampleDuration }),
|
|
277
|
+
...(defaultSampleSize === 0 ? {} : { defaultSampleSize }),
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export function parseIsoBmffInitializationTiming(
|
|
282
|
+
data: Uint8Array,
|
|
283
|
+
): IsoBmffTrackTiming | null {
|
|
284
|
+
const topLevel = parseBoxes(data, 0, data.length)
|
|
285
|
+
if (!topLevel) return null
|
|
286
|
+
const ftyp = exactlyOne(topLevel, 'ftyp')
|
|
287
|
+
const moov = exactlyOne(topLevel, 'moov')
|
|
288
|
+
if (!ftyp || !moov || ftyp.start > moov.start) return null
|
|
289
|
+
if (topLevel.some(box => box.type === 'moof' || box.type === 'mdat')) return null
|
|
290
|
+
|
|
291
|
+
const moovChildren = children(data, moov)
|
|
292
|
+
if (!moovChildren) return null
|
|
293
|
+
const parsedTracks: ParsedTrack[] = []
|
|
294
|
+
for (const trak of moovChildren.filter(box => box.type === 'trak')) {
|
|
295
|
+
const parsed = parseTrack(data, trak)
|
|
296
|
+
if (!parsed) return null
|
|
297
|
+
parsedTracks.push(parsed)
|
|
298
|
+
}
|
|
299
|
+
const mediaTracks = parsedTracks.filter(
|
|
300
|
+
track => track.handlerType === 'vide' || track.handlerType === 'soun',
|
|
301
|
+
)
|
|
302
|
+
if (mediaTracks.length !== 1) return null
|
|
303
|
+
const mediaTrack = mediaTracks[0]!
|
|
304
|
+
if (mediaTrack.hasEdits) return null
|
|
305
|
+
|
|
306
|
+
const mvex = exactlyOne(moovChildren, 'mvex')
|
|
307
|
+
if (!mvex) return null
|
|
308
|
+
const mvexChildren = children(data, mvex)
|
|
309
|
+
if (!mvexChildren) return null
|
|
310
|
+
const trexEntries: IsoBmffTrackTiming[] = []
|
|
311
|
+
for (const trexBox of mvexChildren.filter(box => box.type === 'trex')) {
|
|
312
|
+
const trex = parseTrex(data, trexBox)
|
|
313
|
+
if (!trex) return null
|
|
314
|
+
trexEntries.push(trex)
|
|
315
|
+
}
|
|
316
|
+
const matchingTrex = trexEntries.filter(trex => trex.trackId === mediaTrack.trackId)
|
|
317
|
+
if (matchingTrex.length !== 1) return null
|
|
318
|
+
const trex = matchingTrex[0]!
|
|
319
|
+
return {
|
|
320
|
+
trackId: mediaTrack.trackId,
|
|
321
|
+
timescale: mediaTrack.timescale,
|
|
322
|
+
...(trex.defaultSampleDuration === undefined
|
|
323
|
+
? {}
|
|
324
|
+
: { defaultSampleDuration: trex.defaultSampleDuration }),
|
|
325
|
+
...(trex.defaultSampleSize === undefined
|
|
326
|
+
? {}
|
|
327
|
+
: { defaultSampleSize: trex.defaultSampleSize }),
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function parseMfhdSequence(data: Uint8Array, box: IsoBox): number | null {
|
|
332
|
+
const full = parseFullBox(data, box)
|
|
333
|
+
if (!full || full.version !== 0 || full.flags !== 0 || box.end - full.bodyStart !== 4) {
|
|
334
|
+
return null
|
|
335
|
+
}
|
|
336
|
+
return view(data).getUint32(full.bodyStart, false)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function parseTfhd(data: Uint8Array, box: IsoBox): ParsedTfhd | null {
|
|
340
|
+
const full = parseFullBox(data, box)
|
|
341
|
+
if (!full || full.version !== 0 || (full.flags & ~TFHD_KNOWN_FLAGS) !== 0) return null
|
|
342
|
+
if ((full.flags & TFHD_BASE_DATA_OFFSET_PRESENT) !== 0 ||
|
|
343
|
+
(full.flags & TFHD_DEFAULT_BASE_IS_MOOF) === 0 ||
|
|
344
|
+
(full.flags & TFHD_DURATION_IS_EMPTY) !== 0) {
|
|
345
|
+
return null
|
|
346
|
+
}
|
|
347
|
+
const dataView = view(data)
|
|
348
|
+
let offset = full.bodyStart
|
|
349
|
+
if (offset + 4 > box.end) return null
|
|
350
|
+
const trackId = dataView.getUint32(offset, false)
|
|
351
|
+
offset += 4
|
|
352
|
+
if ((full.flags & TFHD_SAMPLE_DESCRIPTION_INDEX_PRESENT) !== 0) {
|
|
353
|
+
if (offset + 4 > box.end) return null
|
|
354
|
+
offset += 4
|
|
355
|
+
}
|
|
356
|
+
let defaultSampleDuration: number | undefined
|
|
357
|
+
if ((full.flags & TFHD_DEFAULT_SAMPLE_DURATION_PRESENT) !== 0) {
|
|
358
|
+
if (offset + 4 > box.end) return null
|
|
359
|
+
defaultSampleDuration = dataView.getUint32(offset, false)
|
|
360
|
+
offset += 4
|
|
361
|
+
}
|
|
362
|
+
let defaultSampleSize: number | undefined
|
|
363
|
+
if ((full.flags & TFHD_DEFAULT_SAMPLE_SIZE_PRESENT) !== 0) {
|
|
364
|
+
if (offset + 4 > box.end) return null
|
|
365
|
+
defaultSampleSize = dataView.getUint32(offset, false)
|
|
366
|
+
offset += 4
|
|
367
|
+
}
|
|
368
|
+
if ((full.flags & TFHD_DEFAULT_SAMPLE_FLAGS_PRESENT) !== 0) {
|
|
369
|
+
if (offset + 4 > box.end) return null
|
|
370
|
+
offset += 4
|
|
371
|
+
}
|
|
372
|
+
if (offset !== box.end) return null
|
|
373
|
+
return {
|
|
374
|
+
trackId,
|
|
375
|
+
...(defaultSampleDuration === undefined ? {} : { defaultSampleDuration }),
|
|
376
|
+
...(defaultSampleSize === undefined ? {} : { defaultSampleSize }),
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function parseTfdt(data: Uint8Array, box: IsoBox): bigint | null {
|
|
381
|
+
const full = parseFullBox(data, box)
|
|
382
|
+
if (!full || full.flags !== 0) return null
|
|
383
|
+
if (full.version === 0 && box.end - full.bodyStart === 4) {
|
|
384
|
+
return BigInt(view(data).getUint32(full.bodyStart, false))
|
|
385
|
+
}
|
|
386
|
+
if (full.version === 1 && box.end - full.bodyStart === 8) {
|
|
387
|
+
return readU64(data, full.bodyStart)
|
|
388
|
+
}
|
|
389
|
+
return null
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function parseMdatLayout(data: Uint8Array, offset: number): MdatLayout | null {
|
|
393
|
+
if (offset < 0 || offset + 8 > data.length || boxType(data, offset + 4) !== 'mdat') return null
|
|
394
|
+
const dataView = view(data)
|
|
395
|
+
const shortSize = dataView.getUint32(offset, false)
|
|
396
|
+
let headerSize = 8
|
|
397
|
+
let declaredSize: bigint
|
|
398
|
+
if (shortSize === 0) {
|
|
399
|
+
return null
|
|
400
|
+
} else if (shortSize === 1) {
|
|
401
|
+
const extended = readU64(data, offset + 8)
|
|
402
|
+
if (extended === null) return null
|
|
403
|
+
headerSize = 16
|
|
404
|
+
declaredSize = extended
|
|
405
|
+
} else {
|
|
406
|
+
declaredSize = BigInt(shortSize)
|
|
407
|
+
}
|
|
408
|
+
if (declaredSize < BigInt(headerSize) || declaredSize < BigInt(data.length - offset)) {
|
|
409
|
+
return null
|
|
410
|
+
}
|
|
411
|
+
const declaredEnd = BigInt(offset) + declaredSize
|
|
412
|
+
if (declaredEnd > U64_MAX) return null
|
|
413
|
+
return { dataStart: BigInt(offset + headerSize), declaredEnd }
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function resolvedDefault(
|
|
417
|
+
entryValue: number | undefined,
|
|
418
|
+
tfhdValue: number | undefined,
|
|
419
|
+
trexValue: number | undefined,
|
|
420
|
+
): number | null {
|
|
421
|
+
const value = entryValue ?? tfhdValue ?? trexValue
|
|
422
|
+
return value === undefined || value === 0 ? null : value
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function parseTrunSamples(
|
|
426
|
+
data: Uint8Array,
|
|
427
|
+
box: IsoBox,
|
|
428
|
+
moofStart: number,
|
|
429
|
+
baseDecodeTime: bigint,
|
|
430
|
+
tfhd: ParsedTfhd,
|
|
431
|
+
track: IsoBmffTrackTiming,
|
|
432
|
+
mdat: MdatLayout,
|
|
433
|
+
maxSamples: number,
|
|
434
|
+
): IsoBmffSampleTiming[] | null {
|
|
435
|
+
const full = parseFullBox(data, box)
|
|
436
|
+
if (!full || (full.version !== 0 && full.version !== 1) ||
|
|
437
|
+
(full.flags & ~TRUN_KNOWN_FLAGS) !== 0 ||
|
|
438
|
+
(full.flags & TRUN_DATA_OFFSET_PRESENT) === 0 ||
|
|
439
|
+
((full.flags & TRUN_FIRST_SAMPLE_FLAGS_PRESENT) !== 0 &&
|
|
440
|
+
(full.flags & TRUN_SAMPLE_FLAGS_PRESENT) !== 0)) {
|
|
441
|
+
return null
|
|
442
|
+
}
|
|
443
|
+
const dataView = view(data)
|
|
444
|
+
let offset = full.bodyStart
|
|
445
|
+
if (offset + 8 > box.end) return null
|
|
446
|
+
const sampleCount = dataView.getUint32(offset, false)
|
|
447
|
+
offset += 4
|
|
448
|
+
if (sampleCount === 0 || sampleCount > maxSamples) return null
|
|
449
|
+
const relativeDataOffset = dataView.getInt32(offset, false)
|
|
450
|
+
offset += 4
|
|
451
|
+
if (relativeDataOffset < 0) return null
|
|
452
|
+
const dataOffset = BigInt(relativeDataOffset)
|
|
453
|
+
const absoluteDataOffset = BigInt(moofStart) + dataOffset
|
|
454
|
+
if (absoluteDataOffset > BigInt(data.length) || absoluteDataOffset < mdat.dataStart) return null
|
|
455
|
+
if ((full.flags & TRUN_FIRST_SAMPLE_FLAGS_PRESENT) !== 0) {
|
|
456
|
+
if (offset + 4 > box.end) return null
|
|
457
|
+
offset += 4
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
let decodeTime = baseDecodeTime
|
|
461
|
+
let bytePosition = dataOffset
|
|
462
|
+
const samples: IsoBmffSampleTiming[] = []
|
|
463
|
+
for (let index = 0; index < sampleCount; index++) {
|
|
464
|
+
let entryDuration: number | undefined
|
|
465
|
+
if ((full.flags & TRUN_SAMPLE_DURATION_PRESENT) !== 0) {
|
|
466
|
+
if (offset + 4 > box.end) return null
|
|
467
|
+
entryDuration = dataView.getUint32(offset, false)
|
|
468
|
+
offset += 4
|
|
469
|
+
}
|
|
470
|
+
let entrySize: number | undefined
|
|
471
|
+
if ((full.flags & TRUN_SAMPLE_SIZE_PRESENT) !== 0) {
|
|
472
|
+
if (offset + 4 > box.end) return null
|
|
473
|
+
entrySize = dataView.getUint32(offset, false)
|
|
474
|
+
offset += 4
|
|
475
|
+
}
|
|
476
|
+
if ((full.flags & TRUN_SAMPLE_FLAGS_PRESENT) !== 0) {
|
|
477
|
+
if (offset + 4 > box.end) return null
|
|
478
|
+
offset += 4
|
|
479
|
+
}
|
|
480
|
+
let compositionOffset = 0
|
|
481
|
+
if ((full.flags & TRUN_SAMPLE_CTS_OFFSET_PRESENT) !== 0) {
|
|
482
|
+
if (offset + 4 > box.end) return null
|
|
483
|
+
compositionOffset = full.version === 1
|
|
484
|
+
? dataView.getInt32(offset, false)
|
|
485
|
+
: dataView.getUint32(offset, false)
|
|
486
|
+
offset += 4
|
|
487
|
+
}
|
|
488
|
+
if (offset > box.end) return null
|
|
489
|
+
|
|
490
|
+
const duration = resolvedDefault(
|
|
491
|
+
entryDuration,
|
|
492
|
+
tfhd.defaultSampleDuration,
|
|
493
|
+
track.defaultSampleDuration,
|
|
494
|
+
)
|
|
495
|
+
const size = resolvedDefault(entrySize, tfhd.defaultSampleSize, track.defaultSampleSize)
|
|
496
|
+
if (duration === null || size === null) return null
|
|
497
|
+
const sampleEnd = bytePosition + BigInt(size)
|
|
498
|
+
const absoluteSampleEnd = BigInt(moofStart) + sampleEnd
|
|
499
|
+
if (absoluteSampleEnd > mdat.declaredEnd || absoluteSampleEnd > U64_MAX) return null
|
|
500
|
+
const presentationTime = decodeTime + BigInt(compositionOffset)
|
|
501
|
+
if (presentationTime < I64_MIN || presentationTime > I64_MAX) return null
|
|
502
|
+
samples.push({
|
|
503
|
+
decodeTime,
|
|
504
|
+
presentationTime,
|
|
505
|
+
duration,
|
|
506
|
+
timescale: track.timescale,
|
|
507
|
+
size,
|
|
508
|
+
bytePosition,
|
|
509
|
+
})
|
|
510
|
+
decodeTime += BigInt(duration)
|
|
511
|
+
if (decodeTime > U64_MAX) return null
|
|
512
|
+
bytePosition = sampleEnd
|
|
513
|
+
}
|
|
514
|
+
return offset === box.end ? samples : null
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
export function parseIsoBmffMovieFragmentTiming(
|
|
518
|
+
data: Uint8Array,
|
|
519
|
+
track: IsoBmffTrackTiming,
|
|
520
|
+
maxSamples: number,
|
|
521
|
+
): IsoBmffMovieFragmentTiming | null {
|
|
522
|
+
if (!Number.isInteger(maxSamples) || maxSamples <= 0) return null
|
|
523
|
+
const first = parseBox(data, 0, data.length)
|
|
524
|
+
if (!first) return null
|
|
525
|
+
const moof = first.type === 'styp'
|
|
526
|
+
? parseBox(data, first.end, data.length)
|
|
527
|
+
: first
|
|
528
|
+
if (!moof || moof.type !== 'moof' || moof.end >= data.length) return null
|
|
529
|
+
const moofChildren = children(data, moof)
|
|
530
|
+
if (!moofChildren) return null
|
|
531
|
+
const mfhd = exactlyOne(moofChildren, 'mfhd')
|
|
532
|
+
const traf = exactlyOne(moofChildren, 'traf')
|
|
533
|
+
if (!mfhd || !traf) return null
|
|
534
|
+
const movieFragmentSequenceNumber = parseMfhdSequence(data, mfhd)
|
|
535
|
+
if (movieFragmentSequenceNumber === null || movieFragmentSequenceNumber === 0) return null
|
|
536
|
+
|
|
537
|
+
const trafChildren = children(data, traf)
|
|
538
|
+
if (!trafChildren) return null
|
|
539
|
+
const tfhdBox = exactlyOne(trafChildren, 'tfhd')
|
|
540
|
+
const tfdtBox = exactlyOne(trafChildren, 'tfdt')
|
|
541
|
+
const trunBox = exactlyOne(trafChildren, 'trun')
|
|
542
|
+
if (!tfhdBox || !tfdtBox || !trunBox) return null
|
|
543
|
+
const tfhd = parseTfhd(data, tfhdBox)
|
|
544
|
+
const baseDecodeTime = parseTfdt(data, tfdtBox)
|
|
545
|
+
if (!tfhd || tfhd.trackId !== track.trackId || baseDecodeTime === null) return null
|
|
546
|
+
const mdat = parseMdatLayout(data, moof.end)
|
|
547
|
+
if (!mdat) return null
|
|
548
|
+
const samples = parseTrunSamples(
|
|
549
|
+
data,
|
|
550
|
+
trunBox,
|
|
551
|
+
moof.start,
|
|
552
|
+
baseDecodeTime,
|
|
553
|
+
tfhd,
|
|
554
|
+
track,
|
|
555
|
+
mdat,
|
|
556
|
+
maxSamples,
|
|
557
|
+
)
|
|
558
|
+
if (!samples) return null
|
|
559
|
+
return { movieFragmentSequenceNumber, samples }
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function sameTrack(a: IsoBmffTrackTiming, b: IsoBmffTrackTiming): boolean {
|
|
563
|
+
return a.trackId === b.trackId &&
|
|
564
|
+
a.timescale === b.timescale &&
|
|
565
|
+
a.defaultSampleDuration === b.defaultSampleDuration &&
|
|
566
|
+
a.defaultSampleSize === b.defaultSampleSize
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function sameSample(a: IsoBmffSampleTiming, b: IsoBmffSampleTiming): boolean {
|
|
570
|
+
return a.decodeTime === b.decodeTime &&
|
|
571
|
+
a.presentationTime === b.presentationTime &&
|
|
572
|
+
a.duration === b.duration &&
|
|
573
|
+
a.timescale === b.timescale &&
|
|
574
|
+
a.size === b.size &&
|
|
575
|
+
a.bytePosition === b.bytePosition
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
type PendingMovieFragment = Array<IsoBmffSampleTiming | null>
|
|
579
|
+
|
|
580
|
+
/** Bounded per-track FT=0/FT=1 timing state. */
|
|
581
|
+
export class IsoBmffTimingResolver {
|
|
582
|
+
#track: IsoBmffTrackTiming | null = null
|
|
583
|
+
#fragments = new Map<string, PendingMovieFragment>()
|
|
584
|
+
#pendingSamples = 0
|
|
585
|
+
#evictedSamples = 0
|
|
586
|
+
#lastMovieFragmentRejection: IsoBmffMovieFragmentRejection | null = null
|
|
587
|
+
|
|
588
|
+
constructor(readonly maxPendingSamples: number) {
|
|
589
|
+
if (!Number.isInteger(maxPendingSamples) || maxPendingSamples <= 0) {
|
|
590
|
+
throw new Error('[IsoBmffTimingResolver] maxPendingSamples must be a positive integer')
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
get pendingSampleCount(): number {
|
|
595
|
+
return this.#pendingSamples
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Slots reclaimed by window displacement rather than by delivery or
|
|
600
|
+
* abandonment. Deliberately separate from the combiner's own release count:
|
|
601
|
+
* "nobody ever saw this sample" and "the combiner gave up on it" are
|
|
602
|
+
* different failures with different owners, and one number cannot say which.
|
|
603
|
+
*/
|
|
604
|
+
get evictedSampleCount(): number {
|
|
605
|
+
return this.#evictedSamples
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/** Typed reason for the most recent rejected movie fragment. */
|
|
609
|
+
get lastMovieFragmentRejection(): IsoBmffMovieFragmentRejection | null {
|
|
610
|
+
return this.#lastMovieFragmentRejection
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
addInitialization(data: Uint8Array): boolean {
|
|
614
|
+
const timing = parseIsoBmffInitializationTiming(data)
|
|
615
|
+
if (!timing) return false
|
|
616
|
+
if (this.#track) return sameTrack(this.#track, timing)
|
|
617
|
+
this.#track = timing
|
|
618
|
+
return true
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
addMovieFragment(
|
|
622
|
+
mpuSequenceNumber: number,
|
|
623
|
+
data: Uint8Array,
|
|
624
|
+
additionalSampleLimit = this.maxPendingSamples,
|
|
625
|
+
): boolean {
|
|
626
|
+
this.#lastMovieFragmentRejection = null
|
|
627
|
+
if (!Number.isInteger(additionalSampleLimit) || additionalSampleLimit < 0) {
|
|
628
|
+
this.#lastMovieFragmentRejection = 'invalid'
|
|
629
|
+
return false
|
|
630
|
+
}
|
|
631
|
+
if (!this.#track || !isU32(mpuSequenceNumber)) {
|
|
632
|
+
this.#lastMovieFragmentRejection = 'invalid'
|
|
633
|
+
return false
|
|
634
|
+
}
|
|
635
|
+
const parsed = parseIsoBmffMovieFragmentTiming(
|
|
636
|
+
data,
|
|
637
|
+
this.#track,
|
|
638
|
+
this.maxPendingSamples,
|
|
639
|
+
)
|
|
640
|
+
if (!parsed) {
|
|
641
|
+
this.#lastMovieFragmentRejection = 'invalid'
|
|
642
|
+
return false
|
|
643
|
+
}
|
|
644
|
+
const key = fragmentKey(mpuSequenceNumber, parsed.movieFragmentSequenceNumber)
|
|
645
|
+
const existing = this.#fragments.get(key)
|
|
646
|
+
if (existing) {
|
|
647
|
+
return existing.length === parsed.samples.length && existing.every(
|
|
648
|
+
(sample, index) => sample !== null && sameSample(sample, parsed.samples[index]!),
|
|
649
|
+
)
|
|
650
|
+
}
|
|
651
|
+
// Sliding window, not a one-way ratchet. `consumeSample` and
|
|
652
|
+
// `releaseSample` between them cover every sample some component observed
|
|
653
|
+
// -- but a sample whose data units never arrive at all is observed by
|
|
654
|
+
// nobody, so neither path ever runs and its slot is held until `reset()`.
|
|
655
|
+
// Under sustained loss those orphans accumulate until the budget is full
|
|
656
|
+
// of samples that can never arrive, at which point every later moof is
|
|
657
|
+
// refused and media stops permanently with no error.
|
|
658
|
+
//
|
|
659
|
+
// Displacement is the signal no component can raise: once the budget is
|
|
660
|
+
// full and a newer fragment is in hand, the oldest pending fragment's
|
|
661
|
+
// samples are older than the whole window and cannot still be in flight.
|
|
662
|
+
// Reclaiming them keeps the timing that is arriving now and discards the
|
|
663
|
+
// timing that is not; refusing the new fragment does exactly the reverse,
|
|
664
|
+
// which is what wedged the stream. Evicted timing is not silent loss --
|
|
665
|
+
// a late data unit then finds no entry and is dropped against a named
|
|
666
|
+
// reason, which is attributable, bounded, and recoverable.
|
|
667
|
+
let freed = 0
|
|
668
|
+
while (
|
|
669
|
+
this.#fragments.size > 0 &&
|
|
670
|
+
(this.#pendingSamples + parsed.samples.length > this.maxPendingSamples ||
|
|
671
|
+
parsed.samples.length - freed > additionalSampleLimit)
|
|
672
|
+
) {
|
|
673
|
+
freed += this.#evictOldestFragment()
|
|
674
|
+
}
|
|
675
|
+
// Net new charge against the caller's pool is what it must afford: `freed`
|
|
676
|
+
// slots were already counted there and are handed back by this call.
|
|
677
|
+
if (parsed.samples.length - freed > additionalSampleLimit) {
|
|
678
|
+
this.#lastMovieFragmentRejection = 'budget'
|
|
679
|
+
return false
|
|
680
|
+
}
|
|
681
|
+
if (this.#pendingSamples + parsed.samples.length > this.maxPendingSamples) {
|
|
682
|
+
this.#lastMovieFragmentRejection = 'budget'
|
|
683
|
+
return false
|
|
684
|
+
}
|
|
685
|
+
this.#fragments.set(key, [...parsed.samples])
|
|
686
|
+
this.#pendingSamples += parsed.samples.length
|
|
687
|
+
return true
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
sampleTiming(
|
|
691
|
+
mpuSequenceNumber: number,
|
|
692
|
+
movieFragmentSequenceNumber: number,
|
|
693
|
+
sampleNumber: number,
|
|
694
|
+
): IsoBmffSampleTiming | null {
|
|
695
|
+
if (!isU32(mpuSequenceNumber) || !isU32(movieFragmentSequenceNumber) ||
|
|
696
|
+
movieFragmentSequenceNumber === 0 || !isU32(sampleNumber) || sampleNumber === 0) {
|
|
697
|
+
return null
|
|
698
|
+
}
|
|
699
|
+
const samples = this.#fragments.get(
|
|
700
|
+
fragmentKey(mpuSequenceNumber, movieFragmentSequenceNumber),
|
|
701
|
+
)
|
|
702
|
+
return samples?.[sampleNumber - 1] ?? null
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
consumeSample(
|
|
706
|
+
mpuSequenceNumber: number,
|
|
707
|
+
movieFragmentSequenceNumber: number,
|
|
708
|
+
sampleNumber: number,
|
|
709
|
+
expected: IsoBmffSampleTiming,
|
|
710
|
+
): boolean {
|
|
711
|
+
const samples = this.#fragments.get(
|
|
712
|
+
fragmentKey(mpuSequenceNumber, movieFragmentSequenceNumber),
|
|
713
|
+
)
|
|
714
|
+
const sample = samples?.[sampleNumber - 1]
|
|
715
|
+
if (!sample || !sameSample(sample, expected)) return false
|
|
716
|
+
return this.#clearSlot(mpuSequenceNumber, movieFragmentSequenceNumber, sampleNumber)
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* Free the budget slot of a sample that will never be delivered.
|
|
721
|
+
*
|
|
722
|
+
* `consumeSample` is the delivery path and is the only decrement on a
|
|
723
|
+
* healthy stream. A sample whose data units never complete is never
|
|
724
|
+
* delivered; window displacement in `addMovieFragment` eventually reclaims
|
|
725
|
+
* it, but only after it has aged out of the whole window. This path frees
|
|
726
|
+
* the slot as soon as the combiner knows the sample is gone, so the budget
|
|
727
|
+
* tracks what is actually in flight rather than what has merely aged.
|
|
728
|
+
*
|
|
729
|
+
* The caller is whoever abandoned the sample, so the release is driven by
|
|
730
|
+
* the abandonment itself rather than by a timer, an LRU, or an age bound --
|
|
731
|
+
* the slot is freed exactly when its sample provably cannot arrive, which
|
|
732
|
+
* is a protocol event the combiner already detects and counts.
|
|
733
|
+
*
|
|
734
|
+
* Deliberately takes no `expected` timing: the caller is discarding, not
|
|
735
|
+
* matching, and requiring it would make the release fail exactly when the
|
|
736
|
+
* timing entry is the thing being reclaimed. Returns false when the slot
|
|
737
|
+
* was already freed, so a double release cannot drive the count negative.
|
|
738
|
+
*/
|
|
739
|
+
releaseSample(
|
|
740
|
+
mpuSequenceNumber: number,
|
|
741
|
+
movieFragmentSequenceNumber: number,
|
|
742
|
+
sampleNumber: number,
|
|
743
|
+
): boolean {
|
|
744
|
+
return this.#clearSlot(mpuSequenceNumber, movieFragmentSequenceNumber, sampleNumber)
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Drop the oldest pending fragment whole and return the slots it held.
|
|
749
|
+
*
|
|
750
|
+
* Oldest is insertion order, which for a moof stream is arrival order, so
|
|
751
|
+
* this is the least-recently-declared timing -- the entries least likely to
|
|
752
|
+
* still have data units in flight.
|
|
753
|
+
*/
|
|
754
|
+
#evictOldestFragment(): number {
|
|
755
|
+
const oldest = this.#fragments.keys().next().value
|
|
756
|
+
if (oldest === undefined) return 0
|
|
757
|
+
const samples = this.#fragments.get(oldest)!
|
|
758
|
+
let live = 0
|
|
759
|
+
for (const sample of samples) if (sample !== null) live++
|
|
760
|
+
this.#fragments.delete(oldest)
|
|
761
|
+
this.#pendingSamples -= live
|
|
762
|
+
this.#evictedSamples += live
|
|
763
|
+
return live
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/** Null one slot, decrement the budget, and drop the fragment when empty. */
|
|
767
|
+
#clearSlot(
|
|
768
|
+
mpuSequenceNumber: number,
|
|
769
|
+
movieFragmentSequenceNumber: number,
|
|
770
|
+
sampleNumber: number,
|
|
771
|
+
): boolean {
|
|
772
|
+
if (!isU32(mpuSequenceNumber) || !isU32(movieFragmentSequenceNumber) ||
|
|
773
|
+
movieFragmentSequenceNumber === 0 || !isU32(sampleNumber) || sampleNumber === 0) {
|
|
774
|
+
return false
|
|
775
|
+
}
|
|
776
|
+
const key = fragmentKey(mpuSequenceNumber, movieFragmentSequenceNumber)
|
|
777
|
+
const samples = this.#fragments.get(key)
|
|
778
|
+
const index = sampleNumber - 1
|
|
779
|
+
if (!samples || !samples[index]) return false
|
|
780
|
+
samples[index] = null
|
|
781
|
+
this.#pendingSamples--
|
|
782
|
+
if (samples.every(value => value === null)) this.#fragments.delete(key)
|
|
783
|
+
return true
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
reset(): void {
|
|
787
|
+
this.#track = null
|
|
788
|
+
this.#fragments.clear()
|
|
789
|
+
this.#pendingSamples = 0
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
function fragmentKey(mpuSequenceNumber: number, movieFragmentSequenceNumber: number): string {
|
|
794
|
+
return `${mpuSequenceNumber}:${movieFragmentSequenceNumber}`
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
function isU32(value: number): boolean {
|
|
798
|
+
return Number.isInteger(value) && value >= 0 && value <= 0xffff_ffff
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/** Convert exact media ticks to microseconds without first narrowing the ticks. */
|
|
802
|
+
export function mediaTicksToMicroseconds(ticks: bigint, timescale: number): number | null {
|
|
803
|
+
if (!Number.isInteger(timescale) || timescale <= 0) return null
|
|
804
|
+
const numerator = ticks * MICROSECONDS_PER_SECOND
|
|
805
|
+
const scale = BigInt(timescale)
|
|
806
|
+
const whole = numerator / scale
|
|
807
|
+
const remainder = numerator % scale
|
|
808
|
+
if (whole < BigInt(Number.MIN_SAFE_INTEGER) || whole > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
809
|
+
return null
|
|
810
|
+
}
|
|
811
|
+
const result = Number(whole) + Number(remainder) / timescale
|
|
812
|
+
return Number.isFinite(result) ? result : null
|
|
813
|
+
}
|