pub struct Pipeline { /* private fields */ }Expand description
Top-level pipeline: one or more sources (see PipelineBuilder, with
everything reachable from each source’s own src pads already linked)
plus the bus every source reports events on and the Clock every
crate::elements::Pacer in it shares.
run() is asynchronous: it starts every source on its own background
thread and returns immediately, rather than blocking the caller for the
whole play-through. Returned as Arc<Pipeline> (that’s what
Pipeline::new/PipelineBuilder::build return) — the background
threads deliberately do not retain an owning handle, so dropping the
last external Arc can stop them. The Arc also lets Pipeline::pause/
Pipeline::resume/Pipeline::stop be called from another thread
while it’s running.
There’s no separate “is it done yet” query or callback: watch
Pipeline::bus instead. BusReceiver::iter/
BusReceiver::log_events block until every Bus sender has been
dropped. Under the normal ownership path that happens once every
source’s background thread (and everything reachable from it) has
fully finished, so draining the bus doubles as “wait for completion” —
with more than one source, that means waiting for all of them, not
just the first to reach Eos. A caller that clones the Context
supplied to a source’s own wire closure also retains its Bus
sender; in that case bus draining intentionally remains blocked until
that extra context is dropped. A source-level failure (returned from
crate::element::SourceElement::run itself, as opposed to one
reported from inside a Queue) shows up there too, as a
BusEvent::Error under that source’s own name, since there’s no
synchronous return path left to carry it.
A Pipeline isn’t reusable once run() has been called (whether it
finished via every source’s natural Eos, Pipeline::finish, or
Pipeline::stop) — a
second run() call is a no-op; build a fresh Pipeline for another
play-through.
Implementations§
Source§impl Pipeline
impl Pipeline
Sourcepub fn new<S: SourceElement + 'static>(
id: impl Into<String>,
source: S,
wire: impl FnOnce(&mut S, &Arc<Context>) -> Result<()>,
) -> Result<Arc<Self>>
pub fn new<S: SourceElement + 'static>( id: impl Into<String>, source: S, wire: impl FnOnce(&mut S, &Arc<Context>) -> Result<()>, ) -> Result<Arc<Self>>
id names this pipeline — stamped into the source’s own pp_log as
its pipeline_id right away, and folded into the Context handed
to wire (see super::ChainBuilder’s own docs).
wire is called once with the freshly created source and a
Context bundling this pipeline’s Bus, id, PipelineGraph
(already seeded with the source itself), and Clock (share it with
every crate::elements::Pacer via Clock::clone — one clock per
pipeline, so every paced branch agrees on the same t=0 and the same
pause/resume timeline) — everything a super::ChainBuilder/
crate::elements::Tee needs, in one Arc clone instead of four
separate arguments. wire creates detached chains and attaches
them through Context::attach. Pads left unattached drop data.
The single-source special case of PipelineBuilder — see its own
docs for combining more than one live source (e.g. a video capture
and an audio capture) into one Pipeline.
Sourcepub fn id(&self) -> &str
pub fn id(&self) -> &str
This pipeline’s own id, as passed to Pipeline::new.
pub fn bus(&self) -> &BusReceiver
Sourcepub fn graph(&self) -> GraphSnapshot
pub fn graph(&self) -> GraphSnapshot
Returns a consistent node/edge snapshot of the live graph. Detached branches do not appear; a successful attach or detach increments its revision exactly once.
pub fn elements(&self) -> Vec<NodeInfo>
Sourcepub fn topology(&self) -> String
pub fn topology(&self) -> String
Human-readable rundown of Pipeline::elements: one line per
branch — each element nothing else in the graph feeds into (a
terminal sink, or an empty crate::elements::Tee with no sinks
attached yet) — formatted Type(name) - Type(name) - ... by
walking that element’s upstream chain back to the source.
Multiple branches (fan-out across more than one src pad, or a
Tee) are joined by newlines.
Sourcepub fn clock(&self) -> &Arc<Clock> ⓘ
pub fn clock(&self) -> &Arc<Clock> ⓘ
The clock every Pacer in this pipeline paces against — see
Pipeline::pause for why callers don’t usually need to touch
this directly.
Sourcepub fn playback_clock(&self) -> &Arc<PlaybackClock> ⓘ
pub fn playback_clock(&self) -> &Arc<PlaybackClock> ⓘ
Media-position clock shared by audio output and video scheduling.
Sourcepub fn run(&self)
pub fn run(&self)
Starts driving the source on a background thread and returns
immediately — see the type-level docs for how to learn when it’s
actually done. A no-op if this Pipeline is already running or
has already finished a previous run — this type has no “reset”
path; build a fresh Pipeline for another play-through.
Sourcepub fn pause(&self)
pub fn pause(&self)
Blocks until every element downstream of every source has paused —
see crate::control::drain_control (source side) and
crate::queue::Queue’s worker loop (each thread boundary). Also
pauses this pipeline’s Clock before that synchronous cascade
starts, so time spent waiting for a busy downstream element to
acknowledge Pause is frozen too and a Pacer doesn’t see a jump
once resumed. No-op if run() isn’t currently in progress on
another thread.
Sourcepub fn resume(&self)
pub fn resume(&self)
Undoes Pipeline::pause. Resumes the Clock first, so it’s
already shifted forward by the time Pacers start receiving
frames again.
Sourcepub fn stop(&self)
pub fn stop(&self)
Performs an early, full stop — abandons buffered work rather than
draining to a natural Eos. This call is synchronous: it sends
ControlMsg::Stop to every source in turn and waits for each
one’s own cascade to finish before moving to the next — sequential,
not parallel, across sources (fine for the handful of sources this
is meant for). It therefore cannot preempt an arbitrary
source read or Sink::consume call already blocked inside user or
external-library code; the call returns only after that work gives
the control cascade a turn. After it returns, watch Pipeline::bus
for every source’s background thread to finish. Not reusable
afterward — build a new Pipeline for the next play-through.
Sourcepub fn finish(&self)
pub fn finish(&self)
Gracefully completes every source and waits for the whole graph to
drain. Each source stops producing and places MediaBuffer::Eos behind
its already-produced data; queues preserve that order, stateful codecs
flush delayed output, and muxers finalize only after their EOS arrives.
Unlike Pipeline::stop, this does not abandon queued work. If the
pipeline is paused, it resumes the control cascade first so a full
paused queue cannot prevent its ordered EOS from being enqueued. The
call returns only after every source thread (and the Queue workers each
source owns) has finished. The pipeline is not reusable afterward.
Sourcepub fn seek(&self, target: Duration)
pub fn seek(&self, target: Duration)
Jumps to an absolute position from the start of the media. Blocks
until every source has repositioned (see
crate::element::SourceElement::seek) and every element
downstream of each has reacted (a Queue drops its stale backlog, a
decoder flushes, a Pacer re-anchors both its pts reference and
this pipeline’s Clock) — same synchronous cascade as pause/
resume/stop. One-shot, unlike pause: nothing further to undo
afterward, playback just continues from the new position. No-op
if run() isn’t currently in progress on another thread.
Signals the clock’s interrupt epoch before starting the synchronous
cascade so a Pacer in a long wait can return its worker promptly.
The clock’s playback anchor is still reset later, inside
Sink::control on Pacer, after
that in-flight frame is
out of the way.
A source that doesn’t support seeking (e.g. a live capture) reports
that via its own crate::element::SourceElement::seek returning
an error — surfaced on Pipeline::bus as a
BusEvent::Error under that source’s name, same as any other
per-source failure, rather than failing this call outright or
skipping that source silently.