From fed1e9d794c9f0617d5fc63333afb1f759a000bf Mon Sep 17 00:00:00 2001 From: TheCryptoDonkey Date: Sun, 20 Sep 2026 21:09:53 +0100 Subject: [PATCH] Receive Unified Plan tracks on Android --- .../kithmoot/media/BrowserCallInteropTest.kt | 4 +++- .../dev/forgesworn/kithmoot/media/WebRtcEngine.kt | 11 ++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/androidTest/kotlin/dev/forgesworn/kithmoot/media/BrowserCallInteropTest.kt b/app/src/androidTest/kotlin/dev/forgesworn/kithmoot/media/BrowserCallInteropTest.kt index 6b0f883..d1f515e 100644 --- a/app/src/androidTest/kotlin/dev/forgesworn/kithmoot/media/BrowserCallInteropTest.kt +++ b/app/src/androidTest/kotlin/dev/forgesworn/kithmoot/media/BrowserCallInteropTest.kt @@ -80,7 +80,9 @@ class BrowserCallInteropTest { if (ready) scope.launch { runCatching { link.onNegotiationNeeded() }.onFailure { failure.set(it.toString()) } } } override fun onAddTrack(receiver: RtpReceiver?, streams: Array?) { receiver?.track()?.let { received[it.id()] = it } } - override fun onTrack(transceiver: RtpTransceiver?) = Unit + override fun onTrack(transceiver: RtpTransceiver?) { + transceiver?.receiver?.track()?.let { received[it.id()] = it } + } } val pc = requireNotNull(factory.createPeerConnection(configuration, observer)) val videoSource = factory.createVideoSource(false) diff --git a/app/src/main/kotlin/dev/forgesworn/kithmoot/media/WebRtcEngine.kt b/app/src/main/kotlin/dev/forgesworn/kithmoot/media/WebRtcEngine.kt index d363429..6a2f285 100644 --- a/app/src/main/kotlin/dev/forgesworn/kithmoot/media/WebRtcEngine.kt +++ b/app/src/main/kotlin/dev/forgesworn/kithmoot/media/WebRtcEngine.kt @@ -506,9 +506,14 @@ class WebRtcEngine( refreshRemoteTracks() } - // Unified Plan fires this once a transceiver's receiver has a - // track to hand over. - override fun onTrack(transceiver: RtpTransceiver?) = refreshRemoteTracks() + // Unified Plan delivers the receiver here. Do not rely on the + // older onAddTrack callback also firing: refreshRemoteTracks reads + // the separately owned objects in `received`, because a fresh + // getTransceivers() snapshot disposes its previous Java wrappers. + override fun onTrack(transceiver: RtpTransceiver?) { + transceiver?.receiver?.track()?.let { received[it.id()] = it } + refreshRemoteTracks() + } } fun attach(connection: PeerConnection) {