@blockcast/mmt-container 0.1.0-main.149f78a4adae
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 +148 -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 +17109 -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 +549 -0
- package/dist/carp-catalog.js.map +7 -0
- package/dist/catalog-fec-params.d.ts +82 -0
- package/dist/catalog-fec-params.d.ts.map +1 -0
- package/dist/catalog-fec-params.js +66 -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 +168 -0
- package/dist/cmaf-block-assembler.d.ts.map +1 -0
- package/dist/cmaf-block-assembler.js +1755 -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 +235 -0
- package/dist/codec-utils.d.ts.map +1 -0
- package/dist/codec-utils.js +1225 -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 +266 -0
- package/dist/fec-manager.d.ts.map +1 -0
- package/dist/fec-manager.js +1447 -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 +76 -0
- package/dist/fec-worker-setup.d.ts.map +1 -0
- package/dist/fec-worker-setup.js +603 -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 +330 -0
- package/dist/index.js.map +7 -0
- package/dist/iso-bmff-timing.d.ts +47 -0
- package/dist/iso-bmff-timing.d.ts.map +1 -0
- package/dist/iso-bmff-timing.js +526 -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 +1267 -0
- package/dist/manifest-auth-plan.js.map +7 -0
- package/dist/media-router.d.ts +338 -0
- package/dist/media-router.d.ts.map +1 -0
- package/dist/media-router.js +802 -0
- package/dist/media-router.js.map +7 -0
- package/dist/mfu-reassembler.d.ts +264 -0
- package/dist/mfu-reassembler.d.ts.map +1 -0
- package/dist/mfu-reassembler.js +2668 -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 +304 -0
- package/dist/mmtp-container-parser.d.ts.map +1 -0
- package/dist/mmtp-container-parser.js +5378 -0
- package/dist/mmtp-container-parser.js.map +7 -0
- package/dist/mmtp-container-parser.no-modules.js +7853 -0
- package/dist/mmtp-container-parser.no-modules.js.map +7 -0
- package/dist/mmtp-decode-pipeline.d.ts +96 -0
- package/dist/mmtp-decode-pipeline.d.ts.map +1 -0
- package/dist/mmtp-decode-pipeline.js +5589 -0
- package/dist/mmtp-decode-pipeline.js.map +7 -0
- package/dist/mmtp-router.d.ts +383 -0
- package/dist/mmtp-router.d.ts.map +1 -0
- package/dist/mmtp-router.js +8384 -0
- package/dist/mmtp-router.js.map +7 -0
- package/dist/mmtp-to-cmaf.d.ts +166 -0
- package/dist/mmtp-to-cmaf.d.ts.map +1 -0
- package/dist/mmtp-to-cmaf.js +781 -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 +330 -0
- package/dist/multicast-manager.d.ts.map +1 -0
- package/dist/multicast-manager.js +11032 -0
- package/dist/multicast-manager.js.map +7 -0
- package/dist/multicast-transport.d.ts +62 -0
- package/dist/multicast-transport.d.ts.map +1 -0
- package/dist/multicast-transport.js +338 -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 +7819 -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 +117 -0
- package/dist/repair-fetch.js.map +7 -0
- package/dist/sample-combiner.d.ts +182 -0
- package/dist/sample-combiner.d.ts.map +1 -0
- package/dist/sample-combiner.js +571 -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 +1220 -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 +269 -0
- package/dist/track-session.d.ts.map +1 -0
- package/dist/track-session.js +597 -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 +81 -0
- package/dist/wasm-mfu-reassembler.d.ts.map +1 -0
- package/dist/wasm-mfu-reassembler.js +1915 -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 +5635 -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 +80 -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 +270 -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 +309 -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 +275 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.js +644 -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 +898 -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 +80 -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 +294 -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 +174 -0
- package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-fec/dist/oti.js +256 -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 +275 -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 +644 -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 +898 -0
- package/node_modules/@blockcast/mmt-fec/package.json +79 -0
- package/node_modules/@blockcast/mmt-fec/src/block-manager.ts +369 -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 +319 -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 +90 -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 +462 -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 +636 -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 +283 -0
- package/src/align.ts +235 -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 +776 -0
- package/src/catalog-fec-params.ts +167 -0
- package/src/catalog-network-source.ts +49 -0
- package/src/catalog-validator.ts +34 -0
- package/src/cmaf-block-assembler.ts +1058 -0
- package/src/cmaf-group-batcher.ts +104 -0
- package/src/cmcd-producer.ts +329 -0
- package/src/codec-utils.ts +1539 -0
- package/src/fec-codec.ts +61 -0
- package/src/fec-manager.ts +1939 -0
- package/src/fec-starvation-detector.ts +128 -0
- package/src/fec-worker-setup.ts +177 -0
- package/src/fmp4-completion.ts +47 -0
- package/src/fmp4-reader.ts +112 -0
- package/src/index.ts +443 -0
- package/src/iso-bmff-timing.ts +688 -0
- package/src/loc.ts +181 -0
- package/src/manifest-auth-plan.ts +107 -0
- package/src/media-router.ts +1185 -0
- package/src/mfu-reassembler.ts +2842 -0
- package/src/mfu-reassembly-policy.ts +134 -0
- package/src/mmtp-container-parser.ts +1498 -0
- package/src/mmtp-decode-pipeline.ts +315 -0
- package/src/mmtp-router.ts +3027 -0
- package/src/mmtp-to-cmaf.ts +956 -0
- package/src/multicast-auth-catalog.ts +340 -0
- package/src/multicast-input.ts +439 -0
- package/src/multicast-manager.ts +1503 -0
- package/src/multicast-transport.ts +320 -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 +217 -0
- package/src/sample-combiner.ts +846 -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 +778 -0
- package/src/transport-pool.ts +128 -0
- package/src/wasm-mfu-reassembler.ts +372 -0
- package/src/wasm-mmtp-container-parser.ts +23 -0
- package/test-vectors/align.json +199 -0
- package/test-vectors/catalog/README.md +25 -0
- package/test-vectors/catalog/negative/legacy-selection-params.json +15 -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-unaligned-symbol.json +26 -0
- package/test-vectors/catalog/negative/repair-track-legacy-shape.json +18 -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-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/subsample-placement-v1.json +230 -0
package/dist/align.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// src/align.ts
|
|
2
|
+
function secondsFromTicks(ticks, timescale) {
|
|
3
|
+
if (!Number.isFinite(ticks)) {
|
|
4
|
+
throw new Error(`[align] secondsFromTicks: ticks must be finite, got ${ticks}`);
|
|
5
|
+
}
|
|
6
|
+
if (!Number.isFinite(timescale) || timescale <= 0) {
|
|
7
|
+
throw new Error(
|
|
8
|
+
`[align] secondsFromTicks: timescale must be positive and finite, got ${timescale}`
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
return ticks / timescale;
|
|
12
|
+
}
|
|
13
|
+
function asSeconds(n) {
|
|
14
|
+
if (!Number.isFinite(n)) {
|
|
15
|
+
throw new Error(`[align] asSeconds: value must be finite, got ${n}`);
|
|
16
|
+
}
|
|
17
|
+
return n;
|
|
18
|
+
}
|
|
19
|
+
function groupIdForTicks(ticks, groupDurationTicks) {
|
|
20
|
+
if (!Number.isInteger(ticks)) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`[align] groupIdForTicks: ticks must be an integer, got ${ticks}`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
if (!Number.isInteger(groupDurationTicks) || groupDurationTicks <= 0) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`[align] groupIdForTicks: groupDurationTicks must be a positive integer, got ${groupDurationTicks}`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
if (ticks < 0) return 0;
|
|
31
|
+
return Math.floor(ticks / groupDurationTicks);
|
|
32
|
+
}
|
|
33
|
+
function groupIdFor(mediaTimeSec, groupDurationSec) {
|
|
34
|
+
if (!Number.isFinite(mediaTimeSec)) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`[align] groupIdFor: mediaTimeSec must be a finite number, got ${mediaTimeSec}`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
if (!Number.isFinite(groupDurationSec) || groupDurationSec <= 0) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`[align] groupIdFor: groupDurationSec must be a positive finite number, got ${groupDurationSec}`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
if (mediaTimeSec < 0) return 0;
|
|
45
|
+
const TS = 1e9;
|
|
46
|
+
const ticks = Math.round(mediaTimeSec * TS);
|
|
47
|
+
const durTicks = Math.round(groupDurationSec * TS);
|
|
48
|
+
if (durTicks <= 0) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`[align] groupIdFor: groupDurationSec=${groupDurationSec} rounds to <1 tick at 1e9 Hz; pass groupIdForTicks directly for sub-nanosecond durations`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
if (!Number.isSafeInteger(ticks)) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`[align] groupIdFor: mediaTimeSec=${mediaTimeSec} overflows safe-integer ticks at 1e9 Hz (>~104 days); use groupIdForTicks with a narrower timescale`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return groupIdForTicks(ticks, durTicks);
|
|
59
|
+
}
|
|
60
|
+
function driftCheck(expected, actual) {
|
|
61
|
+
if (!Number.isInteger(expected) || !Number.isInteger(actual)) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`[align] driftCheck: both arguments must be integer groupIds, got expected=${expected} actual=${actual}`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
const deltaGroups = actual - expected;
|
|
67
|
+
if (deltaGroups === 0) return { kind: "aligned", deltaGroups: 0 };
|
|
68
|
+
return { kind: "drifted", deltaGroups };
|
|
69
|
+
}
|
|
70
|
+
function subgroupKeyFor(input) {
|
|
71
|
+
if (input.kind === "mpu-metadata") return "metadata:0";
|
|
72
|
+
const values = input.kind === "timed" ? [input.movieFragmentSequenceNumber, input.sampleNumber] : [input.itemId];
|
|
73
|
+
for (const value of values) {
|
|
74
|
+
if (!Number.isInteger(value) || value < 0 || value > 4294967295) {
|
|
75
|
+
throw new Error(`[align] subgroup key coordinates must be uint32, got ${value}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return input.kind === "timed" ? `timed:${input.movieFragmentSequenceNumber}:${input.sampleNumber}` : `non-timed:${input.itemId}`;
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
asSeconds,
|
|
82
|
+
driftCheck,
|
|
83
|
+
groupIdFor,
|
|
84
|
+
groupIdForTicks,
|
|
85
|
+
secondsFromTicks,
|
|
86
|
+
subgroupKeyFor
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=align.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/align.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Shared group-alignment primitive for MMT over MoQ switching sets.\n *\n * Pure math \u2014 no MMT wire parsing, no CMCD, no I/O. Callers wire the output\n * into their own drift-observation plumbing (see media-router.ts for the\n * libmmt wiring).\n *\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * Contract (integer-ticks form, authoritative):\n *\n * groupId = ticks < 0 ? 0 : floor(ticks / groupDurationTicks)\n *\n * Where `ticks` is a media timestamp expressed at the catalog's `timescale`\n * (Hz), and `groupDurationTicks = groupDurationSec * timescale`.\n *\n * Integer math means there is no epsilon and no float rounding to reason\n * about. The seconds-form wrapper `groupIdFor(Seconds, seconds)` exists for\n * legacy callers but converts to ticks internally.\n *\n * Every sender/receiver that emits or consumes MoQ groups from an MMT or\n * CMAF switching set MUST derive groupId from this formula so that base,\n * delta, and repair tracks agree on the group boundary for a given media\n * timestamp across languages and processes.\n *\n * Test vectors that exercise the contract live at\n * `packages/container/test-vectors/align.json`; the Go and Rust siblings\n * load the same fixture so cross-language agreement is executable, not\n * prose. **Formula changes require updating the fixture AND all three\n * sibling implementations in the same release** \u2014 divergence between\n * sender/relay/receiver is worse than any formula change.\n *\n * Canonical implementations:\n * Go: Blockcast/multicast `cmd/caddy/sender/group_align.go`\n * (commit 104eeff) \u2014 sender-side groupId stamping on egress.\n * Rust: moqtail/moqtail `apps/relay/src/server/abr.rs`\n * (commit 39accbf; experimental branch, may be rebased \u2014 rely\n * on the SHA, not the branch name) \u2014 relay-side check.\n * TS: THIS FILE (libmmt) \u2014 consumed by moq-lib + moqtail-ts via\n * @blockcast/mmt-container.\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n */\n\n/**\n * Branded seconds type. Construct only via `secondsFromTicks(ticks, timescale)`\n * or `asSeconds(n)` (the latter exists solely for tests and bring-up). The\n * brand prevents accidentally passing a raw tick count \u2014 or a Date.now()\n * millisecond \u2014 to an API that expects a media-time in seconds.\n */\nexport type Seconds = number & { readonly __brand: 'Seconds' }\n\n/**\n * Explicit conversion constructor: ticks at `timescale` Hz \u2192 Seconds.\n *\n * Call this at the wire/catalog boundary so the brand flows with the value\n * through the rest of the system. Throws on non-finite inputs or\n * non-positive timescale (CLAUDE.md \u00A7Architectural Principles: error on\n * bad init).\n */\nexport function secondsFromTicks(ticks: number, timescale: number): Seconds {\n if (!Number.isFinite(ticks)) {\n throw new Error(`[align] secondsFromTicks: ticks must be finite, got ${ticks}`)\n }\n if (!Number.isFinite(timescale) || timescale <= 0) {\n throw new Error(\n `[align] secondsFromTicks: timescale must be positive and finite, got ${timescale}`,\n )\n }\n return (ticks / timescale) as Seconds\n}\n\n/**\n * Escape hatch for tests / bring-up code that holds a raw seconds number\n * (e.g. a catalog field that ships as float seconds). Production code\n * should prefer `secondsFromTicks` so the conversion site is explicit.\n */\nexport function asSeconds(n: number): Seconds {\n if (!Number.isFinite(n)) {\n throw new Error(`[align] asSeconds: value must be finite, got ${n}`)\n }\n return n as Seconds\n}\n\n/**\n * Deterministic groupId from integer ticks. Authoritative form of the\n * contract (see module docstring).\n *\n * @param ticks \u2014 media presentation time in ticks (integer).\n * Negative values clamp to group 0 (matches\n * the Go sibling's base-clamp).\n * @param groupDurationTicks \u2014 group duration in ticks (positive integer).\n * @returns non-negative integer groupId.\n *\n * Throws on non-integer/non-finite inputs or non-positive duration. These\n * are init-time errors, not packet-hot-path errors \u2014 callers ingesting\n * wire data should validate once at catalog load, not once per packet.\n */\nexport function groupIdForTicks(ticks: number, groupDurationTicks: number): number {\n if (!Number.isInteger(ticks)) {\n throw new Error(\n `[align] groupIdForTicks: ticks must be an integer, got ${ticks}`,\n )\n }\n if (!Number.isInteger(groupDurationTicks) || groupDurationTicks <= 0) {\n throw new Error(\n `[align] groupIdForTicks: groupDurationTicks must be a positive integer, got ${groupDurationTicks}`,\n )\n }\n if (ticks < 0) return 0\n return Math.floor(ticks / groupDurationTicks)\n}\n\n/**\n * Seconds-form wrapper around `groupIdForTicks`. Kept for backwards\n * compatibility with existing callers that hold `Seconds` (or a raw\n * `number` that semantically represents seconds).\n *\n * Internally converts to ticks using a synthetic 1e9 Hz timescale so the\n * integer-math contract is the single source of truth. The `| number`\n * branch of the parameter type is a migration ramp \u2014 new code should\n * pass `Seconds` explicitly (via `secondsFromTicks` or `asSeconds`).\n *\n * @param mediaTimeSec \u2014 finite number of seconds; negatives clamp to 0.\n * @param groupDurationSec \u2014 positive finite seconds.\n *\n * @deprecated Use `groupIdForTicks(ticks, groupDurationTicks)` with\n * tick-space inputs from the catalog. The seconds wrapper rounds to the\n * nearest nanosecond and throws above ~104 days of media time; the\n * integer-ticks form has no rounding and a much wider safe range.\n *\n * The rounding is not benign: when `groupDurationTicks / timescale` is not\n * ns-exact (33333@90k, 1001@30k, 1024@44.1k \u2014 all real catalog cadences)\n * the quantized duration under-counts and `expected` slips a whole group.\n * See the divergence fixture in `__tests__/align.test.ts`.\n *\n * No non-test caller remains in this package: `MediaRouter` now takes\n * `GroupBoundaryTicks` (PCL-2211). Removal is tracked by BLO-21176.\n */\nexport function groupIdFor(\n mediaTimeSec: Seconds | number,\n groupDurationSec: number,\n): number {\n if (!Number.isFinite(mediaTimeSec as number)) {\n throw new Error(\n `[align] groupIdFor: mediaTimeSec must be a finite number, got ${mediaTimeSec}`,\n )\n }\n if (!Number.isFinite(groupDurationSec) || groupDurationSec <= 0) {\n throw new Error(\n `[align] groupIdFor: groupDurationSec must be a positive finite number, got ${groupDurationSec}`,\n )\n }\n if ((mediaTimeSec as number) < 0) return 0\n // 1e9 Hz keeps both operands inside Number.MAX_SAFE_INTEGER (2^53-1)\n // for ~104 days of media time. Beyond that, Math.round returns a\n // non-safe-integer float that Number.isInteger still accepts \u2014 throw\n // explicitly so the caller picks a narrower timescale rather than\n // silently quantizing.\n const TS = 1_000_000_000\n const ticks = Math.round((mediaTimeSec as number) * TS)\n const durTicks = Math.round(groupDurationSec * TS)\n if (durTicks <= 0) {\n throw new Error(\n `[align] groupIdFor: groupDurationSec=${groupDurationSec} rounds to <1 tick at 1e9 Hz; pass groupIdForTicks directly for sub-nanosecond durations`,\n )\n }\n if (!Number.isSafeInteger(ticks)) {\n throw new Error(\n `[align] groupIdFor: mediaTimeSec=${mediaTimeSec} overflows safe-integer ticks at 1e9 Hz (>~104 days); use groupIdForTicks with a narrower timescale`,\n )\n }\n return groupIdForTicks(ticks, durTicks)\n}\n\n/**\n * Result of a drift check between expected and actual groupIds.\n *\n * Discriminated on `kind` so callers must handle both outcomes explicitly\n * (the previous `{ drifted: boolean, deltaGroups: number }` shape let a\n * drifted result slip through with a silent `if (result.drifted)` gate).\n */\nexport type DriftCheckResult =\n | { readonly kind: 'aligned'; readonly deltaGroups: 0 }\n | { readonly kind: 'drifted'; readonly deltaGroups: number }\n\n/**\n * Compare a packet-stamped groupId against the formula-derived expectation.\n *\n * Pure observer \u2014 does not throw on drift, does not mutate anything.\n * Callers decide how to react (e.g. bump a CMCD counter, log, ignore).\n *\n * @param expected \u2014 groupId as derived via `groupIdForTicks` or `groupIdFor`.\n * @param actual \u2014 groupId as stamped on the incoming packet/group.\n */\nexport function driftCheck(expected: number, actual: number): DriftCheckResult {\n if (!Number.isInteger(expected) || !Number.isInteger(actual)) {\n throw new Error(\n `[align] driftCheck: both arguments must be integer groupIds, got expected=${expected} actual=${actual}`,\n )\n }\n const deltaGroups = actual - expected\n if (deltaGroups === 0) return { kind: 'aligned', deltaGroups: 0 }\n return { kind: 'drifted', deltaGroups }\n}\n\nexport type MmtpSubgroupKeyInput =\n | { readonly kind: 'mpu-metadata' }\n | {\n readonly kind: 'timed'\n readonly movieFragmentSequenceNumber: number\n readonly sampleNumber: number\n }\n | { readonly kind: 'non-timed'; readonly itemId: number }\n\n/**\n * Canonical, domain-separated key for MMTP payloads sharing one MoQ subgroup.\n * This is a map/storage key, not the scalar MoQ subgroup ID. MPU metadata is\n * carried in subgroup 0; media identity remains explicit and collision-free.\n */\nexport function subgroupKeyFor(input: MmtpSubgroupKeyInput): string {\n if (input.kind === 'mpu-metadata') return 'metadata:0'\n\n const values =\n input.kind === 'timed'\n ? [input.movieFragmentSequenceNumber, input.sampleNumber]\n : [input.itemId]\n for (const value of values) {\n if (!Number.isInteger(value) || value < 0 || value > 0xffff_ffff) {\n throw new Error(`[align] subgroup key coordinates must be uint32, got ${value}`)\n }\n }\n\n return input.kind === 'timed'\n ? `timed:${input.movieFragmentSequenceNumber}:${input.sampleNumber}`\n : `non-timed:${input.itemId}`\n}\n"],
|
|
5
|
+
"mappings": ";AA0DO,SAAS,iBAAiB,OAAe,WAA4B;AAC1E,MAAI,CAAC,OAAO,SAAS,KAAK,GAAG;AAC3B,UAAM,IAAI,MAAM,uDAAuD,KAAK,EAAE;AAAA,EAChF;AACA,MAAI,CAAC,OAAO,SAAS,SAAS,KAAK,aAAa,GAAG;AACjD,UAAM,IAAI;AAAA,MACR,wEAAwE,SAAS;AAAA,IACnF;AAAA,EACF;AACA,SAAQ,QAAQ;AAClB;AAOO,SAAS,UAAU,GAAoB;AAC5C,MAAI,CAAC,OAAO,SAAS,CAAC,GAAG;AACvB,UAAM,IAAI,MAAM,gDAAgD,CAAC,EAAE;AAAA,EACrE;AACA,SAAO;AACT;AAgBO,SAAS,gBAAgB,OAAe,oBAAoC;AACjF,MAAI,CAAC,OAAO,UAAU,KAAK,GAAG;AAC5B,UAAM,IAAI;AAAA,MACR,0DAA0D,KAAK;AAAA,IACjE;AAAA,EACF;AACA,MAAI,CAAC,OAAO,UAAU,kBAAkB,KAAK,sBAAsB,GAAG;AACpE,UAAM,IAAI;AAAA,MACR,+EAA+E,kBAAkB;AAAA,IACnG;AAAA,EACF;AACA,MAAI,QAAQ,EAAG,QAAO;AACtB,SAAO,KAAK,MAAM,QAAQ,kBAAkB;AAC9C;AA4BO,SAAS,WACd,cACA,kBACQ;AACR,MAAI,CAAC,OAAO,SAAS,YAAsB,GAAG;AAC5C,UAAM,IAAI;AAAA,MACR,iEAAiE,YAAY;AAAA,IAC/E;AAAA,EACF;AACA,MAAI,CAAC,OAAO,SAAS,gBAAgB,KAAK,oBAAoB,GAAG;AAC/D,UAAM,IAAI;AAAA,MACR,8EAA8E,gBAAgB;AAAA,IAChG;AAAA,EACF;AACA,MAAK,eAA0B,EAAG,QAAO;AAMzC,QAAM,KAAK;AACX,QAAM,QAAQ,KAAK,MAAO,eAA0B,EAAE;AACtD,QAAM,WAAW,KAAK,MAAM,mBAAmB,EAAE;AACjD,MAAI,YAAY,GAAG;AACjB,UAAM,IAAI;AAAA,MACR,wCAAwC,gBAAgB;AAAA,IAC1D;AAAA,EACF;AACA,MAAI,CAAC,OAAO,cAAc,KAAK,GAAG;AAChC,UAAM,IAAI;AAAA,MACR,oCAAoC,YAAY;AAAA,IAClD;AAAA,EACF;AACA,SAAO,gBAAgB,OAAO,QAAQ;AACxC;AAsBO,SAAS,WAAW,UAAkB,QAAkC;AAC7E,MAAI,CAAC,OAAO,UAAU,QAAQ,KAAK,CAAC,OAAO,UAAU,MAAM,GAAG;AAC5D,UAAM,IAAI;AAAA,MACR,6EAA6E,QAAQ,WAAW,MAAM;AAAA,IACxG;AAAA,EACF;AACA,QAAM,cAAc,SAAS;AAC7B,MAAI,gBAAgB,EAAG,QAAO,EAAE,MAAM,WAAW,aAAa,EAAE;AAChE,SAAO,EAAE,MAAM,WAAW,YAAY;AACxC;AAgBO,SAAS,eAAe,OAAqC;AAClE,MAAI,MAAM,SAAS,eAAgB,QAAO;AAE1C,QAAM,SACJ,MAAM,SAAS,UACX,CAAC,MAAM,6BAA6B,MAAM,YAAY,IACtD,CAAC,MAAM,MAAM;AACnB,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,YAAa;AAChE,YAAM,IAAI,MAAM,wDAAwD,KAAK,EAAE;AAAA,IACjF;AAAA,EACF;AAEA,SAAO,MAAM,SAAS,UAClB,SAAS,MAAM,2BAA2B,IAAI,MAAM,YAAY,KAChE,aAAa,MAAM,MAAM;AAC/B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audio Init Data Parser — extract frame samples from a codec descriptor.
|
|
3
|
+
*
|
|
4
|
+
* Consumes the RAW codec configuration bytes (AudioSpecificConfig for AAC,
|
|
5
|
+
* OpusHead for Opus) — i.e. the catalog `description` field (hang
|
|
6
|
+
* `AudioConfig.description`), NOT the catalog `initData` field.
|
|
7
|
+
*
|
|
8
|
+
* Since BLO-9884 these are two distinct catalog fields: `initData` is a
|
|
9
|
+
* base64 ISOBMFF init segment (ftyp + moov) per draft-ietf-moq-cmsf-00 §3.1,
|
|
10
|
+
* while `description` carries the bare codec descriptor. Hang's `root.ts`
|
|
11
|
+
* parses a CMSF `initData` segment with `decodeInitSegment()` and routes the
|
|
12
|
+
* descriptor it recovers (`init.description`) into `description`; the bytes
|
|
13
|
+
* that reach this parser are therefore always the bare descriptor. Do NOT
|
|
14
|
+
* pass a ftyp+moov `initData` blob here — the ASC bit-reader would interpret
|
|
15
|
+
* the ftyp box size word as an audioObjectType and return a garbage frame
|
|
16
|
+
* count (the audio analogue of the "Failed to parse avcC" CMAF regression
|
|
17
|
+
* documented in root.ts).
|
|
18
|
+
*
|
|
19
|
+
* Supported codecs:
|
|
20
|
+
* - AAC (mp4a.40.*): AudioSpecificConfig per ISO 14496-3 §1.6.2.1
|
|
21
|
+
* - Opus: fixed 960 samples per RFC 6716 §2.1.4
|
|
22
|
+
*
|
|
23
|
+
* Reference: hang-mmt-fec/rs/moq-mux/src/import/aac.rs:AacConfig::parse()
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Parse AAC AudioSpecificConfig (ASC) to extract frame samples.
|
|
27
|
+
*
|
|
28
|
+
* ASC is a bit-packed structure (ISO 14496-3 §1.6.2.1):
|
|
29
|
+
* audioObjectType (5 bits, or 5+6 if ==31)
|
|
30
|
+
* samplingFrequencyIndex (4 bits, explicit rate if ==0xf)
|
|
31
|
+
* channelConfiguration (4 bits)
|
|
32
|
+
* ... (SBR/PS extensions follow)
|
|
33
|
+
*
|
|
34
|
+
* The audioObjectType determines frame samples:
|
|
35
|
+
* LC-AAC → 1024, HE-AAC(SBR) → 2048, AAC-LD → 512, AAC-ELD → 480
|
|
36
|
+
*
|
|
37
|
+
* @param asc - Raw AudioSpecificConfig bytes (NOT ADTS, NOT fMP4 esds box)
|
|
38
|
+
* @returns frame samples, or null if ASC is invalid/too short
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseAacFrameSamples(asc: Uint8Array): number | null;
|
|
41
|
+
/**
|
|
42
|
+
* Parse AAC ASC to extract sample rate.
|
|
43
|
+
* Useful when catalog samplerate is missing but initData is available.
|
|
44
|
+
*/
|
|
45
|
+
export declare function parseAacSampleRate(asc: Uint8Array): number | null;
|
|
46
|
+
/**
|
|
47
|
+
* Opus frame samples: 960 at 48kHz (20ms) per RFC 6716 §2.1.4.
|
|
48
|
+
*
|
|
49
|
+
* Opus supports variable frame sizes (2.5, 5, 10, 20, 40, 60, 80, 100, 120ms)
|
|
50
|
+
* but the frame size is per-packet (in the TOC byte), not in the init data.
|
|
51
|
+
* OpusHead (RFC 7845) carries sample_rate and channel_count only.
|
|
52
|
+
*
|
|
53
|
+
* 960 samples at 48kHz = 20ms is the normative default per RFC 6716.
|
|
54
|
+
*/
|
|
55
|
+
export declare function parseOpusFrameSamples(_opusHead?: Uint8Array): number;
|
|
56
|
+
/**
|
|
57
|
+
* Extract frame samples from a bare codec descriptor based on codec string.
|
|
58
|
+
*
|
|
59
|
+
* @param codec - Codec string from catalog (e.g., "mp4a.40.2", "opus")
|
|
60
|
+
* @param codecConfig - Raw codec descriptor bytes: AudioSpecificConfig for
|
|
61
|
+
* AAC, OpusHead for Opus. This is the catalog `description` field, NOT the
|
|
62
|
+
* catalog `initData` (ftyp+moov) field — see the file header.
|
|
63
|
+
* @returns frame samples, or null if codec unsupported or the descriptor is invalid
|
|
64
|
+
*/
|
|
65
|
+
export declare function frameSamplesFromInit(codec: string, codecConfig: Uint8Array): number | null;
|
|
66
|
+
//# sourceMappingURL=audio-init-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-init-parser.d.ts","sourceRoot":"","sources":["../src/audio-init-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA+BH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAuDnE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CA0BjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAEpE;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAQ1F"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// src/audio-init-parser.ts
|
|
2
|
+
var AAC_SAMPLE_RATES = [
|
|
3
|
+
96e3,
|
|
4
|
+
88200,
|
|
5
|
+
64e3,
|
|
6
|
+
48e3,
|
|
7
|
+
44100,
|
|
8
|
+
32e3,
|
|
9
|
+
24e3,
|
|
10
|
+
22050,
|
|
11
|
+
16e3,
|
|
12
|
+
12e3,
|
|
13
|
+
11025,
|
|
14
|
+
8e3,
|
|
15
|
+
7350
|
|
16
|
+
];
|
|
17
|
+
function aacFrameSamplesForObjectType(objectType) {
|
|
18
|
+
switch (objectType) {
|
|
19
|
+
case 5:
|
|
20
|
+
return 2048;
|
|
21
|
+
// SBR (HE-AAC v1)
|
|
22
|
+
case 29:
|
|
23
|
+
return 2048;
|
|
24
|
+
// PS (HE-AAC v2, implies SBR)
|
|
25
|
+
case 23:
|
|
26
|
+
return 512;
|
|
27
|
+
// ER AAC-LD
|
|
28
|
+
case 39:
|
|
29
|
+
return 480;
|
|
30
|
+
// ER AAC-ELD
|
|
31
|
+
default:
|
|
32
|
+
return 1024;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function parseAacFrameSamples(asc) {
|
|
36
|
+
if (asc.length < 2) return null;
|
|
37
|
+
let bitPos = 0;
|
|
38
|
+
const readBits = (n) => {
|
|
39
|
+
let val = 0;
|
|
40
|
+
for (let i = 0; i < n; i++) {
|
|
41
|
+
const byteIdx = bitPos + i >> 3;
|
|
42
|
+
const bitIdx = 7 - (bitPos + i & 7);
|
|
43
|
+
if (byteIdx >= asc.length) return -1;
|
|
44
|
+
val = val << 1 | asc[byteIdx] >> bitIdx & 1;
|
|
45
|
+
}
|
|
46
|
+
bitPos += n;
|
|
47
|
+
return val;
|
|
48
|
+
};
|
|
49
|
+
let objectType = readBits(5);
|
|
50
|
+
if (objectType === 31) {
|
|
51
|
+
objectType = 32 + readBits(6);
|
|
52
|
+
}
|
|
53
|
+
if (objectType < 0) return null;
|
|
54
|
+
const freqIndex = readBits(4);
|
|
55
|
+
if (freqIndex < 0) return null;
|
|
56
|
+
if (freqIndex === 15) {
|
|
57
|
+
readBits(24);
|
|
58
|
+
}
|
|
59
|
+
readBits(4);
|
|
60
|
+
if (objectType === 2 && asc.length >= 4) {
|
|
61
|
+
const remaining = asc.length * 8 - bitPos;
|
|
62
|
+
if (remaining >= 11) {
|
|
63
|
+
const syncExt = readBits(11);
|
|
64
|
+
if (syncExt === 695) {
|
|
65
|
+
const extObjectType = readBits(5);
|
|
66
|
+
if (extObjectType === 5 || extObjectType === 22) {
|
|
67
|
+
return 2048;
|
|
68
|
+
}
|
|
69
|
+
if (extObjectType === 29) {
|
|
70
|
+
return 2048;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return aacFrameSamplesForObjectType(objectType);
|
|
76
|
+
}
|
|
77
|
+
function parseAacSampleRate(asc) {
|
|
78
|
+
if (asc.length < 2) return null;
|
|
79
|
+
let bitPos = 0;
|
|
80
|
+
const readBits = (n) => {
|
|
81
|
+
let val = 0;
|
|
82
|
+
for (let i = 0; i < n; i++) {
|
|
83
|
+
const byteIdx = bitPos + i >> 3;
|
|
84
|
+
const bitIdx = 7 - (bitPos + i & 7);
|
|
85
|
+
if (byteIdx >= asc.length) return -1;
|
|
86
|
+
val = val << 1 | asc[byteIdx] >> bitIdx & 1;
|
|
87
|
+
}
|
|
88
|
+
bitPos += n;
|
|
89
|
+
return val;
|
|
90
|
+
};
|
|
91
|
+
let objectType = readBits(5);
|
|
92
|
+
if (objectType === 31) readBits(6);
|
|
93
|
+
const freqIndex = readBits(4);
|
|
94
|
+
if (freqIndex < 0) return null;
|
|
95
|
+
if (freqIndex === 15) {
|
|
96
|
+
return readBits(24);
|
|
97
|
+
}
|
|
98
|
+
return AAC_SAMPLE_RATES[freqIndex] ?? null;
|
|
99
|
+
}
|
|
100
|
+
function parseOpusFrameSamples(_opusHead) {
|
|
101
|
+
return 960;
|
|
102
|
+
}
|
|
103
|
+
function frameSamplesFromInit(codec, codecConfig) {
|
|
104
|
+
if (codec.startsWith("mp4a")) {
|
|
105
|
+
return parseAacFrameSamples(codecConfig);
|
|
106
|
+
}
|
|
107
|
+
if (codec.startsWith("opus") || codec === "Opus") {
|
|
108
|
+
return parseOpusFrameSamples(codecConfig);
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
export {
|
|
113
|
+
frameSamplesFromInit,
|
|
114
|
+
parseAacFrameSamples,
|
|
115
|
+
parseAacSampleRate,
|
|
116
|
+
parseOpusFrameSamples
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=audio-init-parser.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/audio-init-parser.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Audio Init Data Parser \u2014 extract frame samples from a codec descriptor.\n *\n * Consumes the RAW codec configuration bytes (AudioSpecificConfig for AAC,\n * OpusHead for Opus) \u2014 i.e. the catalog `description` field (hang\n * `AudioConfig.description`), NOT the catalog `initData` field.\n *\n * Since BLO-9884 these are two distinct catalog fields: `initData` is a\n * base64 ISOBMFF init segment (ftyp + moov) per draft-ietf-moq-cmsf-00 \u00A73.1,\n * while `description` carries the bare codec descriptor. Hang's `root.ts`\n * parses a CMSF `initData` segment with `decodeInitSegment()` and routes the\n * descriptor it recovers (`init.description`) into `description`; the bytes\n * that reach this parser are therefore always the bare descriptor. Do NOT\n * pass a ftyp+moov `initData` blob here \u2014 the ASC bit-reader would interpret\n * the ftyp box size word as an audioObjectType and return a garbage frame\n * count (the audio analogue of the \"Failed to parse avcC\" CMAF regression\n * documented in root.ts).\n *\n * Supported codecs:\n * - AAC (mp4a.40.*): AudioSpecificConfig per ISO 14496-3 \u00A71.6.2.1\n * - Opus: fixed 960 samples per RFC 6716 \u00A72.1.4\n *\n * Reference: hang-mmt-fec/rs/moq-mux/src/import/aac.rs:AacConfig::parse()\n */\n\n// ISO 14496-3 Table 1.14: samplingFrequencyIndex \u2192 Hz\nconst AAC_SAMPLE_RATES = [\n 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,\n 16000, 12000, 11025, 8000, 7350,\n] as const\n\n/**\n * AAC Audio Object Types that determine frame size.\n * ISO 14496-3 Table 1.3:\n * 1 = AAC-Main \u2192 1024 samples\n * 2 = AAC-LC \u2192 1024 samples\n * 3 = AAC-SSR \u2192 1024 samples\n * 4 = AAC-LTP \u2192 1024 samples\n * 5 = SBR \u2192 2048 samples (HE-AAC v1)\n * 6 = AAC-Scalable \u2192 1024 samples\n * 23 = ER AAC-LD \u2192 512 samples\n * 39 = ER AAC-ELD \u2192 480 samples\n * 29 = PS \u2192 2048 samples (HE-AAC v2, implies SBR)\n */\nfunction aacFrameSamplesForObjectType(objectType: number): number {\n switch (objectType) {\n case 5: return 2048 // SBR (HE-AAC v1)\n case 29: return 2048 // PS (HE-AAC v2, implies SBR)\n case 23: return 512 // ER AAC-LD\n case 39: return 480 // ER AAC-ELD\n default: return 1024 // LC, Main, SSR, LTP, Scalable, etc.\n }\n}\n\n/**\n * Parse AAC AudioSpecificConfig (ASC) to extract frame samples.\n *\n * ASC is a bit-packed structure (ISO 14496-3 \u00A71.6.2.1):\n * audioObjectType (5 bits, or 5+6 if ==31)\n * samplingFrequencyIndex (4 bits, explicit rate if ==0xf)\n * channelConfiguration (4 bits)\n * ... (SBR/PS extensions follow)\n *\n * The audioObjectType determines frame samples:\n * LC-AAC \u2192 1024, HE-AAC(SBR) \u2192 2048, AAC-LD \u2192 512, AAC-ELD \u2192 480\n *\n * @param asc - Raw AudioSpecificConfig bytes (NOT ADTS, NOT fMP4 esds box)\n * @returns frame samples, or null if ASC is invalid/too short\n */\nexport function parseAacFrameSamples(asc: Uint8Array): number | null {\n if (asc.length < 2) return null\n\n // Bit reader\n let bitPos = 0\n const readBits = (n: number): number => {\n let val = 0\n for (let i = 0; i < n; i++) {\n const byteIdx = (bitPos + i) >> 3\n const bitIdx = 7 - ((bitPos + i) & 7)\n if (byteIdx >= asc.length) return -1\n val = (val << 1) | ((asc[byteIdx]! >> bitIdx) & 1)\n }\n bitPos += n\n return val\n }\n\n // audioObjectType: 5 bits, extended to 5+6=11 bits if ==31\n let objectType = readBits(5)\n if (objectType === 31) {\n objectType = 32 + readBits(6)\n }\n if (objectType < 0) return null\n\n // samplingFrequencyIndex: 4 bits\n const freqIndex = readBits(4)\n if (freqIndex < 0) return null\n if (freqIndex === 0xf) {\n // Explicit 24-bit sample rate follows\n readBits(24)\n }\n\n // channelConfiguration: 4 bits\n readBits(4)\n\n // Check for SBR/PS signaling (implicit in HE-AAC)\n // If base objectType is AAC-LC and SBR extension is present, frame size doubles\n if (objectType === 2 /* AAC-LC */ && asc.length >= 4) {\n // Check for SBR extension: 11-bit sync word 0x2b7\n const remaining = (asc.length * 8) - bitPos\n if (remaining >= 11) {\n const syncExt = readBits(11)\n if (syncExt === 0x2b7) {\n const extObjectType = readBits(5)\n if (extObjectType === 5 /* SBR */ || extObjectType === 22 /* ER SBR */) {\n return 2048 // SBR present \u2192 2048 samples\n }\n if (extObjectType === 29 /* PS */) {\n return 2048 // PS implies SBR \u2192 2048 samples\n }\n }\n }\n }\n\n return aacFrameSamplesForObjectType(objectType)\n}\n\n/**\n * Parse AAC ASC to extract sample rate.\n * Useful when catalog samplerate is missing but initData is available.\n */\nexport function parseAacSampleRate(asc: Uint8Array): number | null {\n if (asc.length < 2) return null\n\n let bitPos = 0\n const readBits = (n: number): number => {\n let val = 0\n for (let i = 0; i < n; i++) {\n const byteIdx = (bitPos + i) >> 3\n const bitIdx = 7 - ((bitPos + i) & 7)\n if (byteIdx >= asc.length) return -1\n val = (val << 1) | ((asc[byteIdx]! >> bitIdx) & 1)\n }\n bitPos += n\n return val\n }\n\n // Skip audioObjectType (5 or 11 bits)\n let objectType = readBits(5)\n if (objectType === 31) readBits(6)\n\n const freqIndex = readBits(4)\n if (freqIndex < 0) return null\n if (freqIndex === 0xf) {\n return readBits(24)\n }\n return AAC_SAMPLE_RATES[freqIndex] ?? null\n}\n\n/**\n * Opus frame samples: 960 at 48kHz (20ms) per RFC 6716 \u00A72.1.4.\n *\n * Opus supports variable frame sizes (2.5, 5, 10, 20, 40, 60, 80, 100, 120ms)\n * but the frame size is per-packet (in the TOC byte), not in the init data.\n * OpusHead (RFC 7845) carries sample_rate and channel_count only.\n *\n * 960 samples at 48kHz = 20ms is the normative default per RFC 6716.\n */\nexport function parseOpusFrameSamples(_opusHead?: Uint8Array): number {\n return 960\n}\n\n/**\n * Extract frame samples from a bare codec descriptor based on codec string.\n *\n * @param codec - Codec string from catalog (e.g., \"mp4a.40.2\", \"opus\")\n * @param codecConfig - Raw codec descriptor bytes: AudioSpecificConfig for\n * AAC, OpusHead for Opus. This is the catalog `description` field, NOT the\n * catalog `initData` (ftyp+moov) field \u2014 see the file header.\n * @returns frame samples, or null if codec unsupported or the descriptor is invalid\n */\nexport function frameSamplesFromInit(codec: string, codecConfig: Uint8Array): number | null {\n if (codec.startsWith('mp4a')) {\n return parseAacFrameSamples(codecConfig)\n }\n if (codec.startsWith('opus') || codec === 'Opus') {\n return parseOpusFrameSamples(codecConfig)\n }\n return null\n}\n"],
|
|
5
|
+
"mappings": ";AA0BA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EACjD;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAM;AAC7B;AAeA,SAAS,6BAA6B,YAA4B;AAChE,UAAQ,YAAY;AAAA,IAClB,KAAK;AAAI,aAAO;AAAA;AAAA,IAChB,KAAK;AAAI,aAAO;AAAA;AAAA,IAChB,KAAK;AAAI,aAAO;AAAA;AAAA,IAChB,KAAK;AAAI,aAAO;AAAA;AAAA,IAChB;AAAS,aAAO;AAAA,EAClB;AACF;AAiBO,SAAS,qBAAqB,KAAgC;AACnE,MAAI,IAAI,SAAS,EAAG,QAAO;AAG3B,MAAI,SAAS;AACb,QAAM,WAAW,CAAC,MAAsB;AACtC,QAAI,MAAM;AACV,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,UAAW,SAAS,KAAM;AAChC,YAAM,SAAS,KAAM,SAAS,IAAK;AACnC,UAAI,WAAW,IAAI,OAAQ,QAAO;AAClC,YAAO,OAAO,IAAO,IAAI,OAAO,KAAM,SAAU;AAAA,IAClD;AACA,cAAU;AACV,WAAO;AAAA,EACT;AAGA,MAAI,aAAa,SAAS,CAAC;AAC3B,MAAI,eAAe,IAAI;AACrB,iBAAa,KAAK,SAAS,CAAC;AAAA,EAC9B;AACA,MAAI,aAAa,EAAG,QAAO;AAG3B,QAAM,YAAY,SAAS,CAAC;AAC5B,MAAI,YAAY,EAAG,QAAO;AAC1B,MAAI,cAAc,IAAK;AAErB,aAAS,EAAE;AAAA,EACb;AAGA,WAAS,CAAC;AAIV,MAAI,eAAe,KAAkB,IAAI,UAAU,GAAG;AAEpD,UAAM,YAAa,IAAI,SAAS,IAAK;AACrC,QAAI,aAAa,IAAI;AACnB,YAAM,UAAU,SAAS,EAAE;AAC3B,UAAI,YAAY,KAAO;AACrB,cAAM,gBAAgB,SAAS,CAAC;AAChC,YAAI,kBAAkB,KAAe,kBAAkB,IAAiB;AACtE,iBAAO;AAAA,QACT;AACA,YAAI,kBAAkB,IAAa;AACjC,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,6BAA6B,UAAU;AAChD;AAMO,SAAS,mBAAmB,KAAgC;AACjE,MAAI,IAAI,SAAS,EAAG,QAAO;AAE3B,MAAI,SAAS;AACb,QAAM,WAAW,CAAC,MAAsB;AACtC,QAAI,MAAM;AACV,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,UAAW,SAAS,KAAM;AAChC,YAAM,SAAS,KAAM,SAAS,IAAK;AACnC,UAAI,WAAW,IAAI,OAAQ,QAAO;AAClC,YAAO,OAAO,IAAO,IAAI,OAAO,KAAM,SAAU;AAAA,IAClD;AACA,cAAU;AACV,WAAO;AAAA,EACT;AAGA,MAAI,aAAa,SAAS,CAAC;AAC3B,MAAI,eAAe,GAAI,UAAS,CAAC;AAEjC,QAAM,YAAY,SAAS,CAAC;AAC5B,MAAI,YAAY,EAAG,QAAO;AAC1B,MAAI,cAAc,IAAK;AACrB,WAAO,SAAS,EAAE;AAAA,EACpB;AACA,SAAO,iBAAiB,SAAS,KAAK;AACxC;AAWO,SAAS,sBAAsB,WAAgC;AACpE,SAAO;AACT;AAWO,SAAS,qBAAqB,OAAe,aAAwC;AAC1F,MAAI,MAAM,WAAW,MAAM,GAAG;AAC5B,WAAO,qBAAqB,WAAW;AAAA,EACzC;AACA,MAAI,MAAM,WAAW,MAAM,KAAK,UAAU,QAAQ;AAChD,WAAO,sBAAsB,WAAW;AAAA,EAC1C;AACA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AudioRingBuffer — plain FIFO audio buffer (no clock recovery).
|
|
3
|
+
*
|
|
4
|
+
* Source of truth for the audio buffer algorithm used in both moq-lib and
|
|
5
|
+
* moqtail AudioWorklet processors. AudioWorklet isolation requires the
|
|
6
|
+
* worklet copy to be self-contained (no imports), so changes here must be
|
|
7
|
+
* manually synced to:
|
|
8
|
+
* - moqtail-private/apps/client-js/src/lib/audio-worklet-processor.js
|
|
9
|
+
* - hang-mmt-fec/js/watch/src/audio/ring-buffer.ts (uses @moq/lite Time types)
|
|
10
|
+
*
|
|
11
|
+
* Rationale: FEC guarantees gap-free, ordered audio on multicast; MoQ
|
|
12
|
+
* delivers ordered audio without drops. The decoder output rate matches
|
|
13
|
+
* the AudioContext destination rate closely enough that skip/dup clock
|
|
14
|
+
* recovery is unnecessary and harmful — a single sample skip at 48 kHz is
|
|
15
|
+
* a ~21 µs phase glitch, and repeated skip/dup produces audible pitch
|
|
16
|
+
* wobble on pure tones (measured: 16 Hz offset + ±11 Hz spread on a 1 kHz
|
|
17
|
+
* test tone before this refactor).
|
|
18
|
+
*/
|
|
19
|
+
export interface AudioRingBufferConfig {
|
|
20
|
+
/** Number of audio channels */
|
|
21
|
+
channels: number;
|
|
22
|
+
/** Sample rate in Hz */
|
|
23
|
+
rate: number;
|
|
24
|
+
/** Buffer latency in milliseconds */
|
|
25
|
+
latencyMs: number;
|
|
26
|
+
/** Start in unstalled state (for source switching) */
|
|
27
|
+
startUnstalled?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare class AudioRingBuffer {
|
|
30
|
+
#private;
|
|
31
|
+
readonly channels: number;
|
|
32
|
+
readonly rate: number;
|
|
33
|
+
constructor(config: AudioRingBufferConfig);
|
|
34
|
+
get stalled(): boolean;
|
|
35
|
+
get capacity(): number;
|
|
36
|
+
get length(): number;
|
|
37
|
+
/**
|
|
38
|
+
* Append decoded audio samples to the FIFO.
|
|
39
|
+
* Timestamp parameter retained for API compatibility but is ignored —
|
|
40
|
+
* FIFO is sequence-based, not time-based.
|
|
41
|
+
*/
|
|
42
|
+
write(_timestampUs: number, data: Float32Array[]): void;
|
|
43
|
+
/**
|
|
44
|
+
* Read samples into output buffers — plain FIFO, no clock recovery.
|
|
45
|
+
* FEC + MoQ delivery guarantees no gaps, so skip/dup is unnecessary.
|
|
46
|
+
* Underrun → zero-fill.
|
|
47
|
+
*/
|
|
48
|
+
read(output: Float32Array[]): number;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=audio-ring-buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-ring-buffer.d.ts","sourceRoot":"","sources":["../src/audio-ring-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,qBAAqB;IACpC,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAOV,MAAM,EAAE,qBAAqB;IAYzC,IAAI,OAAO,IAAI,OAAO,CAA0B;IAChD,IAAI,QAAQ,IAAI,MAAM,CAAmC;IACzD,IAAI,MAAM,IAAI,MAAM,CAA+C;IAEnE;;;;OAIG;IACH,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,IAAI;IA8BvD;;;;OAIG;IACH,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM;CAwBrC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
var __typeError = (msg) => {
|
|
2
|
+
throw TypeError(msg);
|
|
3
|
+
};
|
|
4
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
8
|
+
|
|
9
|
+
// src/audio-ring-buffer.ts
|
|
10
|
+
var _buffer, _writeIndex, _readIndex, _stalled;
|
|
11
|
+
var AudioRingBuffer = class {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
__privateAdd(this, _buffer);
|
|
14
|
+
__privateAdd(this, _writeIndex, 0);
|
|
15
|
+
__privateAdd(this, _readIndex, 0);
|
|
16
|
+
__privateAdd(this, _stalled);
|
|
17
|
+
this.channels = config.channels;
|
|
18
|
+
this.rate = config.rate;
|
|
19
|
+
__privateSet(this, _stalled, !(config.startUnstalled ?? false));
|
|
20
|
+
const samples = Math.ceil(config.rate * (config.latencyMs / 1e3));
|
|
21
|
+
__privateSet(this, _buffer, []);
|
|
22
|
+
for (let i = 0; i < config.channels; i++) {
|
|
23
|
+
__privateGet(this, _buffer)[i] = new Float32Array(samples);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
get stalled() {
|
|
27
|
+
return __privateGet(this, _stalled);
|
|
28
|
+
}
|
|
29
|
+
get capacity() {
|
|
30
|
+
return __privateGet(this, _buffer)[0].length;
|
|
31
|
+
}
|
|
32
|
+
get length() {
|
|
33
|
+
return __privateGet(this, _writeIndex) - __privateGet(this, _readIndex);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Append decoded audio samples to the FIFO.
|
|
37
|
+
* Timestamp parameter retained for API compatibility but is ignored —
|
|
38
|
+
* FIFO is sequence-based, not time-based.
|
|
39
|
+
*/
|
|
40
|
+
write(_timestampUs, data) {
|
|
41
|
+
const samples = data[0].length;
|
|
42
|
+
const start = __privateGet(this, _writeIndex);
|
|
43
|
+
const end = start + samples;
|
|
44
|
+
const overflow = end - __privateGet(this, _readIndex) - __privateGet(this, _buffer)[0].length;
|
|
45
|
+
if (overflow >= 0) {
|
|
46
|
+
__privateSet(this, _stalled, false);
|
|
47
|
+
__privateSet(this, _readIndex, __privateGet(this, _readIndex) + overflow);
|
|
48
|
+
}
|
|
49
|
+
if (__privateGet(this, _stalled) && end - __privateGet(this, _readIndex) >= Math.floor(__privateGet(this, _buffer)[0].length / 2)) {
|
|
50
|
+
__privateSet(this, _stalled, false);
|
|
51
|
+
}
|
|
52
|
+
for (let ch = 0; ch < this.channels; ch++) {
|
|
53
|
+
const src = data[ch];
|
|
54
|
+
const dst = __privateGet(this, _buffer)[ch];
|
|
55
|
+
for (let i = 0; i < samples; i++) {
|
|
56
|
+
dst[(start + i) % dst.length] = src[i];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
__privateSet(this, _writeIndex, end);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Read samples into output buffers — plain FIFO, no clock recovery.
|
|
63
|
+
* FEC + MoQ delivery guarantees no gaps, so skip/dup is unnecessary.
|
|
64
|
+
* Underrun → zero-fill.
|
|
65
|
+
*/
|
|
66
|
+
read(output) {
|
|
67
|
+
if (__privateGet(this, _stalled)) return 0;
|
|
68
|
+
const available = __privateGet(this, _writeIndex) - __privateGet(this, _readIndex);
|
|
69
|
+
if (available === 0) return 0;
|
|
70
|
+
const requested = output[0].length;
|
|
71
|
+
const readSamples = Math.min(available, requested);
|
|
72
|
+
for (let ch = 0; ch < this.channels; ch++) {
|
|
73
|
+
const dst = output[ch];
|
|
74
|
+
const src = __privateGet(this, _buffer)[ch];
|
|
75
|
+
for (let i = 0; i < readSamples; i++) {
|
|
76
|
+
dst[i] = src[(__privateGet(this, _readIndex) + i) % src.length];
|
|
77
|
+
}
|
|
78
|
+
for (let i = readSamples; i < requested; i++) {
|
|
79
|
+
dst[i] = 0;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
__privateSet(this, _readIndex, __privateGet(this, _readIndex) + readSamples);
|
|
83
|
+
return readSamples;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
_buffer = new WeakMap();
|
|
87
|
+
_writeIndex = new WeakMap();
|
|
88
|
+
_readIndex = new WeakMap();
|
|
89
|
+
_stalled = new WeakMap();
|
|
90
|
+
export {
|
|
91
|
+
AudioRingBuffer
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=audio-ring-buffer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/audio-ring-buffer.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * AudioRingBuffer \u2014 plain FIFO audio buffer (no clock recovery).\n *\n * Source of truth for the audio buffer algorithm used in both moq-lib and\n * moqtail AudioWorklet processors. AudioWorklet isolation requires the\n * worklet copy to be self-contained (no imports), so changes here must be\n * manually synced to:\n * - moqtail-private/apps/client-js/src/lib/audio-worklet-processor.js\n * - hang-mmt-fec/js/watch/src/audio/ring-buffer.ts (uses @moq/lite Time types)\n *\n * Rationale: FEC guarantees gap-free, ordered audio on multicast; MoQ\n * delivers ordered audio without drops. The decoder output rate matches\n * the AudioContext destination rate closely enough that skip/dup clock\n * recovery is unnecessary and harmful \u2014 a single sample skip at 48 kHz is\n * a ~21 \u00B5s phase glitch, and repeated skip/dup produces audible pitch\n * wobble on pure tones (measured: 16 Hz offset + \u00B111 Hz spread on a 1 kHz\n * test tone before this refactor).\n */\n\nexport interface AudioRingBufferConfig {\n /** Number of audio channels */\n channels: number;\n /** Sample rate in Hz */\n rate: number;\n /** Buffer latency in milliseconds */\n latencyMs: number;\n /** Start in unstalled state (for source switching) */\n startUnstalled?: boolean;\n}\n\nexport class AudioRingBuffer {\n readonly channels: number;\n readonly rate: number;\n\n #buffer: Float32Array[];\n #writeIndex = 0;\n #readIndex = 0;\n #stalled: boolean;\n\n constructor(config: AudioRingBufferConfig) {\n this.channels = config.channels;\n this.rate = config.rate;\n this.#stalled = !(config.startUnstalled ?? false);\n\n const samples = Math.ceil(config.rate * (config.latencyMs / 1000));\n this.#buffer = [];\n for (let i = 0; i < config.channels; i++) {\n this.#buffer[i] = new Float32Array(samples);\n }\n }\n\n get stalled(): boolean { return this.#stalled; }\n get capacity(): number { return this.#buffer[0].length; }\n get length(): number { return this.#writeIndex - this.#readIndex; }\n\n /**\n * Append decoded audio samples to the FIFO.\n * Timestamp parameter retained for API compatibility but is ignored \u2014\n * FIFO is sequence-based, not time-based.\n */\n write(_timestampUs: number, data: Float32Array[]): void {\n const samples = data[0].length;\n\n const start = this.#writeIndex;\n const end = start + samples;\n\n // Overflow: discard oldest samples (protects against encoder/AudioContext\n // clock drift when one runs faster than the other).\n const overflow = end - this.#readIndex - this.#buffer[0].length;\n if (overflow >= 0) {\n this.#stalled = false;\n this.#readIndex += overflow;\n }\n\n // Unstall at half capacity \u2014 enough prebuffer for bounded jitter.\n if (this.#stalled && (end - this.#readIndex) >= Math.floor(this.#buffer[0].length / 2)) {\n this.#stalled = false;\n }\n\n // Append samples sequentially\n for (let ch = 0; ch < this.channels; ch++) {\n const src = data[ch];\n const dst = this.#buffer[ch];\n for (let i = 0; i < samples; i++) {\n dst[(start + i) % dst.length] = src[i];\n }\n }\n this.#writeIndex = end;\n }\n\n /**\n * Read samples into output buffers \u2014 plain FIFO, no clock recovery.\n * FEC + MoQ delivery guarantees no gaps, so skip/dup is unnecessary.\n * Underrun \u2192 zero-fill.\n */\n read(output: Float32Array[]): number {\n if (this.#stalled) return 0;\n\n const available = this.#writeIndex - this.#readIndex;\n if (available === 0) return 0;\n\n const requested = output[0].length;\n const readSamples = Math.min(available, requested);\n\n for (let ch = 0; ch < this.channels; ch++) {\n const dst = output[ch];\n const src = this.#buffer[ch];\n for (let i = 0; i < readSamples; i++) {\n dst[i] = src[(this.#readIndex + i) % src.length];\n }\n // Zero-fill remainder on underrun\n for (let i = readSamples; i < requested; i++) {\n dst[i] = 0;\n }\n }\n\n this.#readIndex += readSamples;\n return readSamples;\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;AAAA;AA8BO,IAAM,kBAAN,MAAsB;AAAA,EAS3B,YAAY,QAA+B;AAL3C;AACA,oCAAc;AACd,mCAAa;AACb;AAGE,SAAK,WAAW,OAAO;AACvB,SAAK,OAAO,OAAO;AACnB,uBAAK,UAAW,EAAE,OAAO,kBAAkB;AAE3C,UAAM,UAAU,KAAK,KAAK,OAAO,QAAQ,OAAO,YAAY,IAAK;AACjE,uBAAK,SAAU,CAAC;AAChB,aAAS,IAAI,GAAG,IAAI,OAAO,UAAU,KAAK;AACxC,yBAAK,SAAQ,CAAC,IAAI,IAAI,aAAa,OAAO;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,IAAI,UAAmB;AAAE,WAAO,mBAAK;AAAA,EAAU;AAAA,EAC/C,IAAI,WAAmB;AAAE,WAAO,mBAAK,SAAQ,CAAC,EAAE;AAAA,EAAQ;AAAA,EACxD,IAAI,SAAiB;AAAE,WAAO,mBAAK,eAAc,mBAAK;AAAA,EAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlE,MAAM,cAAsB,MAA4B;AACtD,UAAM,UAAU,KAAK,CAAC,EAAE;AAExB,UAAM,QAAQ,mBAAK;AACnB,UAAM,MAAM,QAAQ;AAIpB,UAAM,WAAW,MAAM,mBAAK,cAAa,mBAAK,SAAQ,CAAC,EAAE;AACzD,QAAI,YAAY,GAAG;AACjB,yBAAK,UAAW;AAChB,yBAAK,YAAL,mBAAK,cAAc;AAAA,IACrB;AAGA,QAAI,mBAAK,aAAa,MAAM,mBAAK,eAAe,KAAK,MAAM,mBAAK,SAAQ,CAAC,EAAE,SAAS,CAAC,GAAG;AACtF,yBAAK,UAAW;AAAA,IAClB;AAGA,aAAS,KAAK,GAAG,KAAK,KAAK,UAAU,MAAM;AACzC,YAAM,MAAM,KAAK,EAAE;AACnB,YAAM,MAAM,mBAAK,SAAQ,EAAE;AAC3B,eAAS,IAAI,GAAG,IAAI,SAAS,KAAK;AAChC,aAAK,QAAQ,KAAK,IAAI,MAAM,IAAI,IAAI,CAAC;AAAA,MACvC;AAAA,IACF;AACA,uBAAK,aAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAK,QAAgC;AACnC,QAAI,mBAAK,UAAU,QAAO;AAE1B,UAAM,YAAY,mBAAK,eAAc,mBAAK;AAC1C,QAAI,cAAc,EAAG,QAAO;AAE5B,UAAM,YAAY,OAAO,CAAC,EAAE;AAC5B,UAAM,cAAc,KAAK,IAAI,WAAW,SAAS;AAEjD,aAAS,KAAK,GAAG,KAAK,KAAK,UAAU,MAAM;AACzC,YAAM,MAAM,OAAO,EAAE;AACrB,YAAM,MAAM,mBAAK,SAAQ,EAAE;AAC3B,eAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,YAAI,CAAC,IAAI,KAAK,mBAAK,cAAa,KAAK,IAAI,MAAM;AAAA,MACjD;AAEA,eAAS,IAAI,aAAa,IAAI,WAAW,KAAK;AAC5C,YAAI,CAAC,IAAI;AAAA,MACX;AAAA,IACF;AAEA,uBAAK,YAAL,mBAAK,cAAc;AACnB,WAAO;AAAA,EACT;AACF;AArFE;AACA;AACA;AACA;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exact timing authored by an ISO-BMFF media fragment.
|
|
3
|
+
*
|
|
4
|
+
* `timestamp`/`duration` fields on the browser-facing APIs are converted to
|
|
5
|
+
* microseconds for legacy callers. This value remains in the media track's
|
|
6
|
+
* native timescale so consumers that own a CMAF/WebCodecs timeline do not
|
|
7
|
+
* have to reconstruct integer ticks from rounded wall-clock values.
|
|
8
|
+
*/
|
|
9
|
+
export interface AuthoredTiming {
|
|
10
|
+
/** Exact decode time in the media track's timescale. */
|
|
11
|
+
decodeTime: bigint;
|
|
12
|
+
/** Exact presentation time in the media track's timescale, including CTS. */
|
|
13
|
+
presentationTime: bigint;
|
|
14
|
+
/**
|
|
15
|
+
* Exact sample duration in the media track's timescale. This remains a
|
|
16
|
+
* number because ISO-BMFF stores sample_duration as an unsigned 32-bit
|
|
17
|
+
* field, whose full range is exactly representable by JavaScript numbers.
|
|
18
|
+
*/
|
|
19
|
+
durationTicks: number;
|
|
20
|
+
/** `mdhd` timescale for all values above. */
|
|
21
|
+
mediaTimescale: number;
|
|
22
|
+
}
|
|
23
|
+
/** Convert authored media ticks to an integer target timescale without first
|
|
24
|
+
* narrowing the authored tick value to a wall-clock float. */
|
|
25
|
+
export declare function scaleAuthoredTicks(ticks: bigint, mediaTimescale: number, targetTimescale: number): number | null;
|
|
26
|
+
/** Convert exact authored presentation time and duration to an assembler's
|
|
27
|
+
* public timestamp scale. */
|
|
28
|
+
export declare function scaleAuthoredTiming(timing: AuthoredTiming, targetTimescale: number): {
|
|
29
|
+
timestamp: number;
|
|
30
|
+
duration: number;
|
|
31
|
+
} | null;
|
|
32
|
+
//# sourceMappingURL=authored-timing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authored-timing.d.ts","sourceRoot":"","sources":["../src/authored-timing.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAA;IAClB,6EAA6E;IAC7E,gBAAgB,EAAE,MAAM,CAAA;IACxB;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,cAAc,EAAE,MAAM,CAAA;CACvB;AAED;8DAC8D;AAC9D,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,GACtB,MAAM,GAAG,IAAI,CAYf;AAED;6BAC6B;AAC7B,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,cAAc,EACtB,eAAe,EAAE,MAAM,GACtB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAchD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// src/authored-timing.ts
|
|
2
|
+
function scaleAuthoredTicks(ticks, mediaTimescale, targetTimescale) {
|
|
3
|
+
if (!Number.isSafeInteger(mediaTimescale) || mediaTimescale <= 0 || !Number.isSafeInteger(targetTimescale) || targetTimescale <= 0) return null;
|
|
4
|
+
const negative = ticks < 0n;
|
|
5
|
+
const numerator = (negative ? -ticks : ticks) * BigInt(targetTimescale);
|
|
6
|
+
const denominator = BigInt(mediaTimescale);
|
|
7
|
+
const whole = numerator / denominator;
|
|
8
|
+
const remainder = numerator % denominator;
|
|
9
|
+
if (whole > BigInt(Number.MAX_SAFE_INTEGER)) return null;
|
|
10
|
+
const value = Number(whole) + Number(remainder) / mediaTimescale;
|
|
11
|
+
return Number.isFinite(value) ? negative ? -value : value : null;
|
|
12
|
+
}
|
|
13
|
+
function scaleAuthoredTiming(timing, targetTimescale) {
|
|
14
|
+
if (!Number.isSafeInteger(timing.durationTicks) || timing.durationTicks <= 0) return null;
|
|
15
|
+
const timestamp = scaleAuthoredTicks(
|
|
16
|
+
timing.presentationTime,
|
|
17
|
+
timing.mediaTimescale,
|
|
18
|
+
targetTimescale
|
|
19
|
+
);
|
|
20
|
+
const duration = scaleAuthoredTicks(
|
|
21
|
+
BigInt(timing.durationTicks),
|
|
22
|
+
timing.mediaTimescale,
|
|
23
|
+
targetTimescale
|
|
24
|
+
);
|
|
25
|
+
if (timestamp === null || duration === null || duration <= 0) return null;
|
|
26
|
+
return { timestamp, duration };
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
scaleAuthoredTicks,
|
|
30
|
+
scaleAuthoredTiming
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=authored-timing.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/authored-timing.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Exact timing authored by an ISO-BMFF media fragment.\n *\n * `timestamp`/`duration` fields on the browser-facing APIs are converted to\n * microseconds for legacy callers. This value remains in the media track's\n * native timescale so consumers that own a CMAF/WebCodecs timeline do not\n * have to reconstruct integer ticks from rounded wall-clock values.\n */\nexport interface AuthoredTiming {\n /** Exact decode time in the media track's timescale. */\n decodeTime: bigint\n /** Exact presentation time in the media track's timescale, including CTS. */\n presentationTime: bigint\n /**\n * Exact sample duration in the media track's timescale. This remains a\n * number because ISO-BMFF stores sample_duration as an unsigned 32-bit\n * field, whose full range is exactly representable by JavaScript numbers.\n */\n durationTicks: number\n /** `mdhd` timescale for all values above. */\n mediaTimescale: number\n}\n\n/** Convert authored media ticks to an integer target timescale without first\n * narrowing the authored tick value to a wall-clock float. */\nexport function scaleAuthoredTicks(\n ticks: bigint,\n mediaTimescale: number,\n targetTimescale: number,\n): number | null {\n if (!Number.isSafeInteger(mediaTimescale) || mediaTimescale <= 0 ||\n !Number.isSafeInteger(targetTimescale) || targetTimescale <= 0) return null\n\n const negative = ticks < 0n\n const numerator = (negative ? -ticks : ticks) * BigInt(targetTimescale)\n const denominator = BigInt(mediaTimescale)\n const whole = numerator / denominator\n const remainder = numerator % denominator\n if (whole > BigInt(Number.MAX_SAFE_INTEGER)) return null\n const value = Number(whole) + Number(remainder) / mediaTimescale\n return Number.isFinite(value) ? (negative ? -value : value) : null\n}\n\n/** Convert exact authored presentation time and duration to an assembler's\n * public timestamp scale. */\nexport function scaleAuthoredTiming(\n timing: AuthoredTiming,\n targetTimescale: number,\n): { timestamp: number; duration: number } | null {\n if (!Number.isSafeInteger(timing.durationTicks) || timing.durationTicks <= 0) return null\n const timestamp = scaleAuthoredTicks(\n timing.presentationTime,\n timing.mediaTimescale,\n targetTimescale,\n )\n const duration = scaleAuthoredTicks(\n BigInt(timing.durationTicks),\n timing.mediaTimescale,\n targetTimescale,\n )\n if (timestamp === null || duration === null || duration <= 0) return null\n return { timestamp, duration }\n}\n"],
|
|
5
|
+
"mappings": ";AAyBO,SAAS,mBACd,OACA,gBACA,iBACe;AACf,MAAI,CAAC,OAAO,cAAc,cAAc,KAAK,kBAAkB,KAC3D,CAAC,OAAO,cAAc,eAAe,KAAK,mBAAmB,EAAG,QAAO;AAE3E,QAAM,WAAW,QAAQ;AACzB,QAAM,aAAa,WAAW,CAAC,QAAQ,SAAS,OAAO,eAAe;AACtE,QAAM,cAAc,OAAO,cAAc;AACzC,QAAM,QAAQ,YAAY;AAC1B,QAAM,YAAY,YAAY;AAC9B,MAAI,QAAQ,OAAO,OAAO,gBAAgB,EAAG,QAAO;AACpD,QAAM,QAAQ,OAAO,KAAK,IAAI,OAAO,SAAS,IAAI;AAClD,SAAO,OAAO,SAAS,KAAK,IAAK,WAAW,CAAC,QAAQ,QAAS;AAChE;AAIO,SAAS,oBACd,QACA,iBACgD;AAChD,MAAI,CAAC,OAAO,cAAc,OAAO,aAAa,KAAK,OAAO,iBAAiB,EAAG,QAAO;AACrF,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,IACP,OAAO;AAAA,IACP;AAAA,EACF;AACA,QAAM,WAAW;AAAA,IACf,OAAO,OAAO,aAAa;AAAA,IAC3B,OAAO;AAAA,IACP;AAAA,EACF;AACA,MAAI,cAAc,QAAQ,aAAa,QAAQ,YAAY,EAAG,QAAO;AACrE,SAAO,EAAE,WAAW,SAAS;AAC/B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|