supervision 0.2.0-next.2 → 0.2.0-next.3

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/index.js CHANGED
@@ -1114,10 +1114,11 @@ async function openMediabunnyMediaSource(sourceInput) {
1114
1114
  })
1115
1115
  .catch(() => null)
1116
1116
  : Promise.resolve(null);
1117
- const [displayWidth, displayHeight, firstTimestamp, packetStats] = await Promise.all([
1117
+ const [displayWidth, displayHeight, firstTimestamp, timeResolution, packetStats,] = await Promise.all([
1118
1118
  primaryVideoTrack.getDisplayWidth(),
1119
1119
  primaryVideoTrack.getDisplayHeight(),
1120
1120
  primaryVideoTrack.getFirstTimestamp(),
1121
+ primaryVideoTrack.getTimeResolution(),
1121
1122
  packetStatsPromise,
1122
1123
  ]);
1123
1124
  const duration = isUrlSourceInput(sourceInput)
@@ -1145,6 +1146,7 @@ async function openMediabunnyMediaSource(sourceInput) {
1145
1146
  mimeType,
1146
1147
  primaryVideoHeight: displayHeight,
1147
1148
  primaryVideoWidth: displayWidth,
1149
+ timeResolution,
1148
1150
  trackCount: tracks.length,
1149
1151
  videoTrackCount: videoTracks.length,
1150
1152
  },
@@ -3151,6 +3153,7 @@ function createMediaRendererTransport(options) {
3151
3153
  // play the hold is waiting for, so a pause taken during it is not undone by
3152
3154
  // the readiness that arrives afterwards.
3153
3155
  let playbackIntent = 0;
3156
+ let stepIntent = null;
3154
3157
  /** Intent a readiness wait belongs to, or null while none is running. */
3155
3158
  let readinessHoldIntent = null;
3156
3159
  /** Whether a readiness hold still owes the producer its release. */
@@ -3169,8 +3172,15 @@ function createMediaRendererTransport(options) {
3169
3172
  const beginPlaybackIntent = () => {
3170
3173
  activeReadinessWait?.abort();
3171
3174
  activeReadinessWait = undefined;
3175
+ stepIntent = null;
3172
3176
  return ++playbackIntent;
3173
3177
  };
3178
+ const beginStepIntent = () => {
3179
+ if (stepIntent !== null)
3180
+ return stepIntent;
3181
+ stepIntent = beginPlaybackIntent();
3182
+ return stepIntent;
3183
+ };
3174
3184
  const publishSeekSignals = () => {
3175
3185
  options.onScrubbing(gestureInFlight);
3176
3186
  options.onSeeking(isSettling(channel.getStatus(), channel.getSeeking()));
@@ -3460,15 +3470,23 @@ function createMediaRendererTransport(options) {
3460
3470
  options.invalidatePresentedFrame?.();
3461
3471
  const navigationPresentation = ++presentationWait;
3462
3472
  presentationHold = null;
3463
- beginPlaybackIntent();
3473
+ const intent = beginStepIntent();
3464
3474
  await releaseGesture();
3475
+ if (intent !== playbackIntent)
3476
+ return;
3465
3477
  if (navigationPresentation === presentationWait) {
3466
3478
  await releaseReadinessFreeze();
3467
3479
  }
3480
+ if (intent !== playbackIntent)
3481
+ return;
3468
3482
  const presentation = options.beginPresentedFrameNavigation?.();
3469
3483
  const before = channel.getPlayhead().frame;
3470
3484
  try {
3471
3485
  await channel.step(direction);
3486
+ if (intent !== playbackIntent) {
3487
+ presentation?.cancel();
3488
+ return;
3489
+ }
3472
3490
  const after = channel.getPlayhead().frame;
3473
3491
  if (before.index === after.index && before.ticks === after.ticks) {
3474
3492
  // A boundary step intentionally emits no replacement frame. The
@@ -4002,6 +4020,7 @@ async function createMediaRendererCore(options, providers) {
4002
4020
  let pushPresentationReady = false;
4003
4021
  let sampleSink;
4004
4022
  let firstTimestamp = 0;
4023
+ let sampleTimeResolution = null;
4005
4024
  let navigationVersion = 0;
4006
4025
  let outstandingSourceReads = 0;
4007
4026
  let pendingPullScrubTime = null;
@@ -4654,6 +4673,12 @@ async function createMediaRendererCore(options, providers) {
4654
4673
  }
4655
4674
  const { metadata } = mediaSource;
4656
4675
  firstTimestamp = metadata.firstTimestamp;
4676
+ sampleTimeResolution =
4677
+ metadata.timeResolution !== undefined &&
4678
+ Number.isFinite(metadata.timeResolution) &&
4679
+ metadata.timeResolution > 0
4680
+ ? metadata.timeResolution
4681
+ : null;
4657
4682
  // One central projection step for every detection input this renderer can
4658
4683
  // receive: static frames, a caller-owned source, or a composite source.
4659
4684
  // Media dimensions are known here, so a producer can declare its own
@@ -4901,21 +4926,38 @@ async function createMediaRendererCore(options, providers) {
4901
4926
  playbackController.pause();
4902
4927
  runtimeState.setPaused();
4903
4928
  const currentTime = runtimeState.currentTime();
4904
- const epsilon = 1e-6;
4905
4929
  let sample = null;
4906
4930
  try {
4907
4931
  if (direction === "backward") {
4908
- sample = await trackSourceRead(sampleSink.getSample(Math.max(firstTimestamp, currentTime - epsilon), {
4932
+ if (currentTime <= firstTimestamp) {
4933
+ return;
4934
+ }
4935
+ const stepSeconds = sampleTimeResolution === null ? 1e-6 : 1 / sampleTimeResolution;
4936
+ sample = await trackSourceRead(sampleSink.getSample(Math.max(firstTimestamp, currentTime - stepSeconds), {
4909
4937
  skipLiveWait: true,
4910
4938
  }));
4911
4939
  }
4912
4940
  else {
4913
- const iterator = sampleSink.samples(currentTime + epsilon, undefined, {
4941
+ const iterator = sampleSink.samples(currentTime, undefined, {
4914
4942
  skipLiveWait: true,
4915
4943
  });
4916
4944
  try {
4917
- const result = await trackSourceRead(iterator.next());
4918
- sample = result.done ? null : result.value;
4945
+ while (true) {
4946
+ const result = await trackSourceRead(iterator.next());
4947
+ if (result.done) {
4948
+ break;
4949
+ }
4950
+ if (requestVersion !== navigationVersion ||
4951
+ runtimeState.isDestroyed()) {
4952
+ result.value.close();
4953
+ return;
4954
+ }
4955
+ if (result.value.timestamp > currentTime) {
4956
+ sample = result.value;
4957
+ break;
4958
+ }
4959
+ result.value.close();
4960
+ }
4919
4961
  }
4920
4962
  finally {
4921
4963
  await iterator.return?.();