@videojs/spf 10.0.0-beta.30 → 10.0.0-beta.32
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/dist/default/core/actors/create-machine-actor.js +23 -25
- package/dist/default/core/actors/create-machine-actor.js.map +1 -1
- package/dist/default/core/actors/create-transition-actor.js +7 -9
- package/dist/default/core/actors/create-transition-actor.js.map +1 -1
- package/dist/default/core/composition/create-composition.js +26 -29
- package/dist/default/core/composition/create-composition.js.map +1 -1
- package/dist/default/core/composition/share-signals.js +12 -17
- package/dist/default/core/composition/share-signals.js.map +1 -1
- package/dist/default/core/machine.js +3 -4
- package/dist/default/core/machine.js.map +1 -1
- package/dist/default/core/reactors/create-machine-reactor.js +20 -19
- package/dist/default/core/reactors/create-machine-reactor.js.map +1 -1
- package/dist/default/core/signals/effect.js +24 -4
- package/dist/default/core/signals/effect.js.map +1 -1
- package/dist/default/core/signals/primitives.js +10 -14
- package/dist/default/core/signals/primitives.js.map +1 -1
- package/dist/default/core/signals/when.js +6 -8
- package/dist/default/core/signals/when.js.map +1 -1
- package/dist/default/core/tasks/delayed-reschedule.js +7 -11
- package/dist/default/core/tasks/delayed-reschedule.js.map +1 -1
- package/dist/default/core/tasks/task.js +59 -82
- package/dist/default/core/tasks/task.js.map +1 -1
- package/dist/default/hls.js +3 -1
- package/dist/default/index.js +2 -3
- package/dist/default/index.js.map +1 -1
- package/dist/default/media/abr/quality-selection.js +3 -7
- package/dist/default/media/abr/quality-selection.js.map +1 -1
- package/dist/default/media/buffer/back-buffer.js +15 -19
- package/dist/default/media/buffer/back-buffer.js.map +1 -1
- package/dist/default/media/buffer/forward-buffer.js +32 -41
- package/dist/default/media/buffer/forward-buffer.js.map +1 -1
- package/dist/default/media/dom/capabilities.js +26 -37
- package/dist/default/media/dom/capabilities.js.map +1 -1
- package/dist/default/media/dom/mse/append-segment.js +3 -5
- package/dist/default/media/dom/mse/append-segment.js.map +1 -1
- package/dist/default/media/dom/mse/buffer-flusher.js +5 -5
- package/dist/default/media/dom/mse/buffer-flusher.js.map +1 -1
- package/dist/default/media/dom/mse/duration.js +23 -31
- package/dist/default/media/dom/mse/duration.js.map +1 -1
- package/dist/default/media/dom/mse/end-of-stream.js +3 -6
- package/dist/default/media/dom/mse/end-of-stream.js.map +1 -1
- package/dist/default/media/dom/mse/mediasource-setup.js +65 -81
- package/dist/default/media/dom/mse/mediasource-setup.js.map +1 -1
- package/dist/default/media/dom/screen.js +37 -54
- package/dist/default/media/dom/screen.js.map +1 -1
- package/dist/default/media/dom/text/resolve-vtt-segment.js.map +1 -1
- package/dist/default/media/dom/text/text-track-slots.js +15 -23
- package/dist/default/media/dom/text/text-track-slots.js.map +1 -1
- package/dist/default/media/errors.js +25 -34
- package/dist/default/media/errors.js.map +1 -1
- package/dist/default/media/hls/parse-attributes.js +9 -26
- package/dist/default/media/hls/parse-attributes.js.map +1 -1
- package/dist/default/media/hls/parse-media-playlist.js +25 -33
- package/dist/default/media/hls/parse-media-playlist.js.map +1 -1
- package/dist/default/media/hls/parse-multivariant.js +3 -3
- package/dist/default/media/hls/parse-multivariant.js.map +1 -1
- package/dist/default/media/hls/reload-policy.js +19 -27
- package/dist/default/media/hls/reload-policy.js.map +1 -1
- package/dist/default/media/hls/resolve-url.js +1 -3
- package/dist/default/media/hls/resolve-url.js.map +1 -1
- package/dist/default/media/live-window.js +9 -13
- package/dist/default/media/live-window.js.map +1 -1
- package/dist/default/media/media-tracks/media-tracks.js +12 -17
- package/dist/default/media/media-tracks/media-tracks.js.map +1 -1
- package/dist/default/media/mp4/box.js +4 -5
- package/dist/default/media/mp4/box.js.map +1 -1
- package/dist/default/media/mp4/timestamp-origin.js +30 -42
- package/dist/default/media/mp4/timestamp-origin.js.map +1 -1
- package/dist/default/media/primitives/resolution.js +5 -8
- package/dist/default/media/primitives/resolution.js.map +1 -1
- package/dist/default/media/primitives/select-tracks.js +24 -34
- package/dist/default/media/primitives/select-tracks.js.map +1 -1
- package/dist/default/media/text/parse-vtt-timestamp-map.js +6 -8
- package/dist/default/media/text/parse-vtt-timestamp-map.js.map +1 -1
- package/dist/default/media/text/resolve-vtt-metadata.js +8 -9
- package/dist/default/media/text/resolve-vtt-metadata.js.map +1 -1
- package/dist/default/media/types/index.js +10 -18
- package/dist/default/media/types/index.js.map +1 -1
- package/dist/default/media/utils/cdn.js +10 -16
- package/dist/default/media/utils/cdn.js.map +1 -1
- package/dist/default/media/utils/preload.js +4 -6
- package/dist/default/media/utils/preload.js.map +1 -1
- package/dist/default/media/utils/track-selection.js +10 -14
- package/dist/default/media/utils/track-selection.js.map +1 -1
- package/dist/default/media/utils/tracks.js +56 -54
- package/dist/default/media/utils/tracks.js.map +1 -1
- package/dist/default/network/bandwidth-estimator.js +18 -19
- package/dist/default/network/bandwidth-estimator.js.map +1 -1
- package/dist/default/network/chunked-stream-iterable.js +4 -6
- package/dist/default/network/chunked-stream-iterable.js.map +1 -1
- package/dist/default/network/ewma.js +22 -25
- package/dist/default/network/ewma.js.map +1 -1
- package/dist/default/network/fetch.js +30 -37
- package/dist/default/network/fetch.js.map +1 -1
- package/dist/default/playback/actors/dom/segment-loader.js +28 -44
- package/dist/default/playback/actors/dom/segment-loader.js.map +1 -1
- package/dist/default/playback/actors/dom/source-buffer.js.map +1 -1
- package/dist/default/playback/actors/dom/text-tracks.js.map +1 -1
- package/dist/default/playback/actors/text-track-segment-loader.js +24 -35
- package/dist/default/playback/actors/text-track-segment-loader.js.map +1 -1
- package/dist/default/playback/adapters/hls-audio/adapter.js +23 -31
- package/dist/default/playback/adapters/hls-audio/adapter.js.map +1 -1
- package/dist/default/playback/adapters/hls-audio/media.js.map +1 -1
- package/dist/default/playback/adapters/hls-background-video/adapter.js +50 -70
- package/dist/default/playback/adapters/hls-background-video/adapter.js.map +1 -1
- package/dist/default/playback/adapters/hls-background-video/host.js +12 -16
- package/dist/default/playback/adapters/hls-background-video/host.js.map +1 -1
- package/dist/default/playback/adapters/hls-background-video/media.js +5 -8
- package/dist/default/playback/adapters/hls-background-video/media.js.map +1 -1
- package/dist/default/playback/adapters/hls-video/adapter.js +43 -60
- package/dist/default/playback/adapters/hls-video/adapter.js.map +1 -1
- package/dist/default/playback/adapters/hls-video/error-surface.js +13 -18
- package/dist/default/playback/adapters/hls-video/error-surface.js.map +1 -1
- package/dist/default/playback/adapters/hls-video/media-tracks.js +4 -5
- package/dist/default/playback/adapters/hls-video/media-tracks.js.map +1 -1
- package/dist/default/playback/adapters/hls-video/media.js.map +1 -1
- package/dist/default/playback/adapters/mux-audio/media.js +8 -12
- package/dist/default/playback/adapters/mux-audio/media.js.map +1 -1
- package/dist/default/playback/adapters/mux-video/adapter.js +25 -33
- package/dist/default/playback/adapters/mux-video/adapter.js.map +1 -1
- package/dist/default/playback/adapters/mux-video/media.js +7 -9
- package/dist/default/playback/adapters/mux-video/media.js.map +1 -1
- package/dist/default/playback/behaviors/calculate-presentation-duration.js +5 -8
- package/dist/default/playback/behaviors/calculate-presentation-duration.js.map +1 -1
- package/dist/default/playback/behaviors/collect-errors.js +39 -52
- package/dist/default/playback/behaviors/collect-errors.js.map +1 -1
- package/dist/default/playback/behaviors/derive-cdn-priority.js +16 -23
- package/dist/default/playback/behaviors/derive-cdn-priority.js.map +1 -1
- package/dist/default/playback/behaviors/dom/airplay.js +38 -61
- package/dist/default/playback/behaviors/dom/airplay.js.map +1 -1
- package/dist/default/playback/behaviors/dom/apply-start-position.js +23 -35
- package/dist/default/playback/behaviors/dom/apply-start-position.js.map +1 -1
- package/dist/default/playback/behaviors/dom/end-of-stream.js +11 -16
- package/dist/default/playback/behaviors/dom/end-of-stream.js.map +1 -1
- package/dist/default/playback/behaviors/dom/load-segments.js +27 -39
- package/dist/default/playback/behaviors/dom/load-segments.js.map +1 -1
- package/dist/default/playback/behaviors/dom/recover-end-stall.js +21 -26
- package/dist/default/playback/behaviors/dom/recover-end-stall.js.map +1 -1
- package/dist/default/playback/behaviors/dom/seek-to-live-edge.js +41 -60
- package/dist/default/playback/behaviors/dom/seek-to-live-edge.js.map +1 -1
- package/dist/default/playback/behaviors/dom/setup-buffer-actors.js +50 -74
- package/dist/default/playback/behaviors/dom/setup-buffer-actors.js.map +1 -1
- package/dist/default/playback/behaviors/dom/setup-mediasource.js +29 -43
- package/dist/default/playback/behaviors/dom/setup-mediasource.js.map +1 -1
- package/dist/default/playback/behaviors/dom/setup-text-track-actors.js.map +1 -1
- package/dist/default/playback/behaviors/dom/sync-live-seekable-range.js +3 -4
- package/dist/default/playback/behaviors/dom/sync-live-seekable-range.js.map +1 -1
- package/dist/default/playback/behaviors/dom/sync-text-tracks.js +30 -45
- package/dist/default/playback/behaviors/dom/sync-text-tracks.js.map +1 -1
- package/dist/default/playback/behaviors/dom/track-current-time.js +9 -11
- package/dist/default/playback/behaviors/dom/track-current-time.js.map +1 -1
- package/dist/default/playback/behaviors/dom/track-load-triggers.js +24 -32
- package/dist/default/playback/behaviors/dom/track-load-triggers.js.map +1 -1
- package/dist/default/playback/behaviors/dom/track-playback-rate.js +6 -8
- package/dist/default/playback/behaviors/dom/track-playback-rate.js.map +1 -1
- package/dist/default/playback/behaviors/dom/track-player-resolution.js +10 -14
- package/dist/default/playback/behaviors/dom/track-player-resolution.js.map +1 -1
- package/dist/default/playback/behaviors/dom/track-screen-resolution.js +8 -9
- package/dist/default/playback/behaviors/dom/track-screen-resolution.js.map +1 -1
- package/dist/default/playback/behaviors/dom/update-mediasource-duration.js +28 -43
- package/dist/default/playback/behaviors/dom/update-mediasource-duration.js.map +1 -1
- package/dist/default/playback/behaviors/establish-start-media-time.js +32 -42
- package/dist/default/playback/behaviors/establish-start-media-time.js.map +1 -1
- package/dist/default/playback/behaviors/resolve-presentation.js +13 -22
- package/dist/default/playback/behaviors/resolve-presentation.js.map +1 -1
- package/dist/default/playback/behaviors/resolve-track.js +5 -12
- package/dist/default/playback/behaviors/resolve-track.js.map +1 -1
- package/dist/default/playback/behaviors/select-tracks.js +77 -104
- package/dist/default/playback/behaviors/select-tracks.js.map +1 -1
- package/dist/default/playback/behaviors/setup-failover-monitor.js +11 -16
- package/dist/default/playback/behaviors/setup-failover-monitor.js.map +1 -1
- package/dist/default/playback/behaviors/sync-preload.js +9 -13
- package/dist/default/playback/behaviors/sync-preload.js.map +1 -1
- package/dist/default/playback/behaviors/track-switching.js +189 -173
- package/dist/default/playback/behaviors/track-switching.js.map +1 -1
- package/dist/default/playback/engines/hls/engine-audio-only.js +20 -24
- package/dist/default/playback/engines/hls/engine-audio-only.js.map +1 -1
- package/dist/default/playback/engines/hls/engine-background-video.js +22 -27
- package/dist/default/playback/engines/hls/engine-background-video.js.map +1 -1
- package/dist/default/playback/engines/hls/engine.js +22 -25
- package/dist/default/playback/engines/hls/engine.js.map +1 -1
- package/dist/default/playback/primitives/error-messages.js +16 -25
- package/dist/default/playback/primitives/error-messages.js.map +1 -1
- package/dist/default/playback/primitives/failover-fetch.js +9 -14
- package/dist/default/playback/primitives/failover-fetch.js.map +1 -1
- package/dist/default/playback/primitives/head-peek.js +7 -10
- package/dist/default/playback/primitives/head-peek.js.map +1 -1
- package/dist/default/playback/primitives/live-window.js +12 -15
- package/dist/default/playback/primitives/live-window.js.map +1 -1
- package/dist/default/playback/primitives/relocation-pipelines.js +34 -46
- package/dist/default/playback/primitives/relocation-pipelines.js.map +1 -1
- package/dist/default/playback/primitives/report-track-conditions.js +26 -38
- package/dist/default/playback/primitives/report-track-conditions.js.map +1 -1
- package/dist/default/playback/primitives/segment-load-pipeline.js +15 -15
- package/dist/default/playback/primitives/segment-load-pipeline.js.map +1 -1
- package/dist/default/playback/primitives/selection-rules.js +65 -36
- package/dist/default/playback/primitives/selection-rules.js.map +1 -1
- package/dist/default/playback/primitives/text-segment-load-pipeline.js +4 -5
- package/dist/default/playback/primitives/text-segment-load-pipeline.js.map +1 -1
- package/dist/default/playback/primitives/track-types.js +10 -18
- package/dist/default/playback/primitives/track-types.js.map +1 -1
- package/dist/dev/core/actors/actor.d.ts +4 -4
- package/dist/dev/core/actors/actor.d.ts.map +1 -1
- package/dist/dev/core/actors/create-machine-actor.d.ts +38 -47
- package/dist/dev/core/actors/create-machine-actor.d.ts.map +1 -1
- package/dist/dev/core/actors/create-machine-actor.js +23 -25
- package/dist/dev/core/actors/create-machine-actor.js.map +1 -1
- package/dist/dev/core/actors/create-transition-actor.d.ts +11 -15
- package/dist/dev/core/actors/create-transition-actor.d.ts.map +1 -1
- package/dist/dev/core/actors/create-transition-actor.js +7 -9
- package/dist/dev/core/actors/create-transition-actor.js.map +1 -1
- package/dist/dev/core/composition/create-composition.d.ts +70 -102
- package/dist/dev/core/composition/create-composition.d.ts.map +1 -1
- package/dist/dev/core/composition/create-composition.js +26 -29
- package/dist/dev/core/composition/create-composition.js.map +1 -1
- package/dist/dev/core/composition/share-signals.d.ts +17 -24
- package/dist/dev/core/composition/share-signals.d.ts.map +1 -1
- package/dist/dev/core/composition/share-signals.js +12 -17
- package/dist/dev/core/composition/share-signals.js.map +1 -1
- package/dist/dev/core/machine.d.ts +4 -4
- package/dist/dev/core/machine.js +3 -4
- package/dist/dev/core/machine.js.map +1 -1
- package/dist/dev/core/reactors/create-machine-reactor.d.ts +33 -39
- package/dist/dev/core/reactors/create-machine-reactor.d.ts.map +1 -1
- package/dist/dev/core/reactors/create-machine-reactor.js +20 -19
- package/dist/dev/core/reactors/create-machine-reactor.js.map +1 -1
- package/dist/dev/core/signals/effect.d.ts +3 -4
- package/dist/dev/core/signals/effect.d.ts.map +1 -1
- package/dist/dev/core/signals/effect.js +24 -4
- package/dist/dev/core/signals/effect.js.map +1 -1
- package/dist/dev/core/signals/primitives.d.ts +10 -12
- package/dist/dev/core/signals/primitives.d.ts.map +1 -1
- package/dist/dev/core/signals/primitives.js +10 -14
- package/dist/dev/core/signals/primitives.js.map +1 -1
- package/dist/dev/core/signals/when.js +6 -8
- package/dist/dev/core/signals/when.js.map +1 -1
- package/dist/dev/core/tasks/delayed-reschedule.js +7 -11
- package/dist/dev/core/tasks/delayed-reschedule.js.map +1 -1
- package/dist/dev/core/tasks/task.d.ts +51 -73
- package/dist/dev/core/tasks/task.d.ts.map +1 -1
- package/dist/dev/core/tasks/task.js +59 -82
- package/dist/dev/core/tasks/task.js.map +1 -1
- package/dist/dev/hls.d.ts +3 -1
- package/dist/dev/hls.js +3 -1
- package/dist/dev/index.d.ts +2 -3
- package/dist/dev/index.d.ts.map +1 -1
- package/dist/dev/index.js +2 -3
- package/dist/dev/index.js.map +1 -1
- package/dist/dev/media/abr/quality-selection.d.ts +7 -10
- package/dist/dev/media/abr/quality-selection.d.ts.map +1 -1
- package/dist/dev/media/abr/quality-selection.js +3 -7
- package/dist/dev/media/abr/quality-selection.js.map +1 -1
- package/dist/dev/media/buffer/back-buffer.d.ts +2 -7
- package/dist/dev/media/buffer/back-buffer.d.ts.map +1 -1
- package/dist/dev/media/buffer/back-buffer.js +15 -19
- package/dist/dev/media/buffer/back-buffer.js.map +1 -1
- package/dist/dev/media/buffer/forward-buffer.d.ts +2 -7
- package/dist/dev/media/buffer/forward-buffer.d.ts.map +1 -1
- package/dist/dev/media/buffer/forward-buffer.js +32 -41
- package/dist/dev/media/buffer/forward-buffer.js.map +1 -1
- package/dist/dev/media/dom/capabilities.js +26 -37
- package/dist/dev/media/dom/capabilities.js.map +1 -1
- package/dist/dev/media/dom/mse/append-segment.d.ts +3 -5
- package/dist/dev/media/dom/mse/append-segment.d.ts.map +1 -1
- package/dist/dev/media/dom/mse/append-segment.js +3 -5
- package/dist/dev/media/dom/mse/append-segment.js.map +1 -1
- package/dist/dev/media/dom/mse/buffer-flusher.d.ts +5 -5
- package/dist/dev/media/dom/mse/buffer-flusher.js +5 -5
- package/dist/dev/media/dom/mse/buffer-flusher.js.map +1 -1
- package/dist/dev/media/dom/mse/duration.js +23 -31
- package/dist/dev/media/dom/mse/duration.js.map +1 -1
- package/dist/dev/media/dom/mse/end-of-stream.js +3 -6
- package/dist/dev/media/dom/mse/end-of-stream.js.map +1 -1
- package/dist/dev/media/dom/mse/mediasource-setup.js +65 -81
- package/dist/dev/media/dom/mse/mediasource-setup.js.map +1 -1
- package/dist/dev/media/dom/screen.d.ts.map +1 -1
- package/dist/dev/media/dom/screen.js +37 -54
- package/dist/dev/media/dom/screen.js.map +1 -1
- package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts.map +1 -1
- package/dist/dev/media/dom/text/resolve-vtt-segment.js.map +1 -1
- package/dist/dev/media/dom/text/text-track-slots.d.ts +10 -16
- package/dist/dev/media/dom/text/text-track-slots.d.ts.map +1 -1
- package/dist/dev/media/dom/text/text-track-slots.js +15 -23
- package/dist/dev/media/dom/text/text-track-slots.js.map +1 -1
- package/dist/dev/media/errors.d.ts +32 -46
- package/dist/dev/media/errors.d.ts.map +1 -1
- package/dist/dev/media/errors.js +25 -34
- package/dist/dev/media/errors.js.map +1 -1
- package/dist/dev/media/hls/parse-attributes.js +9 -26
- package/dist/dev/media/hls/parse-attributes.js.map +1 -1
- package/dist/dev/media/hls/parse-media-playlist.js +25 -33
- package/dist/dev/media/hls/parse-media-playlist.js.map +1 -1
- package/dist/dev/media/hls/parse-multivariant.js +3 -3
- package/dist/dev/media/hls/parse-multivariant.js.map +1 -1
- package/dist/dev/media/hls/reload-policy.js +19 -27
- package/dist/dev/media/hls/reload-policy.js.map +1 -1
- package/dist/dev/media/hls/resolve-url.js +1 -3
- package/dist/dev/media/hls/resolve-url.js.map +1 -1
- package/dist/dev/media/live-window.js +9 -13
- package/dist/dev/media/live-window.js.map +1 -1
- package/dist/dev/media/media-tracks/media-tracks.d.ts +8 -13
- package/dist/dev/media/media-tracks/media-tracks.d.ts.map +1 -1
- package/dist/dev/media/media-tracks/media-tracks.js +12 -17
- package/dist/dev/media/media-tracks/media-tracks.js.map +1 -1
- package/dist/dev/media/mp4/box.js +4 -5
- package/dist/dev/media/mp4/box.js.map +1 -1
- package/dist/dev/media/mp4/timestamp-origin.js +30 -42
- package/dist/dev/media/mp4/timestamp-origin.js.map +1 -1
- package/dist/dev/media/primitives/resolution.d.ts +6 -8
- package/dist/dev/media/primitives/resolution.d.ts.map +1 -1
- package/dist/dev/media/primitives/resolution.js +5 -8
- package/dist/dev/media/primitives/resolution.js.map +1 -1
- package/dist/dev/media/primitives/select-tracks.js +24 -34
- package/dist/dev/media/primitives/select-tracks.js.map +1 -1
- package/dist/dev/media/text/parse-vtt-timestamp-map.js +6 -8
- package/dist/dev/media/text/parse-vtt-timestamp-map.js.map +1 -1
- package/dist/dev/media/text/resolve-vtt-metadata.js +8 -9
- package/dist/dev/media/text/resolve-vtt-metadata.js.map +1 -1
- package/dist/dev/media/types/index.d.ts +106 -177
- package/dist/dev/media/types/index.d.ts.map +1 -1
- package/dist/dev/media/types/index.js +10 -18
- package/dist/dev/media/types/index.js.map +1 -1
- package/dist/dev/media/utils/cdn.d.ts +4 -6
- package/dist/dev/media/utils/cdn.d.ts.map +1 -1
- package/dist/dev/media/utils/cdn.js +10 -16
- package/dist/dev/media/utils/cdn.js.map +1 -1
- package/dist/dev/media/utils/preload.js +4 -6
- package/dist/dev/media/utils/preload.js.map +1 -1
- package/dist/dev/media/utils/track-selection.js +10 -14
- package/dist/dev/media/utils/track-selection.js.map +1 -1
- package/dist/dev/media/utils/tracks.js +56 -54
- package/dist/dev/media/utils/tracks.js.map +1 -1
- package/dist/dev/network/bandwidth-estimator.d.ts +7 -9
- package/dist/dev/network/bandwidth-estimator.d.ts.map +1 -1
- package/dist/dev/network/bandwidth-estimator.js +18 -19
- package/dist/dev/network/bandwidth-estimator.js.map +1 -1
- package/dist/dev/network/chunked-stream-iterable.js +4 -6
- package/dist/dev/network/chunked-stream-iterable.js.map +1 -1
- package/dist/dev/network/ewma.js +22 -25
- package/dist/dev/network/ewma.js.map +1 -1
- package/dist/dev/network/fetch.js +30 -37
- package/dist/dev/network/fetch.js.map +1 -1
- package/dist/dev/playback/actors/dom/segment-loader.d.ts +7 -11
- package/dist/dev/playback/actors/dom/segment-loader.d.ts.map +1 -1
- package/dist/dev/playback/actors/dom/segment-loader.js +28 -44
- package/dist/dev/playback/actors/dom/segment-loader.js.map +1 -1
- package/dist/dev/playback/actors/dom/source-buffer.d.ts +5 -7
- package/dist/dev/playback/actors/dom/source-buffer.d.ts.map +1 -1
- package/dist/dev/playback/actors/dom/source-buffer.js.map +1 -1
- package/dist/dev/playback/actors/dom/text-tracks.js.map +1 -1
- package/dist/dev/playback/actors/text-track-segment-loader.d.ts +10 -16
- package/dist/dev/playback/actors/text-track-segment-loader.d.ts.map +1 -1
- package/dist/dev/playback/actors/text-track-segment-loader.js +24 -35
- package/dist/dev/playback/actors/text-track-segment-loader.js.map +1 -1
- package/dist/dev/playback/actors/text-tracks.d.ts +5 -8
- package/dist/dev/playback/actors/text-tracks.d.ts.map +1 -1
- package/dist/dev/playback/adapters/hls-audio/adapter.d.ts +11 -14
- package/dist/dev/playback/adapters/hls-audio/adapter.d.ts.map +1 -1
- package/dist/dev/playback/adapters/hls-audio/adapter.js +23 -31
- package/dist/dev/playback/adapters/hls-audio/adapter.js.map +1 -1
- package/dist/dev/playback/adapters/hls-audio/media.d.ts.map +1 -1
- package/dist/dev/playback/adapters/hls-audio/media.js.map +1 -1
- package/dist/dev/playback/adapters/hls-background-video/adapter.d.ts +28 -39
- package/dist/dev/playback/adapters/hls-background-video/adapter.d.ts.map +1 -1
- package/dist/dev/playback/adapters/hls-background-video/adapter.js +50 -70
- package/dist/dev/playback/adapters/hls-background-video/adapter.js.map +1 -1
- package/dist/dev/playback/adapters/hls-background-video/host.d.ts +12 -16
- package/dist/dev/playback/adapters/hls-background-video/host.d.ts.map +1 -1
- package/dist/dev/playback/adapters/hls-background-video/host.js +12 -16
- package/dist/dev/playback/adapters/hls-background-video/host.js.map +1 -1
- package/dist/dev/playback/adapters/hls-background-video/media.d.ts +5 -8
- package/dist/dev/playback/adapters/hls-background-video/media.d.ts.map +1 -1
- package/dist/dev/playback/adapters/hls-background-video/media.js +5 -8
- package/dist/dev/playback/adapters/hls-background-video/media.js.map +1 -1
- package/dist/dev/playback/adapters/hls-video/adapter.d.ts +12 -14
- package/dist/dev/playback/adapters/hls-video/adapter.d.ts.map +1 -1
- package/dist/dev/playback/adapters/hls-video/adapter.js +43 -60
- package/dist/dev/playback/adapters/hls-video/adapter.js.map +1 -1
- package/dist/dev/playback/adapters/hls-video/error-surface.d.ts +4 -5
- package/dist/dev/playback/adapters/hls-video/error-surface.d.ts.map +1 -1
- package/dist/dev/playback/adapters/hls-video/error-surface.js +13 -18
- package/dist/dev/playback/adapters/hls-video/error-surface.js.map +1 -1
- package/dist/dev/playback/adapters/hls-video/media-tracks.d.ts +4 -5
- package/dist/dev/playback/adapters/hls-video/media-tracks.d.ts.map +1 -1
- package/dist/dev/playback/adapters/hls-video/media-tracks.js +4 -5
- package/dist/dev/playback/adapters/hls-video/media-tracks.js.map +1 -1
- package/dist/dev/playback/adapters/hls-video/media.d.ts.map +1 -1
- package/dist/dev/playback/adapters/hls-video/media.js.map +1 -1
- package/dist/dev/playback/adapters/mux-audio/media.d.ts +8 -12
- package/dist/dev/playback/adapters/mux-audio/media.d.ts.map +1 -1
- package/dist/dev/playback/adapters/mux-audio/media.js +8 -12
- package/dist/dev/playback/adapters/mux-audio/media.js.map +1 -1
- package/dist/dev/playback/adapters/mux-video/adapter.d.ts +9 -11
- package/dist/dev/playback/adapters/mux-video/adapter.d.ts.map +1 -1
- package/dist/dev/playback/adapters/mux-video/adapter.js +25 -33
- package/dist/dev/playback/adapters/mux-video/adapter.js.map +1 -1
- package/dist/dev/playback/adapters/mux-video/media.d.ts +7 -9
- package/dist/dev/playback/adapters/mux-video/media.d.ts.map +1 -1
- package/dist/dev/playback/adapters/mux-video/media.js +7 -9
- package/dist/dev/playback/adapters/mux-video/media.js.map +1 -1
- package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts +5 -8
- package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/calculate-presentation-duration.js +5 -8
- package/dist/dev/playback/behaviors/calculate-presentation-duration.js.map +1 -1
- package/dist/dev/playback/behaviors/collect-errors.d.ts +2 -0
- package/dist/dev/playback/behaviors/collect-errors.js +39 -52
- package/dist/dev/playback/behaviors/collect-errors.js.map +1 -1
- package/dist/dev/playback/behaviors/derive-cdn-priority.js +16 -23
- package/dist/dev/playback/behaviors/derive-cdn-priority.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/airplay.js +38 -61
- package/dist/dev/playback/behaviors/dom/airplay.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/apply-start-position.js +23 -35
- package/dist/dev/playback/behaviors/dom/apply-start-position.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/end-of-stream.js +11 -16
- package/dist/dev/playback/behaviors/dom/end-of-stream.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/load-segments.d.ts +5 -8
- package/dist/dev/playback/behaviors/dom/load-segments.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/dom/load-segments.js +27 -39
- package/dist/dev/playback/behaviors/dom/load-segments.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/recover-end-stall.js +21 -26
- package/dist/dev/playback/behaviors/dom/recover-end-stall.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/seek-to-live-edge.js +41 -60
- package/dist/dev/playback/behaviors/dom/seek-to-live-edge.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js +50 -74
- package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/setup-mediasource.js +29 -43
- package/dist/dev/playback/behaviors/dom/setup-mediasource.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts +3 -3
- package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/sync-live-seekable-range.js +3 -4
- package/dist/dev/playback/behaviors/dom/sync-live-seekable-range.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/sync-text-tracks.js +30 -45
- package/dist/dev/playback/behaviors/dom/sync-text-tracks.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/track-current-time.d.ts +2 -2
- package/dist/dev/playback/behaviors/dom/track-current-time.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/dom/track-current-time.js +9 -11
- package/dist/dev/playback/behaviors/dom/track-current-time.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts +6 -12
- package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/dom/track-load-triggers.js +24 -32
- package/dist/dev/playback/behaviors/dom/track-load-triggers.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts +2 -2
- package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/dom/track-playback-rate.js +6 -8
- package/dist/dev/playback/behaviors/dom/track-playback-rate.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/track-player-resolution.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/dom/track-player-resolution.js +10 -14
- package/dist/dev/playback/behaviors/dom/track-player-resolution.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/track-screen-resolution.js +8 -9
- package/dist/dev/playback/behaviors/dom/track-screen-resolution.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js +28 -43
- package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js.map +1 -1
- package/dist/dev/playback/behaviors/establish-start-media-time.d.ts +15 -19
- package/dist/dev/playback/behaviors/establish-start-media-time.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/establish-start-media-time.js +32 -42
- package/dist/dev/playback/behaviors/establish-start-media-time.js.map +1 -1
- package/dist/dev/playback/behaviors/resolve-presentation.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/resolve-presentation.js +13 -22
- package/dist/dev/playback/behaviors/resolve-presentation.js.map +1 -1
- package/dist/dev/playback/behaviors/resolve-track.js +5 -12
- package/dist/dev/playback/behaviors/resolve-track.js.map +1 -1
- package/dist/dev/playback/behaviors/select-tracks.d.ts +28 -39
- package/dist/dev/playback/behaviors/select-tracks.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/select-tracks.js +77 -104
- package/dist/dev/playback/behaviors/select-tracks.js.map +1 -1
- package/dist/dev/playback/behaviors/setup-failover-monitor.d.ts +1 -4
- package/dist/dev/playback/behaviors/setup-failover-monitor.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/setup-failover-monitor.js +11 -16
- package/dist/dev/playback/behaviors/setup-failover-monitor.js.map +1 -1
- package/dist/dev/playback/behaviors/sync-preload.js +9 -13
- package/dist/dev/playback/behaviors/sync-preload.js.map +1 -1
- package/dist/dev/playback/behaviors/track-switching.d.ts +110 -0
- package/dist/dev/playback/behaviors/track-switching.d.ts.map +1 -0
- package/dist/dev/playback/behaviors/track-switching.js +189 -173
- package/dist/dev/playback/behaviors/track-switching.js.map +1 -1
- package/dist/dev/playback/engines/hls/engine-audio-only.d.ts +59 -72
- package/dist/dev/playback/engines/hls/engine-audio-only.d.ts.map +1 -1
- package/dist/dev/playback/engines/hls/engine-audio-only.js +20 -24
- package/dist/dev/playback/engines/hls/engine-audio-only.js.map +1 -1
- package/dist/dev/playback/engines/hls/engine-background-video.d.ts +51 -78
- package/dist/dev/playback/engines/hls/engine-background-video.d.ts.map +1 -1
- package/dist/dev/playback/engines/hls/engine-background-video.js +22 -27
- package/dist/dev/playback/engines/hls/engine-background-video.js.map +1 -1
- package/dist/dev/playback/engines/hls/engine.d.ts +115 -155
- package/dist/dev/playback/engines/hls/engine.d.ts.map +1 -1
- package/dist/dev/playback/engines/hls/engine.js +22 -25
- package/dist/dev/playback/engines/hls/engine.js.map +1 -1
- package/dist/dev/playback/primitives/derive-start-media-time.d.ts +3 -3
- package/dist/dev/playback/primitives/derive-start-media-time.d.ts.map +1 -1
- package/dist/dev/playback/primitives/error-messages.js +16 -25
- package/dist/dev/playback/primitives/error-messages.js.map +1 -1
- package/dist/dev/playback/primitives/failover-fetch.js +9 -14
- package/dist/dev/playback/primitives/failover-fetch.js.map +1 -1
- package/dist/dev/playback/primitives/head-peek.js +7 -10
- package/dist/dev/playback/primitives/head-peek.js.map +1 -1
- package/dist/dev/playback/primitives/live-window.js +12 -15
- package/dist/dev/playback/primitives/live-window.js.map +1 -1
- package/dist/dev/playback/primitives/relocation-pipelines.js +34 -46
- package/dist/dev/playback/primitives/relocation-pipelines.js.map +1 -1
- package/dist/dev/playback/primitives/report-track-conditions.d.ts +1 -4
- package/dist/dev/playback/primitives/report-track-conditions.d.ts.map +1 -1
- package/dist/dev/playback/primitives/report-track-conditions.js +26 -38
- package/dist/dev/playback/primitives/report-track-conditions.js.map +1 -1
- package/dist/dev/playback/primitives/segment-load-pipeline.js +15 -15
- package/dist/dev/playback/primitives/segment-load-pipeline.js.map +1 -1
- package/dist/dev/playback/primitives/selection-rules.d.ts +45 -17
- package/dist/dev/playback/primitives/selection-rules.d.ts.map +1 -1
- package/dist/dev/playback/primitives/selection-rules.js +65 -36
- package/dist/dev/playback/primitives/selection-rules.js.map +1 -1
- package/dist/dev/playback/primitives/source-buffer-messages.d.ts +6 -9
- package/dist/dev/playback/primitives/source-buffer-messages.d.ts.map +1 -1
- package/dist/dev/playback/primitives/text-segment-load-pipeline.d.ts +20 -29
- package/dist/dev/playback/primitives/text-segment-load-pipeline.d.ts.map +1 -1
- package/dist/dev/playback/primitives/text-segment-load-pipeline.js +4 -5
- package/dist/dev/playback/primitives/text-segment-load-pipeline.js.map +1 -1
- package/dist/dev/playback/primitives/text-track-messages.d.ts.map +1 -1
- package/dist/dev/playback/primitives/track-types.js +10 -18
- package/dist/dev/playback/primitives/track-types.js.map +1 -1
- package/package.json +25 -28
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-url.js","names":[],"sources":["../../../../src/media/hls/resolve-url.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"resolve-url.js","names":[],"sources":["../../../../src/media/hls/resolve-url.ts"],"sourcesContent":["/** Resolve a potentially relative URL against a base URL using native URL API. */\nexport function resolveUrl(url: string, baseUrl: string): string {\n return new URL(url, baseUrl).href;\n}\n"],"mappings":";;AACA,SAAgB,WAAW,KAAa,SAAyB;CAC/D,OAAO,IAAI,IAAI,KAAK,OAAO,CAAC,CAAC;AAC/B"}
|
|
@@ -2,21 +2,17 @@ import { isResolvedPresentation, isResolvedTrack } from "./types/index.js";
|
|
|
2
2
|
import { findTrackById } from "./utils/tracks.js";
|
|
3
3
|
//#region src/media/live-window.ts
|
|
4
4
|
/**
|
|
5
|
-
* Derive the live window of the track with the given id — the single source of
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* bears the timeline (video when present, else audio).
|
|
5
|
+
* Derive the live window of the track with the given id — the single source of truth for "where is live," consumed (via
|
|
6
|
+
* `liveWindowFromState`) by the seek-to-live-edge and live-seekable-range behaviors so neither re-derives (or
|
|
7
|
+
* re-presumes) the window shape. Type-agnostic: the caller decides which track bears the timeline (video when present,
|
|
8
|
+
* else audio).
|
|
10
9
|
*
|
|
11
|
-
* The window is a **live read** over the current `segments` array — never
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* here slides while the origin stays fixed (see
|
|
15
|
-
* `internal/design/spf/live-presentation-timeline-model.md`).
|
|
10
|
+
* The window is a **live read** over the current `segments` array — never stored on the track. The anchor triple is
|
|
11
|
+
* frozen per source; per-segment `startTime` values are re-derived against it on every reload, so the edge here slides
|
|
12
|
+
* while the origin stays fixed (see `internal/design/spf/live-presentation-timeline-model.md`).
|
|
16
13
|
*
|
|
17
|
-
* Returns `null` when there is no live edge to track: an unresolved
|
|
18
|
-
*
|
|
19
|
-
* (VoD, or live that has ended — a finite `Track.duration`).
|
|
14
|
+
* Returns `null` when there is no live edge to track: an unresolved presentation or track, a track with no segments, or
|
|
15
|
+
* a **complete** playlist (VoD, or live that has ended — a finite `Track.duration`).
|
|
20
16
|
*/
|
|
21
17
|
function liveWindowFor(presentation, trackId) {
|
|
22
18
|
if (!isResolvedPresentation(presentation) || !trackId) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live-window.js","names":[],"sources":["../../../src/media/live-window.ts"],"sourcesContent":["/**\n * Derive the live window of the track with the given id — the single source of
|
|
1
|
+
{"version":3,"file":"live-window.js","names":[],"sources":["../../../src/media/live-window.ts"],"sourcesContent":["/**\n * Derive the live window of the track with the given id — the single source of truth for \"where is live,\" consumed (via\n * `liveWindowFromState`) by the seek-to-live-edge and live-seekable-range behaviors so neither re-derives (or\n * re-presumes) the window shape. Type-agnostic: the caller decides which track bears the timeline (video when present,\n * else audio).\n *\n * The window is a **live read** over the current `segments` array — never stored on the track. The anchor triple is\n * frozen per source; per-segment `startTime` values are re-derived against it on every reload, so the edge here slides\n * while the origin stays fixed (see `internal/design/spf/live-presentation-timeline-model.md`).\n *\n * Returns `null` when there is no live edge to track: an unresolved presentation or track, a track with no segments, or\n * a **complete** playlist (VoD, or live that has ended — a finite `Track.duration`).\n */\nimport { isResolvedPresentation, isResolvedTrack, type MaybeResolvedPresentation } from './types';\nimport { findTrackById } from './utils/tracks';\n\nexport interface LiveWindow {\n /** Earliest time still in the window (seconds, presentation timeline). */\n start: number;\n /** The live edge — latest time in the window (seconds). */\n end: number;\n}\n\nexport function liveWindowFor(\n presentation: MaybeResolvedPresentation | undefined,\n trackId: string | undefined\n): LiveWindow | null {\n if (!isResolvedPresentation(presentation) || !trackId) return null;\n\n const track = findTrackById(presentation, trackId);\n if (!track || !isResolvedTrack(track) || track.segments.length === 0) return null;\n\n // Complete playlist (VoD, or live that has ended) → no live edge. `Track.duration`\n // is the parser's completeness signal (finite = complete, Infinity = still growing).\n if (Number.isFinite(track.duration)) return null;\n\n const { segments } = track;\n const last = segments[segments.length - 1]!;\n\n return {\n start: segments[0]!.startTime,\n end: last.startTime + last.duration,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,SAAgB,cACd,cACA,SACmB;CACnB,IAAI,CAAC,uBAAuB,YAAY,KAAK,CAAC,SAAS,OAAO;CAE9D,MAAM,QAAQ,cAAc,cAAc,OAAO;CACjD,IAAI,CAAC,SAAS,CAAC,gBAAgB,KAAK,KAAK,MAAM,SAAS,WAAW,GAAG,OAAO;CAI7E,IAAI,OAAO,SAAS,MAAM,QAAQ,GAAG,OAAO;CAE5C,MAAM,EAAE,aAAa;CACrB,MAAM,OAAO,SAAS,SAAS,SAAS;CAExC,OAAO;EACL,OAAO,SAAS,EAAE,CAAE;EACpB,KAAK,KAAK,YAAY,KAAK;CAC7B;AACF"}
|
|
@@ -18,27 +18,22 @@ interface AudioDedupeKey {
|
|
|
18
18
|
*/
|
|
19
19
|
declare function dedupedVideoTracks(presentation: MaybeResolvedPresentation | undefined): VideoTrack[];
|
|
20
20
|
/**
|
|
21
|
-
* The distinct audio tracks of a presentation, deduped by `language` + `name`
|
|
22
|
-
*
|
|
21
|
+
* The distinct audio tracks of a presentation, deduped by `language` + `name` (first occurrence wins). Returns `[]`
|
|
22
|
+
* when the presentation is unresolved or has no audio tracks.
|
|
23
23
|
*/
|
|
24
24
|
declare function dedupedAudioTracks(presentation: MaybeResolvedPresentation | undefined): AudioTrack[];
|
|
25
25
|
/**
|
|
26
|
-
* Find a video track by id, searching the same candidate set the engine resolves
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* isn't the representative {@link dedupedVideoTracks} kept.
|
|
26
|
+
* Find a video track by id, searching the same candidate set the engine resolves against ({@link dedupedVideoTracks}'s
|
|
27
|
+
* pre-dedupe source). Returns `undefined` when absent. Maps the engine's resolved `selectedVideoTrackId` back to its
|
|
28
|
+
* properties for `active` reflection — the resolved id may be a per-CDN copy that isn't the representative
|
|
29
|
+
* {@link dedupedVideoTracks} kept.
|
|
31
30
|
*/
|
|
32
31
|
declare function findVideoTrackById(presentation: MaybeResolvedPresentation | undefined, id: string | undefined): VideoTrack | undefined;
|
|
33
32
|
/** Audio counterpart of {@link findVideoTrackById}, for `enabled` reflection. */
|
|
34
33
|
declare function findAudioTrackById(presentation: MaybeResolvedPresentation | undefined, id: string | undefined): AudioTrack | undefined;
|
|
35
|
-
/**
|
|
36
|
-
* Build a partial video track that can be used as `userVideoTrackSelection`.
|
|
37
|
-
*/
|
|
34
|
+
/** Build a partial video track that can be used as `userVideoTrackSelection`. */
|
|
38
35
|
declare function toUserVideoTrackSelection<T extends VideoDedupeKey>(rendition?: T): Partial<VideoTrack> | undefined;
|
|
39
|
-
/**
|
|
40
|
-
* Build a partial audio track that can be used as a `userAudioTrackSelection`.
|
|
41
|
-
*/
|
|
36
|
+
/** Build a partial audio track that can be used as a `userAudioTrackSelection`. */
|
|
42
37
|
declare function toUserAudioTrackSelection<T extends AudioDedupeKey>(track?: T): Partial<AudioTrack> | undefined;
|
|
43
38
|
/** Whether two video tracks are the same by dedupe key */
|
|
44
39
|
declare function isSameVideoTrack(a: VideoDedupeKey, b: VideoDedupeKey | undefined): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-tracks.d.ts","names":[],"sources":["../../../../src/media/media-tracks/media-tracks.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"media-tracks.d.ts","names":[],"sources":["../../../../src/media/media-tracks/media-tracks.ts"],"mappings":";;;UAuBiB;EACf,QAAQ;EACR,SAAS;EACT,YAAY;;;UAIG;EACf,WAAW;EACX,OAAO;;;;;;;iBAQO,mBAAmB,cAAc,wCAAwC;;;;;iBAazE,mBAAmB,cAAc,wCAAwC;;;;;;;iBAezE,mBACd,cAAc,uCACd,yBACC;;iBASa,mBACd,cAAc,uCACd,yBACC;;iBA8Ca,0BAA0B,UAAU,gBAAgB,YAAY,IAAI,QAAQ;;iBAK5E,0BAA0B,UAAU,gBAAgB,QAAQ,IAAI,QAAQ;;iBAKxE,iBAAiB,GAAG,gBAAgB,GAAG;;iBAKvC,iBAAiB,GAAG,gBAAgB,GAAG;;cAK1C,oBAAiB,WAAe"}
|
|
@@ -13,8 +13,8 @@ function dedupedVideoTracks(presentation) {
|
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
* The distinct audio tracks of a presentation, deduped by `language` + `name`
|
|
17
|
-
*
|
|
16
|
+
* The distinct audio tracks of a presentation, deduped by `language` + `name` (first occurrence wins). Returns `[]`
|
|
17
|
+
* when the presentation is unresolved or has no audio tracks.
|
|
18
18
|
*/
|
|
19
19
|
function dedupedAudioTracks(presentation) {
|
|
20
20
|
if (!presentation) return [];
|
|
@@ -24,11 +24,10 @@ function dedupedAudioTracks(presentation) {
|
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
|
-
* Find a video track by id, searching the same candidate set the engine resolves
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* isn't the representative {@link dedupedVideoTracks} kept.
|
|
27
|
+
* Find a video track by id, searching the same candidate set the engine resolves against ({@link dedupedVideoTracks}'s
|
|
28
|
+
* pre-dedupe source). Returns `undefined` when absent. Maps the engine's resolved `selectedVideoTrackId` back to its
|
|
29
|
+
* properties for `active` reflection — the resolved id may be a per-CDN copy that isn't the representative
|
|
30
|
+
* {@link dedupedVideoTracks} kept.
|
|
32
31
|
*/
|
|
33
32
|
function findVideoTrackById(presentation, id) {
|
|
34
33
|
if (!presentation || !id) return void 0;
|
|
@@ -42,16 +41,16 @@ function findAudioTrackById(presentation, id) {
|
|
|
42
41
|
return track?.type === "audio" ? track : void 0;
|
|
43
42
|
}
|
|
44
43
|
/**
|
|
45
|
-
* Shallow-equal two key objects by their own properties. Both come from the same
|
|
46
|
-
*
|
|
44
|
+
* Shallow-equal two key objects by their own properties. Both come from the same key builder, so they carry the same
|
|
45
|
+
* keys — a one-directional scan suffices.
|
|
47
46
|
*/
|
|
48
47
|
function sameKey(a, b) {
|
|
49
48
|
for (const attr in a) if (a[attr] !== b[attr]) return false;
|
|
50
49
|
return true;
|
|
51
50
|
}
|
|
52
51
|
/**
|
|
53
|
-
* Dedupe tracks by a key function, keeping the first occurrence of each key.
|
|
54
|
-
*
|
|
52
|
+
* Dedupe tracks by a key function, keeping the first occurrence of each key. Keys are compared field-by-field ({@link
|
|
53
|
+
* sameKey}).
|
|
55
54
|
*/
|
|
56
55
|
function dedupe({ tracks, keyFn }) {
|
|
57
56
|
const seen = [];
|
|
@@ -64,9 +63,7 @@ function dedupe({ tracks, keyFn }) {
|
|
|
64
63
|
}
|
|
65
64
|
return kept;
|
|
66
65
|
}
|
|
67
|
-
/**
|
|
68
|
-
* Build a partial video track that can be used as `userVideoTrackSelection`.
|
|
69
|
-
*/
|
|
66
|
+
/** Build a partial video track that can be used as `userVideoTrackSelection`. */
|
|
70
67
|
function toUserVideoTrackSelection(rendition) {
|
|
71
68
|
return rendition ? {
|
|
72
69
|
width: rendition.width,
|
|
@@ -74,9 +71,7 @@ function toUserVideoTrackSelection(rendition) {
|
|
|
74
71
|
bandwidth: rendition.bandwidth
|
|
75
72
|
} : void 0;
|
|
76
73
|
}
|
|
77
|
-
/**
|
|
78
|
-
* Build a partial audio track that can be used as a `userAudioTrackSelection`.
|
|
79
|
-
*/
|
|
74
|
+
/** Build a partial audio track that can be used as a `userAudioTrackSelection`. */
|
|
80
75
|
function toUserAudioTrackSelection(track) {
|
|
81
76
|
return track ? {
|
|
82
77
|
language: track.language,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-tracks.js","names":[],"sources":["../../../../src/media/media-tracks/media-tracks.ts"],"sourcesContent":["/**\n * Media-track translation utilities.\n *\n * Pure, DOM-free transforms from SPF's CMAF-HAM track model onto the deduped
|
|
1
|
+
{"version":3,"file":"media-tracks.js","names":[],"sources":["../../../../src/media/media-tracks/media-tracks.ts"],"sourcesContent":["/**\n * Media-track translation utilities.\n *\n * Pure, DOM-free transforms from SPF's CMAF-HAM track model onto the deduped lists a media-element adapter exposes\n * (video renditions, audio tracks), plus the selection-criteria builders that turn a chosen rendition/track back into a\n * `user*TrackSelection` partial the engine's track-switching reads.\n *\n * These return SPF _model vocabulary_ (`bandwidth`, `codecs: string[]`, `frameRate` as a rational `FrameRate`); the\n * consuming adapter owns the mapping (e.g. for DOM `bandwidth` -> `bitrate`, `codecs.join(',')` -> `codec`, `name` ->\n * `label`).\n *\n * Deduplication is by _properties_, never URL, so a multi-CDN source that lists the same rendition on several hosts\n * collapses to one entry: video renditions by `width` + `height` + `bandwidth`, audio tracks by `language` + `name`.\n * The selection builders emit those same properties as the match criteria, so selecting a collapsed entry re-selects,\n * for example, every underlying per-CDN track.\n */\n\nimport type { AudioTrack, FrameRate, MaybeResolvedPresentation, VideoTrack } from '../types';\nimport { findTrackById, getTracksByType } from '../utils/tracks';\n\nexport type { AudioTrack, VideoTrack };\n\n/** Properties that identify a distinct video rendition (multi-CDN copies share them). */\nexport interface VideoDedupeKey {\n width?: VideoTrack['width'];\n height?: VideoTrack['height'];\n bandwidth?: VideoTrack['bandwidth'];\n}\n\n/** Properties that identify a distinct audio track (multi-CDN copies share them). */\nexport interface AudioDedupeKey {\n language?: AudioTrack['language'];\n name?: AudioTrack['name'];\n}\n\n/**\n * The distinct video tracks of a presentation, deduped by {@link VideoDedupeKey} (first occurrence wins).\n *\n * Returns `[]` when the presentation is unresolved or has no video tracks.\n */\nexport function dedupedVideoTracks(presentation: MaybeResolvedPresentation | undefined): VideoTrack[] {\n if (!presentation) return [];\n\n return dedupe({\n tracks: getTracksByType(presentation, 'video') as readonly VideoTrack[],\n keyFn: toUserVideoTrackSelection,\n });\n}\n\n/**\n * The distinct audio tracks of a presentation, deduped by `language` + `name` (first occurrence wins). Returns `[]`\n * when the presentation is unresolved or has no audio tracks.\n */\nexport function dedupedAudioTracks(presentation: MaybeResolvedPresentation | undefined): AudioTrack[] {\n if (!presentation) return [];\n\n return dedupe({\n tracks: getTracksByType(presentation, 'audio') as readonly AudioTrack[],\n keyFn: toUserAudioTrackSelection,\n });\n}\n\n/**\n * Find a video track by id, searching the same candidate set the engine resolves against ({@link dedupedVideoTracks}'s\n * pre-dedupe source). Returns `undefined` when absent. Maps the engine's resolved `selectedVideoTrackId` back to its\n * properties for `active` reflection — the resolved id may be a per-CDN copy that isn't the representative\n * {@link dedupedVideoTracks} kept.\n */\nexport function findVideoTrackById(\n presentation: MaybeResolvedPresentation | undefined,\n id: string | undefined\n): VideoTrack | undefined {\n if (!presentation || !id) return undefined;\n\n const track = findTrackById(presentation, id);\n\n return track?.type === 'video' ? (track as VideoTrack) : undefined;\n}\n\n/** Audio counterpart of {@link findVideoTrackById}, for `enabled` reflection. */\nexport function findAudioTrackById(\n presentation: MaybeResolvedPresentation | undefined,\n id: string | undefined\n): AudioTrack | undefined {\n if (!presentation || !id) return undefined;\n\n const track = findTrackById(presentation, id);\n\n return track?.type === 'audio' ? (track as AudioTrack) : undefined;\n}\n\n/**\n * Shallow-equal two key objects by their own properties. Both come from the same key builder, so they carry the same\n * keys — a one-directional scan suffices.\n */\nfunction sameKey<K extends object>(a: K, b: K): boolean {\n for (const attr in a) {\n if (a[attr] !== b[attr]) return false;\n }\n\n return true;\n}\n\n/**\n * Dedupe tracks by a key function, keeping the first occurrence of each key. Keys are compared field-by-field ({@link\n * sameKey}).\n */\nfunction dedupe<T, K extends object>({\n tracks,\n keyFn,\n}: {\n tracks: readonly T[];\n keyFn: (track: T) => K | undefined;\n}): T[] {\n const seen: K[] = [];\n const kept: T[] = [];\n\n for (const track of tracks) {\n const key = keyFn(track);\n if (!key || seen.some((other) => sameKey(other, key))) continue;\n\n seen.push(key);\n kept.push(track);\n }\n\n return kept;\n}\n\n/** Build a partial video track that can be used as `userVideoTrackSelection`. */\nexport function toUserVideoTrackSelection<T extends VideoDedupeKey>(rendition?: T): Partial<VideoTrack> | undefined {\n return rendition ? { width: rendition.width, height: rendition.height, bandwidth: rendition.bandwidth } : undefined;\n}\n\n/** Build a partial audio track that can be used as a `userAudioTrackSelection`. */\nexport function toUserAudioTrackSelection<T extends AudioDedupeKey>(track?: T): Partial<AudioTrack> | undefined {\n return track ? { language: track.language, name: track.name } : undefined;\n}\n\n/** Whether two video tracks are the same by dedupe key */\nexport function isSameVideoTrack(a: VideoDedupeKey, b: VideoDedupeKey | undefined): boolean {\n return !!b && a.width === b.width && a.height === b.height && a.bandwidth === b.bandwidth;\n}\n\n/** Whether two audio tracks are the same by dedupe key */\nexport function isSameAudioTrack(a: AudioDedupeKey, b: AudioDedupeKey | undefined): boolean {\n return !!b && (a.language ?? '') === (b.language ?? '') && a.name === b.name;\n}\n\n/** Collapse a rational frame rate (numerator/denominator) to frames per second. */\nexport const frameRateToNumber = (frameRate: FrameRate) => {\n return frameRate.frameRateNumerator / (frameRate.frameRateDenominator ?? 1);\n};\n"],"mappings":";;;;;;;AAwCA,SAAgB,mBAAmB,cAAmE;CACpG,IAAI,CAAC,cAAc,OAAO,CAAC;CAE3B,OAAO,OAAO;EACZ,QAAQ,gBAAgB,cAAc,OAAO;EAC7C,OAAO;CACT,CAAC;AACH;;;;;AAMA,SAAgB,mBAAmB,cAAmE;CACpG,IAAI,CAAC,cAAc,OAAO,CAAC;CAE3B,OAAO,OAAO;EACZ,QAAQ,gBAAgB,cAAc,OAAO;EAC7C,OAAO;CACT,CAAC;AACH;;;;;;;AAQA,SAAgB,mBACd,cACA,IACwB;CACxB,IAAI,CAAC,gBAAgB,CAAC,IAAI,OAAO,KAAA;CAEjC,MAAM,QAAQ,cAAc,cAAc,EAAE;CAE5C,OAAO,OAAO,SAAS,UAAW,QAAuB,KAAA;AAC3D;;AAGA,SAAgB,mBACd,cACA,IACwB;CACxB,IAAI,CAAC,gBAAgB,CAAC,IAAI,OAAO,KAAA;CAEjC,MAAM,QAAQ,cAAc,cAAc,EAAE;CAE5C,OAAO,OAAO,SAAS,UAAW,QAAuB,KAAA;AAC3D;;;;;AAMA,SAAS,QAA0B,GAAM,GAAe;CACtD,KAAK,MAAM,QAAQ,GACjB,IAAI,EAAE,UAAU,EAAE,OAAO,OAAO;CAGlC,OAAO;AACT;;;;;AAMA,SAAS,OAA4B,EACnC,QACA,SAIM;CACN,MAAM,OAAY,CAAC;CACnB,MAAM,OAAY,CAAC;CAEnB,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,MAAM,MAAM,KAAK;EACvB,IAAI,CAAC,OAAO,KAAK,MAAM,UAAU,QAAQ,OAAO,GAAG,CAAC,GAAG;EAEvD,KAAK,KAAK,GAAG;EACb,KAAK,KAAK,KAAK;CACjB;CAEA,OAAO;AACT;;AAGA,SAAgB,0BAAoD,WAAgD;CAClH,OAAO,YAAY;EAAE,OAAO,UAAU;EAAO,QAAQ,UAAU;EAAQ,WAAW,UAAU;CAAU,IAAI,KAAA;AAC5G;;AAGA,SAAgB,0BAAoD,OAA4C;CAC9G,OAAO,QAAQ;EAAE,UAAU,MAAM;EAAU,MAAM,MAAM;CAAK,IAAI,KAAA;AAClE;;AAGA,SAAgB,iBAAiB,GAAmB,GAAwC;CAC1F,OAAO,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE;AAClF;;AAGA,SAAgB,iBAAiB,GAAmB,GAAwC;CAC1F,OAAO,CAAC,CAAC,MAAM,EAAE,YAAY,SAAS,EAAE,YAAY,OAAO,EAAE,SAAS,EAAE;AAC1E;;AAGA,MAAa,qBAAqB,cAAyB;CACzD,OAAO,UAAU,sBAAsB,UAAU,wBAAwB;AAC3E"}
|
|
@@ -32,9 +32,8 @@ function* iterateBoxesOfType(view, type, start = 0, end = view.byteLength) {
|
|
|
32
32
|
for (const box of iterateBoxes(view, start, end)) if (box.type === type) yield box;
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
-
* Depth-first descent to the first box matching a nested path, e.g.
|
|
36
|
-
* `
|
|
37
|
-
* absent.
|
|
35
|
+
* Depth-first descent to the first box matching a nested path, e.g. `['moov', 'trak', 'mdia', 'mdhd']`. Returns
|
|
36
|
+
* `undefined` if any level is absent.
|
|
38
37
|
*/
|
|
39
38
|
function findBox(view, path, start = 0, end = view.byteLength) {
|
|
40
39
|
const [head, ...rest] = path;
|
|
@@ -46,8 +45,8 @@ function findBox(view, path, start = 0, end = view.byteLength) {
|
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
/**
|
|
49
|
-
* Read the version byte of a FullBox — the `version(1) + flags(3)` header at the
|
|
50
|
-
*
|
|
48
|
+
* Read the version byte of a FullBox — the `version(1) + flags(3)` header at the start of the payload of `mdhd` /
|
|
49
|
+
* `tkhd` / `tfdt` / `hdlr` / `elst` / etc.
|
|
51
50
|
*/
|
|
52
51
|
function readFullBoxVersion(view, dataStart) {
|
|
53
52
|
return view.getUint8(dataStart);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"box.js","names":[],"sources":["../../../../src/media/mp4/box.ts"],"sourcesContent":["/**\n * Minimal ISO-BMFF (MP4/CMAF) box walker.\n *\n * Just enough to locate boxes by nested path — the framework needs a couple of
|
|
1
|
+
{"version":3,"file":"box.js","names":[],"sources":["../../../../src/media/mp4/box.ts"],"sourcesContent":["/**\n * Minimal ISO-BMFF (MP4/CMAF) box walker.\n *\n * Just enough to locate boxes by nested path — the framework needs a couple of leaf fields (`mdhd` timescale, `tfdt`\n * baseMediaDecodeTime) to derive a segment's decode-time origin, not a full demuxer. DOM-free: operates on an\n * `ArrayBuffer` / `Uint8Array` via `DataView`.\n *\n * Box layout: `[u32 size][u32 type][payload]`. `size === 1` means a `u64 largesize` follows the type (payload after\n * it); `size === 0` means the box runs to the end of its container.\n */\n\n/** A located box: its 4-char type and byte offsets within the buffer. */\nexport interface Box {\n type: string;\n /** Offset of the box's first byte (its size field). */\n start: number;\n /** Offset of the box's payload — after `size` + `type` (+ `largesize`). */\n dataStart: number;\n /** Offset one past the box's last byte. */\n end: number;\n}\n\nexport function toDataView(data: ArrayBuffer | Uint8Array): DataView {\n return data instanceof Uint8Array ? new DataView(data.buffer, data.byteOffset, data.byteLength) : new DataView(data);\n}\n\n/** Read a 4-character box type / FourCC at `offset`. */\nexport function readFourCC(view: DataView, offset: number): string {\n return String.fromCharCode(\n view.getUint8(offset),\n view.getUint8(offset + 1),\n view.getUint8(offset + 2),\n view.getUint8(offset + 3)\n );\n}\n\n/** Iterate the boxes directly contained in `[start, end)`. */\nexport function* iterateBoxes(view: DataView, start = 0, end = view.byteLength): Generator<Box> {\n let offset = start;\n\n while (offset + 8 <= end) {\n let size = view.getUint32(offset);\n const type = readFourCC(view, offset + 4);\n let dataStart = offset + 8;\n\n if (size === 1) {\n size = Number(view.getBigUint64(offset + 8));\n dataStart = offset + 16;\n } else if (size === 0) {\n size = end - offset;\n }\n\n // A size smaller than its own header is malformed — stop rather than loop.\n if (size < dataStart - offset) return;\n\n yield { type, start: offset, dataStart, end: offset + size };\n offset += size;\n }\n}\n\n/** Iterate the direct child boxes of a given `type` within `[start, end)`. */\nexport function* iterateBoxesOfType(view: DataView, type: string, start = 0, end = view.byteLength): Generator<Box> {\n for (const box of iterateBoxes(view, start, end)) {\n if (box.type === type) yield box;\n }\n}\n\n/**\n * Depth-first descent to the first box matching a nested path, e.g. `['moov', 'trak', 'mdia', 'mdhd']`. Returns\n * `undefined` if any level is absent.\n */\nexport function findBox(view: DataView, path: readonly string[], start = 0, end = view.byteLength): Box | undefined {\n const [head, ...rest] = path;\n\n for (const box of iterateBoxes(view, start, end)) {\n if (box.type !== head) continue;\n\n if (rest.length === 0) return box;\n\n const found = findBox(view, rest, box.dataStart, box.end);\n if (found) return found;\n }\n\n return undefined;\n}\n\n/**\n * Read the version byte of a FullBox — the `version(1) + flags(3)` header at the start of the payload of `mdhd` /\n * `tkhd` / `tfdt` / `hdlr` / `elst` / etc.\n */\nexport function readFullBoxVersion(view: DataView, dataStart: number): number {\n return view.getUint8(dataStart);\n}\n"],"mappings":";AAsBA,SAAgB,WAAW,MAA0C;CACnE,OAAO,gBAAgB,aAAa,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU,IAAI,IAAI,SAAS,IAAI;AACrH;;AAGA,SAAgB,WAAW,MAAgB,QAAwB;CACjE,OAAO,OAAO,aACZ,KAAK,SAAS,MAAM,GACpB,KAAK,SAAS,SAAS,CAAC,GACxB,KAAK,SAAS,SAAS,CAAC,GACxB,KAAK,SAAS,SAAS,CAAC,CAC1B;AACF;;AAGA,UAAiB,aAAa,MAAgB,QAAQ,GAAG,MAAM,KAAK,YAA4B;CAC9F,IAAI,SAAS;CAEb,OAAO,SAAS,KAAK,KAAK;EACxB,IAAI,OAAO,KAAK,UAAU,MAAM;EAChC,MAAM,OAAO,WAAW,MAAM,SAAS,CAAC;EACxC,IAAI,YAAY,SAAS;EAEzB,IAAI,SAAS,GAAG;GACd,OAAO,OAAO,KAAK,aAAa,SAAS,CAAC,CAAC;GAC3C,YAAY,SAAS;EACvB,OAAO,IAAI,SAAS,GAClB,OAAO,MAAM;EAIf,IAAI,OAAO,YAAY,QAAQ;EAE/B,MAAM;GAAE;GAAM,OAAO;GAAQ;GAAW,KAAK,SAAS;EAAK;EAC3D,UAAU;CACZ;AACF;;AAGA,UAAiB,mBAAmB,MAAgB,MAAc,QAAQ,GAAG,MAAM,KAAK,YAA4B;CAClH,KAAK,MAAM,OAAO,aAAa,MAAM,OAAO,GAAG,GAC7C,IAAI,IAAI,SAAS,MAAM,MAAM;AAEjC;;;;;AAMA,SAAgB,QAAQ,MAAgB,MAAyB,QAAQ,GAAG,MAAM,KAAK,YAA6B;CAClH,MAAM,CAAC,MAAM,GAAG,QAAQ;CAExB,KAAK,MAAM,OAAO,aAAa,MAAM,OAAO,GAAG,GAAG;EAChD,IAAI,IAAI,SAAS,MAAM;EAEvB,IAAI,KAAK,WAAW,GAAG,OAAO;EAE9B,MAAM,QAAQ,QAAQ,MAAM,MAAM,IAAI,WAAW,IAAI,GAAG;EACxD,IAAI,OAAO,OAAO;CACpB;AAGF;;;;;AAMA,SAAgB,mBAAmB,MAAgB,WAA2B;CAC5E,OAAO,KAAK,SAAS,SAAS;AAChC"}
|
|
@@ -3,54 +3,43 @@ import { findBox, iterateBoxesOfType, readFourCC, readFullBoxVersion, toDataView
|
|
|
3
3
|
/**
|
|
4
4
|
* Decode-time origin extraction from fMP4/CMAF segments.
|
|
5
5
|
*
|
|
6
|
-
* Non-zero-PTS sources encode media at a non-zero start time (an instant clip
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* **decode-time origin** — read straight from the container:
|
|
6
|
+
* Non-zero-PTS sources encode media at a non-zero start time (an instant clip starting at asset second 60, an Apple
|
|
7
|
+
* bipbop asset starting at 10s, …). To relocate such a source onto a 0-based presentation timeline via
|
|
8
|
+
* `SourceBuffer.timestampOffset`, the engine needs that start time — the **decode-time origin** — read straight from
|
|
9
|
+
* the container:
|
|
11
10
|
*
|
|
12
|
-
* - `tfdt.baseMediaDecodeTime` (from a media segment's `moof`) — the decode
|
|
13
|
-
*
|
|
14
|
-
* a DTS
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* - `mdhd.timescale` (from the init segment's `moov`) — ticks per second for
|
|
18
|
-
* that track, needed to convert the raw tick count to seconds.
|
|
11
|
+
* - `tfdt.baseMediaDecodeTime` (from a media segment's `moof`) — the decode time of the segment's first sample, in the
|
|
12
|
+
* track's media timescale. This is a DTS: relocating by `−(baseMediaDecodeTime / timescale)` lands the earliest DTS
|
|
13
|
+
* at exactly 0, so a negative-DTS append failure on Chromium is impossible by construction.
|
|
14
|
+
* - `mdhd.timescale` (from the init segment's `moov`) — ticks per second for that track, needed to convert the raw tick
|
|
15
|
+
* count to seconds.
|
|
19
16
|
*
|
|
20
17
|
* ## Presumptive vs. track-selected reads
|
|
21
18
|
*
|
|
22
|
-
* The two variants share only the leaf field-readers (`mdhd` timescale, `tfdt`
|
|
23
|
-
*
|
|
24
|
-
* split is deliberate so the presumptive pair is *proportionally* smaller under
|
|
19
|
+
* The two variants share only the leaf field-readers (`mdhd` timescale, `tfdt` baseMediaDecodeTime) and the box walker.
|
|
20
|
+
* Everything else differs, and the split is deliberate so the presumptive pair is _proportionally_ smaller under
|
|
25
21
|
* tree-shaking:
|
|
26
22
|
*
|
|
27
|
-
* - **Presumptive** — {@link readFirstMediaTimescale} / {@link readFirstBaseMediaDecodeTime}
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* `
|
|
35
|
-
*
|
|
36
|
-
* `
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* presumptive read there risks `300000 / 6000 = 50s` instead of
|
|
41
|
-
* `60000 / 6000 = 10s`). This pair adds `trak`/`traf` iteration plus the handler
|
|
42
|
-
* and `track_id` reads. We only ever ask for buffered media handlers
|
|
43
|
-
* (`vide` / `soun`); the caption track is never selected — we read the origin,
|
|
44
|
-
* not the captions (caption *rendering* is out of scope).
|
|
23
|
+
* - **Presumptive** — {@link readFirstMediaTimescale} / {@link readFirstBaseMediaDecodeTime} read the first `mdhd`
|
|
24
|
+
* timescale and first `tfdt` baseMediaDecodeTime. There's no `track_id` (nothing to match against) and no
|
|
25
|
+
* `trak`/`traf` iteration — a direct `findBox` to the first leaf. Correct when the init/segment holds a single media
|
|
26
|
+
* track (the common CMAF case). A caption-free platform imports only this pair and tree-shakes away all the matching
|
|
27
|
+
* machinery below.
|
|
28
|
+
* - **Track-selected** — {@link findMediaTrack} / {@link readBaseMediaDecodeTime}. `findMediaTrack` returns `{ trackId,
|
|
29
|
+
* timescale }` for the `trak` whose `hdlr` handler matches; `readBaseMediaDecodeTime` takes that `trackId` and reads
|
|
30
|
+
* the `traf` whose `tfhd.track_id` matches. The `track_id` is the join that ties one track's timescale to the _same_
|
|
31
|
+
* track's baseMediaDecodeTime — required when a source muxes CEA-608/708 captions (a `clcp` track shares the same
|
|
32
|
+
* `moov` and `moof`, each track with its own timescale + baseMediaDecodeTime, so a presumptive read there risks
|
|
33
|
+
* `300000 / 6000 = 50s` instead of `60000 / 6000 = 10s`). This pair adds `trak`/`traf` iteration plus the handler and
|
|
34
|
+
* `track_id` reads. We only ever ask for buffered media handlers (`vide` / `soun`); the caption track is never
|
|
35
|
+
* selected — we read the origin, not the captions (caption _rendering_ is out of scope).
|
|
45
36
|
*
|
|
46
|
-
* Both raw values are returned un-divided to leave room for an edit-list (`elst`)
|
|
47
|
-
*
|
|
48
|
-
* streams do not.
|
|
37
|
+
* Both raw values are returned un-divided to leave room for an edit-list (`elst`) presentation-time correction term if
|
|
38
|
+
* a source ever carries one — the validated streams do not.
|
|
49
39
|
*/
|
|
50
40
|
/**
|
|
51
|
-
* The `track_ID` + timescale of the `trak` whose `mdhd` handler matches
|
|
52
|
-
*
|
|
53
|
-
* matching track exists.
|
|
41
|
+
* The `track_ID` + timescale of the `trak` whose `mdhd` handler matches `handlerType`, skipping a muxed `clcp` caption
|
|
42
|
+
* track. `undefined` if no matching track exists.
|
|
54
43
|
*/
|
|
55
44
|
function findMediaTrack(initSegment, handlerType) {
|
|
56
45
|
const view = toDataView(initSegment);
|
|
@@ -68,9 +57,8 @@ function findMediaTrack(initSegment, handlerType) {
|
|
|
68
57
|
}
|
|
69
58
|
}
|
|
70
59
|
/**
|
|
71
|
-
* `baseMediaDecodeTime` (in the track's media timescale) from the `traf` matching
|
|
72
|
-
*
|
|
73
|
-
* `undefined` if no matching `tfdt` exists.
|
|
60
|
+
* `baseMediaDecodeTime` (in the track's media timescale) from the `traf` matching `trackId` (via `tfhd.track_id`) —
|
|
61
|
+
* required for muxed multi-`traf` segments. `undefined` if no matching `tfdt` exists.
|
|
74
62
|
*/
|
|
75
63
|
function readBaseMediaDecodeTime(mediaSegment, trackId) {
|
|
76
64
|
const view = toDataView(mediaSegment);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timestamp-origin.js","names":[],"sources":["../../../../src/media/mp4/timestamp-origin.ts"],"sourcesContent":["/**\n * Decode-time origin extraction from fMP4/CMAF segments.\n *\n * Non-zero-PTS sources encode media at a non-zero start time (an instant clip
|
|
1
|
+
{"version":3,"file":"timestamp-origin.js","names":[],"sources":["../../../../src/media/mp4/timestamp-origin.ts"],"sourcesContent":["/**\n * Decode-time origin extraction from fMP4/CMAF segments.\n *\n * Non-zero-PTS sources encode media at a non-zero start time (an instant clip starting at asset second 60, an Apple\n * bipbop asset starting at 10s, …). To relocate such a source onto a 0-based presentation timeline via\n * `SourceBuffer.timestampOffset`, the engine needs that start time — the **decode-time origin** — read straight from\n * the container:\n *\n * - `tfdt.baseMediaDecodeTime` (from a media segment's `moof`) — the decode time of the segment's first sample, in the\n * track's media timescale. This is a DTS: relocating by `−(baseMediaDecodeTime / timescale)` lands the earliest DTS\n * at exactly 0, so a negative-DTS append failure on Chromium is impossible by construction.\n * - `mdhd.timescale` (from the init segment's `moov`) — ticks per second for that track, needed to convert the raw tick\n * count to seconds.\n *\n * ## Presumptive vs. track-selected reads\n *\n * The two variants share only the leaf field-readers (`mdhd` timescale, `tfdt` baseMediaDecodeTime) and the box walker.\n * Everything else differs, and the split is deliberate so the presumptive pair is _proportionally_ smaller under\n * tree-shaking:\n *\n * - **Presumptive** — {@link readFirstMediaTimescale} / {@link readFirstBaseMediaDecodeTime} read the first `mdhd`\n * timescale and first `tfdt` baseMediaDecodeTime. There's no `track_id` (nothing to match against) and no\n * `trak`/`traf` iteration — a direct `findBox` to the first leaf. Correct when the init/segment holds a single media\n * track (the common CMAF case). A caption-free platform imports only this pair and tree-shakes away all the matching\n * machinery below.\n * - **Track-selected** — {@link findMediaTrack} / {@link readBaseMediaDecodeTime}. `findMediaTrack` returns `{ trackId,\n * timescale }` for the `trak` whose `hdlr` handler matches; `readBaseMediaDecodeTime` takes that `trackId` and reads\n * the `traf` whose `tfhd.track_id` matches. The `track_id` is the join that ties one track's timescale to the _same_\n * track's baseMediaDecodeTime — required when a source muxes CEA-608/708 captions (a `clcp` track shares the same\n * `moov` and `moof`, each track with its own timescale + baseMediaDecodeTime, so a presumptive read there risks\n * `300000 / 6000 = 50s` instead of `60000 / 6000 = 10s`). This pair adds `trak`/`traf` iteration plus the handler and\n * `track_id` reads. We only ever ask for buffered media handlers (`vide` / `soun`); the caption track is never\n * selected — we read the origin, not the captions (caption _rendering_ is out of scope).\n *\n * Both raw values are returned un-divided to leave room for an edit-list (`elst`) presentation-time correction term if\n * a source ever carries one — the validated streams do not.\n */\nimport { type Box, findBox, iterateBoxesOfType, readFourCC, readFullBoxVersion, toDataView } from './box';\n\n/** MSE-buffered media handler types (`mdhd`/`hdlr`). Captions/subtitles excluded. */\nexport type MediaHandlerType = 'vide' | 'soun';\n\nexport interface MediaTrackInfo {\n /** `tkhd.track_id` — used to match the corresponding `traf` in media segments. */\n trackId: number;\n /** `mdhd.timescale` — ticks per second for this track. */\n timescale: number;\n}\n\n// --- presumptive: first leaf, no track_id, no iteration -----------------------\n\n/**\n * Presumptive: the `timescale` of the **first** `mdhd` in an init segment. Correct only for single-media-track inits —\n * for muxed captions use {@link findMediaTrack}. `undefined` if no `mdhd` exists.\n */\nexport function readFirstMediaTimescale(initSegment: ArrayBuffer | Uint8Array): number | undefined {\n const view = toDataView(initSegment);\n const mdhd = findBox(view, ['moov', 'trak', 'mdia', 'mdhd']);\n\n return mdhd ? readMdhdTimescale(view, mdhd) : undefined;\n}\n\n/**\n * Presumptive: `baseMediaDecodeTime` from the **first** `tfdt` of a media segment. Correct only for single-`traf`\n * segments — for muxed captions use {@link readBaseMediaDecodeTime}. `undefined` if no `tfdt` exists.\n */\nexport function readFirstBaseMediaDecodeTime(mediaSegment: ArrayBuffer | Uint8Array): number | undefined {\n const view = toDataView(mediaSegment);\n const tfdt = findBox(view, ['moof', 'traf', 'tfdt']);\n\n return tfdt ? readTfdtBaseMediaDecodeTime(view, tfdt) : undefined;\n}\n\n// --- track-selected: iterate + match by handler / track_id --------------------\n\n/**\n * The `track_ID` + timescale of the `trak` whose `mdhd` handler matches `handlerType`, skipping a muxed `clcp` caption\n * track. `undefined` if no matching track exists.\n */\nexport function findMediaTrack(\n initSegment: ArrayBuffer | Uint8Array,\n handlerType: MediaHandlerType\n): MediaTrackInfo | undefined {\n const view = toDataView(initSegment);\n const moov = findBox(view, ['moov']);\n if (!moov) return undefined;\n\n for (const trak of iterateBoxesOfType(view, 'trak', moov.dataStart, moov.end)) {\n if (readTrakHandler(view, trak) !== handlerType) continue;\n\n const tkhd = findBox(view, ['tkhd'], trak.dataStart, trak.end);\n const mdhd = findBox(view, ['mdia', 'mdhd'], trak.dataStart, trak.end);\n if (!tkhd || !mdhd) return undefined;\n\n // tkhd FullBox: version(1)+flags(3), creation/modification dates (v0: 4+4, v1:\n // 8+8), then track_id.\n const trackId = view.getUint32(tkhd.dataStart + 4 + (readFullBoxVersion(view, tkhd.dataStart) === 1 ? 16 : 8));\n\n return { trackId, timescale: readMdhdTimescale(view, mdhd) };\n }\n\n return undefined;\n}\n\n/**\n * `baseMediaDecodeTime` (in the track's media timescale) from the `traf` matching `trackId` (via `tfhd.track_id`) —\n * required for muxed multi-`traf` segments. `undefined` if no matching `tfdt` exists.\n */\nexport function readBaseMediaDecodeTime(mediaSegment: ArrayBuffer | Uint8Array, trackId: number): number | undefined {\n const view = toDataView(mediaSegment);\n const moof = findBox(view, ['moof']);\n if (!moof) return undefined;\n\n for (const traf of iterateBoxesOfType(view, 'traf', moof.dataStart, moof.end)) {\n if (readTrafTrackId(view, traf) !== trackId) continue;\n\n const tfdt = findBox(view, ['tfdt'], traf.dataStart, traf.end);\n\n return tfdt ? readTfdtBaseMediaDecodeTime(view, tfdt) : undefined;\n }\n\n return undefined;\n}\n\n// --- shared leaf field-readers ------------------------------------------------\n\n/** `mdhd.timescale`: FullBox version(1)+flags(3) + dates (v0: 4+4, v1: 8+8) + timescale. */\nfunction readMdhdTimescale(view: DataView, mdhd: Box): number {\n return view.getUint32(mdhd.dataStart + 4 + (readFullBoxVersion(view, mdhd.dataStart) === 1 ? 16 : 8));\n}\n\n/** `tfdt.baseMediaDecodeTime`: FullBox, then the value — v0: (4), v1: (8). */\nfunction readTfdtBaseMediaDecodeTime(view: DataView, tfdt: Box): number {\n const at = tfdt.dataStart + 4;\n\n return readFullBoxVersion(view, tfdt.dataStart) === 1 ? Number(view.getBigUint64(at)) : view.getUint32(at);\n}\n\n// --- track-selection readers (referenced only by the track-selected variants) -\n\n/** `hdlr.handler_type` for a `trak`: FullBox version(1)+flags(3) + pre_defined(4) + handler_type(4). */\nfunction readTrakHandler(view: DataView, trak: Box): string | undefined {\n const hdlr = findBox(view, ['mdia', 'hdlr'], trak.dataStart, trak.end);\n\n return hdlr ? readFourCC(view, hdlr.dataStart + 8) : undefined;\n}\n\n/** `tfhd.track_id` for a `traf`: FullBox version(1)+flags(3) + track_id(4). */\nfunction readTrafTrackId(view: DataView, traf: Box): number | undefined {\n const tfhd = findBox(view, ['tfhd'], traf.dataStart, traf.end);\n\n return tfhd ? view.getUint32(tfhd.dataStart + 4) : undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+EA,SAAgB,eACd,aACA,aAC4B;CAC5B,MAAM,OAAO,WAAW,WAAW;CACnC,MAAM,OAAO,QAAQ,MAAM,CAAC,MAAM,CAAC;CACnC,IAAI,CAAC,MAAM,OAAO,KAAA;CAElB,KAAK,MAAM,QAAQ,mBAAmB,MAAM,QAAQ,KAAK,WAAW,KAAK,GAAG,GAAG;EAC7E,IAAI,gBAAgB,MAAM,IAAI,MAAM,aAAa;EAEjD,MAAM,OAAO,QAAQ,MAAM,CAAC,MAAM,GAAG,KAAK,WAAW,KAAK,GAAG;EAC7D,MAAM,OAAO,QAAQ,MAAM,CAAC,QAAQ,MAAM,GAAG,KAAK,WAAW,KAAK,GAAG;EACrE,IAAI,CAAC,QAAQ,CAAC,MAAM,OAAO,KAAA;EAM3B,OAAO;GAAE,SAFO,KAAK,UAAU,KAAK,YAAY,KAAK,mBAAmB,MAAM,KAAK,SAAS,MAAM,IAAI,KAAK,EAE5F;GAAG,WAAW,kBAAkB,MAAM,IAAI;EAAE;CAC7D;AAGF;;;;;AAMA,SAAgB,wBAAwB,cAAwC,SAAqC;CACnH,MAAM,OAAO,WAAW,YAAY;CACpC,MAAM,OAAO,QAAQ,MAAM,CAAC,MAAM,CAAC;CACnC,IAAI,CAAC,MAAM,OAAO,KAAA;CAElB,KAAK,MAAM,QAAQ,mBAAmB,MAAM,QAAQ,KAAK,WAAW,KAAK,GAAG,GAAG;EAC7E,IAAI,gBAAgB,MAAM,IAAI,MAAM,SAAS;EAE7C,MAAM,OAAO,QAAQ,MAAM,CAAC,MAAM,GAAG,KAAK,WAAW,KAAK,GAAG;EAE7D,OAAO,OAAO,4BAA4B,MAAM,IAAI,IAAI,KAAA;CAC1D;AAGF;;AAKA,SAAS,kBAAkB,MAAgB,MAAmB;CAC5D,OAAO,KAAK,UAAU,KAAK,YAAY,KAAK,mBAAmB,MAAM,KAAK,SAAS,MAAM,IAAI,KAAK,EAAE;AACtG;;AAGA,SAAS,4BAA4B,MAAgB,MAAmB;CACtE,MAAM,KAAK,KAAK,YAAY;CAE5B,OAAO,mBAAmB,MAAM,KAAK,SAAS,MAAM,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC,IAAI,KAAK,UAAU,EAAE;AAC3G;;AAKA,SAAS,gBAAgB,MAAgB,MAA+B;CACtE,MAAM,OAAO,QAAQ,MAAM,CAAC,QAAQ,MAAM,GAAG,KAAK,WAAW,KAAK,GAAG;CAErE,OAAO,OAAO,WAAW,MAAM,KAAK,YAAY,CAAC,IAAI,KAAA;AACvD;;AAGA,SAAS,gBAAgB,MAAgB,MAA+B;CACtE,MAAM,OAAO,QAAQ,MAAM,CAAC,MAAM,GAAG,KAAK,WAAW,KAAK,GAAG;CAE7D,OAAO,OAAO,KAAK,UAAU,KAAK,YAAY,CAAC,IAAI,KAAA;AACrD"}
|
|
@@ -2,18 +2,16 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Pixel dimensions, and the one projection every reader of them needs.
|
|
4
4
|
*
|
|
5
|
-
* Shared by the surfaces a rendition cap measures — a screen (`media/dom/screen`),
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* DOM-free selection rules name the type they read instead of restating its shape.
|
|
5
|
+
* Shared by the surfaces a rendition cap measures — a screen (`media/dom/screen`), a player element
|
|
6
|
+
* (`behaviors/dom/track-player-resolution`) — and by the caps that compare renditions against them. Lives outside the
|
|
7
|
+
* DOM layer because scaling and rounding two numbers needs no DOM, which is also what lets the DOM-free selection rules
|
|
8
|
+
* name the type they read instead of restating its shape.
|
|
10
9
|
*/
|
|
11
10
|
/**
|
|
12
11
|
* A surface's pixel dimensions.
|
|
13
12
|
*
|
|
14
|
-
* A width and a height rather than a `"720p"`-style tier, because a tier only
|
|
15
|
-
*
|
|
16
|
-
* mis-measures an anamorphic or otherwise non-16:9 rendition.
|
|
13
|
+
* A width and a height rather than a `"720p"`-style tier, because a tier only describes a surface once you assume its
|
|
14
|
+
* aspect ratio — the assumption that mis-measures an anamorphic or otherwise non-16:9 rendition.
|
|
17
15
|
*/
|
|
18
16
|
interface Resolution {
|
|
19
17
|
readonly width: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolution.d.ts","names":[],"sources":["../../../../src/media/primitives/resolution.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolution.d.ts","names":[],"sources":["../../../../src/media/primitives/resolution.ts"],"mappings":";;;;;;;;;;;;;;;UAeiB;WACN;WACA"}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
//#region src/media/primitives/resolution.ts
|
|
2
2
|
/**
|
|
3
|
-
* Apply `scale` to a size and normalize it to whole pixels, or `undefined` where
|
|
4
|
-
* that leaves nothing to describe.
|
|
3
|
+
* Apply `scale` to a size and normalize it to whole pixels, or `undefined` where that leaves nothing to describe.
|
|
5
4
|
*
|
|
6
|
-
* Rounded because pixels are whole and a fractional scale doesn't divide a
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* absence as "unknown, don't cap" while an area of zero would read as a cap of
|
|
11
|
-
* zero — pinning every source to its smallest rendition.
|
|
5
|
+
* Rounded because pixels are whole and a fractional scale doesn't divide a surface evenly. A non-positive or non-finite
|
|
6
|
+
* axis yields `undefined` rather than a zero-area reading: an element that isn't being rendered reports `0 × 0` and a
|
|
7
|
+
* nonsense dimension reports `NaN`, and the caps consuming this read absence as "unknown, don't cap" while an area of
|
|
8
|
+
* zero would read as a cap of zero — pinning every source to its smallest rendition.
|
|
12
9
|
*
|
|
13
10
|
* @param size - Dimensions to project, in the units `scale` converts from
|
|
14
11
|
* @param scale - Multiplier for both axes, e.g. `devicePixelRatio`; defaults to 1
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolution.js","names":[],"sources":["../../../../src/media/primitives/resolution.ts"],"sourcesContent":["/**\n * Pixel dimensions, and the one projection every reader of them needs.\n *\n * Shared by the surfaces a rendition cap measures — a screen (`media/dom/screen`)
|
|
1
|
+
{"version":3,"file":"resolution.js","names":[],"sources":["../../../../src/media/primitives/resolution.ts"],"sourcesContent":["/**\n * Pixel dimensions, and the one projection every reader of them needs.\n *\n * Shared by the surfaces a rendition cap measures — a screen (`media/dom/screen`), a player element\n * (`behaviors/dom/track-player-resolution`) — and by the caps that compare renditions against them. Lives outside the\n * DOM layer because scaling and rounding two numbers needs no DOM, which is also what lets the DOM-free selection rules\n * name the type they read instead of restating its shape.\n */\n\n/**\n * A surface's pixel dimensions.\n *\n * A width and a height rather than a `\"720p\"`-style tier, because a tier only describes a surface once you assume its\n * aspect ratio — the assumption that mis-measures an anamorphic or otherwise non-16:9 rendition.\n */\nexport interface Resolution {\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Apply `scale` to a size and normalize it to whole pixels, or `undefined` where that leaves nothing to describe.\n *\n * Rounded because pixels are whole and a fractional scale doesn't divide a surface evenly. A non-positive or non-finite\n * axis yields `undefined` rather than a zero-area reading: an element that isn't being rendered reports `0 × 0` and a\n * nonsense dimension reports `NaN`, and the caps consuming this read absence as \"unknown, don't cap\" while an area of\n * zero would read as a cap of zero — pinning every source to its smallest rendition.\n *\n * @param size - Dimensions to project, in the units `scale` converts from\n * @param scale - Multiplier for both axes, e.g. `devicePixelRatio`; defaults to 1\n * @returns The scaled, whole-pixel resolution, or `undefined` when either axis\n * doesn't survive it\n */\nexport function scaleResolution(size: Resolution, scale = 1): Resolution | undefined {\n const width = Math.round(size.width * scale);\n const height = Math.round(size.height * scale);\n\n return width > 0 && height > 0 ? { width, height } : undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;AAiCA,SAAgB,gBAAgB,MAAkB,QAAQ,GAA2B;CACnF,MAAM,QAAQ,KAAK,MAAM,KAAK,QAAQ,KAAK;CAC3C,MAAM,SAAS,KAAK,MAAM,KAAK,SAAS,KAAK;CAE7C,OAAO,QAAQ,KAAK,SAAS,IAAI;EAAE;EAAO;CAAO,IAAI,KAAA;AACvD"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
//#region src/media/primitives/select-tracks.ts
|
|
2
2
|
/**
|
|
3
|
-
* Test whether a track matches a partial-track description: every present,
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* (`{ id }`, `{ language }`, `{ height }`, …).
|
|
3
|
+
* Test whether a track matches a partial-track description: every present, defined field of `filter` equals the
|
|
4
|
+
* track's. Absent or `undefined` filter fields don't constrain. Used to narrow candidates by a user selection (`{ id
|
|
5
|
+
* }`, `{ language }`, `{ height }`, …).
|
|
7
6
|
*
|
|
8
7
|
* @param track - The track to test
|
|
9
8
|
* @param filter - Partial-track description; only present, defined fields constrain
|
|
@@ -21,51 +20,44 @@ function pixelArea(track) {
|
|
|
21
20
|
return (track.width ?? 0) * (track.height ?? 0);
|
|
22
21
|
}
|
|
23
22
|
/**
|
|
24
|
-
* Narrow to the tracks at or below `maxPixelArea`, and nothing else: no ordering,
|
|
25
|
-
*
|
|
26
|
-
* answer — "none of these fit".
|
|
23
|
+
* Narrow to the tracks at or below `maxPixelArea`, and nothing else: no ordering, no fallback. Survivors keep their
|
|
24
|
+
* incoming order, and an empty result is a real answer — "none of these fit".
|
|
27
25
|
*
|
|
28
|
-
* Deliberately only the filter, because as a selection rule this composes under
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* ({@link byDescendingResolution}, bandwidth ABR). Doing either here would duplicate
|
|
33
|
-
* the composer and give one rule two responsibilities.
|
|
26
|
+
* Deliberately only the filter, because as a selection rule this composes under `applyRules`, which already owns both
|
|
27
|
+
* halves a caller might expect here: an empty result is skipped, so a preference can never narrow the candidate set to
|
|
28
|
+
* nothing; and ordering the survivors is a separate rule's job ({@link byDescendingResolution}, bandwidth ABR). Doing
|
|
29
|
+
* either here would duplicate the composer and give one rule two responsibilities.
|
|
34
30
|
*/
|
|
35
31
|
function tracksUnderPixelArea(tracks, maxPixelArea = Number.POSITIVE_INFINITY) {
|
|
36
32
|
return tracks.filter((track) => pixelArea(track) <= maxPixelArea);
|
|
37
33
|
}
|
|
38
34
|
/**
|
|
39
|
-
* The smallest track area that still covers `minPixelArea`, or `undefined` when
|
|
40
|
-
* no track reaches it.
|
|
35
|
+
* The smallest track area that still covers `minPixelArea`, or `undefined` when no track reaches it.
|
|
41
36
|
*
|
|
42
|
-
* The cap a surface-size rule wants when it should round
|
|
43
|
-
*
|
|
44
|
-
* surface's own area instead would serve a picture smaller than the surface and
|
|
37
|
+
* The cap a surface-size rule wants when it should round _up_ to the ladder: a surface between two tiers is covered by
|
|
38
|
+
* the upper one, and capping at the surface's own area instead would serve a picture smaller than the surface and
|
|
45
39
|
* upscale it.
|
|
46
40
|
*
|
|
47
|
-
* Tracks declaring no dimensions compare as area `0` and so never cover anything,
|
|
48
|
-
*
|
|
41
|
+
* Tracks declaring no dimensions compare as area `0` and so never cover anything, which keeps them out of the cap
|
|
42
|
+
* rather than pinning it to zero.
|
|
49
43
|
*/
|
|
50
44
|
function smallestCoveringPixelArea(tracks, minPixelArea) {
|
|
51
45
|
const covering = tracks.map(pixelArea).filter((area) => area >= minPixelArea);
|
|
52
46
|
return covering.length ? Math.min(...covering) : void 0;
|
|
53
47
|
}
|
|
54
48
|
/**
|
|
55
|
-
* Compare two tracks by resolution, largest first, with bandwidth as the tiebreak
|
|
56
|
-
*
|
|
57
|
-
* `0`, so a track without them sorts last.
|
|
49
|
+
* Compare two tracks by resolution, largest first, with bandwidth as the tiebreak for renditions of identical
|
|
50
|
+
* dimensions. Missing dimensions are treated as area `0`, so a track without them sorts last.
|
|
58
51
|
*
|
|
59
|
-
* A comparator rather than a "highest track" function: the selection-rule chain
|
|
60
|
-
*
|
|
61
|
-
* single track. `preferHighestResolution` is `sort` over this and nothing more.
|
|
52
|
+
* A comparator rather than a "highest track" function: the selection-rule chain takes the head of the list it produces,
|
|
53
|
+
* so ranking never has to collapse to a single track. `preferHighestResolution` is `sort` over this and nothing more.
|
|
62
54
|
*/
|
|
63
55
|
function byDescendingResolution(a, b) {
|
|
64
56
|
return pixelArea(b) - pixelArea(a) || (b.bandwidth ?? 0) - (a.bandwidth ?? 0);
|
|
65
57
|
}
|
|
66
58
|
/**
|
|
67
|
-
* Default audio policy over a candidate list: the three-tier pick a selection-rule
|
|
68
|
-
*
|
|
59
|
+
* Default audio policy over a candidate list: the three-tier pick a selection-rule chain applies once it has narrowed
|
|
60
|
+
* the candidates.
|
|
69
61
|
*
|
|
70
62
|
* Priority: `preferredAudioLanguage` match → `DEFAULT=YES` → first track.
|
|
71
63
|
*/
|
|
@@ -79,13 +71,11 @@ function pickAudioTrackFromTracks(tracks, config) {
|
|
|
79
71
|
return tracks[0]?.id;
|
|
80
72
|
}
|
|
81
73
|
/**
|
|
82
|
-
* Default text-track policy over a candidate list: the opt-in three-tier pick
|
|
83
|
-
*
|
|
84
|
-
* constrained, CDN-scoped set.
|
|
74
|
+
* Default text-track policy over a candidate list: the opt-in three-tier pick `switchTextTrack`'s terminal applies once
|
|
75
|
+
* it has narrowed the renditions to the constrained, CDN-scoped set.
|
|
85
76
|
*
|
|
86
|
-
* Priority: `preferredSubtitleLanguage` match → `DEFAULT=YES + AUTOSELECT=YES`
|
|
87
|
-
*
|
|
88
|
-
* excluded unless `includeForcedTracks` (Apple-spec: a regular track must carry
|
|
77
|
+
* Priority: `preferredSubtitleLanguage` match → `DEFAULT=YES + AUTOSELECT=YES` (only when `enableDefaultTrack`) →
|
|
78
|
+
* `undefined` (opt-in). FORCED tracks are excluded unless `includeForcedTracks` (Apple-spec: a regular track must carry
|
|
89
79
|
* forced content when both exist, so a forced-only track is redundant).
|
|
90
80
|
*/
|
|
91
81
|
function pickTextTrackFromTracks(tracks, config) {
|