7e0867bd7d3d74e9e31e00b6ecb242526d49ca3d
[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 "VideoToolBoxEncoderFactory.h"
33 #include <dlfcn.h>
34 #include <webrtc/api/peerconnectionfactoryproxy.h>
35 #include <webrtc/base/physicalsocketserver.h>
36 #include <webrtc/p2p/client/basicportallocator.h>
37 #include <webrtc/pc/peerconnectionfactory.h>
38 #include <webrtc/sdk/objc/Framework/Classes/VideoToolbox/videocodecfactory.h>
39 #include <wtf/Function.h>
40 #include <wtf/NeverDestroyed.h>
41 #include <wtf/darwin/WeakLinking.h>
42 #endif
43
44 namespace WebCore {
45
46 #if USE(LIBWEBRTC)
47 struct PeerConnectionFactoryAndThreads : public rtc::MessageHandler {
48     std::unique_ptr<LibWebRTCAudioModule> audioDeviceModule;
49     std::unique_ptr<rtc::Thread> networkThread;
50     std::unique_ptr<rtc::Thread> signalingThread;
51     rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory;
52     bool networkThreadWithSocketServer { false };
53     Function<std::unique_ptr<cricket::WebRtcVideoEncoderFactory>()> encoderFactoryGetter;
54     Function<std::unique_ptr<cricket::WebRtcVideoDecoderFactory>()> decoderFactoryGetter;
55
56 private:
57     void OnMessage(rtc::Message*);
58 };
59
60 static inline PeerConnectionFactoryAndThreads& staticFactoryAndThreads()
61 {
62     static NeverDestroyed<PeerConnectionFactoryAndThreads> factoryAndThreads;
63 #if PLATFORM(COCOA)
64     static std::once_flag once;
65     std::call_once(once, [] {
66         factoryAndThreads.get().encoderFactoryGetter = []() -> std::unique_ptr<cricket::WebRtcVideoEncoderFactory> { return std::make_unique<VideoToolboxVideoEncoderFactory>(); };
67         factoryAndThreads.get().decoderFactoryGetter = []() -> std::unique_ptr<cricket::WebRtcVideoDecoderFactory> { return std::make_unique<webrtc::VideoToolboxVideoDecoderFactory>(); };
68     });
69 #endif
70     return factoryAndThreads.get();
71 }
72
73 struct ThreadMessageData : public rtc::MessageData {
74     ThreadMessageData(Function<void()>&& callback)
75         : callback(WTFMove(callback))
76     { }
77     Function<void()> callback;
78 };
79
80 void PeerConnectionFactoryAndThreads::OnMessage(rtc::Message* message)
81 {
82     ASSERT(message->message_id == 1);
83     auto* data = static_cast<ThreadMessageData*>(message->pdata);
84     data->callback();
85     delete data;
86 }
87
88 void LibWebRTCProvider::callOnWebRTCNetworkThread(Function<void()>&& callback)
89 {
90     PeerConnectionFactoryAndThreads& threads = staticFactoryAndThreads();
91     threads.networkThread->Post(RTC_FROM_HERE, &threads, 1, new ThreadMessageData(WTFMove(callback)));
92 }
93
94 void LibWebRTCProvider::callOnWebRTCSignalingThread(Function<void()>&& callback)
95 {
96     PeerConnectionFactoryAndThreads& threads = staticFactoryAndThreads();
97     threads.signalingThread->Post(RTC_FROM_HERE, &threads, 1, new ThreadMessageData(WTFMove(callback)));
98 }
99
100 static void initializePeerConnectionFactoryAndThreads()
101 {
102 #if defined(NDEBUG)
103 #if !LOG_DISABLED || !RELEASE_LOG_DISABLED
104     rtc::LogMessage::LogToDebug(LogWebRTC.state != WTFLogChannelOn ? rtc::LS_NONE : rtc::LS_INFO);
105 #else
106     rtc::LogMessage::LogToDebug(rtc::LS_NONE);
107 #endif
108 #else
109     rtc::LogMessage::LogToDebug(LogWebRTC.state != WTFLogChannelOn ? rtc::LS_WARNING : rtc::LS_INFO);
110 #endif
111     auto& factoryAndThreads = staticFactoryAndThreads();
112
113     ASSERT(!factoryAndThreads.factory);
114
115     factoryAndThreads.networkThread = factoryAndThreads.networkThreadWithSocketServer ? rtc::Thread::CreateWithSocketServer() : rtc::Thread::Create();
116     factoryAndThreads.networkThread->SetName("WebKitWebRTCNetwork", nullptr);
117     bool result = factoryAndThreads.networkThread->Start();
118     ASSERT_UNUSED(result, result);
119
120     factoryAndThreads.signalingThread = rtc::Thread::Create();
121     factoryAndThreads.signalingThread->SetName("WebKitWebRTCSignaling", nullptr);
122     
123     result = factoryAndThreads.signalingThread->Start();
124     ASSERT(result);
125
126     factoryAndThreads.audioDeviceModule = std::make_unique<LibWebRTCAudioModule>();
127
128     std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoderFactory = factoryAndThreads.encoderFactoryGetter ? factoryAndThreads.encoderFactoryGetter() : nullptr;
129     std::unique_ptr<cricket::WebRtcVideoDecoderFactory> decoderFactory = factoryAndThreads.decoderFactoryGetter ? factoryAndThreads.decoderFactoryGetter() : nullptr;
130
131     factoryAndThreads.factory = webrtc::CreatePeerConnectionFactory(factoryAndThreads.networkThread.get(), factoryAndThreads.networkThread.get(), factoryAndThreads.signalingThread.get(), factoryAndThreads.audioDeviceModule.get(), encoderFactory.release(), decoderFactory.release());
132
133     ASSERT(factoryAndThreads.factory);
134 }
135
136 webrtc::PeerConnectionFactoryInterface* LibWebRTCProvider::factory()
137 {
138     if (!webRTCAvailable())
139         return nullptr;
140     if (!staticFactoryAndThreads().factory) {
141         staticFactoryAndThreads().networkThreadWithSocketServer = m_useNetworkThreadWithSocketServer;
142         initializePeerConnectionFactoryAndThreads();
143     }
144     return staticFactoryAndThreads().factory;
145 }
146
147 void LibWebRTCProvider::setDecoderFactoryGetter(Function<std::unique_ptr<cricket::WebRtcVideoDecoderFactory>()>&& getter)
148 {
149     if (!staticFactoryAndThreads().factory)
150         initializePeerConnectionFactoryAndThreads();
151
152     staticFactoryAndThreads().decoderFactoryGetter = WTFMove(getter);
153 }
154
155 void LibWebRTCProvider::setEncoderFactoryGetter(Function<std::unique_ptr<cricket::WebRtcVideoEncoderFactory>()>&& getter)
156 {
157     if (!staticFactoryAndThreads().factory)
158         initializePeerConnectionFactoryAndThreads();
159
160     staticFactoryAndThreads().encoderFactoryGetter = WTFMove(getter);
161 }
162
163 void LibWebRTCProvider::setPeerConnectionFactory(rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>&& factory)
164 {
165     if (!staticFactoryAndThreads().factory)
166         initializePeerConnectionFactoryAndThreads();
167
168     staticFactoryAndThreads().factory = webrtc::PeerConnectionFactoryProxy::Create(staticFactoryAndThreads().signalingThread.get(), WTFMove(factory));
169 }
170
171 static rtc::scoped_refptr<webrtc::PeerConnectionInterface> createActualPeerConnection(webrtc::PeerConnectionObserver& observer, std::unique_ptr<cricket::BasicPortAllocator>&& portAllocator, webrtc::PeerConnectionInterface::RTCConfiguration&& configuration)
172 {
173     ASSERT(staticFactoryAndThreads().factory);
174
175     return staticFactoryAndThreads().factory->CreatePeerConnection(configuration, WTFMove(portAllocator), nullptr, &observer);
176 }
177
178 rtc::scoped_refptr<webrtc::PeerConnectionInterface> LibWebRTCProvider::createPeerConnection(webrtc::PeerConnectionObserver& observer, webrtc::PeerConnectionInterface::RTCConfiguration&& configuration)
179 {
180     // Default WK1 implementation.
181     auto& factoryAndThreads = staticFactoryAndThreads();
182     if (!factoryAndThreads.factory) {
183         staticFactoryAndThreads().networkThreadWithSocketServer = true;
184         initializePeerConnectionFactoryAndThreads();
185     }
186     ASSERT(staticFactoryAndThreads().networkThreadWithSocketServer);
187
188     return createActualPeerConnection(observer, nullptr, WTFMove(configuration));
189 }
190
191 rtc::scoped_refptr<webrtc::PeerConnectionInterface> LibWebRTCProvider::createPeerConnection(webrtc::PeerConnectionObserver& observer, rtc::NetworkManager& networkManager, rtc::PacketSocketFactory& packetSocketFactory, webrtc::PeerConnectionInterface::RTCConfiguration&& configuration)
192 {
193     ASSERT(!staticFactoryAndThreads().networkThreadWithSocketServer);
194
195     auto& factoryAndThreads = staticFactoryAndThreads();
196     if (!factoryAndThreads.factory)
197         initializePeerConnectionFactoryAndThreads();
198
199     std::unique_ptr<cricket::BasicPortAllocator> portAllocator;
200     staticFactoryAndThreads().signalingThread->Invoke<void>(RTC_FROM_HERE, [&]() {
201         auto basicPortAllocator = std::make_unique<cricket::BasicPortAllocator>(&networkManager, &packetSocketFactory);
202         if (!m_enableEnumeratingAllNetworkInterfaces)
203             basicPortAllocator->set_flags(basicPortAllocator->flags() | cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION);
204         portAllocator = WTFMove(basicPortAllocator);
205     });
206
207     return createActualPeerConnection(observer, WTFMove(portAllocator), WTFMove(configuration));
208 }
209
210 #endif // USE(LIBWEBRTC)
211
212 bool LibWebRTCProvider::webRTCAvailable()
213 {
214 #if USE(LIBWEBRTC)
215     return !isNullFunctionPointer(rtc::LogMessage::LogToDebug);
216 #else
217     return true;
218 #endif
219 }
220
221 } // namespace WebCore