blob: 50d447bad55738c3d21e969510dfc61c0ee1ad3e [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_MEDIA_AUDIO_AUDIO_CORE_ROUTE_GRAPH_H_
#define SRC_MEDIA_AUDIO_AUDIO_CORE_ROUTE_GRAPH_H_
#include <fuchsia/media/cpp/fidl.h>
#include <lib/fit/bridge.h>
#include <array>
#include <deque>
#include <unordered_map>
#include <fbl/ref_ptr.h>
#include "src/media/audio/audio_core/audio_input.h"
#include "src/media/audio/audio_core/audio_output.h"
#include "src/media/audio/audio_core/device_config.h"
#include "src/media/audio/audio_core/link_matrix.h"
#include "src/media/audio/audio_core/threading_model.h"
namespace media::audio {
// |RoutingProfile| informs the |RouteGraph| on how or whether it should establish links for a
// particular input or output to the mixer.
struct RoutingProfile {
bool routable = false;
StreamUsage usage = {};
};
// |RouteGraph| is responsible for managing connections between inputs and outputs of the mixer.
//
// |RouteGraph| owns user-level inputs and outputs (|AudioRenderer|s and |AudioCapturer|s).
//
// Renderers are routed by Usage to the most recently plugged output that supports their Usage.
//
// Capturers are routed to the most recently plugged device that supports their usage.
class RouteGraph {
public:
// Constructs a graph from the given config and link matrix. Each parameter must outlive the
// RouteGraph.
RouteGraph(LinkMatrix* link_matrix);
~RouteGraph();
// TODO(fxbug.dev/13339): Remove throttle_output_.
// Sets a throttle output which is linked to all AudioRenderers to throttle the rate at which we
// return packets to clients.
void SetThrottleOutput(ThreadingModel* threading_model,
std::shared_ptr<AudioOutput> throttle_output);
// Adds an |AudioInput| to the route graph. An audio input may be connected to transmit samples
// to an |AudioCapturer|.
void AddDevice(AudioDevice* input);
// Removes an |AudioInput| from the route graph. Any connected |AudioCapturer|s will be rerouted.
void RemoveDevice(AudioDevice* input);
// Returns a boolean indicating if a |device| is contained in the route graph.
bool ContainsDevice(const AudioDevice* device);
// Adds an |AudioRenderer| to the route graph. An |AudioRenderer| may be connected to
// |AudioOutput|s.
void AddRenderer(std::shared_ptr<AudioObject> renderer);
// Sets the routing profile with which the route graph selects |AudioOutput|s for the
// |AudioRenderer|.
void SetRendererRoutingProfile(const AudioObject& renderer, RoutingProfile profile);
void RemoveRenderer(const AudioObject& renderer);
// Adds an |AudioCapturer| to the route graph. An |AudioCapturer| may be connected to
// |AudioInput|s to receive samples from them.
void AddCapturer(std::shared_ptr<AudioObject> capturer);
// Sets the routing profile with which the route graph selects |AudioInput|s for the
// |AudioCapturer|.
void SetCapturerRoutingProfile(const AudioObject& capturer, RoutingProfile profile);
void RemoveCapturer(const AudioObject& capturer);
private:
struct RoutableOwnedObject {
std::shared_ptr<AudioObject> ref;
RoutingProfile profile;
};
struct Target {
Target() = default;
Target(AudioDevice* _device, std::shared_ptr<LoudnessTransform> _transform)
: device(_device), transform(_transform) {
FX_DCHECK(!!device == !!transform);
}
bool is_linkable() const { return device; }
AudioDevice* device = nullptr;
std::shared_ptr<LoudnessTransform> transform = nullptr;
};
using Targets = std::array<Target, kStreamUsageCount>;
using UnlinkCommand = std::array<bool, kStreamUsageCount>;
void UpdateGraphForDeviceChange();
// Calculate the new targets based on our routing policy and available devices.
// Returns the new targets and an unlink command to unlink any out of date
// routing links.
std::pair<Targets, UnlinkCommand> CalculateTargets() const;
void Unlink(UnlinkCommand unlink_command);
Target TargetForUsage(const StreamUsage& usage) const;
LinkMatrix& link_matrix_;
Targets targets_ = {};
// TODO(fxbug.dev/39624): convert to weak_ptr when ownership is explicit.
std::deque<AudioDevice*> devices_;
std::unordered_map<const AudioObject*, RoutableOwnedObject> capturers_;
std::unordered_map<const AudioObject*, RoutableOwnedObject> renderers_;
std::unordered_map<const AudioObject*, RoutableOwnedObject> loopback_capturers_;
// TODO(fxbug.dev/13339): Remove throttle_output_.
std::optional<fit::completer<void, void>> throttle_release_fence_;
std::shared_ptr<AudioOutput> throttle_output_;
};
} // namespace media::audio
#endif // SRC_MEDIA_AUDIO_AUDIO_CORE_ROUTE_GRAPH_H_