Title: [276214] trunk/Source
Revision
276214
Author
[email protected]
Date
2021-04-17 17:10:13 -0700 (Sat, 17 Apr 2021)

Log Message

LibWebRTCCodecs eagerly launches the GPUProcess and always relaunches it on exit
https://bugs.webkit.org/show_bug.cgi?id=224704

Reviewed by Darin Adler.

LibWebRTCCodecs eagerly launches the GPUProcess and always relaunches it on exit. The GPUProcess
should only be (re-)launched when needed. In the case of the LibWebRTCCodecs, it seems it only
needs a GPUProcess connection if it has m_decoders / m_encoders are non-empty.

* WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:
(WebKit::LibWebRTCCodecs::ensureGPUProcessConnectionOnMainThread):
Renamed startListeningForIPC() to ensureGPUProcessConnectionOnMainThread(). Only do the
connection initialization if m_connection is not null.

(WebKit::LibWebRTCCodecs::ensureGPUProcessConnectionAndDispatchToThread):
Version of dispatchToThread() which makes sure that the GPUProcessConnection is initialized
before dispatching. It is used when constructing a decoder / encoder. It sets the
m_needsGPUProcessConnection flag to true to indicate someone needed the connection
(and that we should re-initiate it in case it is severed). If the connection is already
initialized, then it does a simple dispatchToThread(). If the connection is not initialized
yet, then we have to hop to the main thread (if not already on it) to initialize the
GPUProcessConnection.

(WebKit::LibWebRTCCodecs::gpuProcessConnectionMayNoLongerBeNeeded):
Function that gets called on the background thread every time a encoder / decoder is
removed. Its purpose is to set m_needsGPUProcessConnection back to false once we no
longer have any encoder / decoder, so that gpuProcessConnectionDidClose() does not
attempt to relaunch the GPUProcess if it goes away.

LibWebRTCCodecs::setCallbacks():
Check if VP9Support is enabled via PlatformMediaSessionManager instead of from the
GPUProcessConnection. This avoids eagerly launching the GPUProcess. The
GPUProcessConnection constructor gets its VPx support information from
PlatformMediaSessionManager anyway. The WebPage constructor is where the VPx support
information comes from and it updates the VPx flags on the PlatformMediaSessionManager.
The WebPage constructor only updates the VPx flags on the GPUProcessConnection if this
connection already exists to avoid eagerly launching the GPUProcess.

(WebKit::LibWebRTCCodecs::createDecoder):
- Call ensureGPUProcessConnectionAndDispatchToThread() instead of dispatchToThread()
  to make sure we have a GPUProcessConnection before creating the decoder.
- Add a missing locker for m_connectionLock on the background thread since it is using
  m_connection (pre-existing bug).

(WebKit::LibWebRTCCodecs::releaseDecoder):
Call gpuProcessConnectionMayNoLongerBeNeeded() to reset the m_needsGPUProcessConnection
flag to false if necessary.

(WebKit::LibWebRTCCodecs::createEncoder):
- Call ensureGPUProcessConnectionAndDispatchToThread() instead of dispatchToThread()
  to make sure we have a GPUProcessConnection before creating the encoder.

(WebKit::LibWebRTCCodecs::releaseEncoder):
Call gpuProcessConnectionMayNoLongerBeNeeded() to reset the m_needsGPUProcessConnection
flag to false if necessary.

(WebKit::LibWebRTCCodecs::gpuProcessConnectionDidClose):
- Clear m_connection when the GPUProcess connection is severed (note that this does not
  necessarily indicate a crash since the GPUProcess exits when idle and under memory
  pressure).
- Only re-initiate the GPUProcess connection if m_needsGPUProcessConnection is true,
  meaning that we have encoders/decoders. I use this flag instead of checking m_encoders
  & m_decoders since those containers are modified on the background thread and this
  function is called on the main thread.

* WebProcess/GPU/webrtc/LibWebRTCCodecs.h:
(WebKit::LibWebRTCCodecs::create):
- Stop calling startListeningForIPC() on construction as we don't want to launch the GPUProcess
until an encoder / decoder is created.
- Fix a pre-existing issue where the class subclasses ThreadSafeRefCounted (via
  ThreadMessageReceiverRefCounted) and yet was using std::unique_ptr<> instead of
  RefPtr<>.

* WebProcess/WebProcess.h:

Modified Paths

Diff

Modified: trunk/Source/WTF/wtf/Locker.h (276213 => 276214)


--- trunk/Source/WTF/wtf/Locker.h	2021-04-17 23:55:13 UTC (rev 276213)
+++ trunk/Source/WTF/wtf/Locker.h	2021-04-18 00:10:13 UTC (rev 276214)
@@ -83,6 +83,8 @@
         }
         return result;
     }
+
+    T* lockable() { return m_lockable; }
     
     explicit operator bool() const { return !!m_lockable; }
     

Modified: trunk/Source/WebKit/ChangeLog (276213 => 276214)


--- trunk/Source/WebKit/ChangeLog	2021-04-17 23:55:13 UTC (rev 276213)
+++ trunk/Source/WebKit/ChangeLog	2021-04-18 00:10:13 UTC (rev 276214)
@@ -1,5 +1,82 @@
 2021-04-17  Chris Dumez  <[email protected]>
 
+        LibWebRTCCodecs eagerly launches the GPUProcess and always relaunches it on exit
+        https://bugs.webkit.org/show_bug.cgi?id=224704
+
+        Reviewed by Darin Adler.
+
+        LibWebRTCCodecs eagerly launches the GPUProcess and always relaunches it on exit. The GPUProcess
+        should only be (re-)launched when needed. In the case of the LibWebRTCCodecs, it seems it only
+        needs a GPUProcess connection if it has m_decoders / m_encoders are non-empty.
+
+        * WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:
+        (WebKit::LibWebRTCCodecs::ensureGPUProcessConnectionOnMainThread):
+        Renamed startListeningForIPC() to ensureGPUProcessConnectionOnMainThread(). Only do the
+        connection initialization if m_connection is not null.
+
+        (WebKit::LibWebRTCCodecs::ensureGPUProcessConnectionAndDispatchToThread):
+        Version of dispatchToThread() which makes sure that the GPUProcessConnection is initialized
+        before dispatching. It is used when constructing a decoder / encoder. It sets the
+        m_needsGPUProcessConnection flag to true to indicate someone needed the connection
+        (and that we should re-initiate it in case it is severed). If the connection is already
+        initialized, then it does a simple dispatchToThread(). If the connection is not initialized
+        yet, then we have to hop to the main thread (if not already on it) to initialize the
+        GPUProcessConnection.
+
+        (WebKit::LibWebRTCCodecs::gpuProcessConnectionMayNoLongerBeNeeded):
+        Function that gets called on the background thread every time a encoder / decoder is
+        removed. Its purpose is to set m_needsGPUProcessConnection back to false once we no
+        longer have any encoder / decoder, so that gpuProcessConnectionDidClose() does not
+        attempt to relaunch the GPUProcess if it goes away.
+
+        LibWebRTCCodecs::setCallbacks():
+        Check if VP9Support is enabled via PlatformMediaSessionManager instead of from the
+        GPUProcessConnection. This avoids eagerly launching the GPUProcess. The
+        GPUProcessConnection constructor gets its VPx support information from
+        PlatformMediaSessionManager anyway. The WebPage constructor is where the VPx support
+        information comes from and it updates the VPx flags on the PlatformMediaSessionManager.
+        The WebPage constructor only updates the VPx flags on the GPUProcessConnection if this
+        connection already exists to avoid eagerly launching the GPUProcess.
+
+        (WebKit::LibWebRTCCodecs::createDecoder):
+        - Call ensureGPUProcessConnectionAndDispatchToThread() instead of dispatchToThread()
+          to make sure we have a GPUProcessConnection before creating the decoder.
+        - Add a missing locker for m_connectionLock on the background thread since it is using
+          m_connection (pre-existing bug).
+
+        (WebKit::LibWebRTCCodecs::releaseDecoder):
+        Call gpuProcessConnectionMayNoLongerBeNeeded() to reset the m_needsGPUProcessConnection
+        flag to false if necessary.
+
+        (WebKit::LibWebRTCCodecs::createEncoder):
+        - Call ensureGPUProcessConnectionAndDispatchToThread() instead of dispatchToThread()
+          to make sure we have a GPUProcessConnection before creating the encoder.
+
+        (WebKit::LibWebRTCCodecs::releaseEncoder):
+        Call gpuProcessConnectionMayNoLongerBeNeeded() to reset the m_needsGPUProcessConnection
+        flag to false if necessary.
+
+        (WebKit::LibWebRTCCodecs::gpuProcessConnectionDidClose):
+        - Clear m_connection when the GPUProcess connection is severed (note that this does not
+          necessarily indicate a crash since the GPUProcess exits when idle and under memory
+          pressure).
+        - Only re-initiate the GPUProcess connection if m_needsGPUProcessConnection is true,
+          meaning that we have encoders/decoders. I use this flag instead of checking m_encoders
+          & m_decoders since those containers are modified on the background thread and this
+          function is called on the main thread.
+
+        * WebProcess/GPU/webrtc/LibWebRTCCodecs.h:
+        (WebKit::LibWebRTCCodecs::create):
+        - Stop calling startListeningForIPC() on construction as we don't want to launch the GPUProcess
+        until an encoder / decoder is created.
+        - Fix a pre-existing issue where the class subclasses ThreadSafeRefCounted (via
+          ThreadMessageReceiverRefCounted) and yet was using std::unique_ptr<> instead of
+          RefPtr<>.
+
+        * WebProcess/WebProcess.h:
+
+2021-04-17  Chris Dumez  <[email protected]>
+
         RemoteImageDecoderAVFManager should never re-launch the GPUProcess on destruction
         https://bugs.webkit.org/show_bug.cgi?id=224723
 

Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp (276213 => 276214)


--- trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp	2021-04-17 23:55:13 UTC (rev 276213)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp	2021-04-18 00:10:13 UTC (rev 276214)
@@ -34,6 +34,7 @@
 #include "WebCoreArgumentCoders.h"
 #include "WebProcess.h"
 #include <WebCore/LibWebRTCMacros.h>
+#include <WebCore/PlatformMediaSessionManager.h>
 #include <WebCore/RealtimeVideoUtilities.h>
 #include <WebCore/RemoteVideoSample.h>
 #include <WebCore/RuntimeEnabledFeatures.h>
@@ -163,14 +164,23 @@
     WebProcess::singleton().libWebRTCCodecs().setEncodeRates(*static_cast<LibWebRTCCodecs::Encoder*>(encoder), bitRate, frameRate);
 }
 
+Ref<LibWebRTCCodecs> LibWebRTCCodecs::create()
+{
+    return adoptRef(*new LibWebRTCCodecs);
+}
+
 LibWebRTCCodecs::LibWebRTCCodecs()
     : m_queue(WorkQueue::create("LibWebRTCCodecs", WorkQueue::Type::Serial, WorkQueue::QOS::UserInteractive))
 {
 }
 
-void LibWebRTCCodecs::startListeningForIPC()
+void LibWebRTCCodecs::ensureGPUProcessConnectionOnMainThread(Locker<Lock>& locker)
 {
-    ASSERT(!m_connection);
+    ASSERT(isMainRunLoop());
+    ASSERT_UNUSED(locker, locker.lockable() == &m_connectionLock);
+    if (m_connection)
+        return;
+
     auto& gpuConnection = WebProcess::singleton().ensureGPUProcessConnection();
     gpuConnection.addClient(*this);
     m_connection = makeRef(gpuConnection.connection());
@@ -177,6 +187,29 @@
     m_connection->addThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName(), this);
 }
 
+// May be called on any thread.
+void LibWebRTCCodecs::ensureGPUProcessConnectionAndDispatchToThread(Function<void()>&& task)
+{
+    m_needsGPUProcessConnection = true;
+    {
+        auto locker = holdLock(m_connectionLock);
+        if (m_connection)
+            return dispatchToThread(WTFMove(task));
+    }
+    ensureOnMainRunLoop([this, task = WTFMove(task)]() mutable {
+        auto locker = holdLock(m_connectionLock);
+        ensureGPUProcessConnectionOnMainThread(locker);
+        dispatchToThread(WTFMove(task));
+    });
+}
+
+void LibWebRTCCodecs::gpuProcessConnectionMayNoLongerBeNeeded()
+{
+    ASSERT(!isMainRunLoop());
+    if (m_encoders.isEmpty() && m_decoders.isEmpty())
+        m_needsGPUProcessConnection = false;
+}
+
 LibWebRTCCodecs::~LibWebRTCCodecs()
 {
     ASSERT_NOT_REACHED();
@@ -196,9 +229,8 @@
     WebProcess::singleton().libWebRTCCodecs();
 
 #if ENABLE(VP9)
-    auto& gpuConnection = WebProcess::singleton().ensureGPUProcessConnection();
     // FIMXE: We should disable VP9VTB if VP9 hardware decoding is enabled but there is no support for it.
-    WebProcess::singleton().libWebRTCCodecs().setVP9VTBSupport(gpuConnection.isVP9DecoderEnabled() || gpuConnection.isVPSWDecoderEnabled());
+    WebProcess::singleton().libWebRTCCodecs().setVP9VTBSupport(PlatformMediaSessionManager::shouldEnableVP9Decoder() || PlatformMediaSessionManager::shouldEnableVP9SWDecoder());
 #endif
 
     webrtc::setVideoDecoderCallbacks(createVideoDecoder, releaseVideoDecoder, decodeVideoFrame, registerDecodeCompleteCallback);
@@ -212,7 +244,8 @@
     decoder->identifier = RTCDecoderIdentifier::generateThreadSafe();
     decoder->type = type;
 
-    dispatchToThread([this, decoder = WTFMove(decoder)]() mutable {
+    ensureGPUProcessConnectionAndDispatchToThread([this, decoder = WTFMove(decoder)]() mutable {
+        auto locker = holdLock(m_connectionLock);
         decoder->connection = m_connection;
         createRemoteDecoder(*decoder, *m_connection);
 
@@ -228,8 +261,10 @@
     ASSERT(!decoder.decodedImageCallback);
     dispatchToThread([this, decoderIdentifier = decoder.identifier] {
         ASSERT(m_decoders.contains(decoderIdentifier));
-        if (auto decoder = m_decoders.take(decoderIdentifier))
+        if (auto decoder = m_decoders.take(decoderIdentifier)) {
             decoder->connection->send(Messages::LibWebRTCCodecsProxy::ReleaseDecoder { decoderIdentifier }, 0);
+            gpuProcessConnectionMayNoLongerBeNeeded();
+        }
     });
     return 0;
 }
@@ -331,7 +366,7 @@
     for (auto& keyValue : formatParameters)
         parameters.append(std::make_pair(String::fromUTF8(keyValue.first.data(), keyValue.first.length()), String::fromUTF8(keyValue.second.data(), keyValue.second.length())));
 
-    dispatchToThread([this, encoder = WTFMove(encoder), type, parameters = WTFMove(parameters)]() mutable {
+    ensureGPUProcessConnectionAndDispatchToThread([this, encoder = WTFMove(encoder), type, parameters = WTFMove(parameters)]() mutable {
         LockHolder holder(m_connectionLock);
         encoder->connection = m_connection;
         encoder->connection->send(Messages::LibWebRTCCodecsProxy::CreateEncoder { encoder->identifier, formatNameFromCodecType(type), parameters, RuntimeEnabledFeatures::sharedFeatures().webRTCH264LowLatencyEncoderEnabled() }, 0);
@@ -351,6 +386,7 @@
         ASSERT(m_encoders.contains(encoderIdentifier));
         auto encoder = m_encoders.take(encoderIdentifier);
         encoder->connection->send(Messages::LibWebRTCCodecsProxy::ReleaseEncoder { encoderIdentifier }, 0);
+        gpuProcessConnectionMayNoLongerBeNeeded();
     });
     return 0;
 }
@@ -460,15 +496,13 @@
 
 void LibWebRTCCodecs::gpuProcessConnectionDidClose(GPUProcessConnection&)
 {
-    auto& gpuConnection = WebProcess::singleton().ensureGPUProcessConnection();
-    gpuConnection.addClient(*this);
-    {
-        auto lock = holdLock(m_connectionLock);
-        m_connection->removeThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName());
-        m_connection = makeRef(gpuConnection.connection());
-        m_connection->addThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName(), this);
-    }
+    ASSERT(isMainRunLoop());
+    auto locker = holdLock(m_connectionLock);
+    std::exchange(m_connection, nullptr)->removeThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName());
+    if (!m_needsGPUProcessConnection)
+        return;
 
+    ensureGPUProcessConnectionOnMainThread(locker);
     dispatchToThread([this]() {
         // Lock everything so that we can update encoder/decoder connection.
         LockHolder holder(m_connectionLock);

Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.h (276213 => 276214)


--- trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.h	2021-04-17 23:55:13 UTC (rev 276213)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.h	2021-04-18 00:10:13 UTC (rev 276214)
@@ -62,12 +62,7 @@
 class LibWebRTCCodecs : public IPC::Connection::ThreadMessageReceiverRefCounted, public GPUProcessConnection::Client {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    static std::unique_ptr<LibWebRTCCodecs> create()
-    {
-        auto instance = std::unique_ptr<LibWebRTCCodecs>(new LibWebRTCCodecs);
-        instance->startListeningForIPC();
-        return instance;
-    }
+    static Ref<LibWebRTCCodecs> create();
     ~LibWebRTCCodecs();
 
     static void setCallbacks(bool useGPUProcess);
@@ -125,7 +120,9 @@
 
 private:
     LibWebRTCCodecs();
-    void startListeningForIPC();
+    void ensureGPUProcessConnectionAndDispatchToThread(Function<void()>&&);
+    void ensureGPUProcessConnectionOnMainThread(Locker<Lock>&);
+    void gpuProcessConnectionMayNoLongerBeNeeded();
 
     void failedDecoding(RTCDecoderIdentifier);
     void completedDecoding(RTCDecoderIdentifier, uint32_t timeStamp, WebCore::RemoteVideoSample&&);
@@ -144,6 +141,8 @@
 
     HashMap<RTCEncoderIdentifier, std::unique_ptr<Encoder>> m_encoders;
 
+    std::atomic<bool> m_needsGPUProcessConnection;
+
     Lock m_connectionLock;
     RefPtr<IPC::Connection> m_connection;
     Ref<WorkQueue> m_queue;

Modified: trunk/Source/WebKit/WebProcess/WebProcess.h (276213 => 276214)


--- trunk/Source/WebKit/WebProcess/WebProcess.h	2021-04-17 23:55:13 UTC (rev 276213)
+++ trunk/Source/WebKit/WebProcess/WebProcess.h	2021-04-18 00:10:13 UTC (rev 276214)
@@ -621,7 +621,7 @@
 #if ENABLE(GPU_PROCESS)
     RefPtr<GPUProcessConnection> m_gpuProcessConnection;
 #if PLATFORM(COCOA) && USE(LIBWEBRTC)
-    std::unique_ptr<LibWebRTCCodecs> m_libWebRTCCodecs;
+    RefPtr<LibWebRTCCodecs> m_libWebRTCCodecs;
 #endif
 #endif
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to