Repository navigation
Conversation
Adds dev.onvoid.webrtc.client: a WebRtc runtime that owns the factory and everything created through it, peers with built-in perfect negotiation, futures instead of nested observers, and one event thread per peer that never runs on a WebRTC thread. Pure Java, no native changes.
The guide covers the runtime, signaling and perfect negotiation, threads, media, data channels, manual negotiation, stats and closing. The example connects two peers in one process without hardware or a server.
A video sink owns the reference to each frame it gets. The dispatcher retained it once more, so every delivered frame leaked, and frames that arrived after a subscription closed were never released.
Jetty 12.1 needs a context around the handlers; without one every page and WebSocket request failed with a NullPointerException. The WebSocket upgrade handler now wraps the static content inside a root context.
The Java client is a peer of the client API, with SignalingManager as its Signaling over the example's own message format. A new peer calls the browser whenever it joins. WebSocket sends are queued, since a WebSocket takes one at a time, and the browser reuses its connection when the Java side renegotiates.
The test asserted more than 10 fps, which the H.264 encoder on macOS arm64 had not ramped up to yet. It now checks that the decoder gets well ahead of the slow handler within the same time.
An unreachable STUN or TURN server held up the end of gathering past the operation timeout, so Gathering.COMPLETE failed on networks that block UDP. It now waits at most PeerOptions.gatheringTimeout, 3 seconds by default, and goes with the candidates gathered by then.
It negotiates by hand with complete gathering, receives video and audio, and ends the session with a DELETE of the resource the server created.
A first call with the client API comes first; the core API walkthrough follows unchanged. The introduction names both APIs.
Sender.sendTones completes once the tones have been sent, and onTone reports each tone on the peer's event thread. Tones still queued are replaced, and the earlier future is cancelled.
Messages that arrive while a channel has no message handler are kept up to 16 MiB; past that the oldest are dropped, and the peer's error handlers hear of it once.
Both peers created a channel at once, but one offer could arrive before the other was made, so nothing collided and the impolite test timed out. A test signaling now holds the messages until both peers have sent an offer.
It converts frames on their own thread, paints on the EDT, keeps the aspect ratio and rotation, and can mirror a local preview.
Whip.to(endpoint).publish(rtc) and Whep.from(endpoint).play(rtc) negotiate a peer over HTTP and complete once it is connected. Closing a session deletes it on the server; a failed setup leaves nothing behind. The WHEP example uses Whep now.
A native crash ends the test JVM with an hs_err report beside the module, which the upload left out. The client tests also note each test in the surefire reports before it starts, so the last line names the one that ran.
A peer whose Signaling.attach failed was closed in the background and dropped from the runtime, so closing the runtime could dispose the factory, and WebRTC's threads with it, while that peer's close() still ran on them. The macOS runners crashed in RTCPeerConnection.close() that way. createPeer now closes a failed peer before it throws. Closing the runtime waits until no peer or track is left, and leaves the factory undisposed if something did not close in time.
LocalMedia.videoTrack and audioTrack wrap an existing source, such as those a MediaFileSource of the media module feeds. The source stays the caller's and is not disposed with the track.
WebRtc.close() returns once every peer is closed; the whenClosed futures complete afterwards on the peers' event threads, which a slow macOS runner had not reached yet. The test now waits for them, and the javadoc and the guide say what close() guarantees.
The tone went to the event executor straight from WebRTC's thread, and the future through the control executor, so on a fast control thread the future could complete first. Both now go through the control executor, in order.
The guide's media file snippet now runs as a test of the media module. It also showed that the runtime has to exist before the MediaFileSource, since the runtime loads the native library the file's sources need; the guide says so now.
camera() returns a LocalCamera, whose switchCamera puts a new native track over the other camera in place of the old one, on every sender, without renegotiating. Cameras that cannot capture at once, like the two sensors of a laptop camera, are handed over by closing the old one first, and a failed switch keeps the camera the track had. Tested with a real camera; the test skips without one.
MediaRecorder.addTrack takes a Sender or a RemoteTrack. The client API hands the media module their encoded frames through a package exported to it alone, taken on the peer's control executor, where key frames are asked for too; once the sender or receiver is gone those requests do nothing, so closing the peer mid-recording just ends the track in the file.
Without PulseAudio, reading the audio devices and watching for changes threw, so devices() failed, and with it camera(). A list the system cannot read is empty now, and without change reports the lists are read on each call.
macOS negotiates H.264 first, which the test did not expect, and which WebM cannot hold. The test records into Matroska and checks for video of the sent size, whatever its codec.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
dev.onvoid.webrtc.client, a pure Java layer over the existing API:WebRtcruntime that owns the factory and everything created through it; closing it closes all in order. Nodispose()in the API.Signalingand browser-compatible JSON messages. Manual negotiation for SFUs, with ICE gathering bounded by a timeout.BlockingCallExceptioninstead of deadlocking.MediaFileSource, switching cameras), remote tracks with frame drop policies, data channels with backpressure, DTMF, stats.WhipandWhepsessions over HTTP,VideoView(Swing) indev.onvoid.webrtc.client.swing, and recording client API senders and remote tracks with the media module'sMediaRecorder.No native changes. Also in this PR:
design/client-api.md), a guide page, the get-started guide opening with the client API, and a README entry.ClientApiExample; the web and WHEP examples ported to the client API.