Skip to main content

ChangeGate

Struct ChangeGate 

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

Forwards a video frame only when its picture is not the one it last forwarded, and never more often than min_interval.

§What it is for

A live source produces frames at a rate, not on change. A screen capture of a still desktop captures nothing and re-emits the picture it already has; a compositor with nothing to recompose does the same. Everything downstream of that then works at the full rate to produce a result identical to the last one — and for a terminal that repaints a window per frame, that is the whole cost of an idle scene.

Put this in front of such a terminal and the idle scene costs nothing: it is not called at all until the picture changes.

§Why the rate limit lives here too

These two are one decision, and separating them breaks the second one.

A terminal that drops frames of its own — most do, to hold a preview to a rate a window can usefully repaint at — can drop a frame that did carry a change. The repeats that follow carry that same new picture, so a gate placed before such a terminal will suppress every one of them, and the display stays on the picture before the change until something else changes. Dropping to a rate and dropping repeats have to happen in that order, in one place, or the second silently defeats itself.

So the contract this offers a terminal is the useful one: the newest picture, no more often than this, and never the same one twice. A terminal behind this one should draw everything it receives.

§What it compares

Which buffer the pixels live in, not the frame around them — see buffer::picture_id. It holds the frame it forwarded, which is what makes that identity sound: a picture still held cannot be handed out again with something else in it.

What it holds is the pooled reference it was given, not an av_frame_ref of the picture inside it. A frame reference keeps the buffer allocated but leaves the producer’s pool free to hand that slot out again — and a producer that composites or scales into its pooled frames then puts new pixels at the very address this is comparing against, so a real change reads as “unchanged” and, if the scene goes still right after, the display stays on the picture before it. Holding the pooled reference keeps that slot checked out for exactly as long as this names it. It costs the producer one frame, which its pool simply grows by.

It reads no pixels, so it works the same on a GPU frame as on one in system memory, and costs a pointer comparison either way.

Implementations§

Source§

impl ChangeGate

Source

pub fn new(name: impl Into<String>, min_interval: Duration) -> Self

min_interval is the shortest time between two forwarded frames. Duration::ZERO forwards every change as it arrives.

Trait Implementations§

Source§

impl Element for ChangeGate

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 Sink for ChangeGate

Source§

fn input_contract(&self) -> InputContract

Whatever arrives, wherever its pixels live: this compares pointers and reads nothing, so it passes the upstream contract straight through.

Source§

fn consume(&mut self, buf: MediaBuffer) -> Result<()>

Processes one buffer synchronously on the caller’s thread. Read more
Source§

fn control(&mut self, msg: ControlMsg) -> Result<()>

Reacts to a ControlMsg (pause/resume/stop) and, for anything with a downstream of its own, forwards it on — same shape as consume, just a separate channel from MediaBuffer so it can reach every element (not just ones that already know how to interpret a data buffer) and, at a crate::queue::Queue, jump ahead of whatever data is backed up instead of waiting behind it. No default: every Sink has to consciously decide what this means for it, rather than silently dropping it.
Source§

fn ready_consume(&mut self) -> bool

Returns whether calling Self::consume can make progress now. Read more
Source§

impl Source for ChangeGate

Source§

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

Returns every output pad owned by this element. 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> Filter for T
where T: Source + Sink,

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