RtcSession owns a str0m::Rtc + Opus decoder/encoder + EchoAudioPipe + a bound UDP socket (spec §3.1, §4.5). accept_offer calls str0m 0.21's sdp_api().accept_offer() natively — no hand-rolled SDP munger; str0m fills DTLS fingerprint + ICE creds + Opus codec. The loop driver drains poll_output per str0m's single-mutation invariant, routes inbound MediaData through Opus decode + EchoAudioPipe sink, sends Transmit packets on the UDP socket, and checks the 60 s idle timeout. DEV-DEVIATION: loop runs on tokio (spec §3.4); step 4 replaces with a dedicated timing thread per ARCHITECTURE.md. str0m 0.21 API adjustments from the brief's sketch (verified against src/str0m-0.21.0): - SdpAnswer has no .mid() accessor; use answer.media_lines[0].mid() via the Deref<Target=Sdp> impl. - Input::Receive carries the Instant as the first tuple element (Input::Receive(now, recv)); handle_input takes a single Input arg. - Receive constructed via Receive::new(proto, src, dst, buf) (the DatagramRecv field is private). - UDP socket binds 127.0.0.1:0 (Candidate::host rejects the unspecified address 0.0.0.0). - BROWSER_SDP_OFFER fixture restored a=group:BUNDLE 0 (str0m's Sdp::assert_consistency rejects SDP without a session group).
18 lines
450 B
TOML
18 lines
450 B
TOML
# crates/rutster-media/Cargo.toml
|
|
[package]
|
|
name = "rutster-media"
|
|
version = "0.0.0"
|
|
license.workspace = true
|
|
edition.workspace = true
|
|
repository.workspace = true
|
|
description = "Media core: str0m WebRTC + Opus⇄PCM boundary (slice 1)."
|
|
|
|
[dependencies]
|
|
rutster-call-model = { path = "../rutster-call-model" }
|
|
opus = { workspace = true }
|
|
str0m = { workspace = true }
|
|
thiserror = { workspace = true }
|
|
tracing = { workspace = true }
|
|
|
|
[dev-dependencies]
|