Report CoreAudioCaptureSource failure in case shared unit stops working properly
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Jul 2017 17:44:04 +0000 (17:44 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Jul 2017 17:44:04 +0000 (17:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=174494

Patch by Youenn Fablet <youenn@apple.com> on 2017-07-14
Reviewed by Eric Carlson.

Source/WebCore:

Manual test by interrupting an audio capture on Mac.

This patch adds a timer to CoreAudioSharedUnit.
In case the capture callback is not called after one second, the shared unit is said to fail.
Each source is notified that capture is failing.
This will in turn trigger onend track event so that web pages can remedy capture failure.

Timer starts with 10 seconds for audio data to start being captured.
It is then decreased to 2 seconds.

* platform/mediastream/RealtimeMediaSource.cpp:
(WebCore::RealtimeMediaSource::captureFailed):
* platform/mediastream/RealtimeMediaSource.h:
* platform/mediastream/mac/CoreAudioCaptureSource.cpp:
(WebCore::CoreAudioSharedUnit::CoreAudioSharedUnit):
(WebCore::CoreAudioSharedUnit::processMicrophoneSamples):
(WebCore::CoreAudioSharedUnit::startInternal):
(WebCore::CoreAudioSharedUnit::verifyIsCapturing):
(WebCore::CoreAudioSharedUnit::stopInternal):

Source/WebKit:

In case of capture failure, send a CaptureFailure message so that the
correct behavior happens in the Web process.

* UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp:
* WebProcess/cocoa/UserMediaCaptureManager.cpp:
(WebKit::UserMediaCaptureManager::captureFailed):
* WebProcess/cocoa/UserMediaCaptureManager.h:
* WebProcess/cocoa/UserMediaCaptureManager.messages.in:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@219511 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp
Source/WebCore/platform/mediastream/RealtimeMediaSource.h
Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.cpp
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp
Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp
Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.h
Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.messages.in

index d57dbf0..32f8f38 100644 (file)
@@ -1,3 +1,30 @@
+2017-07-14  Youenn Fablet  <youenn@apple.com>
+
+        Report CoreAudioCaptureSource failure in case shared unit stops working properly
+        https://bugs.webkit.org/show_bug.cgi?id=174494
+
+        Reviewed by Eric Carlson.
+
+        Manual test by interrupting an audio capture on Mac.
+
+        This patch adds a timer to CoreAudioSharedUnit.
+        In case the capture callback is not called after one second, the shared unit is said to fail.
+        Each source is notified that capture is failing.
+        This will in turn trigger onend track event so that web pages can remedy capture failure.
+
+        Timer starts with 10 seconds for audio data to start being captured.
+        It is then decreased to 2 seconds.
+
+        * platform/mediastream/RealtimeMediaSource.cpp:
+        (WebCore::RealtimeMediaSource::captureFailed):
+        * platform/mediastream/RealtimeMediaSource.h:
+        * platform/mediastream/mac/CoreAudioCaptureSource.cpp:
+        (WebCore::CoreAudioSharedUnit::CoreAudioSharedUnit):
+        (WebCore::CoreAudioSharedUnit::processMicrophoneSamples):
+        (WebCore::CoreAudioSharedUnit::startInternal):
+        (WebCore::CoreAudioSharedUnit::verifyIsCapturing):
+        (WebCore::CoreAudioSharedUnit::stopInternal):
+
 2017-07-14  Jer Noble  <jer.noble@apple.com>
 
         Adding the 'autoplay' attribute to a media element during a user gesture should remove user gesture restrictions.
index 284ef58..1b75025 100644 (file)
@@ -189,6 +189,7 @@ void RealtimeMediaSource::requestStop(Observer* callingObserver)
 void RealtimeMediaSource::captureFailed()
 {
     m_isProducingData = false;
+    m_captureDidFailed = true;
 
     for (Observer& observer : m_observers)
         observer.sourceStopped();
index fc293a4..1f087f6 100644 (file)
@@ -143,6 +143,8 @@ public:
     bool muted() const { return m_muted; }
     void setMuted(bool);
 
+    bool captureDidFail() const { return m_captureDidFailed; }
+
     virtual bool interrupted() const { return m_interrupted; }
     virtual void setInterrupted(bool, bool);
 
@@ -265,6 +267,7 @@ private:
     bool m_pendingSettingsDidChangeNotification { false };
     bool m_isProducingData { false };
     bool m_interrupted { false };
+    bool m_captureDidFailed { false };
 };
 
 struct CaptureSourceOrError {
index d40be19..0f84765 100644 (file)
@@ -39,6 +39,7 @@
 #include "CoreAudioSPI.h"
 #include "Logging.h"
 #include "MediaTimeAVFoundation.h"
+#include "Timer.h"
 #include "WebAudioSourceProviderAVFObjC.h"
 #include <AudioToolbox/AudioConverter.h>
 #include <AudioUnit/AudioUnit.h>
@@ -125,6 +126,8 @@ private:
     void startInternal();
     void stopInternal();
 
+    void verifyIsCapturing();
+
     Vector<std::reference_wrapper<CoreAudioCaptureSource>> m_clients;
 
     AudioUnit m_ioUnit { nullptr };
@@ -164,9 +167,12 @@ private:
 
     String m_ioUnitName;
     uint64_t m_speakerProcsCalled { 0 };
-    uint64_t m_microphoneProcsCalled { 0 };
 #endif
 
+    uint64_t m_microphoneProcsCalled { 0 };
+    uint64_t m_microphoneProcsCalledLastTime { 0 };
+    Timer m_verifyCapturingTimer;
+
     bool m_enableEchoCancellation { true };
     double m_volume { 1 };
     int m_sampleRate;
@@ -181,6 +187,7 @@ CoreAudioSharedUnit& CoreAudioSharedUnit::singleton()
 }
 
 CoreAudioSharedUnit::CoreAudioSharedUnit()
+    : m_verifyCapturingTimer(*this, &CoreAudioSharedUnit::verifyIsCapturing)
 {
     m_sampleRate = AudioSession::sharedSession().sampleRate();
 }
@@ -443,9 +450,7 @@ OSStatus CoreAudioSharedUnit::speakerCallback(void *inRefCon, AudioUnitRenderAct
 
 OSStatus CoreAudioSharedUnit::processMicrophoneSamples(AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& timeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* /*ioData*/)
 {
-#if !LOG_DISABLED
     ++m_microphoneProcsCalled;
-#endif
 
     // Pull through the vpio unit to our mic buffer.
     m_microphoneSampleBuffer->reset();
@@ -591,6 +596,31 @@ void CoreAudioSharedUnit::startInternal()
     }
 
     m_ioUnitStarted = true;
+
+    m_verifyCapturingTimer.startRepeating(10_s);
+    m_microphoneProcsCalled = 0;
+    m_microphoneProcsCalledLastTime = 0;
+}
+
+void CoreAudioSharedUnit::verifyIsCapturing()
+{
+    if (m_microphoneProcsCalledLastTime != m_microphoneProcsCalled) {
+        m_microphoneProcsCalledLastTime = m_microphoneProcsCalled;
+        if (m_verifyCapturingTimer.repeatInterval() == 10_s)
+            m_verifyCapturingTimer.startRepeating(2_s);
+        return;
+    }
+
+#if !RELEASE_LOG_DISABLED
+    RELEASE_LOG(Media, "CoreAudioSharedUnit::verifyIsCapturing - capture failed\n");
+#endif
+    for (CoreAudioCaptureSource& client : m_clients)
+        client.captureFailed();
+
+    m_producingCount = 0;
+    m_clients.clear();
+    stopInternal();
+    cleanupAudioUnit();
 }
 
 void CoreAudioSharedUnit::stopProducingData()
@@ -616,6 +646,8 @@ OSStatus CoreAudioSharedUnit::suspend()
 
 void CoreAudioSharedUnit::stopInternal()
 {
+    m_verifyCapturingTimer.stop();
+
     if (!m_ioUnit || !m_ioUnitStarted)
         return;
 
index e17c0f7..8ad810f 100644 (file)
@@ -1,3 +1,19 @@
+2017-07-14  Youenn Fablet  <youenn@apple.com>
+
+        Report CoreAudioCaptureSource failure in case shared unit stops working properly
+        https://bugs.webkit.org/show_bug.cgi?id=174494
+
+        Reviewed by Eric Carlson.
+
+        In case of capture failure, send a CaptureFailure message so that the
+        correct behavior happens in the Web process.
+
+        * UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp:
+        * WebProcess/cocoa/UserMediaCaptureManager.cpp:
+        (WebKit::UserMediaCaptureManager::captureFailed):
+        * WebProcess/cocoa/UserMediaCaptureManager.h:
+        * WebProcess/cocoa/UserMediaCaptureManager.messages.in:
+
 2017-07-13  Chris Dumez  <cdumez@apple.com>
 
         Better deal with changes to the ResourceLoadStatisticsStore file on disk
index 093048d..d83ace2 100644 (file)
@@ -65,6 +65,10 @@ public:
     int64_t numberOfFrames() { return m_numberOfFrames; }
 
     void sourceStopped() final {
+        if (m_source->captureDidFail()) {
+            m_manager.process().send(Messages::UserMediaCaptureManager::CaptureFailed(m_id), 0);
+            return;
+        }
         m_manager.process().send(Messages::UserMediaCaptureManager::SourceStopped(m_id), 0);
     }
 
index c3651ab..1e895f8 100644 (file)
@@ -200,6 +200,12 @@ void UserMediaCaptureManager::sourceStopped(uint64_t id)
     m_sources.get(id)->stop();
 }
 
+void UserMediaCaptureManager::captureFailed(uint64_t id)
+{
+    ASSERT(m_sources.contains(id));
+    m_sources.get(id)->captureFailed();
+}
+
 void UserMediaCaptureManager::sourceMutedChanged(uint64_t id, bool muted)
 {
     ASSERT(m_sources.contains(id));
index 11dfc7a..39a4f29 100644 (file)
@@ -62,6 +62,7 @@ private:
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
 
     // Messages::UserMediaCaptureManager
+    void captureFailed(uint64_t id);
     void sourceStopped(uint64_t id);
     void sourceMutedChanged(uint64_t id, bool muted);
     void sourceSettingsChanged(uint64_t id, const WebCore::RealtimeMediaSourceSettings&);
index 616841c..280c415 100644 (file)
@@ -22,6 +22,7 @@
 # THE POSSIBILITY OF SUCH DAMAGE.
 
 messages -> UserMediaCaptureManager {
+    CaptureFailed(uint64_t id)
     SourceStopped(uint64_t id)
     SourceMutedChanged(uint64_t id, bool muted)
     SourceSettingsChanged(uint64_t id, WebCore::RealtimeMediaSourceSettings settings)