class ReadableStream

Defined at line 91 of file ../../src/media/audio/audio_core/stream.h

A read-only stream of audio data.

ReadableStreams should be created and held as shared_ptr

<

>s.

Public Methods

std::optional<Buffer> ReadLock (ReadLockContext & ctx, Fixed dest_frame, int64_t frame_count)

ReadableStream is implemented by audio pipeline stages that consume zero or more source

streams and produce a destination stream. ReadLock acquires a read lock on the destination

stream. The parameters `dest_frame` and `frame_count` represent a range of frames on the

destination stream's frame timeline.

THE RETURNED BUFFER

If no data is available for the requested frame range, ReadLock returns std::nullopt.

Otherwise, ReadLock returns a buffer representing all or part of the requested range.

If `start()` on the returned buffer is greater than `dest_frame`, then the stream

has no data for those initial frames and it may be treated as silence. Conversely, if `end()`

on the returned buffer is less than `dest_frame + frame_count`, this indicates the full

frame range is not available on a single contiguous buffer. Clients should call `ReadLock`

again, with `dest_frame` set to the `end()` of the previous buffer, to query if the stream

has more frames.

The buffer must contain an integral number of frames and must satisfy the following

conditions:

- buffer.start() > dest_frame - Fixed(1)

- buffer.end()

<

= dest_frame + Fixed(frame_count)

- buffer.length()

<

= frame_count

The buffer's `start()` is the position of the left edge of the first frame in the buffer.

For example, given `ReadLock(Fixed(10), 5)`, if the stream's frames happen to be aligned

on positions 9.1, 10.1, 11.1, etc., then ReadLock should return a buffer with `start() = 9.1`

and `length() = 5`.

The stream will remain locked until the buffer is destructed.

THE PASSAGE OF TIME

Each ReadableStream maintains a current frame position (aka time). This position must always

move forward. Position advances to X after a call to `Trim(X)`. Position is also advanced by

ReadLock, which calls Trim as follows:

- If ReadLock returns std::nullopt, we advance time to

`Trim(dest_frame + frame_count)`.

- When a buffer is unlocked, we advance time to

`Trim(buffer.start + buffer.frames_consumed)`.

Put differently, time advances when ReadLock is called, when a buffer is consumed, and on

explicit calls to Trim. Time does not go backwards: each call to ReadLock must have

`dest_frame >= NextAvailableFrame()`.

RESET

Changing a stream's ref_time_to_frac_presentation_frame TimelineFunction discards all history

recorded by prior calls to ReadLock and Trim. This allows time to go backwards as a one-time

event after a Play or Pause command seeks backwards in a stream. Note that when time advances

normally past X, then is reset to X or earlier (by Play), all internal caches are discarded

and there's no requirement for a source to reproduce the same audio that was played at X the

first time.

Defined at line 37 of file ../../src/media/audio/audio_core/stream.cc

void Trim (Fixed dest_frame)

Trims the stream by releasing any frames before the given frame. This is a declaration

that the caller will not attempt to ReadLock any frame before dest_frame. If the stream has

allocated buffers for frames before dest_frame, it can free those buffers now.

Must not be called while the stream is locked.

Defined at line 122 of file ../../src/media/audio/audio_core/stream.cc

std::optional<Fixed> NextAvailableFrame ()

Reports the next frame that can be requested from ReadLock. This is the highest frame passed

to Trim. Returns std::nullopt if Trim has not been called or if the stream has been reset since

the last Trim.

Defined at line 259 of file ../../src/media/audio/audio_core/stream.h

Protected Methods

void ReadableStream (std::string name, Format format)

`name` should uniquely identify the stream. Used for debugging.

Defined at line 32 of file ../../src/media/audio/audio_core/stream.cc

std::optional<Buffer> ReadLockImpl (ReadLockContext & ctx, Fixed dest_frame, int64_t frame_count)

Child classes must provide stream-specific implementations of ReadLockImpl and TrimImpl.

These are called by ReadLock and Trim, respectively.

ReadLock and Trim add some default behavior, including logging, tracing, caching of

partially-consumed buffers, and validation of pre and post conditions.

void ReadUnlock ()

Child classes may override this to be notified when the most-recently locked buffer is

unlocked.

Defined at line 278 of file ../../src/media/audio/audio_core/stream.h

void TrimImpl (Fixed dest_frame)
std::optional<Buffer> MakeCachedBuffer (Fixed start_frame, int64_t frame_count, void * payload, StreamUsageMask usage_mask, float total_applied_gain_db)

ReadLockImpl should use this to create a cached buffer. If the buffer is not fully

consumed after one ReadLock, the next ReadLock call will return the same buffer

without asking ReadLockImpl to recreate the same data. ReadableStream will hold

onto this buffer until the buffer is fully consumed or trimmed away.

This is useful for pipeline stages that compute buffers dynamically, such as mixers

and effects. The std::optional return type is for convenience (so that `MakeCachedBuffer(...)`

can be returned directly from ReadLockImpl) -- the returned value is never std::nullopt.

REQUIRED:

- The buffer's `start()` must obey the buffer constraints described by ReadLock,

however the buffer's `length()` can be arbitrarily large. This is useful for pipeline

stages that generate data in fixed-sized blocks: they may cache the entire block for

future ReadLock calls.

- The payload must remain valid until the buffer is fully consumed, i.e. until the

stream is Trim'd past the end of the buffer.

Defined at line 177 of file ../../src/media/audio/audio_core/stream.cc

std::optional<Buffer> MakeUncachedBuffer (Fixed start_frame, int64_t frame_count, void * payload, StreamUsageMask usage_mask, float total_applied_gain_db)

ReadLockImpl should use this to create an uncached buffer. If the buffer is not fully

consumed after one ReadLock, the next ReadLock call will ask ReadLockImpl to recreate

the buffer.

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

buffer lifetimes. Examples include ring buffers and packet queues. The std::optional

return type is for convenience -- the returned value is never std::nullopt.

REQUIRED:

- The buffer's `start()` and `length()` must obey the buffer constraints described

by ReadLock (above).

- The payload must remain valid until the buffer is unlocked.

Defined at line 189 of file ../../src/media/audio/audio_core/stream.cc

std::optional<Buffer> ForwardBuffer (std::optional<Buffer> && buffer, std::optional<Fixed> start_frame)

ReadLockImpl should use this when forwarding a Buffer from an upstream source.

This may be used by no-op pipeline stages. It is necessary to call ForwardBuffer,

rather than simply returning a buffer from an upstream source, so that this stream

will be Trim'd when the buffer is unlocked:

// Good: calls this->Trim() and src->Trim() when unlocked

return ForwardBuffer(src->ReadLock(ctx, dest_frame, frame_count));

// Bad: calls src->Trim() when unlocked, but not this->Trim()

return src->ReadLock(ctx, dest_frame, frame_count);

If `start_frame` is specified, the returned buffer's starting frame is set to the

given value. The buffer's length is unchanged. This is useful when doing SampleAndHold

on a source stream. For example:

auto buffer = src->ReadLock(ctx, frame, frame_count);

auto start_frame = buffer->start().Ceiling();

return ForwardBufferWithModifiedStart(std::move(buffer), start_frame);

If start_frame is not specified, the buffer is forwarded unchanged.

Defined at line 208 of file ../../src/media/audio/audio_core/stream.cc

Records