class Node

Defined at line 120 of file ../../src/media/audio/services/mixer/fidl/node.h

Node is the base type for all nodes in the mix graph.

# ORDINARY vs META NODES

"Ordinary" nodes have zero or more source edges and at most one destination edge. An "ordinary

edge" is an edge that connects two ordinary nodes.

```

| |

V V // N.sources()

+-----+

| N |

+-----+

| // N.dest()

V

```

"Meta" nodes don't have direct source or destination edges. Instead they connect to other nodes

indirectly via encapsulated "child" nodes. For example:

```

A

|

+----------V-----------+

| +---+ Meta |

| | I | | // Meta.child_sources()

| +---+ |

| +----+ +----+ +----+ |

| | O1 | | O2 | | O3 | | // Meta.child_dests()

| +----+ +----+ +----+ |

+---|------|------|----+

| | |

V V V

B C D

```

For the above meta node, our graph includes the following edges:

```

A -> I // A.dest() = {I}, I.sources() = {A}

O1 -> B // etc.

O2 -> C

O3 -> D

```

We use meta nodes to represent nodes that may have more than one destination edge.

Meta nodes cannot be nested within meta nodes. Every child node must be an ordinary node.

A "meta edge" is any edge that connects a meta node to another node via the meta node's children.

In the above example, "A->Meta", "Meta->B, "Meta->C", and "Meta->D" are meta edges. The

separation of ordinary vs meta nodes allows us to embed "pipeline subtrees" within the DAG:

* The ordinary edges form a forest of pipeline trees

* The union of ordinary edges and meta edges form a DAG of nodes

For more discussion on these two structures, see ../docs/index.md.

# NODE CREATION AND DELETION

After creation, nodes live until there are no more references. Our DAG structure stores forwards

and backwards pointers, which means that each edge includes cyclic references between the source

and destination nodes. Hence, a node ill not be deleted until all of its edges are explicitly

deleted by `DeleteEdge` calls.

# META NODE CHILDREN

Meta nodes can create their children in two ways:

* When the meta node is created. In this mode, the meta node's children are set immediately after

the meta node is created, by `SetBuiltInChildren` and from that point forward, child nodes

cannot be added or removed. The child nodes are "built-in" to the meta node.

* Dynamically each time we create an edge `A -> Meta` or `Meta -> A`. In this mode, there is one

`child_source` node for each "source" edge of the meta node, and one `child_dest` node for each

"destination" edge of the meta node.

CustomNode uses built-in child nodes because the set of input and output ports is fixed.

SplitterNode and MetaProducerNode use dynamic child nodes that are created and deleted along with

incoming and outgoing edges.

# THREAD SAFETY

Nodes are not thread safe. Nodes must be accessed by the main FIDL thread only and should

never be reachable from any other thread. For more information, see ../README.md.

Public Methods

fpromise::result<void, fuchsia_audio_mixer::CreateEdgeError> CreateEdge (const GraphContext & ctx, NodePtr source, NodePtr dest, CreateEdgeOptions options)

Defined at line 82 of file ../../src/media/audio/services/mixer/fidl/node.cc

Type type ()

Returns the type of this node.

Defined at line 162 of file ../../src/media/audio/services/mixer/fidl/node.h

std::string_view name ()

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

The name may not be a unique identifier.

Defined at line 166 of file ../../src/media/audio/services/mixer/fidl/node.h

std::shared_ptr<Clock> reference_clock ()

Returns the reference clock used by this node. For ordinary nodes, this corresponds

to the same clock used by the underlying `pipeline_stage()`.

Defined at line 170 of file ../../src/media/audio/services/mixer/fidl/node.h

PipelineDirection pipeline_direction ()

Reports the kind of pipeline this node participates in.

Defined at line 173 of file ../../src/media/audio/services/mixer/fidl/node.h

fpromise::result<void, fuchsia_audio_mixer::DeleteEdgeError> DeleteEdge (const GraphContext & ctx, NodePtr source, NodePtr dest)

Deletes the edge from `source` -> `dest`. This is the inverse of `CreateEdge`.

Returns an error if the edge does not exist.

Defined at line 259 of file ../../src/media/audio/services/mixer/fidl/node.cc

void PrepareToDelete (const GraphContext & ctx, NodePtr node)

Calls `DeleteEdge` for each incoming and outgoing edge, then deletes all child nodes. After

this is called, all references to this `node` can be dropped.

Defined at line 385 of file ../../src/media/audio/services/mixer/fidl/node.cc

const std::vector<NodePtr> & sources ()

Returns this ordinary node's source edges.

REQUIRED: type() != Type::kMeta

Defined at line 466 of file ../../src/media/audio/services/mixer/fidl/node.cc

NodePtr dest ()

Returns this ordinary node's destination edge, or nullptr if none.

REQUIRED: type() != Type::kMeta

Defined at line 471 of file ../../src/media/audio/services/mixer/fidl/node.cc

const std::vector<NodePtr> & child_sources ()

Returns this meta node's child source nodes.

REQUIRED: type() == Type::kMeta

Defined at line 476 of file ../../src/media/audio/services/mixer/fidl/node.cc

const std::vector<NodePtr> & child_dests ()

Returns this meta node's child destination nodes.

REQUIRED: type() == Type::kMeta

Defined at line 481 of file ../../src/media/audio/services/mixer/fidl/node.cc

NodePtr parent ()

Returns the parent of this node, or nullptr if this is not a child of a meta node.

REQUIRED: type() != Type::kMeta

Defined at line 486 of file ../../src/media/audio/services/mixer/fidl/node.cc

PipelineStagePtr pipeline_stage ()

Returns the PipelineStage owned by this node.

REQUIRED: type() != Type::kMeta

Defined at line 491 of file ../../src/media/audio/services/mixer/fidl/node.cc

std::shared_ptr<GraphThread> thread ()

Returns the thread which controls this node's PipelineStage. This is eventually-consistent with

value returned by `pipeline_stage()->thread()`.

REQUIRED: type() != Type::kMeta

Defined at line 496 of file ../../src/media/audio/services/mixer/fidl/node.cc

void set_thread (std::shared_ptr<GraphThread> t)

Set the Thread which controls our PipelineStage. Caller is responsible for asynchronously

updating `PipelineStage::thread()` as described in ../docs/execution_model.md.

REQUIRED: type() != Type::kMeta

Defined at line 501 of file ../../src/media/audio/services/mixer/fidl/node.cc

zx::duration max_downstream_output_pipeline_delay ()

Reports the maximum presentation delay of all output pipelines downstream of this node. This is

the maximum delay over all longest paths `this -> ... -> X`, where all nodes from `this` to `X`

have `pipeline_direction() == kOutput` and the path hops over meta nodes using implicit edges

from each child_source to each child_dest.

If `this` is a leaf consumer node at the bottom of the graph, we return the "external" delay

between this consumer and the physical speaker at the end of the output pipeline.

See ../docs/delay.md.

REQUIRED: type() != Type::kMeta

&

&

pipeline_direction() == PipelineDirection::kOutput

Defined at line 514 of file ../../src/media/audio/services/mixer/fidl/node.cc

zx::duration max_downstream_input_pipeline_delay ()

Reports the maximum presentation delay of all input pipelines downstream of this node. This can

be called in two cases:

* When this node has `pipeline_direction() == kInput`, in which case this returns the

downstream delay of that input pipeline. This is the maximum delay over all longest paths

`this -> ... -> X`, where all nodes have `pipeline_direction() == kInput`.

* When this node has `pipeline_direction() == kOutput`, in which case this returns the

largest delay of any downstream input pipeline, which must start after a loopback interface.

More formally, this is the maximum delay over all longest paths `L -> ... -> X`, where there

exists a path `this -> ... -> L` such that:

* all nodes before `L` have `pipeline_direction() == kOutput`, and

* all nodes from `L` onwards have `pipeline_direction() == kInput`

These paths hop over meta nodes using implicit edges from each child_source to each child_dest.

See ../docs/delay.md.

REQUIRED: type() != Type::kMeta

Defined at line 520 of file ../../src/media/audio/services/mixer/fidl/node.cc

zx::duration max_upstream_input_pipeline_delay ()

Reports the maximum presentation delay of all input pipelines upstream of this node. This is

the maximum delay over all paths `X -> ... -> this`, where all nodes from `X` to `this` have

`pipeline_direction() == kInput` and the path hops over meta nodes using implicit edges from

each child_source to each child_dest.

If `this` is a leaf producer node at the top of the graph, we return the "external" delay

between the physical microphone (at the start of the input pipeline) and this producer node.

See ../docs/delay.md.

REQUIRED: type() != Type::kMeta

&

&

pipeline_direction() == PipelineDirection::kInput

Defined at line 525 of file ../../src/media/audio/services/mixer/fidl/node.cc

std::optional<std::pair<ThreadId, fit::closure>> SetMaxDelays (Delays delays)

Defined at line 531 of file ../../src/media/audio/services/mixer/fidl/node.cc

zx::duration PresentationDelayForSourceEdge (const Node * source)

Returns total presentation delay of a source edge.

If `source != nullptr`, we return the delay of the edge `source -> this`. This typically

consists of processing delays and buffering delays, as disussed in ../docs/delay.md.

If `source == nullptr`, then this node must be a child_dest of a parent meta node. At meta

nodes, data typically flows into the child_source nodes, then into an intermediate buffer, then

into the child_dest nodes. In this case, PresentationDelayForSourceEdge returns the delay

introduced by the child_dest node processing and reading data from the intermediate buffer.

REQUIRED: type() != Type::kMeta

REQUIRED: (source == nullptr and source in parent->child_dests()) or source in sources()

Protected Methods

void ~Node ()

Defined at line 295 of file ../../src/media/audio/services/mixer/fidl/node.h

void Node (const Node & )

Defined at line 297 of file ../../src/media/audio/services/mixer/fidl/node.h

Node & operator= (const Node & )

Defined at line 298 of file ../../src/media/audio/services/mixer/fidl/node.h

void Node (Node && )

Defined at line 300 of file ../../src/media/audio/services/mixer/fidl/node.h

Node & operator= (Node && )

Defined at line 301 of file ../../src/media/audio/services/mixer/fidl/node.h

void PrepareToDeleteChildSource (NodePtr child_source)

Called just after a source edge is removed from a meta node. This allows subclasses to delete

any bookkeeping for that edge. This does not need to be reimplemented by all subclasses. The

default implementation is a no-op.

REQUIRED: type() == Type::kMeta

Defined at line 326 of file ../../src/media/audio/services/mixer/fidl/node.h

void PrepareToDeleteChildDest (NodePtr child_dest)

Called just after a destination edge is removed from a meta node. This allows subclasses to

delete any bookkeeping for that edge. This does not need to be reimplemented by all subclasses.

The default implementation is a no-op.

REQUIRED: type() == Type::kMeta

Defined at line 333 of file ../../src/media/audio/services/mixer/fidl/node.h

void PrepareToDeleteSelf ()

Called by `PrepareToDelete` just after incoming links, outgoing links, and child nodes have

been removed. This allows subclasses to delete any references to this node which would prevent

this node from being deleted. The default implementation is a no-op.

This is called for both meta and ordinary nodes.

Defined at line 340 of file ../../src/media/audio/services/mixer/fidl/node.h

void Node (Type type, std::string_view name, std::shared_ptr<Clock> reference_clock, PipelineDirection pipeline_direction, PipelineStagePtr pipeline_stage, NodePtr parent)

Defined at line 59 of file ../../src/media/audio/services/mixer/fidl/node.cc

NodePtr CreateNewChildSource ()

Creates an ordinary child node to accept the next source edge. Returns nullptr if no more child

source nodes can be created. If this mutates any internal state, that state must be reverted

back accordingly by a corresponding `PrepareToDeleteChildSource` call.

REQUIRED: type() == Type::kMeta

NodePtr CreateNewChildDest ()

Creates an ordinary child node to accept the next destination edge. Returns nullptr if no more

child destination nodes can be created. If this mutates any internal state, that state must be

reverted back accordingly by a corresponding `PrepareToDeleteChildDest` call.

REQUIRED: type() == Type::kMeta

bool CanAcceptSourceFormat (const Format & format)

Reports whether this node can accept a source edge with the given format. If MaxSources() is 0,

this should return false.

REQUIRED: type() != Type::kMeta

std::optional<size_t> MaxSources ()

Reports the maximum number of source edges allowed, or `std::nullopt` for no limit.

REQUIRED: type() != Type::kMeta

bool AllowsDest ()

Reports whether this node can accept a destination edge, i.e. whether it can be a source for

any other node.

REQUIRED: type() != Type::kMeta

void SetBuiltInChildren (std::vector<NodePtr> child_sources, std::vector<NodePtr> child_dests)

Sets built-in child nodes for this meta node. If a meta node has built-in children, this must

be called immediately after the meta node is created. See "META NODE CHILDREN" in the class

comments.

REQUIRED: type() == Type::kMeta

Defined at line 551 of file ../../src/media/audio/services/mixer/fidl/node.cc

Enumerations

enum Type
Name Value
kConsumer 0
kProducer 1
kMixer 2
kCustom 3
kMeta 4
kFake 5

Node type. Except for `kMeta`, all types refer to ordinary nodes.

Defined at line 152 of file ../../src/media/audio/services/mixer/fidl/node.h

Records

Friends

class FakeGraph