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