blob: 7351f5a52a5a0e3713f72ab23396752d15eef22a [file] [log] [blame]
// Copyright 2020 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_STREAM_USAGE_H_
#define SRC_MEDIA_AUDIO_AUDIO_CORE_STREAM_USAGE_H_
#include <fuchsia/media/cpp/fidl.h>
#include <lib/fidl/cpp/enum.h>
#include <type_traits>
#include <unordered_set>
#include <variant>
#include "src/lib/syslog/cpp/logger.h"
namespace media::audio {
static_assert(fuchsia::media::RENDER_USAGE_COUNT == 5);
#define EXPAND_EACH_FIDL_RENDER_USAGE \
EXPAND_RENDER_USAGE(BACKGROUND) \
EXPAND_RENDER_USAGE(MEDIA) \
EXPAND_RENDER_USAGE(INTERRUPTION) \
EXPAND_RENDER_USAGE(SYSTEM_AGENT) \
EXPAND_RENDER_USAGE(COMMUNICATION)
static constexpr uint32_t kStreamInternalRenderUsageCount = 1;
#define EXPAND_EACH_INTERNAL_RENDER_USAGE EXPAND_RENDER_USAGE(ULTRASOUND)
#define EXPAND_EACH_RENDER_USAGE \
EXPAND_EACH_FIDL_RENDER_USAGE \
EXPAND_EACH_INTERNAL_RENDER_USAGE
static_assert(fuchsia::media::CAPTURE_USAGE_COUNT == 4);
#define EXPAND_EACH_FIDL_CAPTURE_USAGE \
EXPAND_CAPTURE_USAGE(BACKGROUND) \
EXPAND_CAPTURE_USAGE(FOREGROUND) \
EXPAND_CAPTURE_USAGE(SYSTEM_AGENT) \
EXPAND_CAPTURE_USAGE(COMMUNICATION)
static constexpr uint32_t kStreamInternalCaptureUsageCount = 2;
#define EXPAND_EACH_INTERNAL_CAPTURE_USAGE \
EXPAND_CAPTURE_USAGE(LOOPBACK) \
EXPAND_CAPTURE_USAGE(ULTRASOUND)
#define EXPAND_EACH_CAPTURE_USAGE \
EXPAND_EACH_FIDL_CAPTURE_USAGE \
EXPAND_EACH_INTERNAL_CAPTURE_USAGE
static constexpr uint32_t kStreamRenderUsageCount =
fuchsia::media::RENDER_USAGE_COUNT + kStreamInternalRenderUsageCount;
enum class RenderUsage : std::underlying_type_t<fuchsia::media::AudioRenderUsage> {
#define EXPAND_RENDER_USAGE(U) U = fidl::ToUnderlying(fuchsia::media::AudioRenderUsage::U),
EXPAND_EACH_FIDL_RENDER_USAGE
#undef EXPAND_RENDER_USAGE
#define EXPAND_RENDER_USAGE(U) U,
EXPAND_EACH_INTERNAL_RENDER_USAGE
#undef EXPAND_RENDER_USAGE
};
constexpr std::array<RenderUsage, fuchsia::media::RENDER_USAGE_COUNT> kFidlRenderUsages = {{
#define EXPAND_RENDER_USAGE(U) RenderUsage::U,
EXPAND_EACH_FIDL_RENDER_USAGE
#undef EXPAND_RENDER_USAGE
}};
constexpr std::array<RenderUsage, kStreamRenderUsageCount> kRenderUsages = {{
#define EXPAND_RENDER_USAGE(U) RenderUsage::U,
EXPAND_EACH_RENDER_USAGE
#undef EXPAND_RENDER_USAGE
}};
static constexpr uint32_t kStreamCaptureUsageCount =
fuchsia::media::CAPTURE_USAGE_COUNT + kStreamInternalCaptureUsageCount;
enum class CaptureUsage : std::underlying_type_t<fuchsia::media::AudioCaptureUsage> {
#define EXPAND_CAPTURE_USAGE(U) U = fidl::ToUnderlying(fuchsia::media::AudioCaptureUsage::U),
EXPAND_EACH_FIDL_CAPTURE_USAGE
#undef EXPAND_CAPTURE_USAGE
#define EXPAND_CAPTURE_USAGE(U) U,
EXPAND_EACH_INTERNAL_CAPTURE_USAGE
#undef EXPAND_CAPTURE_USAGE
};
constexpr std::array<CaptureUsage, fuchsia::media::CAPTURE_USAGE_COUNT> kFidlCaptureUsages = {{
#define EXPAND_CAPTURE_USAGE(U) CaptureUsage::U,
EXPAND_EACH_FIDL_CAPTURE_USAGE
#undef EXPAND_CAPTURE_USAGE
}};
static constexpr uint32_t kStreamUsageCount = kStreamRenderUsageCount + kStreamCaptureUsageCount;
// Since we define the RenderUsage enum to have the same numeric values for each fidl enum entry,
// we can convert by casting the underlying numeric value.
static RenderUsage RenderUsageFromFidlRenderUsage(fuchsia::media::AudioRenderUsage u) {
return static_cast<RenderUsage>(fidl::ToUnderlying(u));
}
static CaptureUsage CaptureUsageFromFidlCaptureUsage(fuchsia::media::AudioCaptureUsage u) {
return static_cast<CaptureUsage>(fidl::ToUnderlying(u));
}
[[maybe_unused]] static std::optional<fuchsia::media::AudioRenderUsage>
FidlRenderUsageFromRenderUsage(RenderUsage u) {
auto underlying = static_cast<std::underlying_type_t<RenderUsage>>(u);
if (underlying < fuchsia::media::RENDER_USAGE_COUNT) {
return {static_cast<fuchsia::media::AudioRenderUsage>(underlying)};
}
return {};
}
[[maybe_unused]] static std::optional<fuchsia::media::AudioCaptureUsage>
FidlCaptureUsageFromCaptureUsage(CaptureUsage u) {
auto underlying = static_cast<std::underlying_type_t<CaptureUsage>>(u);
if (underlying < fuchsia::media::CAPTURE_USAGE_COUNT) {
return {static_cast<fuchsia::media::AudioCaptureUsage>(underlying)};
}
return {};
}
class StreamUsage {
public:
static constexpr StreamUsage WithRenderUsage(RenderUsage u) { return StreamUsage(u); }
static constexpr StreamUsage WithCaptureUsage(CaptureUsage u) { return StreamUsage(u); }
static constexpr StreamUsage WithRenderUsage(fuchsia::media::AudioRenderUsage u) {
return StreamUsage(RenderUsageFromFidlRenderUsage(u));
}
static constexpr StreamUsage WithCaptureUsage(fuchsia::media::AudioCaptureUsage u) {
return StreamUsage(CaptureUsageFromFidlCaptureUsage(u));
}
StreamUsage() = default;
bool operator==(const StreamUsage& other) const { return usage_ == other.usage_; }
bool operator!=(const StreamUsage& other) const { return !(*this == other); }
// RenderUsage
bool is_render_usage() const { return std::holds_alternative<RenderUsage>(usage_); }
StreamUsage& set_render_usage(RenderUsage usage) {
usage_ = usage;
return *this;
}
RenderUsage render_usage() const {
FX_DCHECK(is_render_usage());
return std::get<RenderUsage>(usage_);
}
// CaptureUsage
bool is_capture_usage() const { return std::holds_alternative<CaptureUsage>(usage_); }
StreamUsage& set_capture_usage(CaptureUsage usage) {
usage_ = usage;
return *this;
}
CaptureUsage capture_usage() const {
FX_DCHECK(is_capture_usage());
return std::get<CaptureUsage>(usage_);
}
// A |StreamUsage| is empty if it contains neither a render usage or a capture usage. This state
// exists to be similar to the semantics of a FIDL union in C++.
bool is_empty() const { return std::holds_alternative<std::monostate>(usage_); }
private:
using Usage = std::variant<std::monostate, RenderUsage, CaptureUsage>;
explicit constexpr StreamUsage(RenderUsage usage) : usage_(usage) {}
explicit constexpr StreamUsage(CaptureUsage usage) : usage_(usage) {}
Usage usage_;
};
constexpr std::array<StreamUsage, kStreamUsageCount> kStreamUsages = {{
#define EXPAND_RENDER_USAGE(U) StreamUsage::WithRenderUsage(RenderUsage::U),
EXPAND_EACH_RENDER_USAGE
#undef EXPAND_RENDER_USAGE
#define EXPAND_CAPTURE_USAGE(U) StreamUsage::WithCaptureUsage(CaptureUsage::U),
EXPAND_EACH_CAPTURE_USAGE
#undef EXPAND_CAPTURE_USAGE
}};
static uint32_t HashStreamUsage(const StreamUsage& u) {
if (u.is_render_usage()) {
return static_cast<uint32_t>(u.render_usage());
}
if (u.is_capture_usage()) {
return static_cast<uint32_t>(u.capture_usage()) + kStreamRenderUsageCount;
}
return kStreamUsageCount;
}
namespace internal {
struct EnumHash {
template <typename T>
size_t operator()(T t) const {
return static_cast<size_t>(t);
}
};
struct StreamUsageHash {
size_t operator()(StreamUsage u) const { return HashStreamUsage(u); }
};
} // namespace internal
using RenderUsageSet = std::unordered_set<RenderUsage, internal::EnumHash>;
using CaptureUsageSet = std::unordered_set<CaptureUsage, internal::EnumHash>;
using StreamUsageSet = std::unordered_set<StreamUsage, internal::StreamUsageHash>;
template <typename Container>
static StreamUsageSet StreamUsageSetFromRenderUsages(const Container& container) {
static_assert(std::is_same<typename Container::value_type, RenderUsage>::value);
StreamUsageSet result;
std::transform(container.cbegin(), container.cend(), std::inserter(result, result.begin()),
[](const auto& u) { return StreamUsage::WithRenderUsage(u); });
return result;
}
template <typename Container>
static StreamUsageSet StreamUsageSetFromCaptureUsages(const Container& container) {
static_assert(std::is_same<typename Container::value_type, CaptureUsage>::value);
StreamUsageSet result;
std::transform(container.cbegin(), container.cend(), std::inserter(result, result.begin()),
[](const auto& u) { return StreamUsage::WithCaptureUsage(u); });
return result;
}
} // namespace media::audio
#undef EXPAND_EACH_CAPTURE_USAGE
#undef EXPAND_EACH_RENDER_USAGE
#undef EXPAND_EACH_FIDL_CAPTURE_USAGE
#undef EXPAND_EACH_FIDL_RENDER_USAGE
#undef EXPAND_EACH_INTERNAL_CAPTURE_USAGE
#undef EXPAND_EACH_INTERNAL_RENDER_USAGE
#endif // SRC_MEDIA_AUDIO_AUDIO_CORE_STREAM_USAGE_H_