Skip to content

Commit

Permalink
Camera view updated to better respond to state
Browse files Browse the repository at this point in the history
In the previous camera view code, the frame didn't respond well to
losses of connection, camera aspect ratio changes, etc.

Instead of changing the stream src, we can layer the camera view
on top of the loading image, so that any time the camera signal is lost,
even if it's because PhotonVision is restarting or you lose connection
to the robot, the loading image is still in memory. This also fixes the
responsiveness to connection loss.
  • Loading branch information
stephenjust committed Sep 28, 2024
1 parent 24fb6af commit 058df18
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 7 deletions.
45 changes: 38 additions & 7 deletions photon-client/src/components/app/photon-camera-stream.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,41 @@ const props = defineProps<{
id: string;
}>();
const emptyStreamSrc = "//:0";
const streamSrc = computed<string>(() => {
const port =
useCameraSettingsStore().currentCameraSettings.stream[props.streamType === "Raw" ? "inputPort" : "outputPort"];
if (!useStateStore().backendConnected || port === 0) {
return loadingImage;
return emptyStreamSrc;
}
return `http://${inject("backendHostname")}:${port}/stream.mjpg`;
});
const streamDesc = computed<string>(() => `${props.streamType} Stream View`);
const streamStyle = computed<StyleValue>(() => {
if (useStateStore().colorPickingMode) {
return { width: "100%", cursor: "crosshair" };
return { cursor: "crosshair" };
}
return { width: "100%" };
return { };
});
const containerStyle = computed<StyleValue>(() => {
const resolution = useCameraSettingsStore().currentVideoFormat.resolution;
const rotation = useCameraSettingsStore().currentPipelineSettings.inputImageRotationMode;
if (rotation === 1 || rotation === 3) {
return {
aspectRatio: `${resolution.height}/${resolution.width}`
};
}
return {
aspectRatio: `${resolution.width}/${resolution.height}`
};
});
const overlayStyle = computed<StyleValue>(() => {
if (useStateStore().colorPickingMode || streamSrc.value == loadingImage) {
if (useStateStore().colorPickingMode || streamSrc.value == emptyStreamSrc) {
return { display: "none" };
} else {
return {};
Expand All @@ -57,13 +71,16 @@ const handleFullscreenRequest = () => {
const mjpgStream: any = ref(null);
onBeforeUnmount(() => {
if (!mjpgStream.value) return;
mjpgStream.value["src"] = null;
mjpgStream.value["src"] = emptyStreamSrc;
});
</script>

<template>
<div class="stream-container">
<img :id="id" ref="mjpgStream" crossorigin="anonymous" :src="streamSrc" :alt="streamDesc" :style="streamStyle" />
<div class="stream-container" :style="containerStyle">
<img :src="loadingImage" class="stream-loading" />
<img :id="id" class="stream-video" ref="mjpgStream" v-show="streamSrc !== emptyStreamSrc" crossorigin="anonymous" :src="streamSrc" :alt="streamDesc" :style="streamStyle" />
<div class="stream-overlay" :style="overlayStyle">
<pv-icon
icon-name="mdi-camera-image"
Expand All @@ -89,7 +106,21 @@ onBeforeUnmount(() => {

<style scoped>
.stream-container {
display: flex;
position: relative;
width: 100%;
}
.stream-loading {
position: absolute;
width: 100%;
height: 100%;
}
.stream-video {
position: absolute;
width: 100%;
height: 100%;
}
.stream-overlay {
Expand Down
1 change: 1 addition & 0 deletions photon-client/src/components/cameras/CamerasView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ th {
.stream {
display: flex;
justify-content: center;
width: 100%;
}

@media only screen and (min-width: 960px) {
Expand Down

0 comments on commit 058df18

Please sign in to comment.