Skip to content

Commit

Permalink
[iOS] Respond to AudioSession interruption and resume
Browse files Browse the repository at this point in the history
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:


Canonical link: https://commits.webkit.org/190629@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@218746 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
eric-carlson committed Jun 23, 2017
1 parent dc8c02e commit 222633f
Show file tree
Hide file tree
Showing 7 changed files with 405 additions and 51 deletions.
37 changes: 37 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,40 @@
2017-06-23 Eric Carlson <eric.carlson@apple.com>

[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 <zdobersek@igalia.com>

[GCrypt] Drop the AES-CFB support
Expand Down
8 changes: 8 additions & 0 deletions Source/WebCore/WebCore.xcodeproj/project.pbxproj
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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>"; };
Expand Down Expand Up @@ -24466,6 +24470,8 @@
CDC675241EAEA9D400727C84 /* AVAudioSessionCaptureDevice.mm */,
CDC675211EAEA9B700727C84 /* AVAudioSessionCaptureDeviceManager.h */,
CDC675201EAEA9B700727C84 /* AVAudioSessionCaptureDeviceManager.mm */,
07AFF4201EFB144700B545B3 /* CoreAudioCaptureSourceIOS.h */,
07AFF4211EFB144700B545B3 /* CoreAudioCaptureSourceIOS.mm */,
);
path = ios;
sourceTree = "<group>";
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down
4 changes: 2 additions & 2 deletions Source/WebCore/platform/mediastream/RealtimeMediaSource.h
Expand Up @@ -235,10 +235,10 @@ class WEBCORE_EXPORT RealtimeMediaSource : public RefCounted<RealtimeMediaSource

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() { }

Expand Down
@@ -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)
139 changes: 139 additions & 0 deletions Source/WebCore/platform/mediastream/ios/CoreAudioCaptureSourceIOS.mm
@@ -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)

0 comments on commit 222633f

Please sign in to comment.