Skip to content

Fix remote video admission for outgoing calls - #145

Merged
jlucaso1 merged 5 commits into
fix/media-recovery-readbackfrom
fix/outgoing-video-call-media
Sep 8, 2026
Merged

Fix remote video admission for outgoing calls#145
jlucaso1 merged 5 commits into
fix/media-recovery-readbackfrom
fix/outgoing-video-call-media

Conversation

@jlucaso1

@jlucaso1 jlucaso1 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Checkpoint

Stacked on #140, which is stacked on #139. This isolates outgoing-call activation from the previous camera, rotation and readback fixes. Requires oxidezap/whatsapp-rust#1472 for ordered source-bearing video events and the native test fixture. All WhatsApp dependencies resolve to that branch at a45320848ce4808bdcc2b4a7436f2a7f1e0c66a0.

Proven Defect

In the failed web-originated call, 166 remote access units reached the session and were published toward the GUI, including three marked keyframes. No remote decoder started. Outgoing acceptance announced only Local=true; without a separate peer Enabled event, Remote remained false and Frames discarded the incoming video. The working Android-originated path explicitly announced both directions. Both logs used the same deployed preview bundle.

Fix

  • Preserve video-child presence from the winning accept through a raw-node lease, independent of missing or invalid orientation. Do not infer video permission from frame arrival or blindly copy the original requested call type.
  • Wait for in-progress registration instead of caching accepts under arbitrary IDs. Completion, failure, cancellation and task drop wake waiters, and a redial cannot extend an old waiter indefinitely.
  • Activate once for the registered call, intended target user, selected device, creator and original live camera.
  • Process ordinary camera states and upgrade/token transitions from one ordered PeerVideoStateChanged handle queue. Ignore legacy companions and global VideoState events for this state mutation. Preserve a legitimate winner-off while ignoring losing-sibling state.
  • Serialize pre-activation replay with the watcher, preserving UpgradeAccept then Stopped and request then Stopped.
  • Keep the existing outgoing video announcement, codec configuration, packetization and GUI frame-admission guards unchanged.

Tests And Evidence

The native fixture completes real Noise XX and login, drives the public outgoing builder, holds actual offer-send completion and injects stanzas through the library parser/handlers. It does not fabricate a winner or OutgoingReady.

The production-chain regression runs library events through EventLanes, the session handler, daemon state, GUI Frames and generated H.264 decoding. It fails before the remote-admission correction and passes after. Sixteen cases cover early acceptance, audio-only and video accepts, absent/invalid orientation, siblings, PN addressing, wrong-user selection, 300 unrelated accepts, duplicates, closed/replaced cameras and teardown. Ordering tests cover delayed consumers, pre-activation replay, queue pressure and legacy-only input.

During verification, the shared-WASM readback control exposed a test synchronization bug. A single timer turn did not guarantee the BGRA probe and Rust continuations completed. Tests now wait for actual copy and closure milestones, with deadlines only for failure. All ordinary and shared suites pass; a duplicate-copy mutation still fails the exact-count assertion. No production readback change was made.

Verification

  • Native workspace, all features: 1,378 tests passed, 12 ignored; one doctest passed, ten ignored.
  • Session: 138 passed. GUI: 371 passed, seven existing measurement tests ignored.
  • Workspace Clippy with warnings denied, formatting and cargo machete passed.
  • Nightly shared-memory GUI check passed.
  • Shared-memory browser session/daemon suites: 21 and nine passed.
  • WebCodecs ordinary and shared configurations: 16 readback, four recovery and three transform tests passed in each.
  • Existing Node cleanup and metadata tests: 22 passed.
  • Default native and web production dependency trees exclude the optional native fixture and upstream test-support feature.

Remaining Boundary

This fixes the proven client-side rejection of remote video. It does NOT establish that Android now displays the outbound web picture.

Separate research captured synthetic caller-before-accept, caller-after-rekey and callee video at RelayTransport::send. Independent Node/OpenSSL verification and FFmpeg decoding succeeded for all three. This covers outgoing packet construction, not browser networking, real relay forwarding or Android ingress. No speculative wire change was made.

The upstream fixture still exposes existing authorization weaknesses and the handle queue remains lossy under pressure. Those are documented, not claimed fixed here. Native fixture stanza injection bypasses inbound Noise framing; no physical Android decoder, live call or GPUI browser painting was used. A live retest of both remote pictures is still required.


Summary by cubic

Fixes remote video admission for outgoing web-originated calls so the incoming stream is decoded and displayed. Acceptance previously announced only the local camera, so Remote stayed false and inbound frames were discarded; the video child from the winning accept is now preserved and activated once.

Bug Fixes

  • Preserve video presence from the winning accept through a raw-node lease, independent of missing or invalid orientation.
  • Wait for in-progress registration instead of caching accepts under arbitrary IDs; completion, failure, cancellation, and task drop wake waiters.
  • Activate once for the registered call, intended target, selected device, creator, and live camera.
  • Reconcile camera states and upgrade/token transitions from one ordered PeerVideoStateChanged handle queue, ignoring legacy companions and global VideoState events.
  • Serialize pre-activation replay with the watcher to preserve accept-then-stopped ordering.
  • Preserve placed phone-number-targeted calls, including cache-lost and wrong-user selection.
  • Count outbound video packets only after the browser admits the send.
  • Keep the outgoing announcement, codec configuration, packetization, and GUI frame-admission guards unchanged.
  • Add a regression suite running 18 outgoing-acceptance cases through session, daemon, GUI, and real H.264 decode that fails before the fix and passes after.
  • Browser readback tests now wait for real copy and closure milestones; no production readback change was made.

Dependencies

  • WhatsApp dependencies now resolve to test/voip-call-fixture for ordered source-bearing video events and the native call fixture; fixture exports are gated behind a test-support feature so production builds stay clean.

Written for commit 273f0fe. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Improved outgoing-call acceptance across audio and video scenarios, including delayed, repeated, or conflicting responses.
    • Improved handling of remote video activation, camera changes, muted video, media recovery, and stale call events.
    • Improved call cleanup when calls are cancelled, declined, ended, or interrupted during startup.
    • Improved browser and native call behavior consistency, including video orientation and camera shutdown after hangup.
  • Documentation

    • Expanded guidance on outgoing-call acceptance, video recovery, and remaining platform-specific verification.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Warning

Review limit reached

Next included review available in 35 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 1e00c31b-c229-4c9c-9231-3d7192454120

📥 Commits

Reviewing files that changed from the base of the PR and between 976f2c5 and 273f0fe.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • .github/workflows/ci.yml
  • Cargo.toml
  • crates/daemon/src/session_bridge/tests.rs
  • crates/gui/src/session/frames.rs
  • crates/gui/tests/webcodecs/README.md
  • crates/gui/tests/webcodecs/readback.rs
  • crates/session/Cargo.toml
  • crates/session/src/relay/web.rs
  • crates/session/src/whatsapp/calls/registry.rs
  • crates/session/src/whatsapp/calls/registry/acceptance_fixture.rs
  • docs/building.md
  • docs/call-performance.md
  • docs/media-recovery.md
  • docs/video-lifecycle.md
ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: b1b6fb09-977f-4965-9d72-28091df392b3

📥 Commits

Reviewing files that changed from the base of the PR and between 05b8e10 and 976f2c5.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (22)
  • Cargo.toml
  • crates/chat-store/Cargo.toml
  • crates/daemon/Cargo.toml
  • crates/daemon/src/session_bridge/mod.rs
  • crates/daemon/src/session_bridge/tests.rs
  • crates/gui/Cargo.toml
  • crates/gui/src/session/frames.rs
  • crates/gui/tests/webcodecs/README.md
  • crates/gui/tests/webcodecs/fixture.js
  • crates/gui/tests/webcodecs/readback.rs
  • crates/session/Cargo.toml
  • crates/session/src/lib.rs
  • crates/session/src/video/plane.rs
  • crates/session/src/whatsapp/calls/mod.rs
  • crates/session/src/whatsapp/calls/registry.rs
  • crates/session/src/whatsapp/calls/registry/acceptance_fixture.rs
  • crates/session/src/whatsapp/lanes.rs
  • crates/session/src/whatsapp/mod.rs
  • docs/media-recovery.md
  • docs/video-lifecycle.md
  • tests/call-fixture/Cargo.toml
  • tests/call-fixture/src/lib.rs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The change adds outgoing-call acceptance handling, native call fixtures, test-support wiring, and remote-video validation. It also replaces WebCodecs timer-based synchronization with explicit copy and frame-consumption waits.

Changes

Outgoing call acceptance

Layer / File(s) Summary
Acceptance fixtures and feature wiring
Cargo.toml, crates/chat-store/Cargo.toml, crates/session/Cargo.toml, tests/call-fixture/*
Dependencies use the call-fixture branch. Native test-support features expose CallFixture.
Call registry acceptance flow
crates/session/src/whatsapp/{calls/*,lanes.rs,mod.rs}
The registry validates advertisements, tracks outgoing startup state, processes peer video events, and cleans up activation state.
Acceptance fixtures and cross-layer tests
crates/session/src/whatsapp/calls/registry/acceptance_fixture.rs, crates/daemon/*, crates/gui/*, docs/*
Sixteen acceptance cases drive session, daemon, and GUI tests for connection and remote-video behavior. Documentation describes the acceptance path and pinned fixture revisions.

WebCodecs readback synchronization

Layer / File(s) Summary
ControlledDecoder milestone waits
crates/gui/tests/webcodecs/fixture.js
The fixture tracks pending waits and resolves them when copies start or frames are consumed. Cleanup cancels pending waits.
Readback test integration and instructions
crates/gui/tests/webcodecs/readback.rs, crates/gui/tests/webcodecs/README.md
Readback tests use explicit copy counts. Documentation covers ordinary and shared-memory test commands.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~60 minutes

Merge Risk: ⚪ Minimal · up to 976f2

No actionable merge-blocking risk is established beyond normal checks.

Sequence Diagram(s)

sequenceDiagram
  participant WhatsAppClient
  participant CallRegistry
  participant SessionBridge
  participant Frames
  WhatsAppClient->>CallRegistry: Forward call accept advertisement
  CallRegistry->>CallRegistry: Validate outgoing target and peer state
  CallRegistry->>SessionBridge: Emit outgoing call states
  SessionBridge->>Frames: Apply call state updates
  Frames->>Frames: Create remote decoder when remote video is expected
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 68.49% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 73 functions across 13 files. (9 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the pull request's primary change: fixing remote video admission for outgoing calls.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 68.49% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 73 functions across 13 files. (9 skipped: 9 unsupported.)

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit checks each call,
The fixture guides each state,
Frames wait for copies,
Tests guard every path,
Clear signals cross the bridge.

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-08T22:20:53.439006Z 273f0fe New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 976f2c5bbf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/gui/Cargo.toml Outdated
Comment thread Cargo.toml Outdated
Comment thread crates/session/src/whatsapp/calls/registry.rs Outdated
Comment thread crates/gui/tests/webcodecs/README.md
@jlucaso1
jlucaso1 merged commit bf86ebc into main Sep 8, 2026
12 checks passed
@jlucaso1
jlucaso1 deleted the fix/outgoing-video-call-media branch September 8, 2026 22:53
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.

1 participant