Skip to content

Conversation

@TheTripleV
Copy link
Contributor

@TheTripleV TheTripleV commented Dec 27, 2025

Duplicate cameras make a DuplicateVisionSource with a DuplicateFrameProvider. DuplicateFrameProvider is a USBFrameProvider but it makes a new Cvsink. All camera properties are either noops or delegate to the source camera.

Workflow

Press the copy button on a camera to duplicate it into a virtual camera
image

Use it like a normal camera. Input settings are disabled because they are really camera settings. Other pipeline specific settings and output settings are allowed to be changed.
image

Duplicate cameras show up when their associated source camera shows up.

Small unrelated fix: If a camera is renamed, it will be renamed in the cameraConfigs screen too now. Though I think the whole camera renaming ux should be moved to the cameraConfigs page.

@github-actions github-actions bot added frontend Having to do with PhotonClient and its related items backend Things relating to photon-core and photon-server labels Dec 27, 2025
@TheTripleV TheTripleV marked this pull request as ready for review December 27, 2025 22:20
@TheTripleV TheTripleV requested a review from a team as a code owner December 27, 2025 22:20
Copy link
Member

@spacey-sooty spacey-sooty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Processed view on duplicate cameras seems to be linked to processed view of main camera even if I change pipelines on the duplicate. Views also seem to randomly display camera lost temporarily when I have a lot of duplicates

@spacey-sooty
Copy link
Member

Oh I also got this crash after running for a while (input empty spammed for a while):

Input was empty!
Fatal glibc error: malloc.c:4376 (_int_malloc): assertion failed: (unsigned long) (size) >= (unsigned long) (nb)

Trying to startup after that crash gave me this (input empty spammed for a while):

Input was empty!
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007e28c17b703e, pid=24928, tid=25010
#
# JRE version: OpenJDK Runtime Environment Temurin-17.0.12+7 (17.0.12+7) (build 17.0.12+7)
# Java VM: OpenJDK 64-Bit Server VM Temurin-17.0.12+7 (17.0.12+7, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
malloc(): invalid size (unsorted)
# C  [libcscore.so+0x6d03e]

@TheTripleV
Copy link
Contributor Author

Comment on lines 310 to 321
<v-col cols="6" md="3" class="pb-0 pb-md-3">
<v-btn
color="secondary"
style="width: 100%"
:disabled="isCameraDuplicate(module)"
:loading="duplicatingCamera"
:variant="theme.global.name.value === 'LightTheme' ? 'elevated' : 'outlined'"
@click="duplicateCamera(module.uniqueName)"
>
<v-icon size="large">mdi-content-copy</v-icon>
</v-btn>
</v-col>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure this button only shows up for USB cameras

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we duplicate a non USB camera? It seems like a nice feature to have

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't test that.
This implementation only works with cscore, which non-usb cameras don't go through.

To do this feature everywhere, we would want to rearchitect how camera input is done. Right now, every vision module (camera + pipeline pair) has a thread. It would be changed so every camera has it's own thread and every pipeline has it's own thread. And data duplication would be fully handled inside photon instead of delegated to cscore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think we can tackle that later. libcamera devices are generally underpowered and can't do OD yet anyways, so i am fine to leave those unsupported.

Question remains -- can we make sure this button is always shown but disabled for non-usb cameras?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Though I don't have a non-usb camera to try the negative case

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can actually simplify this whole check to "is this camera a usb camera"?

Comment on lines 384 to 387
/**
* Called when a source camera is deactivated or deleted. Handles cleanup of dependent duplicates.
*/
private synchronized void handleSourceCameraRemoval(String sourceUniqueName) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the parent camera is deleted, is there any path to recovering its duplicate children? Should we instead delete all children when the parent is deleted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior right now is:

  • When a parent camera is deleted, all active duplicates disappear from the list. Deactivated duplicates remain.
  • When photon starts, all cameras including duplicates appear in the list.
  • When a parent camera is activated, all duplicates are activated too.

Slightly glitchy. There's probably a better way to do that logic here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now,

  • When a parent is deleted, duplicates are deactivated
  • When a parent is activated, all duplicates activate
  • When a parent is deactivated, all duplicates are deactivated

@mcm001
Copy link
Contributor

mcm001 commented Jan 2, 2026

image why does my duplicate claim to be uncalibrated? image image

@TheTripleV
Copy link
Contributor Author

image new more detailed message

@mcm001
Copy link
Contributor

mcm001 commented Jan 7, 2026

image

the resolution/stream resolution here for the duplicated camera is incorrect. Similarly, exposure/brightness changes to the source camera are not reflected on the duplicate camera

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Things relating to photon-core and photon-server frontend Having to do with PhotonClient and its related items

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants