Log Message
Recover WebRTC codecs in case of GPUProcess crash https://bugs.webkit.org/show_bug.cgi?id=221138
Reviewed by Eric Carlson. Source/WebKit: Make LibWebRTCCodecs listen to GPUProcess crash on creation of LibWebRTCCodec. Set the connection also at the same time. This allows to remove the hop to main thread when creating/releasing encoders and decoders. Everything now happens in the dedicated queue, in particular updating of m_connection, encoder and decoder connections, as well as encoders and decoders maps. When using encoder/decoder connection outside of the dedicated queue, a lock is needed. Update LibWebRTCCodecs use of gpu process when creating a peer connection so that this happens in main thread. In case of process crash, we do some setup in main thread (listening to IPC messages for instance). But most of the work is done in a task run in the dedicated queue. In this task, we set the new IPC connection of all running decoders and encoders. We also send IPC message to recreate encoders and decoders. For that purpose, we store some states in encoders and decoders. Covered by API test. * WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp: (WebKit::formatNameFromWebRTCCodecType): (WebKit::createRemoteDecoder): (WebKit::LibWebRTCCodecs::LibWebRTCCodecs): (WebKit::LibWebRTCCodecs::createDecoder): (WebKit::LibWebRTCCodecs::releaseDecoder): (WebKit::LibWebRTCCodecs::decodeFrame): (WebKit::LibWebRTCCodecs::createEncoder): (WebKit::LibWebRTCCodecs::releaseEncoder): (WebKit::LibWebRTCCodecs::initializeEncoder): (WebKit::LibWebRTCCodecs::encodeFrame): (WebKit::LibWebRTCCodecs::setEncodeRates): (WebKit::LibWebRTCCodecs::gpuProcessConnectionDidClose): (WebKit::LibWebRTCCodecs::setConnection): Deleted. * WebProcess/GPU/webrtc/LibWebRTCCodecs.h: * WebProcess/Network/webrtc/LibWebRTCProvider.cpp: (WebKit::LibWebRTCProvider::createPeerConnection): (WebKit::LibWebRTCProvider::createDecoderFactory): (WebKit::LibWebRTCProvider::createEncoderFactory): Tools: * TestWebKitAPI/Tests/WebKit/GetUserMedia.mm: (TestWebKitAPI::TEST): * TestWebKitAPI/Tests/WebKit/getUserMedia.html:
Modified Paths
- trunk/Source/WebKit/ChangeLog
- trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp
- trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.h
- trunk/Source/WebKit/WebProcess/Network/webrtc/LibWebRTCProvider.cpp
- trunk/Source/WebKit/WebProcess/Network/webrtc/LibWebRTCProvider.h
- trunk/Tools/ChangeLog
- trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMedia.mm
- trunk/Tools/TestWebKitAPI/Tests/WebKit/getUserMedia.html
Diff
Modified: trunk/Source/WebKit/ChangeLog (272201 => 272202)
--- trunk/Source/WebKit/ChangeLog 2021-02-02 10:59:00 UTC (rev 272201)
+++ trunk/Source/WebKit/ChangeLog 2021-02-02 11:00:13 UTC (rev 272202)
@@ -1,5 +1,49 @@
2021-02-02 Youenn Fablet <[email protected]>
+ Recover WebRTC codecs in case of GPUProcess crash
+ https://bugs.webkit.org/show_bug.cgi?id=221138
+
+ Reviewed by Eric Carlson.
+
+ Make LibWebRTCCodecs listen to GPUProcess crash on creation of LibWebRTCCodec.
+ Set the connection also at the same time.
+ This allows to remove the hop to main thread when creating/releasing encoders and decoders.
+ Everything now happens in the dedicated queue, in particular updating of m_connection, encoder and decoder connections,
+ as well as encoders and decoders maps.
+ When using encoder/decoder connection outside of the dedicated queue, a lock is needed.
+
+ Update LibWebRTCCodecs use of gpu process when creating a peer connection so that this happens in main thread.
+
+ In case of process crash, we do some setup in main thread (listening to IPC messages for instance).
+ But most of the work is done in a task run in the dedicated queue.
+ In this task, we set the new IPC connection of all running decoders and encoders.
+ We also send IPC message to recreate encoders and decoders.
+ For that purpose, we store some states in encoders and decoders.
+
+ Covered by API test.
+
+ * WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:
+ (WebKit::formatNameFromWebRTCCodecType):
+ (WebKit::createRemoteDecoder):
+ (WebKit::LibWebRTCCodecs::LibWebRTCCodecs):
+ (WebKit::LibWebRTCCodecs::createDecoder):
+ (WebKit::LibWebRTCCodecs::releaseDecoder):
+ (WebKit::LibWebRTCCodecs::decodeFrame):
+ (WebKit::LibWebRTCCodecs::createEncoder):
+ (WebKit::LibWebRTCCodecs::releaseEncoder):
+ (WebKit::LibWebRTCCodecs::initializeEncoder):
+ (WebKit::LibWebRTCCodecs::encodeFrame):
+ (WebKit::LibWebRTCCodecs::setEncodeRates):
+ (WebKit::LibWebRTCCodecs::gpuProcessConnectionDidClose):
+ (WebKit::LibWebRTCCodecs::setConnection): Deleted.
+ * WebProcess/GPU/webrtc/LibWebRTCCodecs.h:
+ * WebProcess/Network/webrtc/LibWebRTCProvider.cpp:
+ (WebKit::LibWebRTCProvider::createPeerConnection):
+ (WebKit::LibWebRTCProvider::createDecoderFactory):
+ (WebKit::LibWebRTCProvider::createEncoderFactory):
+
+2021-02-02 Youenn Fablet <[email protected]>
+
imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-stop.html is flaky when GPUProcess is enabled
https://bugs.webkit.org/show_bug.cgi?id=221197
Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp (272201 => 272202)
--- trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp 2021-02-02 10:59:00 UTC (rev 272201)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp 2021-02-02 11:00:13 UTC (rev 272202)
@@ -115,6 +115,36 @@
return MediaSample::VideoRotation::None;
}
+static inline String formatNameFromWebRTCCodecType(webrtc::VideoCodecType type)
+{
+ switch (type) {
+ case webrtc::kVideoCodecH264:
+ return "H264"_s;
+ case webrtc::kVideoCodecH265:
+ return "H265"_s;
+ case webrtc::kVideoCodecVP9:
+ return "VP9"_s;
+ default:
+ ASSERT_NOT_REACHED();
+ return "H264";
+ }
+}
+
+static void createRemoteDecoder(LibWebRTCCodecs::Decoder& decoder, IPC::Connection& connection)
+{
+ switch (decoder.type) {
+ case LibWebRTCCodecs::Type::H264:
+ connection.send(Messages::LibWebRTCCodecsProxy::CreateH264Decoder { decoder.identifier }, 0);
+ break;
+ case LibWebRTCCodecs::Type::H265:
+ connection.send(Messages::LibWebRTCCodecsProxy::CreateH265Decoder { decoder.identifier }, 0);
+ break;
+ case LibWebRTCCodecs::Type::VP9:
+ connection.send(Messages::LibWebRTCCodecsProxy::CreateVP9Decoder { decoder.identifier }, 0);
+ break;
+ }
+}
+
static int32_t encodeVideoFrame(webrtc::WebKitVideoEncoder encoder, const webrtc::VideoFrame& frame, bool shouldEncodeAsKeyFrame)
{
return WebProcess::singleton().libWebRTCCodecs().encodeFrame(*static_cast<LibWebRTCCodecs::Encoder*>(encoder), frame, shouldEncodeAsKeyFrame);
@@ -136,6 +166,11 @@
LibWebRTCCodecs::LibWebRTCCodecs()
: m_queue(WorkQueue::create("LibWebRTCCodecs", WorkQueue::Type::Serial, WorkQueue::QOS::UserInteractive))
{
+ auto& gpuConnection = WebProcess::singleton().ensureGPUProcessConnection();
+ gpuConnection.addClient(*this);
+
+ m_connection = makeRef(gpuConnection.connection());
+ m_connection->addThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName(), this);
}
LibWebRTCCodecs::~LibWebRTCCodecs()
@@ -154,13 +189,13 @@
return;
}
+ // Let's create WebProcess libWebRTCCodecs since it may be called from various threads.
+ WebProcess::singleton().libWebRTCCodecs();
+
#if ENABLE(VP9)
- // Let's create WebProcess libWebRTCCodecs since it may be called from various threads.
- auto& codecs = WebProcess::singleton().libWebRTCCodecs();
auto& gpuConnection = WebProcess::singleton().ensureGPUProcessConnection();
-
// FIMXE: We should disable VP9VTB if VP9 hardware decoding is enabled but there is no support for it.
- codecs.setVP9VTBSupport(gpuConnection.isVP9DecoderEnabled() || gpuConnection.isVPSWDecoderEnabled());
+ WebProcess::singleton().libWebRTCCodecs().setVP9VTBSupport(gpuConnection.isVP9DecoderEnabled() || gpuConnection.isVPSWDecoderEnabled());
#endif
webrtc::setVideoDecoderCallbacks(createVideoDecoder, releaseVideoDecoder, decodeVideoFrame, registerDecodeCompleteCallback);
@@ -167,18 +202,6 @@
webrtc::setVideoEncoderCallbacks(createVideoEncoder, releaseVideoEncoder, initializeVideoEncoder, encodeVideoFrame, registerEncodeCompleteCallback, setEncodeRatesCallback);
}
-void LibWebRTCCodecs::setConnection(IPC::Connection& connection)
-{
- if (m_connection.get() == &connection)
- return;
-
- if (m_connection)
- m_connection->removeThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName());
-
- m_connection = &connection;
- m_connection->addThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName(), this);
-}
-
LibWebRTCCodecs::Decoder* LibWebRTCCodecs::createDecoder(Type type)
{
auto decoder = makeUnique<Decoder>();
@@ -186,29 +209,13 @@
decoder->identifier = RTCDecoderIdentifier::generateThreadSafe();
decoder->type = type;
- callOnMainRunLoop([this, decoder = WTFMove(decoder), type]() mutable {
- auto& connection = WebProcess::singleton().ensureGPUProcessConnection().connection();
- setConnection(connection);
+ dispatchToThread([this, decoder = WTFMove(decoder)]() mutable {
+ decoder->connection = m_connection;
+ createRemoteDecoder(*decoder, *m_connection);
- decoder->connection = &connection;
-
- switch (type) {
- case Type::H264:
- decoder->connection->send(Messages::LibWebRTCCodecsProxy::CreateH264Decoder { decoder->identifier }, 0);
- break;
- case Type::H265:
- decoder->connection->send(Messages::LibWebRTCCodecsProxy::CreateH265Decoder { decoder->identifier }, 0);
- break;
- case Type::VP9:
- decoder->connection->send(Messages::LibWebRTCCodecsProxy::CreateVP9Decoder { decoder->identifier }, 0);
- break;
- }
-
- dispatchToThread([this, decoder = WTFMove(decoder)]() mutable {
- auto decoderIdentifier = decoder->identifier;
- ASSERT(!m_decoders.contains(decoderIdentifier));
- m_decoders.add(decoderIdentifier, WTFMove(decoder));
- });
+ auto decoderIdentifier = decoder->identifier;
+ ASSERT(!m_decoders.contains(decoderIdentifier));
+ m_decoders.add(decoderIdentifier, WTFMove(decoder));
});
return result;
}
@@ -218,13 +225,10 @@
LockHolder holder(decoder.decodedImageCallbackLock);
decoder.decodedImageCallback = nullptr;
- callOnMainRunLoop([this, decoderIdentifier = decoder.identifier] {
- dispatchToThread([this, decoderIdentifier] {
- ASSERT(m_decoders.contains(decoderIdentifier));
- m_decoders.remove(decoderIdentifier);
- });
-
- WebProcess::singleton().ensureGPUProcessConnection().connection().send(Messages::LibWebRTCCodecsProxy::ReleaseDecoder { decoderIdentifier }, 0);
+ dispatchToThread([this, decoderIdentifier = decoder.identifier] {
+ ASSERT(m_decoders.contains(decoderIdentifier));
+ if (auto decoder = m_decoders.take(decoderIdentifier))
+ decoder->connection->send(Messages::LibWebRTCCodecsProxy::ReleaseDecoder { decoderIdentifier }, 0);
});
return 0;
}
@@ -231,6 +235,7 @@
int32_t LibWebRTCCodecs::decodeFrame(Decoder& decoder, uint32_t timeStamp, const uint8_t* data, size_t size, uint16_t width, uint16_t height)
{
+ LockHolder holder(m_connectionLock);
if (!decoder.connection || decoder.hasError) {
decoder.hasError = false;
return WEBRTC_VIDEO_CODEC_ERROR;
@@ -325,14 +330,15 @@
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())));
- callOnMainRunLoop([this, encoder = WTFMove(encoder), type, parameters = WTFMove(parameters)]() mutable {
- WebProcess::singleton().ensureGPUProcessConnection().connection().send(Messages::LibWebRTCCodecsProxy::CreateEncoder { encoder->identifier, formatNameFromCodecType(type), parameters, RuntimeEnabledFeatures::sharedFeatures().webRTCH264LowLatencyEncoderEnabled() }, 0);
+ dispatchToThread([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);
+ encoder->parameters = WTFMove(parameters);
- dispatchToThread([this, encoder = WTFMove(encoder)]() mutable {
- auto encoderIdentifier = encoder->identifier;
- ASSERT(!m_encoders.contains(encoderIdentifier));
- m_encoders.add(encoderIdentifier, WTFMove(encoder));
- });
+ auto encoderIdentifier = encoder->identifier;
+ ASSERT(!m_encoders.contains(encoderIdentifier));
+ m_encoders.add(encoderIdentifier, WTFMove(encoder));
});
return result;
}
@@ -342,12 +348,10 @@
LockHolder holder(encoder.encodedImageCallbackLock);
encoder.encodedImageCallback = nullptr;
- callOnMainRunLoop([this, encoderIdentifier = encoder.identifier] {
- dispatchToThread([this, encoderIdentifier] {
- ASSERT(m_encoders.contains(encoderIdentifier));
- m_encoders.remove(encoderIdentifier);
- });
- WebProcess::singleton().ensureGPUProcessConnection().connection().send(Messages::LibWebRTCCodecsProxy::ReleaseEncoder { encoderIdentifier }, 0);
+ dispatchToThread([this, encoderIdentifier = encoder.identifier] {
+ ASSERT(m_encoders.contains(encoderIdentifier));
+ auto encoder = m_encoders.take(encoderIdentifier);
+ encoder->connection->send(Messages::LibWebRTCCodecsProxy::ReleaseEncoder { encoderIdentifier }, 0);
});
return 0;
}
@@ -354,18 +358,10 @@
int32_t LibWebRTCCodecs::initializeEncoder(Encoder& encoder, uint16_t width, uint16_t height, unsigned startBitRate, unsigned maxBitRate, unsigned minBitRate, uint32_t maxFrameRate)
{
- callOnMainRunLoop([this, encoderIdentifier = encoder.identifier, width, height, startBitRate, maxBitRate, minBitRate, maxFrameRate] {
- auto& connection = WebProcess::singleton().ensureGPUProcessConnection().connection();
- setConnection(connection);
-
- connection.send(Messages::LibWebRTCCodecsProxy::InitializeEncoder { encoderIdentifier, width, height, startBitRate, maxBitRate, minBitRate, maxFrameRate }, 0);
-
- dispatchToThread([this, encoderIdentifier, connection = makeRef(connection)]() mutable {
- if (auto* encoder = m_encoders.get(encoderIdentifier)) {
- // We set encoder->connection here so that InitializeEncoder is sent before any EncodeFrame message.
- encoder->connection = WTFMove(connection);
- }
- });
+ dispatchToThread([this, encoderIdentifier = encoder.identifier, width, height, startBitRate, maxBitRate, minBitRate, maxFrameRate]() mutable {
+ auto* encoder = m_encoders.get(encoderIdentifier);
+ encoder->initializationData = EncoderInitializationData { width, height, startBitRate, maxBitRate, minBitRate, maxFrameRate };
+ encoder->connection->send(Messages::LibWebRTCCodecsProxy::InitializeEncoder { encoderIdentifier, width, height, startBitRate, maxBitRate, minBitRate, maxFrameRate }, 0);
});
return 0;
}
@@ -372,6 +368,8 @@
int32_t LibWebRTCCodecs::encodeFrame(Encoder& encoder, const webrtc::VideoFrame& frame, bool shouldEncodeAsKeyFrame)
{
+ LockHolder holder(m_connectionLock);
+
if (!encoder.connection)
return WEBRTC_VIDEO_CODEC_ERROR;
@@ -410,11 +408,14 @@
void LibWebRTCCodecs::registerEncodeFrameCallback(Encoder& encoder, void* encodedImageCallback)
{
LockHolder holder(encoder.encodedImageCallbackLock);
+
encoder.encodedImageCallback = encodedImageCallback;
}
void LibWebRTCCodecs::setEncodeRates(Encoder& encoder, uint32_t bitRate, uint32_t frameRate)
{
+ LockHolder holder(m_connectionLock);
+
if (!encoder.connection) {
callOnMainRunLoop([encoderIdentifier = encoder.identifier, bitRate, frameRate] {
WebProcess::singleton().ensureGPUProcessConnection().connection().send(Messages::LibWebRTCCodecsProxy::SetEncodeRates { encoderIdentifier, bitRate, frameRate }, 0);
@@ -458,6 +459,36 @@
m_queue->dispatch(WTFMove(callback));
}
+void LibWebRTCCodecs::gpuProcessConnectionDidClose(GPUProcessConnection&)
+{
+ LockHolder holder(m_connectionLock);
+
+ if (m_connection)
+ m_connection->removeThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName());
+
+ auto& gpuConnection = WebProcess::singleton().ensureGPUProcessConnection();
+ gpuConnection.addClient(*this);
+ gpuConnection.connection().addThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName(), this);
+
+ dispatchToThread([this, connection = makeRef(gpuConnection.connection())] {
+ // Lock everything so that we can update encoder/decoder connection.
+ LockHolder holder(m_connectionLock);
+
+ m_connection = connection.ptr();
+ // Recreate encoders and initialize them, recreate decoders.
+ for (auto& encoder : m_encoders.values()) {
+ connection->send(Messages::LibWebRTCCodecsProxy::CreateEncoder { encoder->identifier, formatNameFromWebRTCCodecType(encoder->codecType), encoder->parameters, RuntimeEnabledFeatures::sharedFeatures().webRTCH264LowLatencyEncoderEnabled() }, 0);
+ if (encoder->initializationData)
+ connection->send(Messages::LibWebRTCCodecsProxy::InitializeEncoder { encoder->identifier, encoder->initializationData->width, encoder->initializationData->height, encoder->initializationData->startBitRate, encoder->initializationData->maxBitRate, encoder->initializationData->minBitRate, encoder->initializationData->maxFrameRate }, 0);
+ encoder->connection = connection.ptr();
+ }
+ for (auto& decoder : m_decoders.values()) {
+ createRemoteDecoder(*decoder, connection.get());
+ decoder->connection = connection.ptr();
+ }
+ });
}
+}
+
#endif
Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.h (272201 => 272202)
--- trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.h 2021-02-02 10:59:00 UTC (rev 272201)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.h 2021-02-02 11:00:13 UTC (rev 272202)
@@ -29,6 +29,7 @@
#include "Connection.h"
#include "DataReference.h"
+#include "GPUProcessConnection.h"
#include "MessageReceiver.h"
#include "RTCDecoderIdentifier.h"
#include "RTCEncoderIdentifier.h"
@@ -58,7 +59,7 @@
namespace WebKit {
-class LibWebRTCCodecs : public IPC::Connection::ThreadMessageReceiverRefCounted {
+class LibWebRTCCodecs : public IPC::Connection::ThreadMessageReceiverRefCounted, public GPUProcessConnection::Client {
WTF_MAKE_FAST_ALLOCATED;
public:
LibWebRTCCodecs();
@@ -83,11 +84,21 @@
int32_t decodeFrame(Decoder&, uint32_t timeStamp, const uint8_t*, size_t, uint16_t width, uint16_t height);
void registerDecodeFrameCallback(Decoder&, void* decodedImageCallback);
+ struct EncoderInitializationData {
+ uint16_t width;
+ uint16_t height;
+ unsigned startBitRate;
+ unsigned maxBitRate;
+ unsigned minBitRate;
+ uint32_t maxFrameRate;
+ };
struct Encoder {
WTF_MAKE_FAST_ALLOCATED;
public:
RTCEncoderIdentifier identifier;
webrtc::VideoCodecType codecType { webrtc::kVideoCodecGeneric };
+ Vector<std::pair<String, String>> parameters;
+ Optional<EncoderInitializationData> initializationData;
void* encodedImageCallback { nullptr };
Lock encodedImageCallbackLock;
RefPtr<IPC::Connection> connection;
@@ -113,11 +124,12 @@
void completedEncoding(RTCEncoderIdentifier, IPC::DataReference&&, const webrtc::WebKitEncodedFrameInfo&);
RetainPtr<CVPixelBufferRef> convertToBGRA(CVPixelBufferRef);
- void setConnection(IPC::Connection&);
-
// IPC::Connection::ThreadMessageReceiver
void dispatchToThread(Function<void()>&&) final;
+ // GPUProcessConnection::Client
+ void gpuProcessConnectionDidClose(GPUProcessConnection&);
+
private:
HashMap<RTCDecoderIdentifier, std::unique_ptr<Decoder>> m_decoders;
HashSet<RTCDecoderIdentifier> m_decodingErrors;
@@ -124,6 +136,7 @@
HashMap<RTCEncoderIdentifier, std::unique_ptr<Encoder>> m_encoders;
+ Lock m_connectionLock;
RefPtr<IPC::Connection> m_connection;
Ref<WorkQueue> m_queue;
std::unique_ptr<WebCore::ImageTransferSessionVT> m_imageTransferSession;
Modified: trunk/Source/WebKit/WebProcess/Network/webrtc/LibWebRTCProvider.cpp (272201 => 272202)
--- trunk/Source/WebKit/WebProcess/Network/webrtc/LibWebRTCProvider.cpp 2021-02-02 10:59:00 UTC (rev 272201)
+++ trunk/Source/WebKit/WebProcess/Network/webrtc/LibWebRTCProvider.cpp 2021-02-02 11:00:13 UTC (rev 272202)
@@ -52,6 +52,9 @@
rtc::scoped_refptr<webrtc::PeerConnectionInterface> LibWebRTCProvider::createPeerConnection(webrtc::PeerConnectionObserver& observer, rtc::PacketSocketFactory* socketFactory, webrtc::PeerConnectionInterface::RTCConfiguration&& configuration)
{
+#if ENABLE(GPU_PROCESS) && PLATFORM(COCOA) && !PLATFORM(MACCATALYST)
+ LibWebRTCCodecs::setCallbacks(RuntimeEnabledFeatures::sharedFeatures().webRTCPlatformCodecsInGPUProcessEnabled());
+#endif
return WebCore::LibWebRTCProvider::createPeerConnection(observer, WebProcess::singleton().libWebRTCNetwork().monitor(), *socketFactory, WTFMove(configuration), makeUnique<AsyncResolverFactory>());
}
@@ -141,26 +144,6 @@
return makeUnique<RTCSocketFactory>(WTFMove(userAgent));
}
-#if PLATFORM(COCOA)
-
-std::unique_ptr<webrtc::VideoDecoderFactory> LibWebRTCProvider::createDecoderFactory()
-{
-#if ENABLE(GPU_PROCESS) && !PLATFORM(MACCATALYST)
- LibWebRTCCodecs::setCallbacks(RuntimeEnabledFeatures::sharedFeatures().webRTCPlatformCodecsInGPUProcessEnabled());
-#endif
- return LibWebRTCProviderCocoa::createDecoderFactory();
-}
-
-std::unique_ptr<webrtc::VideoEncoderFactory> LibWebRTCProvider::createEncoderFactory()
-{
-#if ENABLE(GPU_PROCESS) && !PLATFORM(MACCATALYST)
- LibWebRTCCodecs::setCallbacks(RuntimeEnabledFeatures::sharedFeatures().webRTCPlatformCodecsInGPUProcessEnabled());
-#endif
- return LibWebRTCProviderCocoa::createEncoderFactory();
-}
-
-#endif
-
} // namespace WebKit
#endif // USE(LIBWEBRTC)
Modified: trunk/Source/WebKit/WebProcess/Network/webrtc/LibWebRTCProvider.h (272201 => 272202)
--- trunk/Source/WebKit/WebProcess/Network/webrtc/LibWebRTCProvider.h 2021-02-02 10:59:00 UTC (rev 272201)
+++ trunk/Source/WebKit/WebProcess/Network/webrtc/LibWebRTCProvider.h 2021-02-02 11:00:13 UTC (rev 272202)
@@ -58,11 +58,6 @@
void registerMDNSName(WebCore::DocumentIdentifier, const String& ipAddress, CompletionHandler<void(MDNSNameOrError&&)>&&) final;
void disableNonLocalhostConnections() final;
void startedNetworkThread() final;
-
-#if PLATFORM(COCOA)
- std::unique_ptr<webrtc::VideoDecoderFactory> createDecoderFactory() final;
- std::unique_ptr<webrtc::VideoEncoderFactory> createEncoderFactory() final;
-#endif
};
#else
using LibWebRTCProvider = WebCore::LibWebRTCProvider;
Modified: trunk/Tools/ChangeLog (272201 => 272202)
--- trunk/Tools/ChangeLog 2021-02-02 10:59:00 UTC (rev 272201)
+++ trunk/Tools/ChangeLog 2021-02-02 11:00:13 UTC (rev 272202)
@@ -1,3 +1,14 @@
+2021-02-02 Youenn Fablet <[email protected]>
+
+ Recover WebRTC codecs in case of GPUProcess crash
+ https://bugs.webkit.org/show_bug.cgi?id=221138
+
+ Reviewed by Eric Carlson.
+
+ * TestWebKitAPI/Tests/WebKit/GetUserMedia.mm:
+ (TestWebKitAPI::TEST):
+ * TestWebKitAPI/Tests/WebKit/getUserMedia.html:
+
2021-02-02 Carlos Garcia Campos <[email protected]>
[GTK][WPE] Migrate WebKitTestServer to libsoup 2.48 API
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMedia.mm (272201 => 272202)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMedia.mm 2021-02-02 10:59:00 UTC (rev 272201)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMedia.mm 2021-02-02 11:00:13 UTC (rev 272202)
@@ -38,6 +38,7 @@
#import <WebKit/WKWebViewConfiguration.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WKWebViewPrivateForTesting.h>
+#import <WebKit/_WKExperimentalFeature.h>
#import <WebKit/_WKInternalDebugFeature.h>
#import <WebKit/_WKProcessPoolConfiguration.h>
#import <wtf/text/StringBuilder.h>
@@ -449,8 +450,84 @@
EXPECT_EQ(gpuProcessPID, [processPool _gpuProcessIdentifier]);
EXPECT_EQ(webViewPID, [webView _webProcessIdentifier]);
}
-#endif
+TEST(WebKit2, CrashGPUProcessWhileCapturingAndCalling)
+{
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ auto preferences = [configuration preferences];
+
+ for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) {
+ if ([feature.key isEqualToString:@"CaptureAudioInGPUProcessEnabled"])
+ [preferences _setEnabled:YES forInternalDebugFeature:feature];
+ if ([feature.key isEqualToString:@"CaptureAudioInUIProcessEnabled"])
+ [preferences _setEnabled:NO forInternalDebugFeature:feature];
+ if ([feature.key isEqualToString:@"CaptureVideoInGPUProcessEnabled"])
+ [preferences _setEnabled:YES forInternalDebugFeature:feature];
+ }
+ for (_WKExperimentalFeature *feature in [WKPreferences _experimentalFeatures]) {
+ if ([feature.key isEqualToString:@"WebRTCPlatformCodecsInGPUProcessEnabled"])
+ [preferences _setEnabled:YES forFeature:feature];
+ }
+
+ preferences._mediaCaptureRequiresSecureConnection = NO;
+ configuration.get()._mediaCaptureEnabled = YES;
+ preferences._mockCaptureDevicesEnabled = YES;
+
+ auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]);
+ [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"];
+
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]);
+
+ auto delegate = adoptNS([[GetUserMediaCaptureUIDelegate alloc] init]);
+ webView.get().UIDelegate = delegate.get();
+
+ [webView loadTestPageNamed:@"getUserMedia"];
+ EXPECT_TRUE(waitUntilCaptureState(webView.get(), _WKMediaCaptureStateActiveCamera));
+
+ done = false;
+ [webView stringByEvaluatingJavaScript:@"captureAudioAndVideo(true)"];
+ TestWebKitAPI::Util::run(&done);
+
+ done = false;
+ [webView stringByEvaluatingJavaScript:@"createConnection()"];
+ TestWebKitAPI::Util::run(&done);
+
+ auto webViewPID = [webView _webProcessIdentifier];
+
+ // The GPU process should get launched.
+ auto* processPool = configuration.get().processPool;
+ unsigned timeout = 0;
+ while (![processPool _gpuProcessIdentifier] && timeout++ < 100)
+ TestWebKitAPI::Util::sleep(0.1);
+
+ EXPECT_NE([processPool _gpuProcessIdentifier], 0);
+ if (![processPool _gpuProcessIdentifier])
+ return;
+ auto gpuProcessPID = [processPool _gpuProcessIdentifier];
+
+ // Kill the GPU Process.
+ kill(gpuProcessPID, 9);
+
+ // GPU Process should get relaunched.
+ timeout = 0;
+ while ((![processPool _gpuProcessIdentifier] || [processPool _gpuProcessIdentifier] == gpuProcessPID) && timeout++ < 100)
+ TestWebKitAPI::Util::sleep(0.1);
+ EXPECT_NE([processPool _gpuProcessIdentifier], 0);
+ EXPECT_NE([processPool _gpuProcessIdentifier], gpuProcessPID);
+ gpuProcessPID = [processPool _gpuProcessIdentifier];
+
+ // Make sure the WebProcess did not crash.
+ EXPECT_EQ(webViewPID, [webView _webProcessIdentifier]);
+
+ done = false;
+ [webView stringByEvaluatingJavaScript:@"checkDecodingVideo()"];
+ TestWebKitAPI::Util::run(&done);
+
+ EXPECT_EQ(gpuProcessPID, [processPool _gpuProcessIdentifier]);
+ EXPECT_EQ(webViewPID, [webView _webProcessIdentifier]);
+}
+#endif // ENABLE(GPU_PROCESS)
+
} // namespace TestWebKitAPI
#endif // ENABLE(MEDIA_STREAM)
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/getUserMedia.html (272201 => 272202)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit/getUserMedia.html 2021-02-02 10:59:00 UTC (rev 272201)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/getUserMedia.html 2021-02-02 11:00:13 UTC (rev 272202)
@@ -93,7 +93,7 @@
}
function checkGetCapabilities() {
- window.webkit.messageHandlers.gum.postMessage(RTCRtpSender.getCapabilities('video') != null ? "PASS" : "FAIL");
+ window.webkit.messageHandlers.gum.postMessage(RTCRtpSender.getCapabilities('video') != null ? "PASS" : "FAIL checkGetCapabilities");
}
function getStats(connection, type, kind)
@@ -134,7 +134,7 @@
if (!counter)
counter = 0;
else if (counter > 100) {
- window.webkit.messageHandlers.gum.postMessage("FAIL");
+ window.webkit.messageHandlers.gum.postMessage("FAIL checkVideoStatus");
return;
}
getStats(pc1, "outbound-rtp", "video").then((stats) => {
@@ -146,11 +146,43 @@
});
}
+ function checkDecodingVideoCounterIncreases(counter, framesDecoded) {
+ if (!counter)
+ counter = 0;
+ getStats(pc2, "inbound-rtp", "video").then((stats) => {
+ if (stats && stats.framesDecoded > framesDecoded) {
+ window.webkit.messageHandlers.gum.postMessage("PASS");
+ return;
+ }
+ if (counter > 100) {
+ window.webkit.messageHandlers.gum.postMessage("FAIL checkDecodingVideoCounterIncreases " + framesDecoded + " " + JSON.stringify(stats));
+ return;
+ }
+ setTimeout(() => checkDecodingVideoCounterIncreases(++counter, framesDecoded), 50);
+ });
+ }
+
+ function checkDecodingVideo(counter) {
+ if (!counter)
+ counter = 0;
+ getStats(pc2, "inbound-rtp", "video").then((stats) => {
+ if (stats && stats.framesDecoded > 0) {
+ checkDecodingVideoCounterIncreases(counter, stats.framesDecoded);
+ return;
+ }
+ if (counter > 100) {
+ window.webkit.messageHandlers.gum.postMessage("FAIL checkDecodingVideo " + JSON.stringify(stats));
+ return;
+ }
+ setTimeout(() => checkDecodingVideo(++counter), 50);
+ });
+ }
+
function checkAudioStatus(counter) {
if (!counter)
counter = 0;
else if (counter > 100) {
- window.webkit.messageHandlers.gum.postMessage("FAIL");
+ window.webkit.messageHandlers.gum.postMessage("FAIL checkAudioStatus");
return;
}
getStats(pc2, "inbound-rtp", "audio").then((stats) => {
_______________________________________________ webkit-changes mailing list [email protected] https://lists.webkit.org/mailman/listinfo/webkit-changes
