class PipelineStage

Defined at line 39 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

A stage in a pipeline tree.

Each `PipelineStage` consumes zero or more source streams and produces at most one destination

stream. This abstract class provides functionality common to all pipeline stages.

Public Methods

void AddSource (PipelineStagePtr source, AddSourceOptions options)
void RemoveSource (PipelineStagePtr source)

Removes a source stream.

Required: caller must verify that `source` is currently a source for this stage.

void Advance (MixJobContext & ctx, Fixed frame)

Advances the destination stream by releasing any frames before the given `frame`. This is a

declaration that the caller will not attempt to `Read` any frame before the given `frame`. If

the stage has allocated packets for frames before `frame`, it can free those packets now. After

the destination stream is advanced, the source streams are advanced, recursively.

This must *not* be called while the stage is _locked_, i.e., until the packet returned by the

last `Read` call is destroyed, nor while the stage is _stopped_, i.e., when

`presentation_time_to_frac_frame()` returns `std::nullopt`.

Defined at line 20 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.cc

std::optional<Packet> Read (MixJobContext & ctx, Fixed start_frame, int64_t frame_count)

Reads the destination stream of this stage, and returns the acquired packet. The parameters

`start_frame` and `frame_count` represent a range of frames on the destination stream's frame

timeline.

This must *not* be called while the stage is _locked_, i.e., until the packet returned by the

last `Read` call is destroyed, nor while the stage is _stopped_, i.e., when

`presentation_time_to_frac_frame()` returns `std::nullopt`.

## Returned Packet

Returns `std::nullopt` if no data is available for the requested frame range. Otherwise,

returns a packet representing all or part of the requested range. If the start frame on the

returned packet is greater than `start_frame`, then the stream has no data for those initial

frames, which may be treated as silence. Conversely, if the end frame of the returned packet is

less than `start_frame + frame_count`, this indicates the full frame range is not available on

a single contiguous packet. Clients should call `Read` again, with `start_frame` set to the end

of the previous packet, to see if the stream has more frames.

The returned packet contains an integral number of frames satisfying the following conditions:

* `packet.start() > start_frame - Fixed(1)`

* `packet.end()

<

= start_frame + Fixed(frame_count)`

* `packet.length()

<

= frame_count`

The start frame of the returned packet is the position of the left edge of the first frame in

the packet. For example, given `Read(Fixed(10), 5)`, if the stream's frames happen to be

aligned on positions 9.1, 10.1, 11.1, etc., then `Read` will return a packet with the start

frame of 9.1, and the length of 5.

The stage will remain _locked_ until the returned packet is destroyed.

## The Passage of Time

Each stage maintains a current frame position, which always moves forward. The position is

explicitly advanced to a destination `frame` via an `Advance(frame)` call. Similarly, a `Read`

call advances the position as follows:

* When `Read` is called, the position is advanced to `start_frame` (iff the next readable frame

iess than `start_frame`).

* If `std::nullopt` is returned, the position is advanced to `start_frame + frame_count`.

* Otherwise, the position is advanced to `packet.start() + packet.frames_consumed_` when the

returned packet is destroyed.

Put differently, time advances when `Read` is called, when a packet is consumed, and on

explicit calls to `Advance`. Time does not go backwards, hence, each call to `Read` must have

`start_frame` that is not lesser than the last advanced frame.

Defined at line 31 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.cc

void set_thread (std::shared_ptr<PipelineThread> new_thread)

Sets the stage's thread. This must be called from `thread()`, unless `thread()` is a detached

thread, in which case this may be called from any thread.

Defined at line 71 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.cc

void ~PipelineStage ()

Defined at line 80 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

Fixed FrameFromPresentationTime (zx::time presentation_time)

Returns corresponding frame for a given `presentation_time`.

Required: caller must verify that `presentation_time_to_frac_frame` is valid.

Defined at line 164 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

zx::time PresentationTimeFromFrame (Fixed frame)

Returns corresponding presentation time for a given `frame`.

Required: caller must verify that `presentation_time_to_frac_frame` is valid.

Defined at line 172 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

void UpdatePresentationTimeToFracFrame (std::optional<TimelineFunction> f)

Updates `presentation_time_to_frac_frame`. See discussion in ../docs/timelines.md.

If `f` is not `std::nullopt`, it must be an invertible function.

std::string_view name ()

Returns the stage's name. This is used for diagnostics only.

The name may not be a unique identifier.

Defined at line 179 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

const Format & format ()

Returns the stage's format.

Defined at line 182 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

std::optional<Fixed> next_readable_frame ()

Returns the stage's next readable frame.

Defined at line 185 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

std::shared_ptr<PipelineThread> thread ()

Returns the thread which currently controls this stage. It is safe to call this method on any

thread -- this allows callers to check that they are running on the correct thread. However, if

not called from `thread()`, the returned value may change concurrently.

Defined at line 190 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

UnreadableClock reference_clock ()

Returns the clock used by the stage's destination stream.

The source streams may use different clocks.

Defined at line 200 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

std::optional<TimelineFunction> presentation_time_to_frac_frame ()

Returns a function that translates from presentation time to frame time, where frame time is

represented by a `Fixed::raw_value()` while presentation time is represented by a `zx::time`.

Defined at line 204 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

Protected Methods

void AdvanceSelfImpl (Fixed frame)

`Advance(ctx, frame)` is implemented by the following code:

```

if (AdvanceSelf(frame)) {

AdvanceSourcesImpl(ctx, frame);

}

```

`AdvanceSelf` advances this PipelineStage's `next_readable_frame` to the given `frame`, then

calls `AdvanceSelfImpl`, which discards any stage-specific cached data that is not needed past

`frame`. `AdvanceSourcesImpl` advances this PipelineStage's connected source streams.

void AdvanceSourcesImpl (MixJobContext & ctx, Fixed frame)
std::optional<Packet> ReadImpl (MixJobContext & ctx, Fixed start_frame, int64_t frame_count)

Implements stage-specific `Read`.

Packet MakeCachedPacket (Fixed start_frame, int64_t frame_count, void * payload)

`ReadImpl` should use this to create a cached packet. If the packet is not fully consumed after

one `Read`, the next `Read` call will return the same packet without asking `ReadImpl` to

recreate the same data. `PipelineStage` will hold onto this packet until the packet is fully

consumed or the stream position is advanced beyond the end of the packet.

This is useful for pipeline stages that compute buffers dynamically. Examples include mixers

and effects.

Required:

* The `start_frame` must obey the packet constraints described by `Read`, however the

`frame_count` can be arbitrarily large. This is useful for pipeline stages that generate data

in fixed-sized blocks, as they may cache the entire block for future `Read` calls.

* The `payload` must remain valid until the packet is fully consumed, i.e., until an the stage

is advanced past the end of the packet.

Defined at line 87 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.cc

Packet MakeUncachedPacket (Fixed start_frame, int64_t frame_count, void * payload)

`ReadImpl` should use this to create an uncached packet. If the packet is not fully consumed

after one `Read`, the next `Read` call will ask `ReadImpl` to recreate the packet.

This is useful for pipeline stages that don't need caching or that want precise control over

packet lifetimes. Examples include ring buffers and packet queues.

Required:

* The `start_frame` and the `frame_count` must obey the packet constraints described by `Read`.

* The `payload` must remain valid until the packet is destroyed.

Defined at line 95 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.cc

std::optional<Packet> ForwardPacket (std::optional<Packet> && packet, std::optional<Fixed> start_frame)

`ReadImpl` should use this when forwarding a `Packet` from an upstream source. This may be used

by no-op pipeline stages. It is necessary to call `ForwardPacket`, rather than simply returning

a packet from an upstream source, so that `AdvanceSelf` is called when the packet is destroyed.

If `start_frame` is specified, the start frame of the returned packet is set to the given

value, while the length of the packet is unchanged. This is useful when doing SampleAndHold on

a source stream. For example:

```

auto packet = source->Read(frame, frame_count);

auto start_frame = packet->start_frame().Ceiling();

return ForwardPacket(std::move(packet), start_frame);

```

If `start_frame` is not specified, the packet is forwarded unchanged.

Defined at line 105 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.cc

void PipelineStage (std::string_view name, Format format, UnreadableClock reference_clock, std::shared_ptr<PipelineThread> initial_thread)

Defined at line 213 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

void PipelineStage (const PipelineStage & )

Defined at line 224 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

PipelineStage & operator= (const PipelineStage & )

Defined at line 225 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

void PipelineStage (PipelineStage && )

Defined at line 227 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

PipelineStage & operator= (PipelineStage && )

Defined at line 228 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

void set_presentation_time_to_frac_frame (std::optional<TimelineFunction> f)

Implementation detail of `UpdatePresentationTimeToFracFrame`.

Defined at line 298 of file ../../src/media/audio/services/mixer/mix/pipeline_stage.h

Records