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
impl FrameEnvelope
Sourcepub 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
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.
Sourcepub 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
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.
Sourcepub 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
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
ptrmust point tolenreadable bytes.- The
guardmust keep the underlying buffer alive for the lifetime of this frame (and all its clones). - The data at
ptrmust not be mutated while any clone of this frame exists.
Sourcepub fn ts(&self) -> MonotonicTs
pub fn ts(&self) -> MonotonicTs
Monotonic timestamp (nanoseconds since feed start).
Sourcepub fn format(&self) -> PixelFormat
pub fn format(&self) -> PixelFormat
Pixel format of the decoded frame.
Sourcepub fn residency(&self) -> Residency
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>() */ }
}Sourcepub fn data_access(&self) -> DataAccess
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 value | Meaning |
|---|---|
HostReadable | host_data() returns Some. |
MappableToHost | require_host_data() will materialize. |
Opaque | No host path available. |
Sourcepub fn is_host_readable(&self) -> bool
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.
Sourcepub fn host_data(&self) -> Option<&[u8]>
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().
Sourcepub fn require_host_data(&self) -> Result<Cow<'_, [u8]>, FrameAccessError>
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 kind | First call | Subsequent calls |
|---|---|---|
| Host-resident | Cow::Borrowed (zero-copy) | Same |
| Device + materializer | Cow::Borrowed (materialize → cache) | Cow::Borrowed (cached) |
| Device, opaque | Err(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
OnceLockcache 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);Sourcepub fn accelerated_handle<T: Send + Sync + 'static>(&self) -> Option<&T>
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);
}
_ => {}
}Sourcepub fn metadata(&self) -> &TypedMetadata
pub fn metadata(&self) -> &TypedMetadata
Reference to per-frame metadata.
Trait Implementations§
Source§impl Clone for FrameEnvelope
impl Clone for FrameEnvelope
Source§fn clone(&self) -> FrameEnvelope
fn clone(&self) -> FrameEnvelope
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more