reactor::Track is a handle onto one named media slot the model declared — not something you
construct yourself. Ask for it by name with
client.track(name), or find it by filtering
client.tracks() when you don’t know the name:
push_video_frame / push_audio_frame split and no on_video_frame /
on_audio_frame split at the class level: the track already knows its kind, and the method you call
says which you meant.
A handle, not an owner: it holds the client weakly, so a track parked in a capture thread
cannot keep the session — and the native handle — alive for the life of that thread. Using one
after the client is gone throws
InvalidStateError.Properties
name()
Signature
kind()
Signature
TrackKind::Video or TrackKind::Audio, or empty before the session has declared its tracks.
direction()
Signature
TrackDirection::SendOnly or TrackDirection::RecvOnly, or empty before the session has declared
them. SendOnly is from this client’s point of view: this client sends, the model receives.
mid()
Signature
paused()
Signature
Track holding a stale
true would go on claiming otherwise.
published()
Signature
publish is a control request and unpublish a notification, and neither
leaves anything to query.
It is cleared whenever the status leaves
Ready. A reconnect resumes recvonly tracks and
nothing else, so a slot published before one is not published after it — publish again. See
reconnect().Sending
publish()
Activates this sendonly slot, so the model has something to receive on.
Signature
Ready.
Example
unpublish()
Deactivates the slot. Synchronous, unlike the other track methods — there is no round trip, only a
local state change and a fire-and-forget notification.
Signature
push_frame()
Pushes one BGRA frame into this track.
Signature
Bytes
required
Exactly
width * height * 4 bytes: B, G, R, A per pixel. Checked here, because the native layer
reads what it is told to read and a wrong length is a read past the end of your buffer.std::uint32_t
required
Frame width in pixels.
std::uint32_t
required
Frame height in pixels.
FrameOptions
Metadata and capture time — see below.
Example
InvalidStateError on a recvonly track, before publish(), or once the session
has left Ready; BadRequestError on a buffer whose length does not match the dimensions.
FrameOptions
Definition
Bytes
Bytes the far end reads as this frame’s metadata. Sent as-is — JSON, protobuf or anything else is
between you and the model — and dropped silently by a peer that did not declare it reads them, so
tagging is safe whatever the far end supports. See Frame Metadata.
std::optional<std::int64_t>
When this frame was captured, read from
reactor::time_micros(). Left empty, the frame is
stamped as it is pushed, so several tracks capturing one moment arrive microseconds apart.Example
push_audio()
Pushes interleaved 16-bit PCM into this track.
Signature
sample_rate must be 48000 and channels 1, which is what the source expects; pcm.size must
divide evenly by channels.
Example
set_bitrate()
Bounds what this one sender may spend, in bits per second.
Signature
Definition
Example
Reactor::set_bitrate() is the other ceiling — the whole
connection’s budget. The two are conjunctive, so raising only one changes nothing.A ceiling is permission, not a target: the encoder still spends only what the congestion controller
allocated and what the picture needs. What raising it buys is headroom for the moments that would
otherwise clip.Ready.
Receiving
on_frame()
Receives decoded video frames from this track.
Signature
Example
on_audio().
on_audio()
Receives decoded audio frames. Refuses the wrong kind or direction, as on_frame() does.
Signature
Example
VideoFrame
Definition
std::string_view
The track this arrived on. Every recvonly video track decodes into one callback, so on a session
with several this is what tells them apart.
const std::uint8_t*
BGRA pixels:
width * height * 4 bytes, which size_bytes() returns.std::uint64_t
The sender’s frame counter, or 0 when the frame carried no metadata trailer.
std::uint64_t
The sender’s capture time in microseconds, or 0 with no trailer. Read in the engine’s clock
(
time_micros()), not the system’s.Bytes
Whatever the sender tagged this frame with — bytes, not text. Empty when the frame carried no
trailer, which is the normal case for a model that does not tag.
The handler runs inline on the library’s delivery thread, deliberately. Blocking in it is the
backpressure: while it runs, the library keeps only the newest frame and drops the ones in between.
Handing frames to a queue of your own trades a bounded drop for unbounded latency and memory.This is why media handlers do not go through
Options::executor, and control-event handlers do.AudioFrame
Definition
VideoFrame. The audio queue is short and keeps its backlog rather
than dropping, because there the queue is the jitter buffer and a hole in it is audible — so a slow
handler here costs latency instead of frames.
frames() is samples per channel, which is what a playback device asks for.
Pausing
pause()
Signature
resume()
Signature
TrackList
The tracks a session declared, filterable — for discovery, and for a caller who would rather not
hardcode a name. Returned by client.tracks().
Signature
Example
one() throws NotFoundError when the list is empty and InvalidStateError when it holds more
than one — a filter that matched several and a caller that wanted one is a question with no answer,
and picking the first would answer it wrongly and silently.
TrackKind and TrackDirection
Definition
Signature