Skip to content

Fixed the Android Robot video feed freezing issue in the Flutter Controller. - #551

Merged
thias15 merged 7 commits into
ob-f:masterfrom
3dwesupport:android/robot-connection
Oct 20, 2026
Merged

thias15 merged 7 commits into
ob-f:masterfrom
3dwesupport:android/robot-connection

Conversation

@harishthakur52

Copy link
Copy Markdown
Contributor

Tested for

  1. Android robot -> Android controller
  2. Android robot -> Ios controller
  3. Android robot -> Web controller

Also tested switching simultaneously between different fragments with real robot.

@thias15

thias15 commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the fix and device testing. Two concerns:

  1. The web and native Android controllers recreate their WebRTC connection on STOP/START, but the robot now reuses its connection without sending a new offer. Could you check that video resumes after toggling controller mode off and on?
  2. SWITCH_CAMERA is now rejected whenever a local preview is active. Could we route it to the preview camera so remote front/back switching still works on Free Roam and Logger?

Please cover both cases in testing.

@harishthakur52

Copy link
Copy Markdown
Contributor Author
  1. The robot now sends a fresh offer on every START, and the Flutter controller accepts it. Tested: video comes back after toggling controller mode off and on.

  2. Tested: front/back camera switching works in Free Roam and Logger.

@thias15

thias15 commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Thanks for addressing both concerns. One remaining edge case: the delayed camera-switch callback can run after closeCall() clears videoCapturer, causing a crash if the controller disconnects or controller mode is turned off during the 300 ms delay. Could you cancel pending switches during cleanup and guard against callbacks from a previous session?

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Preview lifecycle gaps, a signaling race, and incomplete resource disposal leave freezing and reliability issues unresolved.

5 open issues
What changed in this PR

This PR addresses Android robot video freezes by sharing preview frames with WebRTC and refreshing controller connections when video restarts.

Changes:

  • Shares CameraX preview frames and manages camera handoffs.
  • Reworks call teardown, restart, and signaling handling.
  • Serializes Flutter signaling and replaces connections for new offers.
File Description
controller/​flutter/​lib/​screens/​controller.dart Queues signaling and replaces connections on new offers.
android/​robot/​src/​main/​java/​org/​openbot/​app/​robot/​env/​WebRtcServer.java Adds shared-frame streaming and revises call lifecycle handling.
android/​robot/​src/​main/​java/​org/​openbot/​app/​robot/​env/​PhoneController.java Restarts video when reusing an open connection.
android/​robot/​src/​main/​java/​org/​openbot/​app/​robot/​common/​CameraFragment.java Registers preview ownership and forwards camera frames.

Review effort: Balanced

Comment on lines +843 to +846
if (peerConnection == null) {
// Late message after the call closed. Throwing here would end this subscription.
Log.d(TAG, "Ignoring WebRTC event: no active call");
return;
try {
if (cameraProvider != null) {
cameraProvider.unbindAll();
WebRtcServer.setLocalPreviewActive(this, true, this::switchCameraForController);
public void onDestroy() {
super.onDestroy();
cameraExecutor.shutdown();
WebRtcServer.setLocalPreviewActive(this, false, null);
Comment on lines +544 to +548
mediaStream = null;
videoSender = null;
audioSender = null;
videoTrackFromCamera = null;
localAudioTrack = null;
// The robot starts a new call with a fresh offer every time it restarts video, so a second
// offer belongs to a new call: replace the peer connection instead of renegotiating on it.
if (await _peerConnection?.getRemoteDescription() != null) {
await _peerConnection?.close();
- Handle start/stop and controller signaling on the main thread so they
  can't race with closeCall().
- Always resume the local preview after an interrupted camera switch.
- Release preview ownership if camera binding fails.
- Dispose local stream/tracks and the replaced Flutter peer connection.
@thias15

thias15 commented Oct 18, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the fixes! I pushed a follow-up commit for the remaining review points:

  • Start/stop and signaling now run on the main thread, so they can't race with teardown.
  • The robot's preview always resumes after an interrupted camera switch.
  • If camera binding fails, WebRTC falls back to its own camera.
  • Fixed resource leaks on teardown, on both the robot and the Flutter controller.

Pausing the feed while the robot app is on a settings screen is expected, so I left that as is.

Could you re-test on a device before we merge?

  1. Connect each controller (Android, iOS, web) and check video.
  2. Toggle controller mode off/on a few times.
  3. Switch camera from the controller in Free Roam and Logger.
  4. Disconnect right after connecting, then reconnect.
  5. Switch camera and immediately disconnect; the robot preview should come back.

@harishthakur52

Copy link
Copy Markdown
Contributor Author

Thanks for the fixes! I pushed a follow-up commit for the remaining review points:

  • Start/stop and signaling now run on the main thread, so they can't race with teardown.
  • The robot's preview always resumes after an interrupted camera switch.
  • If camera binding fails, WebRTC falls back to its own camera.
  • Fixed resource leaks on teardown, on both the robot and the Flutter controller.

Pausing the feed while the robot app is on a settings screen is expected, so I left that as is.

Could you re-test on a device before we merge?

  1. Connect each controller (Android, iOS, web) and check video.
  2. Toggle controller mode off/on a few times.
  3. Switch camera from the controller in Free Roam and Logger.
  4. Disconnect right after connecting, then reconnect.
  5. Switch camera and immediately disconnect; the robot preview should come back.

Thanks for the follow-up! Re-tested on device with 403b845 on the Android, iOS and web controllers: all 5 scenarios pass. Video works, controller mode off/on resumes video, camera switch works in Free Roam and Logger, reconnecting works, and the preview comes back after a switch followed by an immediate disconnect.

Agreed on the settings screen pause.

@thias15 thias15 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Tested on device by the author; review comments addressed.

@thias15
thias15 merged commit 379989d into ob-f:master Oct 20, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants