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