Skip to content

Commit

Permalink
Update support for default/communications devices in AudioManager
Browse files Browse the repository at this point in the history
This CL introduces functions to get the ID name of the following
special devices in AudioManager.
- Default audio input device
- Communications audio input device
- Communications audio output device

There was already a similar function for the default audio output device.

In enumeration results, the label of special device entries now have
appended the label of the corresponding real device.

This CL also adds implementation of the new functionality for Mac,
and reverts the effects of http://crrev.com/520087, which implemented
similar but more limited functionality.

Bug: 780492
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: Iee5afc2fc231913baddaf6ef3fedd4535b3d9841
Reviewed-on: https://chromium-review.googlesource.com/803814
Reviewed-by: Olga Sharonova <olka@chromium.org>
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521682}
  • Loading branch information
Guido Urdaneta authored and Commit Bot committed Dec 5, 2017
1 parent 5e84f2f commit bd7ce60
Show file tree
Hide file tree
Showing 14 changed files with 290 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/renderer_host/media/in_process_video_capture_provider.h"
Expand Down Expand Up @@ -52,9 +51,7 @@ const char kNormalVideoDeviceID[] = "/dev/video0";
const char kNoFormatsVideoDeviceID[] = "/dev/video1";
const char kZeroResolutionVideoDeviceID[] = "/dev/video2";
const char* const kDefaultVideoDeviceID = kZeroResolutionVideoDeviceID;
const char kUserDefaultAudioInputDeviceID[] = "fake_audio_input_2";
const char kSystemDefaultAudioInputLabel[] = "Fake Audio Input 1";
const char kSystemDefaultAudioOutputLabel[] = "Fake Audio Output 1";
const char kDefaultAudioDeviceID[] = "fake_audio_input_2";

const auto kIgnoreLogMessageCB = base::BindRepeating([](const std::string&) {});

Expand Down Expand Up @@ -95,8 +92,7 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
switches::kUseFakeDeviceForMediaStream,
base::StringPrintf("video-input-default-id=%s, "
"audio-input-default-id=%s",
kDefaultVideoDeviceID,
kUserDefaultAudioInputDeviceID));
kDefaultVideoDeviceID, kDefaultAudioDeviceID));
audio_manager_ = std::make_unique<media::MockAudioManager>(
std::make_unique<media::TestAudioThread>());
audio_system_ =
Expand Down Expand Up @@ -202,7 +198,7 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
EXPECT_EQ(kNumExpectedEntries, capabilities.size());
std::string expected_first_device_id =
GetHMACForMediaDeviceID(browser_context_->GetMediaDeviceIDSalt(),
origin_, kUserDefaultAudioInputDeviceID);
origin_, kDefaultAudioDeviceID);
EXPECT_EQ(expected_first_device_id, capabilities[0]->device_id);
for (const auto& capability : capabilities)
EXPECT_TRUE(capability->parameters.IsValid());
Expand Down Expand Up @@ -308,15 +304,8 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
}

// Returns true if all devices have labels, false otherwise.
bool DoesContainLabels(
const MediaDeviceInfoArray& device_infos,
const std::string& system_default_label = std::string()) {
bool DoesContainLabels(const MediaDeviceInfoArray& device_infos) {
for (const auto& device_info : device_infos) {
if (media::AudioDeviceDescription::IsDefaultDevice(
device_info.device_id)) {
EXPECT_TRUE(base::EndsWith(device_info.label, system_default_label,
base::CompareCase::SENSITIVE));
}
if (device_info.label.empty())
return false;
}
Expand All @@ -325,13 +314,8 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {

// Returns true if all devices have labels, false otherwise.
bool DoesContainLabels(const std::vector<MediaDeviceInfoArray>& enumeration) {
for (int i = 0; i < NUM_MEDIA_DEVICE_TYPES; i++) {
std::string default_label;
if (i == MEDIA_DEVICE_TYPE_AUDIO_INPUT)
default_label = kSystemDefaultAudioInputLabel;
else if (i == MEDIA_DEVICE_TYPE_AUDIO_OUTPUT)
default_label = kSystemDefaultAudioOutputLabel;
if (!DoesContainLabels(enumeration[i], default_label))
for (const auto& device_infos : enumeration) {
if (!DoesContainLabels(device_infos))
return false;
}
return true;
Expand Down
78 changes: 16 additions & 62 deletions content/browser/renderer_host/media/media_devices_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,23 @@ std::string GetLogMessageString(MediaDeviceType device_type,
return output_string;
}

media::AudioDeviceDescriptions GetFakeAudioDevices(bool is_input) {
media::AudioDeviceDescriptions result;
MediaDeviceInfoArray GetFakeAudioDevices(bool is_input) {
MediaDeviceInfoArray result;
if (is_input) {
result.emplace_back("Fake Default Audio Input",
media::AudioDeviceDescription::kDefaultDeviceId,
"fake_group_audio_1");
result.emplace_back("Fake Audio Input 1", "fake_audio_input_1",
"fake_group_audio_1");
result.emplace_back("Fake Audio Input 2", "fake_audio_input_2",
result.emplace_back(media::AudioDeviceDescription::kDefaultDeviceId,
"Fake Default Audio Input",
"fake_group_audio_input_default");
result.emplace_back("fake_audio_input_1", "Fake Audio Input 1",
"fake_group_audio_input_1");
result.emplace_back("fake_audio_input_2", "Fake Audio Input 2",
"fake_group_audio_input_2");
} else {
result.emplace_back("Fake Default Audio Output",
media::AudioDeviceDescription::kDefaultDeviceId,
"fake_group_audio_1");
result.emplace_back("Fake Audio Output 1", "fake_audio_output_1",
"fake_group_audio_1");
result.emplace_back("Fake Audio Output 2", "fake_audio_output_2",
result.emplace_back(media::AudioDeviceDescription::kDefaultDeviceId,
"Fake Default Audio Output",
"fake_group_audio_output_default");
result.emplace_back("fake_audio_output_1", "Fake Audio Output 1",
"fake_group_audio_output_1");
result.emplace_back("fake_audio_output_2", "Fake Audio Output 2",
"fake_group_audio_output_2");
}

Expand Down Expand Up @@ -339,7 +339,7 @@ void MediaDevicesManager::EnumerateAudioDevices(bool is_input) {
is_input ? MEDIA_DEVICE_TYPE_AUDIO_INPUT : MEDIA_DEVICE_TYPE_AUDIO_OUTPUT;
if (use_fake_devices_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&MediaDevicesManager::AudioDevicesEnumerated,
FROM_HERE, base::BindOnce(&MediaDevicesManager::DevicesEnumerated,
weak_factory_.GetWeakPtr(), type,
GetFakeAudioDevices(is_input)));
return;
Expand All @@ -365,56 +365,10 @@ void MediaDevicesManager::AudioDevicesEnumerated(
media::AudioDeviceDescriptions device_descriptions) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);

auto it_default_device =
std::find_if(device_descriptions.begin(), device_descriptions.end(),
[](const media::AudioDeviceDescription& description) {
return media::AudioDeviceDescription::IsDefaultDevice(
description.unique_id);
});

auto it_real_default_device = device_descriptions.end();
if (it_default_device != device_descriptions.end()) {
// Find the real device that maps to the default device by finding
// coincidence in the group ID.
// This approach works only when the following is true:
// * group ID is properly supported so that the default device has the
// same group ID as some real device.
// * For input devices, the default device has an associated output device.
// * There is only one device with the same group ID of the default device.
// TODO(guidou): Get the real ID of the default input device from
// media::AudioSystem when the functionality becomes available.
// http://crbug.com/788758
for (auto it = device_descriptions.begin(); it != device_descriptions.end();
++it) {
if (it->group_id == it_default_device->group_id &&
!media::AudioDeviceDescription::IsDefaultDevice(it->unique_id)) {
if (it_real_default_device != device_descriptions.end()) {
// If there is more than one real device with the same group ID as the
// default device, the exact mapping cannot be found.
it_real_default_device = device_descriptions.end();
break;
} else {
it_real_default_device = it;
}
}
}
}

MediaDeviceInfoArray snapshot;
for (const media::AudioDeviceDescription& description : device_descriptions) {
if (it_real_default_device != device_descriptions.end() &&
media::AudioDeviceDescription::IsDefaultDevice(description.unique_id)) {
// TODO(guidou): Make the concatenation of the default and real device
// labels in a properly localized manner. http://crbug.com/788767
snapshot.emplace_back(
description.unique_id,
description.device_name + " - " + it_real_default_device->device_name,
description.group_id);
} else {
snapshot.emplace_back(description);
}
snapshot.emplace_back(description);
}

DevicesEnumerated(type, snapshot);
}

Expand Down
39 changes: 34 additions & 5 deletions media/audio/audio_device_description.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/logging.h"
#include "media/audio/audio_device_description.h"

#include <utility>

#include "base/logging.h"
#include "media/base/localized_strings.h"

namespace media {
Expand All @@ -19,6 +22,12 @@ bool AudioDeviceDescription::IsDefaultDevice(const std::string& device_id) {
device_id == AudioDeviceDescription::kDefaultDeviceId;
}

// static
bool AudioDeviceDescription::IsCommunicationsDevice(
const std::string& device_id) {
return device_id == AudioDeviceDescription::kCommunicationsDeviceId;
}

// static
bool AudioDeviceDescription::IsLoopbackDevice(const std::string& device_id) {
return device_id.compare(kLoopbackInputDeviceId) == 0 ||
Expand Down Expand Up @@ -52,9 +61,29 @@ std::string AudioDeviceDescription::GetCommunicationsDeviceName() {
#endif
}

AudioDeviceDescription::AudioDeviceDescription(const std::string& device_name,
const std::string& unique_id,
const std::string& group_id)
: device_name(device_name), unique_id(unique_id), group_id(group_id) {}
// static
std::string AudioDeviceDescription::GetDefaultDeviceName(
const std::string& real_device_name) {
DCHECK(!real_device_name.empty());
// TODO(guidou): Put the names together in a localized manner.
// http://crbug.com/788767
return GetDefaultDeviceName() + " - " + real_device_name;
}

// static
std::string AudioDeviceDescription::GetCommunicationsDeviceName(
const std::string& real_device_name) {
DCHECK(!real_device_name.empty());
// TODO(guidou): Put the names together in a localized manner.
// http://crbug.com/788767
return GetCommunicationsDeviceName() + " - " + real_device_name;
}

AudioDeviceDescription::AudioDeviceDescription(std::string device_name,
std::string unique_id,
std::string group_id)
: device_name(std::move(device_name)),
unique_id(std::move(unique_id)),
group_id(std::move(group_id)) {}

} // namespace media
18 changes: 15 additions & 3 deletions media/audio/audio_device_description.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ struct MEDIA_EXPORT AudioDeviceDescription {
// Returns true if |device_id| represents the default device.
static bool IsDefaultDevice(const std::string& device_id);

// Returns true if |device_id| represents the communications device.
static bool IsCommunicationsDevice(const std::string& device_id);

// Returns true if |device_id| represents a loopback audio capture device.
static bool IsLoopbackDevice(const std::string& device_id);

Expand All @@ -52,14 +55,23 @@ struct MEDIA_EXPORT AudioDeviceDescription {
// Returns the localized name of the generic "default" device.
static std::string GetDefaultDeviceName();

// Returns a localized version of name of the generic "default" device that
// includes the given |real_device_name|.
static std::string GetDefaultDeviceName(const std::string& real_device_name);

// Returns the localized name of the generic default communications device.
// This device is not supported on all platforms.
static std::string GetCommunicationsDeviceName();

// Returns a localized version of name of the generic communications device
// that includes the given |real_device_name|.
static std::string GetCommunicationsDeviceName(
const std::string& real_device_name);

AudioDeviceDescription(const AudioDeviceDescription& other) = default;
AudioDeviceDescription(const std::string& device_name,
const std::string& unique_id,
const std::string& group_id);
AudioDeviceDescription(std::string device_name,
std::string unique_id,
std::string group_id);

~AudioDeviceDescription() = default;

Expand Down
20 changes: 20 additions & 0 deletions media/audio/audio_device_info_accessor_for_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,24 @@ std::string AudioDeviceInfoAccessorForTests::GetAssociatedOutputDeviceID(
return audio_manager_->GetAssociatedOutputDeviceID(input_device_id);
}

std::string AudioDeviceInfoAccessorForTests::GetDefaultInputDeviceID() {
DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
return audio_manager_->GetDefaultInputDeviceID();
}

std::string AudioDeviceInfoAccessorForTests::GetDefaultOutputDeviceID() {
DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
return audio_manager_->GetDefaultOutputDeviceID();
}

std::string AudioDeviceInfoAccessorForTests::GetCommunicationsInputDeviceID() {
DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
return audio_manager_->GetCommunicationsInputDeviceID();
}

std::string AudioDeviceInfoAccessorForTests::GetCommunicationsOutputDeviceID() {
DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
return audio_manager_->GetCommunicationsOutputDeviceID();
}

} // namespace media
8 changes: 8 additions & 0 deletions media/audio/audio_device_info_accessor_for_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ class AudioDeviceInfoAccessorForTests {

std::string GetAssociatedOutputDeviceID(const std::string& input_device_id);

std::string GetDefaultInputDeviceID();

std::string GetDefaultOutputDeviceID();

std::string GetCommunicationsInputDeviceID();

std::string GetCommunicationsOutputDeviceID();

private:
AudioManager* const audio_manager_;

Expand Down
9 changes: 9 additions & 0 deletions media/audio/audio_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,15 @@ class MEDIA_EXPORT AudioManager {
virtual std::string GetAssociatedOutputDeviceID(
const std::string& input_device_id) = 0;

// These functions return the ID of the default/communications audio
// input/output devices respectively.
// Implementations that do not support this functionality should return an
// empty string.
virtual std::string GetDefaultInputDeviceID() = 0;
virtual std::string GetDefaultOutputDeviceID() = 0;
virtual std::string GetCommunicationsInputDeviceID() = 0;
virtual std::string GetCommunicationsOutputDeviceID() = 0;

private:
friend class AudioSystemHelper;

Expand Down
Loading

0 comments on commit bd7ce60

Please sign in to comment.