Changeset 246215 in webkit


Ignore:
Timestamp:
Jun 7, 2019 3:12:25 PM (5 years ago)
Author:
youenn@apple.com
Message:

mediaDevices.enumerateDevices() doesn't list the system default audio devices with deviceId as "default"
https://bugs.webkit.org/show_bug.cgi?id=198577
<rdar://problem/51454067>

Reviewed by Eric Carlson.

Make the system default microphone/camera be the first in the list.
This ensures that getUserMedia without constraints will pick these devices.
This also ensures enumerateDevices will show these default devices as first in the list.
Make sure that a default device change will refresh the list.

For CoreAudioCaptureSource, we always add the default system input device in the list of capture devices.

Covered by manual testing.

  • platform/mediastream/mac/AVCaptureDeviceManager.h:
  • platform/mediastream/mac/AVCaptureDeviceManager.mm:

(WebCore::toCaptureDevice):
(WebCore::AVCaptureDeviceManager::isMatchingExistingCaptureDevice):
(WebCore::AVCaptureDeviceManager::refreshCaptureDevices):

  • platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp:

(WebCore::getDefaultDeviceID):
(WebCore::CoreAudioCaptureDeviceManager::refreshAudioCaptureDevices):

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r246212 r246215  
     12019-06-07  Youenn Fablet  <youenn@apple.com>
     2
     3        mediaDevices.enumerateDevices() doesn't list the system default audio devices with deviceId as "default"
     4        https://bugs.webkit.org/show_bug.cgi?id=198577
     5        <rdar://problem/51454067>
     6
     7        Reviewed by Eric Carlson.
     8
     9        Make the system default microphone/camera be the first in the list.
     10        This ensures that getUserMedia without constraints will pick these devices.
     11        This also ensures enumerateDevices will show these default devices as first in the list.
     12        Make sure that a default device change will refresh the list.
     13
     14        For CoreAudioCaptureSource, we always add the default system input device in the list of capture devices.
     15
     16        Covered by manual testing.
     17
     18        * platform/mediastream/mac/AVCaptureDeviceManager.h:
     19        * platform/mediastream/mac/AVCaptureDeviceManager.mm:
     20        (WebCore::toCaptureDevice):
     21        (WebCore::AVCaptureDeviceManager::isMatchingExistingCaptureDevice):
     22        (WebCore::AVCaptureDeviceManager::refreshCaptureDevices):
     23        * platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp:
     24        (WebCore::getDefaultDeviceID):
     25        (WebCore::CoreAudioCaptureDeviceManager::refreshAudioCaptureDevices):
     26
    1272019-06-07  Youenn Fablet  <youenn@apple.com>
    228
  • trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h

    r238145 r246215  
    5252    static AVCaptureDeviceManager& singleton();
    5353
    54     void deviceDisconnected(AVCaptureDevice*);
    55 
    5654    void refreshCaptureDevices();
    5755
     
    6563    Vector<CaptureDevice>& captureDevicesInternal();
    6664    void updateCachedAVCaptureDevices();
     65    bool isMatchingExistingCaptureDevice(AVCaptureDevice*);
    6766
    6867    RetainPtr<WebCoreAVCaptureDeviceManagerObserver> m_objcObserver;
  • trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm

    r244922 r246215  
    123123}
    124124
     125static inline CaptureDevice toCaptureDevice(AVCaptureDevice *device)
     126{
     127    CaptureDevice captureDevice { device.uniqueID, CaptureDevice::DeviceType::Camera, device.localizedName };
     128    captureDevice.setEnabled(deviceIsAvailable(device));
     129    return captureDevice;
     130}
     131
     132bool AVCaptureDeviceManager::isMatchingExistingCaptureDevice(AVCaptureDevice *device)
     133{
     134    auto existingCaptureDevice = captureDeviceFromPersistentID(device.uniqueID);
     135    if (!existingCaptureDevice)
     136        return false;
     137
     138    return deviceIsAvailable(device) == existingCaptureDevice.enabled();
     139}
     140
     141static inline bool isDefaultVideoCaptureDeviceFirst(const Vector<CaptureDevice>& devices, const String& defaultDeviceID)
     142{
     143    if (devices.isEmpty())
     144        return false;
     145    return devices[0].persistentId() == defaultDeviceID;
     146}
     147
    125148void AVCaptureDeviceManager::refreshCaptureDevices()
    126149{
     
    132155    updateCachedAVCaptureDevices();
    133156
    134     bool deviceHasChanged = false;
    135157    auto* currentDevices = [PAL::getAVCaptureDeviceClass() devices];
    136158    Vector<CaptureDevice> deviceList;
     159
     160    auto* defaultVideoDevice = [PAL::getAVCaptureDeviceClass() defaultDeviceWithMediaType: AVMediaTypeVideo];
     161
     162    bool deviceHasChanged = false;
     163    if (defaultVideoDevice) {
     164        deviceList.append(toCaptureDevice(defaultVideoDevice));
     165        deviceHasChanged = !isDefaultVideoCaptureDeviceFirst(captureDevices(), defaultVideoDevice.uniqueID);
     166    }
    137167    for (AVCaptureDevice *platformDevice in currentDevices) {
    138 
    139168        if (![platformDevice hasMediaType:AVMediaTypeVideo] && ![platformDevice hasMediaType:AVMediaTypeMuxed])
    140169            continue;
    141170
    142         CaptureDevice captureDevice(platformDevice.uniqueID, CaptureDevice::DeviceType::Camera, platformDevice.localizedName);
    143         captureDevice.setEnabled(deviceIsAvailable(platformDevice));
    144 
    145         CaptureDevice existingCaptureDevice = captureDeviceFromPersistentID(platformDevice.uniqueID);
    146         if (!existingCaptureDevice || (existingCaptureDevice && existingCaptureDevice.type() == CaptureDevice::DeviceType::Camera && captureDevice.enabled() != existingCaptureDevice.enabled()))
     171        if (!deviceHasChanged && !isMatchingExistingCaptureDevice(platformDevice))
    147172            deviceHasChanged = true;
    148173
    149         deviceList.append(WTFMove(captureDevice));
     174        if (platformDevice.uniqueID == defaultVideoDevice.uniqueID)
     175            continue;
     176
     177        deviceList.append(toCaptureDevice(platformDevice));
    150178    }
    151179
  • trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp

    r239531 r246215  
    103103}
    104104
     105static inline Optional<CoreAudioCaptureDevice> getDefaultCaptureInputDevice()
     106{
     107    AudioObjectPropertyAddress address { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
     108    UInt32 propertySize = sizeof(AudioDeviceID);
     109    AudioDeviceID deviceID = kAudioDeviceUnknown;
     110    auto err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &address, 0, nullptr, &propertySize, &deviceID);
     111
     112    if (err != noErr || deviceID == kAudioDeviceUnknown)
     113        return { };
     114    return CoreAudioCaptureDevice::create(deviceID);
     115}
     116
    105117Vector<CoreAudioCaptureDevice>& CoreAudioCaptureDeviceManager::coreAudioCaptureDevices()
    106118{
     
    129141        auto err = AudioObjectAddPropertyListenerBlock(kAudioObjectSystemObject, &address, dispatch_get_main_queue(), m_listenerBlock);
    130142        if (err)
    131             LOG_ERROR("CoreAudioCaptureDeviceManager::devices(%p) AudioObjectAddPropertyListener returned error %d (%.4s)", this, (int)err, (char*)&err);
     143            LOG_ERROR("CoreAudioCaptureDeviceManager::devices(%p) AudioObjectAddPropertyListener for kAudioHardwarePropertyDevices returned error %d (%.4s)", this, (int)err, (char*)&err);
     144
     145        address = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
     146        err = AudioObjectAddPropertyListenerBlock(kAudioObjectSystemObject, &address, dispatch_get_main_queue(), m_listenerBlock);
     147        if (err)
     148            LOG_ERROR("CoreAudioCaptureDeviceManager::devices(%p) AudioObjectAddPropertyListener for kAudioHardwarePropertyDefaultInputDevice returned error %d (%.4s)", this, (int)err, (char*)&err);
    132149    }
    133150
     
    143160    return WTF::nullopt;
    144161}
    145 
    146162
    147163void CoreAudioCaptureDeviceManager::refreshAudioCaptureDevices(NotifyIfDevicesHaveChanged notify)
     
    163179    }
    164180
     181    auto defaultInputDevice = getDefaultCaptureInputDevice();
    165182    bool haveDeviceChanges = false;
     183    if (defaultInputDevice && !m_coreAudioCaptureDevices.isEmpty() && m_coreAudioCaptureDevices.first().deviceID() != defaultInputDevice->deviceID()) {
     184        m_coreAudioCaptureDevices = Vector<CoreAudioCaptureDevice>::from(WTFMove(*defaultInputDevice));
     185        haveDeviceChanges = true;
     186    }
     187
    166188    for (size_t i = 0; i < deviceCount; i++) {
    167189        AudioObjectID deviceID = deviceIDs[i];
Note: See TracChangeset for help on using the changeset viewer.