Skip to main content

FrameEnvelope

Struct FrameEnvelope 

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

An immutable, ref-counted video frame.

Clone is cheap — it bumps the Arc reference count. Pixel data is never copied between stages after construction.

Construct via FrameEnvelope::new_owned for test/synthetic frames, or via the zero-copy bridge in nv-media for live streams.

Implementations§

Source§

impl FrameEnvelope

Source

pub fn new_owned( feed_id: FeedId, seq: u64, ts: MonotonicTs, wall_ts: WallTs, width: u32, height: u32, format: PixelFormat, stride: u32, data: Vec<u8>, metadata: TypedMetadata, ) -> Self

Create a frame with owned pixel data.

This copies the data into the frame. Use the zero-copy bridge in nv-media for production paths.

Source

pub fn new_device( feed_id: FeedId, seq: u64, ts: MonotonicTs, wall_ts: WallTs, width: u32, height: u32, format: PixelFormat, stride: u32, handle: Arc<dyn Any + Send + Sync>, materialize: Option<HostMaterializeFn>, metadata: TypedMetadata, ) -> Self

Create a frame backed by a device-resident accelerated buffer.

The handle is type-erased and stored behind an Arc. Backend adapter crates create the concrete handle type; stages that understand it recover it via accelerated_handle().

§Host materialization

If the backend can download device data to host memory, pass a Some(materialize) closure. This promotes the frame’s DataAccess from Opaque to MappableToHost, enabling CPU consumers to call require_host_data().

Pass None when host fallback is unavailable or undesirable.

§Geometry fields

width, height, format, and stride still describe the logical image layout — they are meaningful metadata even when the raw bytes are not host-accessible.

§Intended uses for the opaque handle
  • Accelerated decode buffers (hardware-decoded video surfaces)
  • GPU tensors destined for inference
  • Accelerator-native frame storage (DMA-buf, OpenCL images, …)

The handle must not be used for general stage metadata or cross-stage messaging. Use TypedMetadata for those purposes.

Source

pub unsafe fn new_mapped( feed_id: FeedId, seq: u64, ts: MonotonicTs, wall_ts: WallTs, width: u32, height: u32, format: PixelFormat, stride: u32, ptr: *const u8, len: usize, guard: Box<dyn Any + Send + Sync>, metadata: TypedMetadata, ) -> Self

Create a frame with a zero-copy mapped buffer.

§Safety
  • ptr must point to len readable bytes.
  • The guard must keep the underlying buffer alive for the lifetime of this frame (and all its clones).
  • The data at ptr must not be mutated while any clone of this frame exists.
Source

pub fn feed_id(&self) -> FeedId

The feed this frame originated from.

Source

pub fn seq(&self) -> u64

Monotonic frame counter within this feed session.

Source

pub fn ts(&self) -> MonotonicTs

Monotonic timestamp (nanoseconds since feed start).

Source

pub fn wall_ts(&self) -> WallTs

Wall-clock timestamp (for output/provenance only).

Source

pub fn width(&self) -> u32

Frame width in pixels.

Source

pub fn height(&self) -> u32

Frame height in pixels.

Source

pub fn format(&self) -> PixelFormat

Pixel format of the decoded frame.

Source

pub fn stride(&self) -> u32

Row stride in bytes.

Source

pub fn residency(&self) -> Residency

Where this frame’s pixel data physically resides.

For a finer-grained classification that distinguishes mappable device frames from opaque ones, see data_access().

match frame.residency() {
    Residency::Host   => { /* use host_data() */ }
    Residency::Device => { /* use accelerated_handle::<T>() */ }
}
Source

pub fn data_access(&self) -> DataAccess

What host-access is available for this frame’s pixel data.

This is the finer-grained companion to residency():

Return valueMeaning
HostReadablehost_data() returns Some.
MappableToHostrequire_host_data() will materialize.
OpaqueNo host path available.
Source

pub fn is_host_readable(&self) -> bool

Whether host-readable pixel bytes are directly available.

Equivalent to self.data_access() == DataAccess::HostReadable. Note: returns false for DataAccess::MappableToHost frames — use require_host_data() to obtain host bytes from those frames.

Source

pub fn host_data(&self) -> Option<&[u8]>

Host-readable pixel bytes, if available.

Returns Some(&[u8]) for host-resident frames (Residency::Host), None for device-resident frames (Residency::Device).

This is the zero-cost accessor for the hot path when frames are known to be host-resident. For a fallback-aware accessor that can materialize device data, see require_host_data().

Source

pub fn require_host_data(&self) -> Result<Cow<'_, [u8]>, FrameAccessError>

Obtain host-readable bytes, materializing from device if needed.

This is the primary ergonomic accessor for CPU consumers that may receive either host-resident or device-resident frames.

Frame kindFirst callSubsequent calls
Host-residentCow::Borrowed (zero-copy)Same
Device + materializerCow::Borrowed (materialize → cache)Cow::Borrowed (cached)
Device, opaqueErr(NotHostAccessible)Same
§Memoization

For DataAccess::MappableToHost frames, the first call invokes the backend’s HostMaterializeFn and caches the result in the frame’s Arc-shared inner state. All subsequent calls (including from clones of this frame) return a zero-copy borrow of the cache.

Failures are also cached: if the materializer returns an error, that error is retained and cloned on subsequent calls. Frame data is immutable, so a transfer that fails for a given frame will not succeed on retry.

§Performance
  • Host-resident frames: the OnceLock cache is never touched; this returns a direct borrow with zero overhead.
  • First materialization: may allocate and/or block (backend-dependent).
  • Cached access: zero-copy borrow from the cached HostBytes.
§Example: CPU-only stage
let pixels = frame.require_host_data()
    .map_err(|e| StageError::ProcessingFailed {
        stage_id: MY_STAGE,
        detail: e.to_string(),
    })?;
process_cpu(&pixels);
Source

pub fn accelerated_handle<T: Send + Sync + 'static>(&self) -> Option<&T>

Downcast the opaque accelerated handle to a concrete type T.

Returns Some(&T) if the frame is device-resident and the handle is of type T. Returns None for host-resident frames or if the concrete type does not match.

§Intended uses

The accelerated handle is intended only for:

  • Backend adapter crates bridging accelerated decode buffers
  • GPU tensors destined for inference
  • Accelerator-native frame storage (DMA-buf, OpenCL images, …)

It must not be used for general stage metadata, arbitrary payload storage, or cross-stage messaging. Use TypedMetadata for those purposes.

§Example
match frame.data_access() {
    DataAccess::HostReadable => {
        let bytes = frame.host_data().unwrap();
        run_on_cpu(bytes);
    }
    DataAccess::MappableToHost | DataAccess::Opaque => {
        let buf = frame.accelerated_handle::<MyAccelBuffer>()
            .expect("expected MyAccelBuffer");
        run_on_device(buf);
    }
    _ => {}
}
Source

pub fn metadata(&self) -> &TypedMetadata

Reference to per-frame metadata.

Trait Implementations§

Source§

impl Clone for FrameEnvelope

Source§

fn clone(&self) -> FrameEnvelope

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for FrameEnvelope

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. 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<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.