Skip to main content

StreamBufferConstraints

Struct StreamBufferConstraints 

Source
pub struct StreamBufferConstraints {
Show 16 fields pub buffer_constraints_version_ordinal: Option<u64>, pub default_settings: Option<StreamBufferSettings>, pub per_packet_buffer_bytes_min: Option<u32>, pub per_packet_buffer_bytes_recommended: Option<u32>, pub per_packet_buffer_bytes_max: Option<u32>, pub packet_count_for_server_min: Option<u32>, pub packet_count_for_server_recommended: Option<u32>, pub packet_count_for_server_recommended_max: Option<u32>, pub packet_count_for_server_max: Option<u32>, pub packet_count_for_client_min: Option<u32>, pub packet_count_for_client_max: Option<u32>, pub single_buffer_mode_allowed: Option<bool>, pub is_physically_contiguous_required: Option<bool>, pub buffer_count_for_server_current: Option<u32>, pub size: Option<SizeU>, pub pixel_format: Option<PixelFormat>, /* private fields */
}
Expand description

This struct conveys the buffer_constraints_version_ordinal.

Historically this table conveyed more fields than it currently does, but those fields are all deprecated in favor of using sysmem instead.

There are separate instances of this struct for stream input and stream output.

Notes about fields:

For uncompressed video, separate and complete frames in their separate buffers (buffer-per-packet mode) are always a requirement.

Fields§

§buffer_constraints_version_ordinal: Option<u64>

This is a version number the server sets on the constraints to allow the server to determine when the client has caught up with the latest constraints sent by the server. The server won’t emit output data until the client has configured output settings and buffers with a buffer_constraints_version_ordinal >= the latest buffer_constraints_version_ordinal that had buffer_constraints_action_required true. See buffer_constraints_action_required comments for more.

A buffer_constraints_version_ordinal of 0 is not permitted, to simplify initial state handling. Other than 0, both odd and even version ordinals are allowed (in contrast to the stream_lifetime_ordinal, neither the client nor server ever has a reason to consider the latest version to be stale, so there would be no benefit to disallowing even values).

§default_settings: Option<StreamBufferSettings>§per_packet_buffer_bytes_min: Option<u32>§per_packet_buffer_bytes_recommended: Option<u32>§per_packet_buffer_bytes_max: Option<u32>§packet_count_for_server_min: Option<u32>§packet_count_for_server_recommended: Option<u32>§packet_count_for_server_recommended_max: Option<u32>§packet_count_for_server_max: Option<u32>§packet_count_for_client_min: Option<u32>§packet_count_for_client_max: Option<u32>§single_buffer_mode_allowed: Option<bool>§is_physically_contiguous_required: Option<bool>§buffer_count_for_server_current: Option<u32>

If a codec has [fuchsia.mediacodec/DetailedCodecDescription.supports_dynamic_buffers] set to true, this field must be set by the server and will be the minimum number of input or output buffers that the server needs to be able to concurrently use (or continue using) to guarantee forward progress. For video decoders, this number assumes a bitstream-standard-compliant stream. Any time the server doesn’t have this many buffers available for the server’s concurrent use (DPB size + 1), processing may pause, but will not fail - in this case the client can add more buffers with AddBuffers to get the processing to start again. When the DPB needs to reference more images, recycling an output buffer won’t necessarily cause processing to start again, as the image may still be in the DPB, so the buffer can’t be re-used yet despite being recycled by the client.

For input, the codec may require this many buffers before the codec will process any input. Currently, for input, this value is static per StreamProcessor instance. The client is allowed to send QueueInput…() messages before this many input buffers have been added, but should not expect any output to necessarily be emitted until at least this many input buffers have been added. This also applies for QueueInputFormatDetails and QueueInputEndOfStream before any QueueInputPacket, for a newly starting stream, so the first two can be sent while there are still zero added input buffers so far. Codecs that only need one input buffer to make forward progress (non-continuous non-smooth forward progress still counts) should set this to one. Most clients will want to add a low number of additional buffers to keep the pipeline running smoothly, to avoid stalling processing while an OnFreeInputPacket is on its way from the codec to the client. Decoders that copy input data into a separate stream buffer (sometimes treated as circular) typically will only need one input buffer for forward progress to be possible, but most clients will still want to add a low number of additional input buffers for smoother thread scheduling, even if such a decoder core might be able to run at 100% utilization with a single input buffer.

For video decoder output, if a client were to only AddBuffers this many buffers overall, every time OnOutputPacket happened, the decoder would be potentially stalled until RecycleOutputPacket is received at the server. For this reason, most clients will prefer to allocate a few more buffers, accounting for other parts of the pipeline (locally in the client or not) that may also need to “camp” on buffers for reasons unrelated to video decode, and possibly also a low number of additional buffers to keep the pipeline running smoothly, to avoid stalling decode while a free buffer on its way to being recycled or similar.

For video decoder output, when set, this value will always be less than or equal to [fuchsia.mediacodec/DetailedCodecDescription.dynamic_buffers_video_decoder_output_safe].

This value can be updated by a new OnOutputConstraints from the server with action_required false. However, despite “action_required” being false, the client must still ensure that the number of buffers currently available for concurrent use by the codec is at least this many.

If a client using dynamic buffers with a video decoder doesn’t want to pay attention to this field, the client should still pay attention to [fuchsia.mediacodec/DetailedCodecDescription.dynamic_buffers_video_decoder_output_safe]. Or the client can instead use SetInputBufferPartialSettings/SetOutputBufferPartialSettings which has approximately the same (potentially adverse) effect in terms of overall buffer count (assuming a correctly operating pipeline). While these less complicated client implementation options might initially seem like they’re wasting some memory, paying attention to buffer_count_for_server_current (in contrast to only dynamic_buffers_video_decoder_output_safe) only saves memory if the stream has the needed optional fields with values less than the max DPB size, which is unfortunately not guaranteed. In particular, h.264 streams without max_num_reorder_frames or max_dec_frame_buffering set in vui_parameters (or anywhere else) seem more common than not (to this author, among streams looked at so far), though this could depend strongly on which particular set of streams a client wants to decode. Client implementers may want to check some of the relevant streams for relevant bitstream header fields before caring about this field and the dynamic changes to the value conveyed by this field, for video decoders. Also, client implementers are free to use other strategies to save memory, such as being stingy with buffer counts but adding buffers dynamically and quickly if it seems like the codec might be starving for buffers (such as if downstream queued output buffers start to run low). This sort of strategy is up to the client, and it’s on the client to get the timing right if it goes with that sort of strategy (not super easy to get perfectly correct / tuned). The platform makes no specific guarantee re. how quickly an additional buffer can be allocated, so a client attempting to run with fewer than dynamic_buffers_video_decoder_output_safe may encounter stream rendering jank or similar, including mid-stream. The platform makes no promises regarding the ability to avoid jank in this situation, such as if there’s a mid-stream header that increases this value for output (not common).

Layers above are encouraged to permit storing smaller images in larger buffers, so that mid-stream dimensions changes don’t each need to re-allocate buffers. Instead, it’s almost always better to just keep using existing larger buffers in this case, to avoid possibility of rendering jank due to allocating buffers not always being as fast as desired combined with output buffer count not necessarily having sufficient extra buffers to absorb the buffer reallocation in a timing sense. However, if a layer above really must re-allocate buffers when the image size changes and the needed buffer size to hold the images goes down, such a client must set force_new_buffers_for_new_dimensions passed to CreateDecoder. Otherwise a video decoder is permitted to start putting smaller images in the existing larger buffers, with OnOutputFormat message(s) indicating this.

§size: Option<SizeU>

Clients are free to ignore this field.

This field is set iff [fuchsia.mediacodec/DetailedCodecDescription.supports_dynamic_buffers] is true and the indicating port is outputting uncompressed video.

This field is provided for informational purposes, for clients that may want to know this information. However, the StreamProcessor and sysmem protocols work fine without the client ever reading this field.

This is the required coded size, without any cropping down to display size.

If the client gets directly involved as a sysmem participant, the client should not set constraints which are incompatible with this size, or allocation will fail. This field should not be taken to imply that a given buffer only has a single allowed image size. That is incorrect in general. Rather, this field indicates a size which will be covered by the required_min_size and required_max_size set by the StreamProcessor sysmem participant using token passed into SetInputBufferPartialSettings, SetOutputBufferPartialSettings, or ParticipateInBufferAllocation.

Despite this size indicating a specific width and height, the allocated buffers may permit a range of image sizes (for video decoder output or video encoder input).

§pixel_format: Option<PixelFormat>

Clients are free to ignore this field.

This field is set iff [fuchsia.mediacodec/DetailedCodecDescription.supports_dynamic_buffers] is true and the indicating port is conveying uncompressed video.

This field is provided for informational purposes, for clients that may want to know this information. However, the StreamProcessor and sysmem protocols work fine without the client ever reading this field.

Among the pixel formats supported by the StreamProcessor server which can carry the full bit depth of the images, and which are broadly supported for carrying images of the needed bit depth, and assuming linear pixel_format_modifier, this is the pixel format that is most performant for the StreamProcessor considered in isolation. If multiple qualified formats are essentially the same performance, this should be the most common format (or chosen arbitrarily among roughly equally-common formats). Most StreamProcessor servers will hard code a particular format to put in this field for each supported bit depth.

Currently, there is no anticipated need for a list here, but please don’t hesitate to reach out if a non-test scenario is encountered which can only be addressed by having a list here (or by attempting several test allocations via ParticipateInBufferAllocation, or by adding a sysmem feature).

In general, sysmem is not guaranteed to select this pixel format, since that depends on the full set of pixel formats supported by the StreamProcessor instance and other sysmem participants. If only the client and StreamProcessor are sysmem participants (such as in some tests), if the client requires this pixel format, buffer allocation can still succeed. Typical non-test clients will not need or want to constrain the sysmem allocation to only allow this pixel format, as that would be more likely to fail allocation in comparison to letting sysmem pick a format mutually supported by all participants.

Trait Implementations§

Source§

impl Clone for StreamBufferConstraints

Source§

fn clone(&self) -> StreamBufferConstraints

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for StreamBufferConstraints

Source§

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

Formats the value using the given formatter. Read more
Source§

impl<D> Decode<StreamBufferConstraints, D> for StreamBufferConstraints
where D: ResourceDialect,

Source§

fn new_empty() -> StreamBufferConstraints

Creates a valid instance of Self. The specific value does not matter, since it will be overwritten by decode.
Source§

unsafe fn decode( &mut self, decoder: &mut Decoder<'_, D>, offset: usize, depth: Depth, ) -> Result<(), Error>

Decodes an object of type T from the decoder’s buffers into self. Read more
Source§

impl Default for StreamBufferConstraints

Source§

fn default() -> StreamBufferConstraints

Returns the “default value” for a type. Read more
Source§

impl<D> Encode<StreamBufferConstraints, D> for &StreamBufferConstraints
where D: ResourceDialect,

Source§

unsafe fn encode( self, encoder: &mut Encoder<'_, D>, offset: usize, depth: Depth, ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
Source§

impl PartialEq for StreamBufferConstraints

Source§

fn eq(&self, other: &StreamBufferConstraints) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl TypeMarker for StreamBufferConstraints

Source§

type Owned = StreamBufferConstraints

The owned Rust type which this FIDL type decodes into.
Source§

fn inline_align(_context: Context) -> usize

Returns the minimum required alignment of the inline portion of the encoded object. It must be a (nonzero) power of two.
Source§

fn inline_size(_context: Context) -> usize

Returns the size of the inline portion of the encoded object, including padding for alignment. Must be a multiple of inline_align.
Source§

fn encode_is_copy() -> bool

Returns true if the memory layout of Self::Owned matches the FIDL wire format and encoding requires no validation. When true, we can optimize encoding arrays and vectors of Self::Owned to a single memcpy. Read more
Source§

fn decode_is_copy() -> bool

Returns true if the memory layout of Self::Owned matches the FIDL wire format and decoding requires no validation. When true, we can optimize decoding arrays and vectors of Self::Owned to a single memcpy.
Source§

impl ValueTypeMarker for StreamBufferConstraints

Source§

type Borrowed<'a> = &'a StreamBufferConstraints

The Rust type to use for encoding. This is a particular Encode<Self> type cheaply obtainable from &Self::Owned. There are three cases: Read more
Source§

fn borrow( value: &<StreamBufferConstraints as TypeMarker>::Owned, ) -> <StreamBufferConstraints as ValueTypeMarker>::Borrowed<'_>

Cheaply converts from &Self::Owned to Self::Borrowed.
Source§

impl Persistable for StreamBufferConstraints

Source§

impl StructuralPartialEq for StreamBufferConstraints

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> Body for T
where T: Persistable,

Source§

type MarkerAtTopLevel = T

The marker type to use when the body is at the top-level.
Source§

type MarkerInResultUnion = T

The marker type to use when the body is nested in a result union.
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, D> Encode<Ambiguous1, D> for T
where D: ResourceDialect,

Source§

unsafe fn encode( self, _encoder: &mut Encoder<'_, D>, _offset: usize, _depth: Depth, ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
Source§

impl<T, D> Encode<Ambiguous2, D> for T
where D: ResourceDialect,

Source§

unsafe fn encode( self, _encoder: &mut Encoder<'_, D>, _offset: usize, _depth: Depth, ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
Source§

impl<E> ErrorType for E

Source§

type Marker = E

The marker type.
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.

§

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