Commit 3a1630fd authored by Guido Urdaneta's avatar Guido Urdaneta Committed by Commit Bot

Improve group ID heuristic for video devices

Thanks to recent changes in audio device enumerations, it is possible
that USB audio devices report their vid/pid in enumeration results similarly
to video input devices.

This CL extends the heuristic to guess associations between video and
audio devices by looking at coincidences in the VID/PID, if available.
Also, this CL excludes the default and communications device entries
from the heuristics since they could be incorrectly detected as
duplicates.

Bug: 627793
Change-Id: I870a033c1dff358025c5da7332ac90004f1d7f5a
Reviewed-on: https://chromium-review.googlesource.com/992292
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Reviewed-by: default avatarHarald Alvestrand <hta@chromium.org>
Cr-Commit-Position: refs/heads/master@{#549165}
parent d30308c2
......@@ -95,6 +95,21 @@ std::string VideoLabelWithoutModelID(const std::string& label) {
return label.substr(0, idx - 1);
}
bool LabelHasUSBModel(const std::string& label) {
return label.size() >= 11 && label[label.size() - 11] == '(' &&
label[label.size() - 6] == ':' && label[label.size() - 1] == ')';
}
std::string GetUSBModelFromLabel(const std::string& label) {
DCHECK(LabelHasUSBModel(label));
return label.substr(label.size() - 10, 9);
}
bool IsRealAudioDeviceID(const std::string& device_id) {
return !media::AudioDeviceDescription::IsDefaultDevice(device_id) &&
!media::AudioDeviceDescription::IsCommunicationsDevice(device_id);
}
} // namespace
std::string GuessVideoGroupID(const MediaDeviceInfoArray& audio_infos,
......@@ -106,25 +121,55 @@ std::string GuessVideoGroupID(const MediaDeviceInfoArray& audio_infos,
if (video_label.size() <= 3)
return video_info.device_id;
auto equals_lambda = [&video_label](const MediaDeviceInfo& info) {
return info.label.find(video_label) != std::string::npos;
};
std::function<bool(const MediaDeviceInfo&)>
video_label_is_included_in_audio_label =
[&video_label](const MediaDeviceInfo& audio_info) {
return audio_info.label.find(video_label) != std::string::npos;
};
bool video_has_usb_model = LabelHasUSBModel(video_info.label);
std::string video_usb_model = video_has_usb_model
? GetUSBModelFromLabel(video_info.label)
: std::string();
std::function<bool(const MediaDeviceInfo&)> usb_model_matches =
[video_has_usb_model,
&video_usb_model](const MediaDeviceInfo& audio_info) {
return video_has_usb_model && LabelHasUSBModel(audio_info.label)
? video_usb_model == GetUSBModelFromLabel(audio_info.label)
: false;
};
for (auto* lambda :
{&video_label_is_included_in_audio_label, &usb_model_matches}) {
// The label for the default and communication audio devices may contain the
// same label as the real devices, so they should be ignored when trying to
// find unique matches.
auto real_device_matches = [lambda](const MediaDeviceInfo& audio_info) {
return IsRealAudioDeviceID(audio_info.device_id) && (*lambda)(audio_info);
};
auto it_first = std::find_if(audio_infos.begin(), audio_infos.end(),
real_device_matches);
if (it_first == audio_infos.end())
continue;
auto it_first =
std::find_if(audio_infos.begin(), audio_infos.end(), equals_lambda);
if (it_first == audio_infos.end())
return video_info.device_id;
auto it = it_first;
bool duplicate_found = false;
while ((it = std::find_if(it + 1, audio_infos.end(),
real_device_matches)) != audio_infos.end()) {
// If there is more than one match, it is impossible to know which group
// ID is the correct one. This may occur if multiple devices of the same
// model are installed.
if (it->group_id != it_first->group_id) {
duplicate_found = true;
break;
}
}
auto it = it_first;
while ((it = std::find_if(it + 1, audio_infos.end(), equals_lambda)) !=
audio_infos.end()) {
// If the label appears with more than one group ID, it is impossible to
// know which group ID is the correct one.
if (it->group_id != it_first->group_id)
return video_info.device_id;
if (!duplicate_found)
return it_first->group_id;
}
return it_first->group_id;
return video_info.device_id;
}
struct MediaDevicesManager::EnumerationRequest {
......
......@@ -630,6 +630,10 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
TEST_F(MediaDevicesManagerTest, GuessVideoGroupID) {
MediaDeviceInfoArray audio_devices = {
{media::AudioDeviceDescription::kDefaultDeviceId,
"Default - Unique USB Mic (1234:5678)", "group_1"},
{media::AudioDeviceDescription::kCommunicationsDeviceId,
"communications - Unique USB Mic (1234:5678)", "group_1"},
{"device_id_1", "Microphone (Logitech Webcam C930e)", "group_1"},
{"device_id_2", "HD Pro Webcam C920", "group_2"},
{"device_id_3", "Microsoft® LifeCam Cinema(TM)", "group_3"},
......@@ -641,6 +645,16 @@ TEST_F(MediaDevicesManagerTest, GuessVideoGroupID) {
{"device_id_9", "Repeated dual-mic webcam device", "group_7"},
{"device_id_10", "Repeated dual-mic webcam device", "group_8"},
{"device_id_11", "Repeated dual-mic webcam device", "group_8"},
{"device_id_12", "Unique USB Mic (1234:5678)", "group_1"},
{"device_id_13", "Another Unique USB Mic (5678:9abc)", "group_9"},
{"device_id_14", "Repeated USB Mic (8765:4321)", "group_10"},
{"device_id_15", "Repeated USB Mic (8765:4321)", "group_11"},
// Extra entry for communications device added here just to make sure
// that it is not incorrectly detected as an extra real device. Real
// enumerations contain only the first entry for the communications
// device.
{media::AudioDeviceDescription::kCommunicationsDeviceId,
"communications - Unique USB Mic (1234:5678)", "group_1"},
};
MediaDeviceInfo logitech_video("logitech_video",
......@@ -662,6 +676,14 @@ TEST_F(MediaDevicesManagerTest, GuessVideoGroupID) {
MediaDeviceInfo repeated_dual_mic2_video(
"repeated_dual_mic2_video", "Repeated dual-mic webcam device", "");
MediaDeviceInfo short_label_video("short_label_video", " ()", "");
MediaDeviceInfo unique_usb_video("unique_usb_video",
"Unique USB webcam (1234:5678)", "");
MediaDeviceInfo another_unique_usb_video(
"another_unique_usb_video", "Another Unique USB webcam (5678:9abc)", "");
MediaDeviceInfo repeated_usb1_video("repeated_usb1_video",
"Repeated USB webcam (8765:4321)", "");
MediaDeviceInfo repeated_usb2_video("repeated_usb2_video",
"Repeated USB webcam (8765:4321)", "");
EXPECT_EQ(GuessVideoGroupID(audio_devices, logitech_video), "group_1");
EXPECT_EQ(GuessVideoGroupID(audio_devices, hd_pro_video), "group_2");
......@@ -679,6 +701,13 @@ TEST_F(MediaDevicesManagerTest, GuessVideoGroupID) {
repeated_dual_mic2_video.device_id);
EXPECT_EQ(GuessVideoGroupID(audio_devices, short_label_video),
short_label_video.device_id);
EXPECT_EQ(GuessVideoGroupID(audio_devices, unique_usb_video), "group_1");
EXPECT_EQ(GuessVideoGroupID(audio_devices, another_unique_usb_video),
"group_9");
EXPECT_EQ(GuessVideoGroupID(audio_devices, repeated_usb1_video),
repeated_usb1_video.device_id);
EXPECT_EQ(GuessVideoGroupID(audio_devices, repeated_usb2_video),
repeated_usb2_video.device_id);
}
} // namespace content
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment