datarhei-dragonfork-core/app/webrtc/portalloc.go
Zac Gaetano 16ae17d2a1 feat(app/webrtc): port allocator + FFmpeg arg builder
Adds Alloc(), the ephemeral loopback UDP port grabber the subsystem
uses to pick the RTP port it will hand to FFmpeg and then re-bind with
core/webrtc.NewSourceOn. Covered by a 100x rebind test.

Adds BuildArgs(), which emits the -f rtp output fragments (video on
the passed port, audio on port+1) with copy codecs by default and an
H.264 baseline / libopus re-encode leg when ForceTranscode is set.
Covered by three unit tests.
2026-04-17 09:52:09 -04:00

31 lines
1.1 KiB
Go

// Package webrtc is the datarhei Core subsystem that turns WebRTC into
// a first-class output alongside RTMP, SRT, and HLS. It owns the WHEP
// HTTP handler, wires FFmpeg's RTP output into per-process Pion
// Sources, and tracks active peer connections.
//
// See docs/design/2026-04-17-datarhei-dragon-fork-m2-webrtc-core-integration.md
// for the full design.
package webrtc
import (
"fmt"
"net"
)
// Alloc binds :0 on loopback UDPv4, records the port the kernel assigned,
// closes the socket, and returns the port number.
//
// The caller is expected to re-bind that exact port via
// core/webrtc.NewSourceOn immediately. There is a microsecond-sized race
// window where another process on the host could grab the port; if that
// happens, the caller's rebind will fail and the error should be
// propagated. In practice this is rare enough that a retry loop would be
// unnecessary churn.
func Alloc() (int, error) {
c, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0})
if err != nil {
return 0, fmt.Errorf("webrtc: portalloc: %w", err)
}
defer c.Close()
return c.LocalAddr().(*net.UDPAddr).Port, nil
}