Skip to main content

FrameRateLimiter

Struct FrameRateLimiter 

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

Forwards video frames at a fixed rate lower than the one they arrive at, stamping what it forwards as a constant-rate stream of its own.

§What it is for

A branch that wants a different rate from the source everything else on the Tee shares. A compositor runs at one rate because the Preview and the reported figure are made of it; a recording made from the same frames need not be written at that rate, and at 60 into 30 it is half the encode and half the file for a result most viewers cannot tell apart.

Lowering the compositor instead would lower everything — the Preview, and the rate the status bar reports a recording would be made at. So the choice belongs on the branch, which is what this is.

§It re-stamps rather than passing timestamps through

Output pts is this element’s own count of what it has forwarded, in 1/rate. That makes the output constant-rate by construction, which is what a recording wants: converting the input timeline instead would leave uneven gaps wherever the ratio is not a whole number — 60 into 24 is two input frames for one output frame and then three — and write a variable-rate file out of a source that was perfectly regular.

The consequence is that a source which stalls is elided rather than represented: ten seconds of nothing becomes a cut, not ten seconds of still picture. That is the same choice a constant frame rate always makes, and it is why the rate this is given has to be the rate the encoder after it is configured for.

Because the count starts at zero, so does the output — a TimestampOrigin after the encoder then has nothing left to shift, and is only needed on a branch that has no limiter.

§Which frames it keeps

The first frame whose own timestamp has reached each output tick, so the spacing follows the input’s timeline rather than its frame count. A source that drops a frame, or pauses and resumes, still comes out at the rate asked for; counting arrivals instead would let a stall shift every frame after it.

§Cost

A reference to the frames it keeps and nothing at all for the ones it drops. No pixels are read, copied or converted here.

Implementations§

Source§

impl FrameRateLimiter

Source

pub fn new( name: impl Into<String>, input_time_base: Rational, rate: Rational, ) -> Self

input_time_base is the unit the incoming frames’ pts are in — the producer’s own, such as CudaVideoCompositor::time_base. rate is frames per second out, and must be the rate whatever follows this is configured for: the timestamps this writes mean nothing else.

Source

pub fn time_base(&self) -> Rational

The unit this element’s output pts are in, which is what an encoder or muxer after it has to be told.

Trait Implementations§

Source§

impl Element for FrameRateLimiter

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 FrameRateLimiter

Source§

fn input_contract(&self) -> InputContract

Video frames. It reads a timestamp and forwards a reference, so where the pixels live is not its business — but packets are not what it handles, and audio has no frame rate to limit.

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 FrameRateLimiter

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