Skip to content

Commit

Permalink
Add Communications device ID support
Browse files Browse the repository at this point in the history
This CL mirrors the special handling that exists for the Default ID, and
supports creating a Communications ID OutputDeviceMixer.

This means that, when creating an output stream, we create a single
mixer for both the kCommunicationsDeviceID and the
current media::AudioManager::GetCommunicationsDeviceID, if the platform
supports GetCommunicationsDeviceID (windows only).

Bug: 1323380
Change-Id: Ic43c832dc53ac1ea32277ff9c9f8b3c276e47a18
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3636937
Reviewed-by: Olga Sharonova <olka@chromium.org>
Commit-Queue: Thomas Guilbert <tguilbert@chromium.org>
Reviewed-by: Sam Zackrisson <saza@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1002395}
  • Loading branch information
tguilbert-google authored and Chromium LUCI CQ committed May 11, 2022
1 parent a5ce126 commit 79b2856
Show file tree
Hide file tree
Showing 4 changed files with 559 additions and 289 deletions.
4 changes: 4 additions & 0 deletions services/audio/audio_manager_power_user.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ class AudioManagerPowerUser {
return audio_manager_->GetDefaultOutputDeviceID();
}

std::string GetCommunicationsOutputDeviceID() {
return audio_manager_->GetCommunicationsOutputDeviceID();
}

media::AudioParameters GetOutputStreamParameters(
const std::string& device_id) {
return media::AudioDeviceDescription::IsDefaultDevice(device_id)
Expand Down
91 changes: 48 additions & 43 deletions services/audio/output_device_mixer_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ OutputDeviceMixerManager::OutputDeviceMixerManager(
: audio_manager_(audio_manager),
current_default_device_id_(
AudioManagerPowerUser(audio_manager_).GetDefaultOutputDeviceID()),
current_communication_device_id_(AudioManagerPowerUser(audio_manager_)
.GetCommunicationsOutputDeviceID()),
create_mixer_callback_(std::move(create_mixer_callback)),
device_change_weak_ptr_factory_(this) {
// This should be a static_assert, but there is no compile time way to run
Expand Down Expand Up @@ -102,6 +104,9 @@ void OutputDeviceMixerManager::OnDeviceChange() {
current_default_device_id_ =
AudioManagerPowerUser(audio_manager_).GetDefaultOutputDeviceID();

current_communication_device_id_ =
AudioManagerPowerUser(audio_manager_).GetCommunicationsOutputDeviceID();

// Invalidate WeakPtrs, cancelling any pending device change callbacks
// generated by the same device change event.
device_change_weak_ptr_factory_.InvalidateWeakPtrs();
Expand All @@ -116,14 +121,14 @@ void OutputDeviceMixerManager::OnDeviceChange() {

void OutputDeviceMixerManager::StartNewListener(
ReferenceOutput::Listener* listener,
const std::string& device_id) {
const std::string& listener_device_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
DCHECK(IsNormalizedIfDefault(device_id));
DCHECK(IsNormalizedIfDefault(listener_device_id));

DCHECK(!listener_registration_.contains(listener));
listener_registration_[listener] = device_id;
listener_registration_[listener] = listener_device_id;

OutputDeviceMixer* mixer = FindMixer(ToMixerDeviceId(device_id));
OutputDeviceMixer* mixer = FindMixer(ToMixerDeviceId(listener_device_id));

if (!mixer)
return;
Expand All @@ -136,37 +141,40 @@ void OutputDeviceMixerManager::StartListening(
const std::string& output_device_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);

std::string device_id = NormalizeIfDefault(output_device_id);
std::string listener_device_id = NormalizeIfDefault(output_device_id);

if (!listener_registration_.contains(listener)) {
StartNewListener(listener, device_id);
StartNewListener(listener, listener_device_id);
return;
}

std::string registered_device_id = listener_registration_.at(listener);
std::string registered_listener_device_id =
listener_registration_.at(listener);

if (ToMixerDeviceId(registered_device_id) != ToMixerDeviceId(device_id)) {
if (ToMixerDeviceId(registered_listener_device_id) !=
ToMixerDeviceId(listener_device_id)) {
// |listener| is listening to a completely different mixer.
StopListening(listener);
StartNewListener(listener, device_id);
StartNewListener(listener, listener_device_id);
return;
}

// |listener| is listening to the right mixer, but we might need to update
// its registration (e.g. when switching between
// |current_default_device_id_| and kNormalizedDefaultId).
if (registered_device_id != device_id)
listener_registration_[listener] = device_id;
// |current_default_device_id_| and kNormalizedDefaultId, or
// |current_communications_device_id_| and kCommunicationsDeviceId).
if (registered_listener_device_id != listener_device_id)
listener_registration_[listener] = listener_device_id;
}

void OutputDeviceMixerManager::StopListening(
ReferenceOutput::Listener* listener) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);

const std::string device_id = listener_registration_.at(listener);
const std::string listener_device_id = listener_registration_.at(listener);
listener_registration_.erase(listener);

OutputDeviceMixer* mixer = FindMixer(ToMixerDeviceId(device_id));
OutputDeviceMixer* mixer = FindMixer(ToMixerDeviceId(listener_device_id));

// The mixer was never created, because there was no playback to that device
// (possibly after a device device change). Listening never started, so there
Expand All @@ -182,14 +190,32 @@ std::string OutputDeviceMixerManager::ToMixerDeviceId(
if (media::AudioDeviceDescription::IsDefaultDevice(device_id))
return kNormalizedDefaultDeviceId;

return device_id == current_default_device_id_ ? kNormalizedDefaultDeviceId
: device_id;
DCHECK(!device_id.empty());

if (device_id == current_default_device_id_)
return kNormalizedDefaultDeviceId;

// It's possible for |current_communication_device_id_| and
// |current_default_device_id_| to match. In that case, replace the
// communications mixer device ID with the default mixer device ID.
// Similarly, replace "communications" with kNormalizedDefaultDeviceId when
// |current_communication_device_id_| is unsupported/unconfigured.
if (device_id == media::AudioDeviceDescription::kCommunicationsDeviceId &&
(current_communication_device_id_.empty() ||
current_communication_device_id_ == current_default_device_id_)) {
return kNormalizedDefaultDeviceId;
}

if (device_id == current_communication_device_id_)
return media::AudioDeviceDescription::kCommunicationsDeviceId;

return device_id;
}

OutputDeviceMixer* OutputDeviceMixerManager::FindMixer(
const std::string& device_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
DCHECK(IsValidMixerId(device_id));
DCHECK_EQ(ToMixerDeviceId(device_id), device_id);

for (const auto& mixer : output_device_mixers_) {
if (mixer->device_id() == device_id)
Expand All @@ -202,7 +228,7 @@ OutputDeviceMixer* OutputDeviceMixerManager::FindMixer(
OutputDeviceMixer* OutputDeviceMixerManager::AddMixer(
const std::string& device_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
DCHECK(IsValidMixerId(device_id));
DCHECK_EQ(ToMixerDeviceId(device_id), device_id);

DCHECK(!FindMixer(device_id));

Expand Down Expand Up @@ -245,29 +271,13 @@ OutputDeviceMixer* OutputDeviceMixerManager::AddMixer(
auto* mixer = output_device_mixer.get();
output_device_mixers_.push_back(std::move(output_device_mixer));

AttachListenersById(device_id, mixer);

// We only create a single "default" mixer for both kNormalizedDefaultDeviceId
// and |current_default_device_id_|. If we just created this "default" mixer,
// also attach any listeners matching a physical |current_default_device_id_|.
if (device_id == kNormalizedDefaultDeviceId &&
current_default_device_id_ != kNormalizedDefaultDeviceId) {
AttachListenersById(current_default_device_id_, mixer);
}

return mixer;
}

void OutputDeviceMixerManager::AttachListenersById(const std::string& device_id,
OutputDeviceMixer* mixer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
DCHECK(IsNormalizedIfDefault(device_id));
DCHECK(mixer);

// Attach any interested listeners.
for (auto&& listener_device_kvp : listener_registration_) {
if (listener_device_kvp.second == device_id)
if (ToMixerDeviceId(listener_device_kvp.second) == mixer->device_id())
mixer->StartListening(listener_device_kvp.first);
}

return mixer;
}

base::OnceClosure OutputDeviceMixerManager::GetOnDeviceChangeCallback() {
Expand Down Expand Up @@ -307,11 +317,6 @@ media::AudioOutputStream* OutputDeviceMixerManager::CreateDeviceListenerStream(
std::move(on_device_change_callback));
}

bool OutputDeviceMixerManager::IsValidMixerId(const std::string& device_id) {
return device_id == kNormalizedDefaultDeviceId ||
device_id != current_default_device_id_;
}

bool OutputDeviceMixerManager::IsNormalizedIfDefault(
const std::string& device_id) {
return device_id == kNormalizedDefaultDeviceId ||
Expand Down
17 changes: 9 additions & 8 deletions services/audio/output_device_mixer_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ class OutputDeviceMixerManager : public DeviceOutputListener {
// Forwards device change notifications to OutputDeviceMixers.
void OnDeviceChange();

// Helper function which merges "default IDs" (as defined by
// AudioDeviceDescription::IsDefaultId()) and physical IDs matching
// GetCurrentDefaultPhysicalDeviceIdOrEmpty() into the same normalized default
// ID. This guarantees we create a single "default ID" OutputDeviceMixer.
// Helper function which maps physical and reserved IDs to normalized mixer
// device IDs. Physical IDs matching the current "default" or "communications"
// physical devices will be converted to reserved IDs
// (kNormalizedDefaultDeviceId or kCommunicationsDeviceId), ensuring we only
// create one mixer per device.
std::string ToMixerDeviceId(const std::string& device_id);

// Returns a callback that call OnDeviceChange(), and that can be cancelled
Expand All @@ -83,9 +84,6 @@ class OutputDeviceMixerManager : public DeviceOutputListener {
const std::string& device_id,
const media::AudioParameters& params);

void AttachListenersById(const std::string& device_id,
OutputDeviceMixer* mixer);

// Returns a mixer if it exists, or nullptr otherwise.
OutputDeviceMixer* FindMixer(const std::string& physical_device_id);

Expand All @@ -95,7 +93,6 @@ class OutputDeviceMixerManager : public DeviceOutputListener {
void StartNewListener(ReferenceOutput::Listener* listener,
const std::string& device_id);

bool IsValidMixerId(const std::string& device_id);
bool IsNormalizedIfDefault(const std::string& device_id);

SEQUENCE_CHECKER(owning_sequence_);
Expand All @@ -105,6 +102,10 @@ class OutputDeviceMixerManager : public DeviceOutputListener {
// if not supported by the platform.
std::string current_default_device_id_;

// Physical device ID of the current communication device, or an empty string
// if not supported by the platform or not configured.
std::string current_communication_device_id_;

OutputDeviceMixer::CreateCallback create_mixer_callback_;
OutputDeviceMixers output_device_mixers_;
ListenerToDeviceMap listener_registration_;
Expand Down

0 comments on commit 79b2856

Please sign in to comment.