diff --git a/steps/src/constants.js b/steps/src/constants.js
index c42fa95..07a451f 100644
--- a/steps/src/constants.js
+++ b/steps/src/constants.js
@@ -12,13 +12,13 @@ export const RADAR_Y_MIN = 0;
export const RADAR_Y_MAX = 80;
// Region of Interest 1 (Tracks Region)
-export const ROI_TRACKS_X_MIN = -10;
-export const ROI_TRACKS_X_MAX = 10;
+export const ROI_TRACKS_X_MIN = -5;
+export const ROI_TRACKS_X_MAX = 5;
export const ROI_TRACKS_Y_MIN = 0;
export const ROI_TRACKS_Y_MAX = 80;
// Region of Interest 2 (Close Region)
-export const ROI_CLOSE_X_MIN = -10;
-export const ROI_CLOSE_X_MAX = 10;
+export const ROI_CLOSE_X_MIN = -5;
+export const ROI_CLOSE_X_MAX = 5;
export const ROI_CLOSE_Y_MIN = 0;
export const ROI_CLOSE_Y_MAX = 20;
\ No newline at end of file
diff --git a/steps/src/dom.js b/steps/src/dom.js
index 321032e..6a5eecd 100644
--- a/steps/src/dom.js
+++ b/steps/src/dom.js
@@ -86,6 +86,7 @@ export const toggleConfirmedOnly = document.getElementById("toggle-confirmed-onl
//----------------------UPDATE FRAME Function----------------------//
// Updates the UI to reflect the current radar frame and synchronizes video playback.
export function updateFrame(frame, forceVideoSeek) {
+ const startTime = performance.now(); //start emasuring timer of performance.
if (
!appState.vizData ||
frame < 0 ||
@@ -155,7 +156,10 @@ export function updateFrame(frame, forceVideoSeek) {
if (appState.p5_instance) appState.p5_instance.redraw(); // Redraw radar sketch
if (appState.speedGraphInstance && !appState.isPlaying)
// Redraw speed graph if not playing.
- appState.speedGraphInstance.redraw();
+ appState.speedGraphInstance.redraw();
+ const endTime = performance.now();
+ appState.lastFrameRenderTime = endTime - startTime; // <-- End timer and update state
+
}
//----------------------RESET VISUALIZATION Function----------------------//
@@ -245,16 +249,18 @@ export function updateDebugOverlay(currentMediaTime) {
content.push(`Video Time (s): ${currentMediaTime.toFixed(3)}`); // Display current video time
content.push(`Target Radar Time (ms): ${targetRadarTimeMs.toFixed(0)}`);
- content.push(
- `Drift (ms): ${driftMs.toFixed(0)}`
- );
- content.push(
- `Video Start Time: ${appState.videoStartDate.toISOString()}`
- );
- content.push(
- `Radar Start Time: ${new Date(appState.radarStartTimeMs).toISOString()}`
- );
+ content.push(`Drift (ms): ${driftMs.toFixed(0)}`);
+ content.push(`Video Start Time: ${appState.videoStartDate.toISOString()}`);
+ content.push(`Radar Start Time: ${new Date(appState.radarStartTimeMs).toISOString()}`);
content.push(`Calculated Offset (ms): ${offsetInput.value}`); // Display calculated offset.
+ const renderTime = appState.lastFrameRenderTime;
+ // Color is green if render time is under 33ms (~30fps budget), otherwise red
+ const renderTimeColor = renderTime > 33 ? "#FF6347" : "#98FB98";
+ content.push(`Frame Render Time: ${renderTime.toFixed(1)}ms`);
+ const videoRenderTime = appState.videoFrameRenderTime;
+ // Color is green if render time is under 34ms (~30fps), otherwise red
+ const videoRenderTimeColor = videoRenderTime > 34 ? "#FF6347" : "#98FB98";
+ content.push(`Video Frame Time: ${videoRenderTime.toFixed(1)}ms`);
} else {
content.push("Load video and radar data to see sync info."); // Prompt to load data.
}
diff --git a/steps/src/main.js b/steps/src/main.js
index 1ff9bc3..aba3d8d 100644
--- a/steps/src/main.js
+++ b/steps/src/main.js
@@ -273,6 +273,23 @@ saveSessionBtn.addEventListener("click", () => {
URL.revokeObjectURL(url);
});
+
+/**
+ * A callback that runs for every new video frame presented to the screen.
+ * It calculates the time since the last frame to measure video performance.
+ */
+function videoFrameCallback(now, metadata) {
+ // 'now' is a high-resolution timestamp provided by the browser
+ if (appState.lastVideoFrameTime > 0) {
+ const delta = now - appState.lastVideoFrameTime;
+ appState.videoFrameRenderTime = delta;
+ }
+ appState.lastVideoFrameTime = now;
+
+ // Re-register the callback for the next frame to create a loop
+ videoPlayer.requestVideoFrameCallback(videoFrameCallback);
+}
+
// When "Load Session" is clicked, it triggers the hidden file input.
loadSessionBtn.addEventListener("click", () => {
sessionFileInput.click();
@@ -503,6 +520,8 @@ videoFileInput.addEventListener("change", (event) => {
calculateAndSetOffset();
loadVideoWithProgress(file);
+ // Start the performance monitoring loop as soon as a video is attached.
+ videoPlayer.requestVideoFrameCallback(videoFrameCallback);
});
// Event listener for offset input change.
diff --git a/steps/src/state.js b/steps/src/state.js
index 0d9ef91..b7af368 100644
--- a/steps/src/state.js
+++ b/steps/src/state.js
@@ -29,6 +29,9 @@ export const appState = {
mediaTimeStart: 0,
// Timestamp (from performance.now()) of the last synchronization check
lastSyncTime: 0,
+ lastFrameRenderTime: 0,
+ lastVideoFrameTime: 0,
+ videoFrameRenderTime: 0,
useCustomTtcScheme: false, // Flag to switch between default and custom
customTtcScheme: {
// Default values match the UI