Skip to content

Conversation

@hexbabe
Copy link
Member

@hexbabe hexbabe commented Dec 29, 2025

RSDK-12758

Uses upstream pion/mediadevices#670.

Will manually test before merging. Please make a first pass review.

Manual Tests

Mac, two webcams

  • Initial state (webcam A and B both work)
  • Unplug webcam A (webcam A disconnects)
  • Replug webcam A (recovers)
  • Unplug webcam B (should not affect webcam A)
  • Verified debug log runs the right setup observer: 2026-01-06T19:25:51.254Z INFO entrypoint server/observer_darwin.go:26 DEBUG! darwin version!!!!!!

Linux, two webcams

  • Same thing. Saw print: DEBUG! non-darwin no-op version!!!!!!!

@hexbabe hexbabe marked this pull request as draft December 29, 2025 16:43
@viambot viambot added the safe to test This pull request is marked safe to test from a trusted zone label Dec 29, 2025
@hexbabe hexbabe marked this pull request as ready for review December 29, 2025 16:45
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 29, 2025
@cheukt
Copy link
Member

cheukt commented Dec 29, 2025

looks reasonable to me

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 29, 2025
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 29, 2025
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 29, 2025
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 29, 2025
@hexbabe
Copy link
Member Author

hexbabe commented Dec 29, 2025

windows build/tests were failing. It slipped past me that we do no_cgo for RDK windows, which makes the observer stub methods undefined for windows builds. Hence, I declared stubs for all the functions in this repo. This is a bit more verbose, but making another upstream change to the open source code would be difficult.

I thought about consolidating all the stubs into one file in videosource instead of separate stub files in main and in videosource, but that didn't work because if main.go explicitly imports videosource (to call the SetupCameraObserver wrapper), it forces videosource to compile on all platforms, including Windows no_cgo where query.go's reference to mediadevicescamera.Initialize() fails.

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Jan 6, 2026
@hexbabe hexbabe requested a review from abe-winter January 6, 2026 20:12
@hexbabe
Copy link
Member Author

hexbabe commented Jan 6, 2026

@-ing you @abe-winter because this ended up being really build-y

The context here is that I made an upstream change to add these "observer" functions you will see in the diff, but I didn't realize we do no_cgo for RDK windows, which made these functions undefined. So I had to add some build flags and extra file stub declarations to make it work.

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Jan 6, 2026
Copy link
Member

@abe-winter abe-winter left a comment

Choose a reason for hiding this comment

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

lgtm + oliviamiller is a better reviewer than me for this, but I left a bunch of questions because this is a subtle system / thread thing

// See web/cmd/server/observer_darwin.go for details on the threading requirements.
func startCameraObserver(logger logging.Logger) {
if err := mediadevicescamera.StartObserver(); err != nil {
logger.Errorw("failed to start darwin mediadevices camera observer", "error", err)
Copy link
Member

Choose a reason for hiding this comment

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

when this errors, is the system left in a bad state? (i.e. how do you know this is an ignorable error)

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think the system will be left in a bad state i.e. it shouldn't hinder the rest of viam-server from behaving. But it will make it so that webcams cannot react to hot unplug/replug. Should I add that to the error?

Copy link
Member

Choose a reason for hiding this comment

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

imo yes add to error -- better if errors say what to do / what to expect

)

// startCameraObserver starts the Darwin camera device observer for hot-plug support.
// This should be called after SetupObserver has been called from the main thread.
Copy link
Member

Choose a reason for hiding this comment

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

what happens if you get the order wrong? crash?

Copy link
Member Author

Choose a reason for hiding this comment

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

StartObserver actually calls SetupObserver under the hood, but we call SetupObserver first in the entrypoint main.go to allow the objective-c NSRunLoop to set up on the main thread. It would be the "wrong" order if we only called StartObserver in the webcam code and didn't call SetupObserver in main.go

// This should be called after SetupObserver has been called from the main thread.
// See web/cmd/server/observer_darwin.go for details on the threading requirements.
func startCameraObserver(logger logging.Logger) {
if err := mediadevicescamera.StartObserver(); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

does this need to be cleaned up ever?

Copy link
Member Author

Choose a reason for hiding this comment

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

it should be cleaned up by DestroyObserver (see the deferred logic in main.go)

// Start camera observer for hot-plug support (darwin only, no-op on other platforms).
// SetupObserver and DestroyObserver are called in RDK's entrypoint main.go.
// See web/cmd/server/observer_darwin.go for details on the threading requirements.
startCameraObserver(logger)
Copy link
Member

Choose a reason for hiding this comment

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

is it safe to call startCameraObserver multiple times?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, I wrote it so that we can make it work like this in RDK (idempotent)

//
// On Darwin/macOS, SetupObserver must be called from the main thread (not a spawned
// goroutine) because AVFoundation requires that camera device notification events and Key-Value
// Observation (KVO) updates occur on the same thread as the producer. The mediadevices
Copy link
Member

Choose a reason for hiding this comment

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

what does 'producer' mean here?

Copy link
Member Author

Choose a reason for hiding this comment

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

The part of the OS that pushes the notification that a device was (dis)connected

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Jan 6, 2026
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Jan 6, 2026
@hexbabe
Copy link
Member Author

hexbabe commented Jan 6, 2026

your questions were helpful, I updated comments and error messages to be clearer @abe-winter

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Jan 6, 2026
@hexbabe hexbabe merged commit c461739 into viamrobotics:main Jan 6, 2026
19 checks passed
@hexbabe hexbabe deleted the RSDK-12758 branch January 6, 2026 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test This pull request is marked safe to test from a trusted zone

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants