Skip to main content

FrameEncoder

Enum FrameEncoder 

Source
pub enum FrameEncoder {
    Nvenc(NvencEncoder),
    Vaapi(VaapiEncoder),
    Vpx(VpxEncoder),
    Hevc(HevcEncoder),
    Av1(SvtAv1Encoder),
    V4l2m2m(V4l2M2mEncoder),
}
Expand description

One full-frame encoder session, whichever backend produced it, so the render and delivery code passes “the frame encoder” around without caring which vendor path or library produced the frames.

Variants§

§

Nvenc(NvencEncoder)

§

Vaapi(VaapiEncoder)

A VA-API session on a render node, hardware.

§

Vpx(VpxEncoder)

libvpx VP8 or VP9, software.

§

Hevc(HevcEncoder)

x265 or kvazaar, software.

§

Av1(SvtAv1Encoder)

SVT-AV1, software.

§

V4l2m2m(V4l2M2mEncoder)

A stateful V4L2 M2M encoder, driven through the kernel interface directly.

Implementations§

Source§

impl FrameEncoder

Source

pub fn codec(&self) -> Codec

The codec the session emits.

Source

pub fn is_hardware(&self) -> bool

Whether the session encodes on a GPU or a hardware engine.

Source

pub fn fixed_rate_control(&self) -> Option<&'static str>

The rate control the session runs whatever mode it was given, for a backend that has one alone: a V4L2 M2M device offers variable bitrate only, and Tegra’s encoder is driven at a constant one. None where the session runs the mode it was given.

Source

pub fn backend_name(&self) -> &'static str

The backend as the logs name it: NVENC, VAAPI, or the software library.

Source

pub fn dmabuf_planes(&self) -> usize

The planes of one dmabuf the session imports as it stands: VA-API’s descriptor maps up to four, each to the object it lies in (a compressed layout’s metadata is a plane beside the pixels); NVENC imports the first plane through EGL, so a buffer of more is composited.

Source

pub fn is_fullcolor(&self) -> bool

Whether the session negotiated 4:4:4 chroma.

Source

pub fn bit_depth(&self) -> u32

The bits per sample the session negotiated: 10 on a VA-API session that opened a 10-bit profile and on a software one whose library codes them, 8 everywhere else.

Source

pub fn is_full_range(&self) -> bool

Whether the session signals full range: a software 4:4:4 of x264’s kind, and the V4L2 M2M sessions whose firmware converts at full range and offers no way to ask for another.

Source

pub fn reconfigure_rate( &mut self, settings: &CaptureSettings, ) -> Result<(), String>

Apply a live bitrate / VBV / frame-rate change. Err means the session lost its codec context and has to be rebuilt.

Source

pub fn encode_host( &mut self, pixels: &[u8], stride: usize, rgba: bool, frame_number: u64, qp: u32, force_idr: bool, ) -> Result<Vec<u8>, String>

Encode one packed host frame (stride bytes per row; rgba names R,G,B,A byte order, otherwise B,G,R,A) at quantizer qp, as a key frame when force_idr.

Source

pub fn encode_client_host( &mut self, pixels: &[u8], stride: usize, rgba: bool, frame_number: u64, qp: u32, force_idr: bool, ) -> Result<Vec<u8>, String>

encode_host for rows a client owns and may unmap after the call, as the wl_shm buffer a Wayland capture encodes as it stands: NVENC uploads them without page-locking them (NvencEncoder::encode_client_packed), and every other session reads them as encode_host does.

Source

pub fn hash_next_upload(&mut self, rows: u32) -> bool

Hash the next host frame’s bands of rows rows where the encoder holds it, beside its encode (NVENC: NvencEncoder::hash_next_upload); false where it cannot, which leaves the hash to the caller.

Source

pub fn take_upload_hashes(&mut self) -> Option<Vec<u64>>

The band hashes hash_next_upload asked for, once the frame is coded.

Source

pub fn last_quality(&self) -> Option<u32>

The quality index (the H.26x quantizer scale video_crf uses) the last frame was coded at, where the session reports its quantizer: what a constant-rate session’s picture is worth against the paint-over quality.

Source

pub fn last_size(&self) -> Option<usize>

The bytes of the last frame the rate control coded, held frames aside, where the session reports them (NVENC, VA-API, x265 and kvazaar, libvpx’s VP9): what tells a constant-rate cleanup that runs through the rate control whether it has converged on a still screen (pipeline::decide_hw_fullframe), with last_quality where the session reports that too.

Source

pub fn measure(&mut self)

Have the next frame’s reconstruction measured against its source, where the session can (last_psnr).

Source

pub fn measures(&self) -> bool

Whether measure has the session measure a frame: VA-API, which reads its reconstruction back, where the driver’s surfaces let it.

Source

pub fn last_psnr(&self) -> Option<f32>

The luma PSNR of the last frame measured (measure), where the session reads its reconstruction back: VA-API. What a constant-rate cleanup through the rate control ends on where it has one, since a picture that stopped improving needs no more frames whatever quantizer the driver reports.

Source

pub fn cap(&mut self, bytes: usize)

Take the next frame back where it comes out past bytes and code it again within them: a band held at a quantizer (hold_quantizer) in a shorter band, a frame of the rate control’s at the coarsest quantizer, refining nothing. NVENC, which leaves the frame out of the predictions as one a client lost, does. VA-API codes the frame at the rate that spends bytes in the cleanup’s frame time instead (follows_cap); elsewhere the frame stands as coded.

Source

pub fn follows_cap(&self) -> bool

Whether a still screen’s cleanup frame is coded at the rate its cap runs at (cap), so the cleanup judges it against that rate’s budget: VA-API at a constant rate, which takes a new target with a picture, and libvpx’s VP9, which takes one live. NVENC takes a frame back instead.

Source

pub fn reach_finer(&self) -> u32

The quantizer steps finer than the paint-over one at which the rate control’s frames come to the paint-over quality, where a constant-rate cleanup runs through it: the software HEVC encoders’ predicted frames at a quantizer leave the motion’s coarse blocks as they are, and x265’s cleanup ended at 45-46 dB at the paint-over quantizer where its key frame there decodes at 50 (HevcEncoder::reach_finer). Elsewhere none.

Source

pub fn ends_cleanup_on_key(&self) -> bool

Whether a constant-rate cleanup through the rate control ends on a key frame held at the paint-over quantizer after a large change and a longer stillness: where the rate control cannot refine a still screen in the frames’ budget and the session says nothing of how far it got (VaapiEncoder::ends_cleanup_on_key). Elsewhere a refresh or the rate control’s own frames do, and a key frame would only cost more (libvpx’s VP9 key frame of 1080p text came out at 231 kB and 30.9 dB at its coarsest).

Source

pub fn refit(&self) -> Option<f64>

Where the last frame was taken back and coded again (cap): how far its held band then reached, or 0 for a frame of the rate control’s.

Source

pub fn take_lost_cleanup(&mut self) -> bool

Whether a frame left a held band out of every prediction with no band of its own to take it back into since this was last asked: NVENC, whose anchors predict from the newest frame every client was sent (NvencEncoder::take_lost_cleanup).

Source

pub fn band_size(&self) -> Option<usize>

The bytes of the last frame held at a quantizer (0 before one), where the session holds a band of a frame at it (hold_quantizer): NVENC’s H.264, HEVC and AV1 sessions, through a QP delta map, and libvpx’s VP8, through a region-of-interest map.

Source

pub fn refines(&self) -> Option<Refiner>

How the session refines blocks of a frame of its rate control’s at a quality of their own (refine_blocks, ledger::Refiner), so a refined block comes to what the region’s own cleanup reaches; None where it does not: NVENC’s H.264, HEVC, and AV1 through the QP delta map (nvenc::REFINE_FINER), libvpx’s VP8 through its region-of-interest map (vpx::REFINE_FINER, which says why not VP9), x265 through its per-block quantizer offsets and kvazaar through its per-tree-block map (HevcEncoder::refine_finer). x264’s session refines within software::encode_cpu (ledger::REFINE_FINER).

Source

pub fn constant_blocks(&mut self, constant: &[bool])

Mark the blocks of the next frame, in raster order, that held still and are clean (BlockLedger::constant), which a session codes as skips without analysis where its library takes such a map and the frame predicts from the one before: libvpx’s VP8 and VP9 through their active map, x265 through its constant-block map, and SVT-AV1 through the map its input copy reads. An empty slice marks none, and a session takes the map only on a frame of its rate control’s, never on a key frame or a held one.

Source

pub fn refine_blocks(&mut self, refinement: &Refinement)

Code the blocks refinement names in the next frame, where it is the rate control’s, at its target quality (ledger), where refines.

Source

pub fn holds_quantizer(&self) -> bool

Whether hold_quantizer holds a frame at the quantizer asked for under the session’s rate control: NVENC, libvpx’s VP8, and SVT-AV1 at a constant rate (where the release takes a new target with a picture) do; x265, VA-API, and libvpx’s VP9 only at a constant quantizer (their holds_quantizer and hold_quantizer say why not at a constant rate, VP9’s that its rate control refines a still screen within the rate); kvazaar, Tegra, and a stateful V4L2 device take no quantizer from the caller. The cleanup of a constant-quality session moves the session’s quality instead of holding a frame (pipeline::decide_constant_quality), so this is read at a constant rate.

Source

pub fn capped(&self) -> bool

Whether the session runs its constant quality under the peak it was asked for: NVENC, libvpx, and SVT-AV1 where asked, SVT-AV1 where the release forces a picture’s quantizer and keeps the sequence’s otherwise (svtav1_sequence_qp); x265, kvazaar, and VA-API never, and the V4L2 and Tegra devices run at the rate whatever the mode (their module docblocks).

Source

pub fn rate_bound(&self, cbr: bool) -> bool

Whether a rate binds the session: a constant rate, or a constant quality whose peak bound its last frame (NVENC through its constant rate, libvpx above its pinned quantizer, SVT-AV1 at a quantizer the peak raised), each of which codes a frame coarser than its quality, so its refinement and block ledger follow what its rate control coded (pipeline::plan_refinement). Under a peak that does not bind, a capped session refines as its uncapped quality does.

Source

pub fn coded_capped(&self) -> bool

Whether the frame just coded was coded under a capped constant quality’s binding peak, coarser than the rate factor would have chosen (ledger::BlockLedger::coded): NVENC through its constant rate, libvpx above its pinned quantizer, SVT-AV1 at a quantizer the peak raised.

Source

pub fn idle(&mut self)

A tick that codes no frame: a capped constant quality’s peak drains for it as for an empty frame, so a still screen lets the peak go and its refresh starts (ledger::BlockLedger::refresh).

Source

pub fn defer_blocks(&mut self, plan: Option<&BlockPlan>)

Hold the blocks plan names as skips in the next frame: the coarse blocks a capped constant quality’s refresh leaves for later frames (ledger::BlockLedger::refresh). NVENC, which takes no skips, holds them at its coarsest quantizer through its QP delta map; an encoder that takes skips (constant_blocks) has them among those.

Source

pub fn reopens_on_quality(&self) -> bool

Whether a change of the session’s constant quality re-opens it, so the frame it applies to is a key frame: x265 and kvazaar take no new quality while they run, and SVT-AV1 none until a capped session’s peak binds (SvtAv1Encoder::reopens_on_quality). The cleanup of a constant-quality session counts such a refresh as its key frame.

Source

pub fn cleans_up_with_key(&self) -> bool

Whether a constant-rate cleanup ends on a key frame after a large change and a longer stillness (pipeline::decide_hw_fullframe). SVT-AV1 holds only a key frame, so that is its cleanup. libvpx’s VP8 holds the refresh before it, predicted frames that restore the picture whole (in bands where the rate leaves room, VpxEncoder::band_size), and its key frame only sent the picture again: 1080p text at 0.25 Mbit/s went quiet on 1.3 MB without it against 2.7, at the same 42 dB, since the key frame came out capped coarser than the picture (216 kB at 21.6 dB) and a second refresh restored it.

Source

pub fn hold_quantizer(&mut self, crf: u32, band: Option<(f64, f64)>)

Encode the next frame at the quantizer the quality index crf selects whatever the rate control, and leave the session’s own rate control and quality as they were for the frame after: the cleanup of a still screen, where holds_quantizer. A session whose engine takes no quantizer from the caller (Tegra, a stateful V4L2 device) codes that frame under its own rate control. band, the share of the picture from and to in raster order, confines the quantizer to that band where band_size says the session holds one, the rest of the frame held at the coarsest quantizer.

Source

pub fn delivered_units( &self, data: Vec<u8>, encoded: u16, ) -> Vec<(Vec<u8>, u16, Reference)>

The data one call returned, cut at the units it carries, each with its own frame’s id and reference: whole and labeled encoded from a session that hands back the frame it encoded, one unit per earlier frame from one that hands them back late (Tegra), so what a consumer reports lost is the unit it dropped and nothing else.

Source

pub fn push_held(&mut self, frame_number: u64) -> Result<Vec<u8>, String>

The frame the last delivered frame predicted from. The access unit a still screen leaves inside an engine that emits a frame only once the next is queued: empty from every other backend, whose units come with their frame.

Source

pub fn holds_frame(&self) -> bool

Source

pub fn last_reference(&self) -> Reference

Source

pub fn invalidate_reference(&mut self, frame_id: u16) -> bool

Leave frame frame_id and every frame after it out of the predictions, so the next frame decodes for a client that lost it. False when the session cannot, and the caller codes a key frame instead.

Source

pub fn take_report(&mut self, report: ReferenceReport) -> bool

Apply what the consumers say of a frame: a loss as invalidate_reference, a frame every one of them holds or was sent to a session keeping long-term references (ReferenceWindow::acknowledge). False where the session codes a key frame instead.

Source

pub fn encode_dmabuf( &mut self, dmabuf: &Dmabuf, frame_number: u64, qp: u32, force_idr: bool, ) -> Result<Vec<u8>, String>

Encode one Wayland dmabuf in place (a zero-copy session).

Source

pub fn encode_dmabuf_after_blit( &mut self, dmabuf: &Dmabuf, frame_number: u64, qp: u32, force_idr: bool, ) -> Result<Vec<u8>, String>

encode_dmabuf, for a buffer the X server signals the session’s blit semaphore after blitting into (blit_semaphore_fd): the frame’s GPU work waits on it on the GPU.

Source

pub fn blit_semaphore_fd(&mut self) -> Option<Result<OwnedFd, String>>

A semaphore for the X server to signal after each blit, as the fd it imports, for encode_dmabuf_after_blit to wait on; None for a session that cannot wait on one (NVENC alone can, through CUDA).

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
§

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

§

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

§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

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

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

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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

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

Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.
§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

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