Diff
Modified: trunk/Source/WebCore/ChangeLog (218745 => 218746)
--- trunk/Source/WebCore/ChangeLog 2017-06-23 12:08:00 UTC (rev 218745)
+++ trunk/Source/WebCore/ChangeLog 2017-06-23 15:40:05 UTC (rev 218746)
@@ -1,3 +1,40 @@
+2017-06-23 Eric Carlson <[email protected]>
+
+ [iOS] Respond to AudioSession interruption and resume
+ https://bugs.webkit.org/show_bug.cgi?id=173718
+ <rdar://problem/32925263>
+
+ Reviewed by Youenn Fablet.
+
+ Tested manually.
+
+ * WebCore.xcodeproj/project.pbxproj: Add CoreAudioCaptureSourceIOS.mm/.h
+
+ * platform/mediastream/RealtimeMediaSource.h: Make createWeakPtr protected so derived classes
+ can use it.
+
+ * platform/mediastream/ios/CoreAudioCaptureSourceIOS.h: Added.
+ * platform/mediastream/ios/CoreAudioCaptureSourceIOS.mm: Added.
+ (-[WebCoreAudioCaptureSourceIOSListener initWithCallback:]):
+ (-[WebCoreAudioCaptureSourceIOSListener invalidate]):
+ (-[WebCoreAudioCaptureSourceIOSListener handleInterruption:]):
+ (-[WebCoreAudioCaptureSourceIOSListener sessionMediaServicesWereReset:]):
+ (WebCore::CoreAudioCaptureSourceIOS::CoreAudioCaptureSourceIOS):
+ (WebCore::CoreAudioCaptureSourceIOS::~CoreAudioCaptureSourceIOS):
+
+ * platform/mediastream/mac/CoreAudioCaptureSource.cpp:
+ (WebCore::CoreAudioSharedUnit::suspended):
+ (WebCore::CoreAudioSharedUnit::setupAudioUnit): Clear m_suspended.
+ (WebCore::CoreAudioSharedUnit::suspend): Don't clear sources or uninitialize the audio unit,
+ suspend is temporary. Set m_suspended.
+ (WebCore::CoreAudioSharedUnit::resume): New, restart the audio unit.
+ (WebCore::CoreAudioCaptureSource::create): Create the correct object.
+ (WebCore::CoreAudioCaptureSource::scheduleReconfiguration): Dispatch to main thread if necessary.
+ (WebCore::CoreAudioCaptureSource::beginInterruption): New, suspend from main thread.
+ (WebCore::CoreAudioCaptureSource::endInterruption): New, resume/reconfigure from main thread.
+ (WebCore::CoreAudioCaptureSource::interrupted):
+ * platform/mediastream/mac/CoreAudioCaptureSource.h:
+
2017-06-23 Zan Dobersek <[email protected]>
[GCrypt] Drop the AES-CFB support
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (218745 => 218746)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-06-23 12:08:00 UTC (rev 218745)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-06-23 15:40:05 UTC (rev 218746)
@@ -261,6 +261,8 @@
07ABEF6E1D8A1C7600F21972 /* MediaDevicesEnumerationRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 07ABEF6D1D8A1C7600F21972 /* MediaDevicesEnumerationRequest.h */; settings = {ATTRIBUTES = (Private, ); }; };
07AC47011952102100EE9723 /* ISOVTTCue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07AC46FF1952102100EE9723 /* ISOVTTCue.cpp */; };
07AC47021952102100EE9723 /* ISOVTTCue.h in Headers */ = {isa = PBXBuildFile; fileRef = 07AC47001952102100EE9723 /* ISOVTTCue.h */; };
+ 07AFF4221EFB144900B545B3 /* CoreAudioCaptureSourceIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 07AFF4201EFB144700B545B3 /* CoreAudioCaptureSourceIOS.h */; };
+ 07AFF4231EFB144900B545B3 /* CoreAudioCaptureSourceIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07AFF4211EFB144700B545B3 /* CoreAudioCaptureSourceIOS.mm */; };
07B0113F1032242200FBDC33 /* AccessibilityMediaControls.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B0113E1032242200FBDC33 /* AccessibilityMediaControls.h */; };
07B0ABCF1032242200FBDC33 /* AccessibilityMathMLElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B0ABCE1032242200FBDC33 /* AccessibilityMathMLElement.h */; };
07B442D6166C70B000556CAD /* InbandTextTrackPrivateAVF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07B442D4166C70B000556CAD /* InbandTextTrackPrivateAVF.cpp */; };
@@ -7687,6 +7689,8 @@
07ABEF6D1D8A1C7600F21972 /* MediaDevicesEnumerationRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaDevicesEnumerationRequest.h; sourceTree = "<group>"; };
07AC46FF1952102100EE9723 /* ISOVTTCue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ISOVTTCue.cpp; sourceTree = "<group>"; };
07AC47001952102100EE9723 /* ISOVTTCue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISOVTTCue.h; sourceTree = "<group>"; };
+ 07AFF4201EFB144700B545B3 /* CoreAudioCaptureSourceIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreAudioCaptureSourceIOS.h; sourceTree = "<group>"; };
+ 07AFF4211EFB144700B545B3 /* CoreAudioCaptureSourceIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CoreAudioCaptureSourceIOS.mm; sourceTree = "<group>"; };
07B0113E1032242200FBDC33 /* AccessibilityMediaControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityMediaControls.h; sourceTree = "<group>"; };
07B0ABCE1032242200FBDC33 /* AccessibilityMathMLElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityMathMLElement.h; sourceTree = "<group>"; };
07B442D4166C70B000556CAD /* InbandTextTrackPrivateAVF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InbandTextTrackPrivateAVF.cpp; sourceTree = "<group>"; };
@@ -24466,6 +24470,8 @@
CDC675241EAEA9D400727C84 /* AVAudioSessionCaptureDevice.mm */,
CDC675211EAEA9B700727C84 /* AVAudioSessionCaptureDeviceManager.h */,
CDC675201EAEA9B700727C84 /* AVAudioSessionCaptureDeviceManager.mm */,
+ 07AFF4201EFB144700B545B3 /* CoreAudioCaptureSourceIOS.h */,
+ 07AFF4211EFB144700B545B3 /* CoreAudioCaptureSourceIOS.mm */,
);
path = ios;
sourceTree = "<group>";
@@ -26908,6 +26914,7 @@
9746AF2114F4DDE6003E7A71 /* Coordinates.h in Headers */,
3F8020351E9E47BF00DEC61D /* CoreAudioCaptureDevice.h in Headers */,
3F8020371E9E47C500DEC61D /* CoreAudioCaptureDeviceManager.h in Headers */,
+ 07AFF4221EFB144900B545B3 /* CoreAudioCaptureSourceIOS.h in Headers */,
CE1252371A15BDBE00864480 /* CoreGraphicsSPI.h in Headers */,
443818001A91B2F8006E04F2 /* CoreMediaSoftLink.h in Headers */,
4449A4051A964B0000B64AD5 /* CoreMediaSPI.h in Headers */,
@@ -31008,6 +31015,7 @@
3F8020361E9E47C300DEC61D /* CoreAudioCaptureDevice.cpp in Sources */,
3F8020381E9E47C900DEC61D /* CoreAudioCaptureDeviceManager.cpp in Sources */,
3FF1FA661E7350FD00C1002F /* CoreAudioCaptureSource.cpp in Sources */,
+ 07AFF4231EFB144900B545B3 /* CoreAudioCaptureSourceIOS.mm in Sources */,
443817FF1A91B2F8006E04F2 /* CoreMediaSoftLink.cpp in Sources */,
CD7D33471C7A16BF00041293 /* CoreVideoSoftLink.cpp in Sources */,
BC5EB9500E82056B00B25965 /* CounterDirectives.cpp in Sources */,
Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (218745 => 218746)
--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h 2017-06-23 12:08:00 UTC (rev 218745)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h 2017-06-23 15:40:05 UTC (rev 218746)
@@ -235,10 +235,10 @@
void videoSampleAvailable(MediaSample&);
void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t);
-
-private:
+
WeakPtr<RealtimeMediaSource> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+private:
virtual void startProducingData() { }
virtual void stopProducingData() { }
Added: trunk/Source/WebCore/platform/mediastream/ios/CoreAudioCaptureSourceIOS.h (0 => 218746)
--- trunk/Source/WebCore/platform/mediastream/ios/CoreAudioCaptureSourceIOS.h (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/ios/CoreAudioCaptureSourceIOS.h 2017-06-23 15:40:05 UTC (rev 218746)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(MEDIA_STREAM) && PLATFORM(IOS)
+
+#include "CoreAudioCaptureSource.h"
+
+OBJC_CLASS WebCoreAudioCaptureSourceIOSListener;
+
+namespace WebCore {
+
+class CoreAudioCaptureSourceIOS final : public CoreAudioCaptureSource {
+private:
+ friend class CoreAudioCaptureSource;
+
+ CoreAudioCaptureSourceIOS(const String& deviceID, const String& label);
+ ~CoreAudioCaptureSourceIOS();
+
+ RetainPtr<WebCoreAudioCaptureSourceIOSListener> m_listener;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
Added: trunk/Source/WebCore/platform/mediastream/ios/CoreAudioCaptureSourceIOS.mm (0 => 218746)
--- trunk/Source/WebCore/platform/mediastream/ios/CoreAudioCaptureSourceIOS.mm (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/ios/CoreAudioCaptureSourceIOS.mm 2017-06-23 15:40:05 UTC (rev 218746)
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CoreAudioCaptureSourceIOS.h"
+
+#if ENABLE(MEDIA_STREAM) && PLATFORM(IOS)
+
+#import "Logging.h"
+#import "SoftLinking.h"
+#import <AVFoundation/AVAudioSession.h>
+#import <wtf/MainThread.h>
+
+typedef AVAudioSession AVAudioSessionType;
+
+SOFT_LINK_FRAMEWORK(AVFoundation)
+SOFT_LINK_CLASS(AVFoundation, AVAudioSession)
+
+SOFT_LINK_POINTER(AVFoundation, AVAudioSessionInterruptionNotification, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVAudioSessionInterruptionTypeKey, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVAudioSessionMediaServicesWereResetNotification, NSString *)
+
+#define AVAudioSession getAVAudioSessionClass()
+#define AVAudioSessionInterruptionNotification getAVAudioSessionInterruptionNotification()
+#define AVAudioSessionInterruptionTypeKey getAVAudioSessionInterruptionTypeKey()
+#define AVAudioSessionMediaServicesWereResetNotification getAVAudioSessionMediaServicesWereResetNotification()
+
+using namespace WebCore;
+
+@interface WebCoreAudioCaptureSourceIOSListener : NSObject {
+ CoreAudioCaptureSourceIOS* _callback;
+}
+
+- (void)invalidate;
+- (void)handleInterruption:(NSNotification*)notification;
+- (void)sessionMediaServicesWereReset:(NSNotification*)notification;
+@end
+
+@implementation WebCoreAudioCaptureSourceIOSListener
+- (id)initWithCallback:(CoreAudioCaptureSourceIOS*)callback
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ _callback = callback;
+
+ NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+ AVAudioSessionType* session = [AVAudioSession sharedInstance];
+
+ [center addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:session];
+ [center addObserver:self selector:@selector(sessionMediaServicesWereReset:) name:AVAudioSessionMediaServicesWereResetNotification object:session];
+
+ return self;
+}
+
+- (void)invalidate
+{
+ _callback = nullptr;
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)handleInterruption:(NSNotification*)notification
+{
+ ASSERT(_callback);
+ if (!_callback)
+ return;
+
+ if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] intValue] == AVAudioSessionInterruptionTypeBegan) {
+ _callback->beginInterruption();
+ return;
+ }
+
+ if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] intValue] == AVAudioSessionInterruptionTypeEnded) {
+ NSError *error = nil;
+ [[AVAudioSession sharedInstance] setActive:YES error:&error];
+
+#if !LOG_DISABLED
+ if (error)
+ LOG(Media, "-[WebCoreAudioCaptureSourceIOSListener handleInterruption] (%p) - error = %s", self, [[error localizedDescription] UTF8String]);
+#endif
+
+ _callback->endInterruption();
+ }
+}
+
+- (void)sessionMediaServicesWereReset:(NSNotification*)notification
+{
+ UNUSED_PARAM(notification);
+ ASSERT(_callback);
+
+ if (!_callback)
+ return;
+
+ // mediaserverd crashed and was relaunched, rebuild everything. See
+ // https://developer.apple.com/library/content/qa/qa1749/_index.html.
+ _callback->scheduleReconfiguration();
+}
+@end
+
+namespace WebCore {
+
+CoreAudioCaptureSourceIOS::CoreAudioCaptureSourceIOS(const String& deviceID, const String& label)
+ : CoreAudioCaptureSource(deviceID, label, 0)
+ , m_listener(adoptNS([[WebCoreAudioCaptureSourceIOSListener alloc] initWithCallback:this]))
+{
+}
+
+CoreAudioCaptureSourceIOS::~CoreAudioCaptureSourceIOS()
+{
+ [m_listener invalidate];
+ m_listener = nullptr;
+}
+
+}
+
+#endif // ENABLE(MEDIA_STREAM) && PLATFORM(IOS)
Modified: trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.cpp (218745 => 218746)
--- trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.cpp 2017-06-23 12:08:00 UTC (rev 218745)
+++ trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.cpp 2017-06-23 15:40:05 UTC (rev 218746)
@@ -35,6 +35,7 @@
#include "AudioSession.h"
#include "CoreAudioCaptureDevice.h"
#include "CoreAudioCaptureDeviceManager.h"
+#include "CoreAudioCaptureSourceIOS.h"
#include "CoreAudioSPI.h"
#include "Logging.h"
#include "MediaTimeAVFoundation.h"
@@ -84,7 +85,10 @@
bool isProducingData() { return m_ioUnitStarted; }
OSStatus suspend();
+ OSStatus resume();
+ bool isSuspended() const { return m_suspended; }
+
OSStatus setupAudioUnit();
void cleanupAudioUnit();
OSStatus reconfigureAudioUnit();
@@ -118,6 +122,9 @@
static OSStatus speakerCallback(void*, AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32, UInt32, AudioBufferList*);
OSStatus provideSpeakerData(AudioUnitRenderActionFlags&, const AudioTimeStamp&, UInt32, UInt32, AudioBufferList*);
+ void startInternal();
+ void stopInternal();
+
Vector<std::reference_wrapper<CoreAudioCaptureSource>> m_clients;
AudioUnit m_ioUnit { nullptr };
@@ -163,6 +170,8 @@
bool m_enableEchoCancellation { true };
double m_volume { 1 };
int m_sampleRate;
+
+ bool m_suspended { false };
};
CoreAudioSharedUnit& CoreAudioSharedUnit::singleton()
@@ -295,6 +304,7 @@
return err;
}
m_ioUnitInitialized = true;
+ m_suspended = false;
uint32_t outputDevice;
if (!defaultOutputDevice(&outputDevice))
@@ -537,6 +547,27 @@
if (m_ioUnitStarted)
return;
+ startInternal();
+}
+
+OSStatus CoreAudioSharedUnit::resume()
+{
+ ASSERT(isMainThread());
+ ASSERT(m_suspended);
+ ASSERT(!m_ioUnitStarted);
+
+ m_suspended = false;
+
+ if (!m_ioUnit)
+ return 0;
+
+ startInternal();
+
+ return 0;
+}
+
+void CoreAudioSharedUnit::startInternal()
+{
OSStatus err;
if (!m_ioUnit) {
err = setupAudioUnit();
@@ -560,10 +591,26 @@
void CoreAudioSharedUnit::stopProducingData()
{
ASSERT(isMainThread());
+ ASSERT(m_producingCount);
- if (--m_producingCount)
+ if (m_producingCount && --m_producingCount)
return;
+ stopInternal();
+}
+
+OSStatus CoreAudioSharedUnit::suspend()
+{
+ ASSERT(isMainThread());
+
+ m_suspended = true;
+ stopInternal();
+
+ return 0;
+}
+
+void CoreAudioSharedUnit::stopInternal()
+{
if (!m_ioUnit || !m_ioUnitStarted)
return;
@@ -576,36 +623,6 @@
m_ioUnitStarted = false;
}
-OSStatus CoreAudioSharedUnit::suspend()
-{
- ASSERT(isMainThread());
-
- m_activeSources.clear();
- m_pendingSources.clear();
-
- if (m_ioUnitStarted) {
- ASSERT(m_ioUnit);
- auto err = AudioOutputUnitStop(m_ioUnit);
- if (err) {
- LOG(Media, "CoreAudioSharedUnit::resume(%p) AudioOutputUnitStop failed with error %d (%.4s)", this, (int)err, (char*)&err);
- return err;
- }
- m_ioUnitStarted = false;
- }
-
- if (m_ioUnitInitialized) {
- ASSERT(m_ioUnit);
- auto err = AudioUnitUninitialize(m_ioUnit);
- if (err) {
- LOG(Media, "CoreAudioSharedUnit::resume(%p) AudioUnitUninitialize failed with error %d (%.4s)", this, (int)err, (char*)&err);
- return err;
- }
- m_ioUnitInitialized = false;
- }
-
- return 0;
-}
-
OSStatus CoreAudioSharedUnit::defaultInputDevice(uint32_t* deviceID)
{
ASSERT(m_ioUnit);
@@ -636,23 +653,19 @@
CaptureSourceOrError CoreAudioCaptureSource::create(const String& deviceID, const MediaConstraints* constraints)
{
- String label;
- uint32_t persistentID = 0;
#if PLATFORM(MAC)
auto device = CoreAudioCaptureDeviceManager::singleton().coreAudioDeviceWithUID(deviceID);
if (!device)
return { };
- label = device->label();
- persistentID = device->deviceID();
+ auto source = adoptRef(*new CoreAudioCaptureSource(deviceID, device->label(), device->deviceID()));
#elif PLATFORM(IOS)
auto device = AVAudioSessionCaptureDeviceManager::singleton().audioSessionDeviceWithUID(deviceID);
if (!device)
return { };
- label = device->label();
+ auto source = adoptRef(*new CoreAudioCaptureSourceIOS(deviceID, device->label()));
#endif
- auto source = adoptRef(*new CoreAudioCaptureSource(deviceID, label, persistentID));
if (constraints) {
auto result = source->applyConstraints(*constraints);
@@ -705,12 +718,25 @@
coreAudioCaptureSourceFactory().setActiveSource(*this);
#endif
- CoreAudioSharedUnit::singleton().startProducingData();
+ auto& unit = CoreAudioSharedUnit::singleton();
+ if (unit.isSuspended()) {
+ m_suspendType = SuspensionType::WhilePlaying;
+ return;
+ }
+
+ unit.startProducingData();
}
void CoreAudioCaptureSource::stopProducingData()
{
- CoreAudioSharedUnit::singleton().stopProducingData();
+ auto& unit = CoreAudioSharedUnit::singleton();
+
+ if (unit.isSuspended()) {
+ m_suspendType = SuspensionType::WhilePaused;
+ return;
+ }
+
+ unit.stopProducingData();
}
const RealtimeMediaSourceCapabilities& CoreAudioCaptureSource::capabilities() const
@@ -784,18 +810,103 @@
void CoreAudioCaptureSource::scheduleReconfiguration()
{
+ if (!isMainThread()) {
+ callOnMainThread([weakThis = createWeakPtr(), this] {
+ if (!weakThis)
+ return;
+
+ scheduleReconfiguration();
+ });
+
+ return;
+ }
+
ASSERT(isMainThread());
auto& unit = CoreAudioSharedUnit::singleton();
- if (!unit.hasAudioUnit() || m_reconfigurationOngoing)
+ if (!unit.hasAudioUnit() || m_reconfigurationState != ReconfigurationState::None)
return;
- m_reconfigurationOngoing = true;
+ m_reconfigurationState = ReconfigurationState::Ongoing;
scheduleDeferredTask([this, &unit] {
+ if (unit.isSuspended()) {
+ m_reconfigurationState = ReconfigurationState::Required;
+ return;
+ }
+
unit.reconfigureAudioUnit();
- m_reconfigurationOngoing = false;
+ m_reconfigurationState = ReconfigurationState::None;
});
}
+void CoreAudioCaptureSource::beginInterruption()
+{
+ if (!isMainThread()) {
+ callOnMainThread([weakThis = createWeakPtr(), this] {
+ if (!weakThis)
+ return;
+
+ beginInterruption();
+ });
+
+ return;
+ }
+
+ ASSERT(isMainThread());
+ auto& unit = CoreAudioSharedUnit::singleton();
+ if (!unit.hasAudioUnit() || unit.isSuspended() || m_suspendPending)
+ return;
+
+ m_suspendPending = true;
+ scheduleDeferredTask([this, &unit] {
+ m_suspendType = unit.isProducingData() ? SuspensionType::WhilePlaying : SuspensionType::WhilePaused;
+ unit.suspend();
+ m_suspendPending = false;
+ });
+}
+
+void CoreAudioCaptureSource::endInterruption()
+{
+ if (!isMainThread()) {
+ callOnMainThread([weakThis = createWeakPtr(), this] {
+ if (!weakThis)
+ return;
+
+ endInterruption();
+ });
+
+ return;
+ }
+
+ ASSERT(isMainThread());
+ auto& unit = CoreAudioSharedUnit::singleton();
+ if (!unit.hasAudioUnit() || !unit.isSuspended() || m_resumePending)
+ return;
+
+ auto type = m_suspendType;
+ m_suspendType = SuspensionType::None;
+ if (type != SuspensionType::WhilePlaying && m_reconfigurationState != ReconfigurationState::Required)
+ return;
+
+ m_resumePending = true;
+ scheduleDeferredTask([this, type, &unit] {
+ if (m_reconfigurationState == ReconfigurationState::Required)
+ unit.reconfigureAudioUnit();
+ if (type == SuspensionType::WhilePlaying)
+ unit.resume();
+ m_reconfigurationState = ReconfigurationState::None;
+ m_resumePending = false;
+ });
+}
+
+bool CoreAudioCaptureSource::interrupted() const
+{
+ auto& unit = CoreAudioSharedUnit::singleton();
+ if (unit.isSuspended())
+ return true;
+
+ return RealtimeMediaSource::interrupted();
+}
+
} // namespace WebCore
#endif // ENABLE(MEDIA_STREAM)
Modified: trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.h (218745 => 218746)
--- trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.h 2017-06-23 12:08:00 UTC (rev 218745)
+++ trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.h 2017-06-23 15:40:05 UTC (rev 218746)
@@ -51,7 +51,7 @@
class CaptureDeviceInfo;
class WebAudioSourceProviderAVFObjC;
-class CoreAudioCaptureSource final : public RealtimeMediaSource {
+class CoreAudioCaptureSource : public RealtimeMediaSource {
public:
static CaptureSourceOrError create(const String& deviceID, const MediaConstraints*);
@@ -68,15 +68,18 @@
CMClockRef timebaseClock();
-private:
+ void beginInterruption();
+ void endInterruption();
+ void scheduleReconfiguration();
+
+protected:
CoreAudioCaptureSource(const String& deviceID, const String& label, uint32_t persistentID);
virtual ~CoreAudioCaptureSource();
+private:
friend class CoreAudioSharedUnit;
friend class CoreAudioCaptureSourceFactory;
- void scheduleReconfiguration();
-
bool isCaptureSource() const final { return true; }
void startProducingData() final;
void stopProducingData() final;
@@ -89,14 +92,22 @@
const RealtimeMediaSourceSettings& settings() const final;
void settingsDidChange() final;
+ bool interrupted() const final;
+
uint32_t m_captureDeviceID { 0 };
- bool m_isSuspended { false };
-
mutable std::optional<RealtimeMediaSourceCapabilities> m_capabilities;
mutable std::optional<RealtimeMediaSourceSettings> m_currentSettings;
- bool m_reconfigurationOngoing { false };
+ enum class SuspensionType { None, WhilePaused, WhilePlaying };
+ SuspensionType m_suspendType { SuspensionType::None };
+
+ enum class ReconfigurationState { None, Required, Ongoing };
+ ReconfigurationState m_reconfigurationState { ReconfigurationState::None };
+
+ bool m_reconfigurationRequired { false };
+ bool m_suspendPending { false };
+ bool m_resumePending { false };
};
} // namespace WebCore