Add media stream release logging
[WebKit-https.git] / Source / WebCore / platform / mediastream / libwebrtc / LibWebRTCProvider.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "LibWebRTCProvider.h"
28
29 #if USE(LIBWEBRTC)
30 #include "LibWebRTCAudioModule.h"
31 #include "Logging.h"
32 #include "RTCRtpCapabilities.h"
33 #include <dlfcn.h>
34
35 ALLOW_UNUSED_PARAMETERS_BEGIN
36
37 #include <webrtc/api/asyncresolverfactory.h>
38 #include <webrtc/api/audio_codecs/builtin_audio_decoder_factory.h>
39 #include <webrtc/api/audio_codecs/builtin_audio_encoder_factory.h>
40 #include <webrtc/api/create_peerconnection_factory.h>
41 #include <webrtc/api/peerconnectionfactoryproxy.h>
42 #include <webrtc/modules/audio_processing/include/audio_processing.h>
43 #include <webrtc/p2p/base/basicpacketsocketfactory.h>
44 #include <webrtc/p2p/client/basicportallocator.h>
45 #include <webrtc/pc/peerconnectionfactory.h>
46 #include <webrtc/rtc_base/physicalsocketserver.h>
47
48 ALLOW_UNUSED_PARAMETERS_END
49
50 #include <wtf/Function.h>
51 #include <wtf/NeverDestroyed.h>
52 #endif
53
54 namespace WebCore {
55
56 #if !USE(LIBWEBRTC)
57 UniqueRef<LibWebRTCProvider> LibWebRTCProvider::create()
58 {
59     return makeUniqueRef<LibWebRTCProvider>();
60 }
61
62 bool LibWebRTCProvider::webRTCAvailable()
63 {
64     return false;
65 }
66 #endif
67
68 void LibWebRTCProvider::setActive(bool)
69 {
70 }
71
72 #if USE(LIBWEBRTC)
73 static inline rtc::SocketAddress prepareSocketAddress(const rtc::SocketAddress& address, bool disableNonLocalhostConnections)
74 {
75     auto result = address;
76     if (disableNonLocalhostConnections)
77         result.SetIP("127.0.0.1");
78     return result;
79 }
80
81 class BasicPacketSocketFactory : public rtc::BasicPacketSocketFactory {
82 public:
83     explicit BasicPacketSocketFactory(rtc::Thread& networkThread)
84         : m_socketFactory(makeUniqueRef<rtc::BasicPacketSocketFactory>(&networkThread))
85     {
86     }
87
88     void setDisableNonLocalhostConnections(bool disableNonLocalhostConnections) { m_disableNonLocalhostConnections = disableNonLocalhostConnections; }
89
90     rtc::AsyncPacketSocket* CreateUdpSocket(const rtc::SocketAddress& address, uint16_t minPort, uint16_t maxPort) final
91     {
92         return m_socketFactory->CreateUdpSocket(prepareSocketAddress(address, m_disableNonLocalhostConnections), minPort, maxPort);
93     }
94
95     rtc::AsyncPacketSocket* CreateServerTcpSocket(const rtc::SocketAddress& address, uint16_t minPort, uint16_t maxPort, int options) final
96     {
97         return m_socketFactory->CreateServerTcpSocket(prepareSocketAddress(address, m_disableNonLocalhostConnections), minPort, maxPort, options);
98     }
99
100     rtc::AsyncPacketSocket* CreateClientTcpSocket(const rtc::SocketAddress& localAddress, const rtc::SocketAddress& remoteAddress, const rtc::ProxyInfo& info, const std::string& name, int options)
101     {
102         return m_socketFactory->CreateClientTcpSocket(prepareSocketAddress(localAddress, m_disableNonLocalhostConnections), remoteAddress, info, name, options);
103     }
104
105 private:
106     bool m_disableNonLocalhostConnections { false };
107     UniqueRef<rtc::BasicPacketSocketFactory> m_socketFactory;
108 };
109
110 struct PeerConnectionFactoryAndThreads : public rtc::MessageHandler {
111     std::unique_ptr<rtc::Thread> networkThread;
112     std::unique_ptr<rtc::Thread> signalingThread;
113     bool networkThreadWithSocketServer { false };
114     std::unique_ptr<LibWebRTCAudioModule> audioDeviceModule;
115     std::unique_ptr<rtc::NetworkManager> networkManager;
116     std::unique_ptr<BasicPacketSocketFactory> packetSocketFactory;
117     std::unique_ptr<rtc::RTCCertificateGenerator> certificateGenerator;
118
119 private:
120     void OnMessage(rtc::Message*);
121 };
122
123 static void doReleaseLogging(rtc::LoggingSeverity severity, const char* message)
124 {
125 #if RELEASE_LOG_DISABLED
126     UNUSED_PARAM(severity);
127     UNUSED_PARAM(message);
128 #else
129     if (severity == rtc::LS_ERROR)
130         RELEASE_LOG_ERROR(WebRTC, "LibWebRTC error: %{public}s", message);
131     else
132         RELEASE_LOG(WebRTC, "LibWebRTC message: %{public}s", message);
133 #endif
134 }
135
136 static void setLogging(rtc::LoggingSeverity level)
137 {
138     rtc::LogMessage::SetLogOutput(level, (level == rtc::LS_NONE) ? nullptr : doReleaseLogging);
139 }
140
141 static rtc::LoggingSeverity computeLogLevel()
142 {
143 #if defined(NDEBUG)
144 #if !LOG_DISABLED || !RELEASE_LOG_DISABLED
145     if (LogWebRTC.state != WTFLogChannelOn)
146         return rtc::LS_ERROR;
147
148     switch (LogWebRTC.level) {
149     case WTFLogLevelAlways:
150     case WTFLogLevelError:
151         return rtc::LS_ERROR;
152     case WTFLogLevelWarning:
153         return rtc::LS_WARNING;
154     case WTFLogLevelInfo:
155         return rtc::LS_INFO;
156     case WTFLogLevelDebug:
157         return rtc::LS_VERBOSE;
158     }
159 #else
160     return rtc::LS_NONE;
161 #endif
162 #else
163     return (LogWebRTC.state != WTFLogChannelOn) ? rtc::LS_WARNING : rtc::LS_INFO;
164 #endif
165 }
166
167 static void initializePeerConnectionFactoryAndThreads(PeerConnectionFactoryAndThreads& factoryAndThreads)
168 {
169     ASSERT(!factoryAndThreads.networkThread);
170
171     factoryAndThreads.networkThread = factoryAndThreads.networkThreadWithSocketServer ? rtc::Thread::CreateWithSocketServer() : rtc::Thread::Create();
172     factoryAndThreads.networkThread->SetName("WebKitWebRTCNetwork", nullptr);
173     bool result = factoryAndThreads.networkThread->Start();
174     ASSERT_UNUSED(result, result);
175
176     factoryAndThreads.signalingThread = rtc::Thread::Create();
177     factoryAndThreads.signalingThread->SetName("WebKitWebRTCSignaling", nullptr);
178
179     result = factoryAndThreads.signalingThread->Start();
180     ASSERT(result);
181
182     factoryAndThreads.audioDeviceModule = std::make_unique<LibWebRTCAudioModule>();
183 }
184
185 static inline PeerConnectionFactoryAndThreads& staticFactoryAndThreads()
186 {
187     static NeverDestroyed<PeerConnectionFactoryAndThreads> factoryAndThreads;
188     return factoryAndThreads.get();
189 }
190
191 static inline PeerConnectionFactoryAndThreads& getStaticFactoryAndThreads(bool useNetworkThreadWithSocketServer)
192 {
193     auto& factoryAndThreads = staticFactoryAndThreads();
194
195     ASSERT(!factoryAndThreads.networkThread || factoryAndThreads.networkThreadWithSocketServer == useNetworkThreadWithSocketServer);
196
197     if (!factoryAndThreads.networkThread) {
198         factoryAndThreads.networkThreadWithSocketServer = useNetworkThreadWithSocketServer;
199         initializePeerConnectionFactoryAndThreads(factoryAndThreads);
200     }
201     return factoryAndThreads;
202 }
203
204 struct ThreadMessageData : public rtc::MessageData {
205     ThreadMessageData(Function<void()>&& callback)
206         : callback(WTFMove(callback))
207     { }
208     Function<void()> callback;
209 };
210
211 void PeerConnectionFactoryAndThreads::OnMessage(rtc::Message* message)
212 {
213     ASSERT(message->message_id == 1);
214     auto* data = static_cast<ThreadMessageData*>(message->pdata);
215     data->callback();
216     delete data;
217 }
218
219 void LibWebRTCProvider::callOnWebRTCNetworkThread(Function<void()>&& callback)
220 {
221     PeerConnectionFactoryAndThreads& threads = staticFactoryAndThreads();
222     threads.networkThread->Post(RTC_FROM_HERE, &threads, 1, new ThreadMessageData(WTFMove(callback)));
223 }
224
225 void LibWebRTCProvider::callOnWebRTCSignalingThread(Function<void()>&& callback)
226 {
227     PeerConnectionFactoryAndThreads& threads = staticFactoryAndThreads();
228     threads.signalingThread->Post(RTC_FROM_HERE, &threads, 1, new ThreadMessageData(WTFMove(callback)));
229 }
230
231 void LibWebRTCProvider::setEnableLogging(bool enableLogging)
232 {
233     if (!m_enableLogging)
234         return;
235     m_enableLogging = enableLogging;
236     setLogging(enableLogging ? computeLogLevel() : rtc::LS_NONE);
237 }
238
239 webrtc::PeerConnectionFactoryInterface* LibWebRTCProvider::factory()
240 {
241     if (m_factory)
242         return m_factory.get();
243
244     if (!webRTCAvailable())
245         return nullptr;
246
247     auto& factoryAndThreads = getStaticFactoryAndThreads(m_useNetworkThreadWithSocketServer);
248
249     m_factory = createPeerConnectionFactory(factoryAndThreads.networkThread.get(), factoryAndThreads.networkThread.get(), factoryAndThreads.audioDeviceModule.get());
250
251     return m_factory;
252 }
253
254 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> LibWebRTCProvider::createPeerConnectionFactory(rtc::Thread* networkThread, rtc::Thread* signalingThread, LibWebRTCAudioModule* audioModule)
255 {
256     return webrtc::CreatePeerConnectionFactory(networkThread, networkThread, signalingThread, audioModule, webrtc::CreateBuiltinAudioEncoderFactory(), webrtc::CreateBuiltinAudioDecoderFactory(), createEncoderFactory(), createDecoderFactory(), nullptr, nullptr);
257 }
258
259 std::unique_ptr<webrtc::VideoDecoderFactory> LibWebRTCProvider::createDecoderFactory()
260 {
261     return nullptr;
262 }
263
264 std::unique_ptr<webrtc::VideoEncoderFactory> LibWebRTCProvider::createEncoderFactory()
265 {
266     return nullptr;
267 }
268
269 void LibWebRTCProvider::setPeerConnectionFactory(rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>&& factory)
270 {
271     m_factory = webrtc::PeerConnectionFactoryProxy::Create(getStaticFactoryAndThreads(m_useNetworkThreadWithSocketServer).signalingThread.get(), WTFMove(factory));
272 }
273
274 void LibWebRTCProvider::disableEnumeratingAllNetworkInterfaces()
275 {
276     m_enableEnumeratingAllNetworkInterfaces = false;
277 }
278
279 void LibWebRTCProvider::enableEnumeratingAllNetworkInterfaces()
280 {
281     m_enableEnumeratingAllNetworkInterfaces = true;
282 }
283
284 rtc::scoped_refptr<webrtc::PeerConnectionInterface> LibWebRTCProvider::createPeerConnection(webrtc::PeerConnectionObserver& observer, webrtc::PeerConnectionInterface::RTCConfiguration&& configuration)
285 {
286     // Default WK1 implementation.
287     ASSERT(m_useNetworkThreadWithSocketServer);
288     auto& factoryAndThreads = getStaticFactoryAndThreads(m_useNetworkThreadWithSocketServer);
289
290     if (!factoryAndThreads.networkManager)
291         factoryAndThreads.networkManager = std::make_unique<rtc::BasicNetworkManager>();
292
293     if (!factoryAndThreads.packetSocketFactory)
294         factoryAndThreads.packetSocketFactory = std::make_unique<BasicPacketSocketFactory>(*factoryAndThreads.networkThread);
295     factoryAndThreads.packetSocketFactory->setDisableNonLocalhostConnections(m_disableNonLocalhostConnections);
296
297     return createPeerConnection(observer, *factoryAndThreads.networkManager, *factoryAndThreads.packetSocketFactory, WTFMove(configuration), nullptr);
298 }
299
300 rtc::scoped_refptr<webrtc::PeerConnectionInterface> LibWebRTCProvider::createPeerConnection(webrtc::PeerConnectionObserver& observer, rtc::NetworkManager& networkManager, rtc::PacketSocketFactory& packetSocketFactory, webrtc::PeerConnectionInterface::RTCConfiguration&& configuration, std::unique_ptr<webrtc::AsyncResolverFactory>&& asyncResolveFactory)
301 {
302     auto& factoryAndThreads = getStaticFactoryAndThreads(m_useNetworkThreadWithSocketServer);
303
304     std::unique_ptr<cricket::BasicPortAllocator> portAllocator;
305     factoryAndThreads.signalingThread->Invoke<void>(RTC_FROM_HERE, [&]() {
306         auto basicPortAllocator = std::make_unique<cricket::BasicPortAllocator>(&networkManager, &packetSocketFactory);
307         if (!m_enableEnumeratingAllNetworkInterfaces)
308             basicPortAllocator->set_flags(basicPortAllocator->flags() | cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION);
309         portAllocator = WTFMove(basicPortAllocator);
310     });
311
312     auto* factory = this->factory();
313     if (!factory)
314         return nullptr;
315
316     webrtc::PeerConnectionDependencies dependencies { &observer };
317     dependencies.allocator = WTFMove(portAllocator);
318     dependencies.async_resolver_factory = WTFMove(asyncResolveFactory);
319
320     return m_factory->CreatePeerConnection(configuration, WTFMove(dependencies));
321 }
322
323 rtc::RTCCertificateGenerator& LibWebRTCProvider::certificateGenerator()
324 {
325     auto& factoryAndThreads = getStaticFactoryAndThreads(m_useNetworkThreadWithSocketServer);
326     if (!factoryAndThreads.certificateGenerator)
327         factoryAndThreads.certificateGenerator = std::make_unique<rtc::RTCCertificateGenerator>(factoryAndThreads.signalingThread.get(), factoryAndThreads.networkThread.get());
328
329     return *factoryAndThreads.certificateGenerator;
330 }
331
332 static inline Optional<cricket::MediaType> typeFromKind(const String& kind)
333 {
334     if (kind == "audio"_s)
335         return cricket::MediaType::MEDIA_TYPE_AUDIO;
336     if (kind == "video"_s)
337         return cricket::MediaType::MEDIA_TYPE_VIDEO;
338     return { };
339 }
340
341 static inline String fromStdString(const std::string& value)
342 {
343     return String::fromUTF8(value.data(), value.length());
344 }
345
346 static inline Optional<uint16_t> toChannels(absl::optional<int> numChannels)
347 {
348     if (!numChannels)
349         return { };
350     return static_cast<uint32_t>(*numChannels);
351 }
352
353 static inline RTCRtpCapabilities toRTCRtpCapabilities(const webrtc::RtpCapabilities& rtpCapabilities)
354 {
355     RTCRtpCapabilities capabilities;
356
357     capabilities.codecs.reserveInitialCapacity(rtpCapabilities.codecs.size());
358     for (auto& codec : rtpCapabilities.codecs)
359         capabilities.codecs.uncheckedAppend(RTCRtpCapabilities::CodecCapability { fromStdString(codec.mime_type()), static_cast<uint32_t>(codec.clock_rate ? *codec.clock_rate : 0), toChannels(codec.num_channels), { } });
360
361     capabilities.headerExtensions.reserveInitialCapacity(rtpCapabilities.header_extensions.size());
362     for (auto& header : rtpCapabilities.header_extensions)
363         capabilities.headerExtensions.uncheckedAppend(RTCRtpCapabilities::HeaderExtensionCapability { fromStdString(header.uri) });
364
365     return capabilities;
366 }
367
368 Optional<RTCRtpCapabilities> LibWebRTCProvider::receiverCapabilities(const String& kind)
369 {
370     auto mediaType = typeFromKind(kind);
371     if (!mediaType)
372         return { };
373
374     auto* factory = this->factory();
375     if (!factory)
376         return { };
377
378     return toRTCRtpCapabilities(factory->GetRtpReceiverCapabilities(*mediaType));
379 }
380
381 Optional<RTCRtpCapabilities> LibWebRTCProvider::senderCapabilities(const String& kind)
382 {
383     auto mediaType = typeFromKind(kind);
384     if (!mediaType)
385         return { };
386
387     auto* factory = this->factory();
388     if (!factory)
389         return { };
390
391     return toRTCRtpCapabilities(factory->GetRtpSenderCapabilities(*mediaType));
392 }
393
394 #endif // USE(LIBWEBRTC)
395
396 } // namespace WebCore