pub struct FfmpegBytes(/* private fields */);Expand description
The bytes every packet and frame this crate produces are carried in.
Owned, Send + Sync, 'static, and clone-is-a-refcount-bump: the
core’s D-seat amputation contract, satisfied. Nothing inside
reaches back into libavcodec.
§Why it is opaque
The obvious spelling was the bare Arc<[u8]> this type wraps, and
0.9.0’s first cut used it. It is opaque for one reason, and the
reason is not aesthetics:
Arc<[u8]> is one storage strategy, and it is not going to be the
only one. Every exit currently allocates, copies, and frees per
frame; a decode loop at 4K is asking the global allocator for eight
megabytes sixty times a second and handing it back. The recorded
answer is a plane pool — reusable slabs handed out at the boundary
and returned when the last consumer drops them
(issue #35).
A pooled slab is a different carrier with the same contract: still
owned, still Send + Sync, still refcount-cloned, still holding no
FFmpeg lifetime.
If the carrier were Arc<[u8]> in the public aliases, adding the
pool would change the type of every frame and every packet in the
crate — a breaking release for a change consumers cannot observe.
Behind this newtype it is a new arm of a private enum: no
signature moves, no consumer recompiles differently, and the
AsRef<[u8]> a consumer actually programs against is unchanged.
That extension point is this type’s justification for existing.
The enum has exactly one arm today. It gains the second when the pool is built and not before — this codebase does not carry members nothing can produce.
Implementations§
Source§impl FfmpegBytes
impl FfmpegBytes
Sourcepub fn try_copy_from_slice(bytes: &[u8]) -> Option<Self>
pub fn try_copy_from_slice(bytes: &[u8]) -> Option<Self>
[Self::copy_from_slice], reporting an allocation failure rather
than aborting on one.
The road every budgeted copy takes. The payload is reserved
with Vec::try_reserve_exact before a byte is written, so a
container whose extradata, side data or attachment the caller’s
ceilings admitted cannot terminate a safe open when the
allocator declines — it answers a named error instead. What is
left infallible afterwards is the Arc header described on
[Inner]: three words, and the same three whatever the payload
weighs.
Sourcepub fn empty() -> Self
pub fn empty() -> Self
The zero-length carrier, shared.
Placeholder plane slots and payload-less packets are frequent — a
video frame allocates four slots and populates one to three of
them — and each would otherwise be its own Arc header
allocation. One empty allocation for the process, cloned by
refcount, instead.
Sourcepub fn as_slice(&self) -> &[u8] ⓘ
pub fn as_slice(&self) -> &[u8] ⓘ
The bytes, as a slice.
The same answer AsRef::as_ref gives; inherent so a caller
reaching through a &FfmpegBytes does not have to name the trait.
Sourcepub fn ptr_eq(&self, other: &Self) -> bool
pub fn ptr_eq(&self, other: &Self) -> bool
true when both handles name the same allocation — a clone of
one another, rather than two copies that happen to be equal.
The property the amputation contract is really about: Clone on
a message is a refcount bump. PartialEq answers a different
question (do these hold the same bytes), and a test that wants to
prove the clone did not copy has to ask this one.
Trait Implementations§
Source§impl AsRef<[u8]> for FfmpegBytes
impl AsRef<[u8]> for FfmpegBytes
Source§impl Clone for FfmpegBytes
impl Clone for FfmpegBytes
Source§fn clone(&self) -> FfmpegBytes
fn clone(&self) -> FfmpegBytes
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for FfmpegBytes
impl Debug for FfmpegBytes
Source§fn fmt(&self, f: &mut Formatter<'_>) -> Result
fn fmt(&self, f: &mut Formatter<'_>) -> Result
Length only, never the bytes.
A derived Debug would print a decoded 4K plane one integer at a
time; this type is reached from the derived Debug of every
packet, frame and side-data entry in the crate, so the terse form
is the one that keeps those useful. Mirrors what FfmpegBuffer’s
own hand-written Debug did through 0.8.
Source§impl Default for FfmpegBytes
impl Default for FfmpegBytes
Source§fn default() -> FfmpegBytes
fn default() -> FfmpegBytes
impl Eq for FfmpegBytes
Source§impl Hash for FfmpegBytes
Hashes exactly what PartialEq compares, which is the contract’s
requirement rather than a preference: the derived hash mixed in the
invisible capacity, so two equal carriers could land in different
buckets and a payload-keyed map would miss.
impl Hash for FfmpegBytes
Hashes exactly what PartialEq compares, which is the contract’s
requirement rather than a preference: the derived hash mixed in the
invisible capacity, so two equal carriers could land in different
buckets and a payload-keyed map would miss.
Source§impl PartialEq for FfmpegBytes
Over the span, not the allocation.
impl PartialEq for FfmpegBytes
Over the span, not the allocation.
The derive compared Inner structurally, and Inner is not a
structural type: a Shared arm holds an allocation that may be
longer than the span, because a producer that sizes its output
before a conversion runs cannot know the true length until
afterwards. Two carriers whose FfmpegBytes::as_slice answers are
byte-for-byte identical therefore compared unequal when one came
off a reservation and the other was copied exactly — and Empty
compared unequal to a zero-length Shared, though both carry
nothing. Capacity a consumer cannot read is not part of the value.
FfmpegBytes::ptr_eq remains the instrument for the other
question — is this handle a refcount bump of that one — and it is
deliberately not what == answers.