Skip to main content

PipelineBridge

Struct PipelineBridge 

Source
pub struct PipelineBridge { /* private fields */ }
Expand description

Carries buffers from one crate::pipeline::Pipeline into another, so the two can start, end and fail independently.

§What it is for

A pipeline is one-shot: a source that dies is not restarted, it is replaced, and replacing it means building a new pipeline. Everything downstream of it would go with it — unless the boundary falls between them. This is that boundary, in the general case.

The general case is what was missing. Crossing from one pipeline into another was already possible through crate::elements::AudioMixer or a video compositor, and an application whose graph meets at one of those needs nothing here. But both of them decide what they carry: a media kind, a format, and a rate of their own. Packets, or frames that are not to be composited, or anything else that only needs to cross, had nowhere to do it.

§Shape

 pipeline "up"                        pipeline "down"
 source ─ … ─ [ PipelineBridgeSink ]  [ PipelineBridge ] ─ … ─ sink
                       └──────── one bounded queue ───────┘

The downstream half is this element, driven as its pipeline’s own SourceElement. The upstream half is a Sink from PipelineBridgeHandle::connect, which whichever pipeline is feeding it terminates at.

§One input at a time

Deliberately, and unlike a mixer: with no way to combine buffers, several inputs would only interleave in whatever order they arrived. A second PipelineBridgeHandle::connect replaces the first, which is the reconnection path — the old Sink then refuses with PipelineBridgeError::Superseded rather than feeding its own replacement.

§What an empty bridge does

Nothing, and its pipeline stays alive doing it. A mixer with no input emits silence and a compositor re-emits its last picture, because each has a rate of its own; a bridge has only what it is given. So a downstream pipeline with no upstream is idle rather than finished, and picks up again when something connects.

§Ends

An input’s Eos ends the input, not the bridge — otherwise the first disconnection would tear down the very pipeline this exists to keep running. PipelineBridgeHandle::input_ended reports it and the next connect starts another.

What ends the bridge is PipelineBridgeHandle::finish, which sends Eos downstream and returns from run. A muxer down there writes its trailer on that; stopping the pipeline instead tells it to abandon the file. The downstream pipeline’s own finish does the same thing from the other side — two doors into one room, which is right when the two halves have different owners.

§Both sides can still be controlled

Each pipeline keeps its own pause, resume, finish and stop, and they mean what they always did. Pausing the downstream one stops the bridge emitting, which fills the queue between them, which is felt on the feeding side as ordinary backpressure — blocking or dropping according to PipelineBridgeOptions::policy. That is a queue behaving like a queue rather than anything the bridge decides.

What does not cross is control itself, with one exception: see Sink::control on the input this hands out. Seeking is refused here outright (SourceElement::is_seekable is false) — the timeline belongs to whatever feeds the bridge, and an application holding both pipelines seeks the one that owns it.

§Timestamps cross unchanged

The two pipelines have their own crate::clock::Clock and crate::playback_clock::PlaybackClock, and this does not re-time what passes through it — it cannot, not knowing what that is. A mixer re-times to its own tick and a compositor to its own rate; a bridge hands over the timestamps it was given.

So downstream must be somewhere those still mean something: a muxer, which writes what it is handed, or anything preceded by crate::elements::TimestampOrigin to re-base them onto the clock that is actually going to be measured against. What must not follow a bridge unguarded is a crate::elements::Pacer — it would be pacing one pipeline’s timestamps against another pipeline’s clock, which is a stream released all at once or one that never arrives.

Implementations§

Source§

impl PipelineBridge

Source

pub fn new( name: impl Into<String>, options: PipelineBridgeOptions, ) -> (Self, PipelineBridgeHandle)

Creates one, and the handle the feeding side connects through.

Trait Implementations§

Source§

impl Element for PipelineBridge

Source§

fn name(&self) -> Arc<str>

Returns a cheap clone (refcount bump, not a deep copy) of this element’s name — crate::bus::BusEvent stores names as Arc<str> for exactly this reason: a hot path like crate::queue::Queue posting BusEvent::Dropped once per overflowed buffer shouldn’t pay for a fresh heap allocation every time it wants to report which element it is.
Source§

fn element_type(&self) -> ElementType

Source§

fn pp_log(&self) -> &PpLog

This element’s identity for crate::bus::Bus::post — same id/name as Element::name, just already wrapped as the crate::pp_log::PpLog its pp_info!/pp_warn!/pp_error! macros need. A stored private field, not built fresh per call, for the same reason name() returns a cheap Arc<str> clone instead of a fresh String — see its own docs.
Source§

fn pp_log_mut(&mut self) -> &mut PpLog

Mutable access to the same field Element::pp_log reads — used by crate::pipeline::ChainBuilder to stamp the owning crate::pipeline::Pipeline’s id onto every element that passes through it, via element_pp_log. Not meant to be called from anywhere else.
Source§

fn graph_id(&self) -> Option<ElementId>

A pre-reserved graph identity for elements that expose dynamic attachment handles. Most elements receive an ID from ChainBuilder and keep the default None implementation.
Source§

fn attach_context(&mut self, _context: &Arc<Context>)

Hands this element the pipeline it is being wired into, at the moment and for the reason Element::pp_log_mut hands it the pipeline’s identity: the clock, the playback clock and the bus are the pipeline’s to give, not the caller’s to choose. Read more
Source§

impl Source for PipelineBridge

Source§

fn src_pads(&mut self) -> &mut [SrcPad]

Returns every output pad owned by this element. Read more
Source§

impl SourceElement for PipelineBridge

Source§

fn is_live(&self) -> bool

Live, because it cannot be asked for a buffer it has not been given. Whether what feeds it is live is the other pipeline’s business and not something this can see.

Source§

fn is_seekable(&self) -> bool

The timeline belongs to whatever is upstream, in a pipeline this one has no authority over.

Source§

fn seek(&mut self, _target: Duration) -> Result<Duration>

Repositions this source to target, an absolute position from the start of the media (e.g. av_seek_frame for crate::elements::FileDemuxer). Called by crate::control::drain_control as part of handling ControlMsg::Seek, before that message is forwarded to the source’s own pads — so whatever’s read next comes from the new position by the time downstream elements receive the new timeline announcement. Buffered and stateful old-timeline data is discarded by the preceding ControlMsg::Flush. Read more
Source§

fn run(&mut self, control: &ControlReceiver, bus: &Bus) -> Result<()>

Drives this source until Eos (normal completion), crate::pipeline::Pipeline::finish, or Stop (see ControlMsg::Stop) — call crate::control::drain_control once per loop iteration to make control responsive between blocking reads. Read more
Source§

fn on_control(&mut self, _msg: &ControlMsg)

Reacts to one control message before it is forwarded to this source’s own pads — the same ordering Self::seek gets, and for the same reason: whatever this source holds must already reflect the message by the time downstream elements see it. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more