Diff
Modified: trunk/Source/WebCore/ChangeLog (211254 => 211255)
--- trunk/Source/WebCore/ChangeLog 2017-01-27 05:36:19 UTC (rev 211254)
+++ trunk/Source/WebCore/ChangeLog 2017-01-27 06:09:41 UTC (rev 211255)
@@ -1,3 +1,71 @@
+2017-01-26 Youenn Fablet <[email protected]>
+
+ [WebRTC] Implement WebRTC PeerConnection backend based on libwebrtc
+ https://bugs.webkit.org/show_bug.cgi?id=167289
+
+ Reviewed by Alex Christensen.
+
+ Introducing an initial implementation of WebRTC peer connection backend based on LibWebRTC.
+ This is done behind a compilation flag which is off by default, until the implementation is ready.
+
+ The backend implements the PeerConnectionBackend API.
+ The implementation is split into LibWebRTCPeerConnectionBackend which contains mostly generic code and
+ passes the real work to LibWebRTCMediaEndpoint.
+ The latter class is implementing the API using LibWebRTC.
+
+ * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp: Added.
+ (WebCore::LibWebRTCMediaEndpoint::LibWebRTCMediaEndpoint):
+ (WebCore::sessionDescriptionType):
+ (WebCore::LibWebRTCMediaEndpoint::doSetLocalDescription):
+ (WebCore::LibWebRTCMediaEndpoint::doSetRemoteDescription):
+ (WebCore::LibWebRTCMediaEndpoint::addPendingIceCandidates):
+ (WebCore::streamId):
+ (WebCore::LibWebRTCMediaEndpoint::doCreateOffer):
+ (WebCore::LibWebRTCMediaEndpoint::doCreateAnswer):
+ (WebCore::LibWebRTCMediaEndpoint::getStats):
+ (WebCore::LibWebRTCMediaEndpoint::StatsCollector::StatsCollector):
+ (WebCore::LibWebRTCMediaEndpoint::StatsCollector::OnStatsDelivered):
+ (WebCore::signalingState):
+ (WebCore::LibWebRTCMediaEndpoint::OnSignalingChange):
+ (WebCore::trackId):
+ (WebCore::createMediaStreamTrack):
+ (WebCore::LibWebRTCMediaEndpoint::addStream):
+ (WebCore::LibWebRTCMediaEndpoint::OnAddStream):
+ (WebCore::LibWebRTCMediaEndpoint::OnRemoveStream):
+ (WebCore::LibWebRTCMediaEndpoint::OnDataChannel):
+ (WebCore::LibWebRTCMediaEndpoint::stop):
+ (WebCore::LibWebRTCMediaEndpoint::OnRenegotiationNeeded):
+ (WebCore::iceConnectionState):
+ (WebCore::LibWebRTCMediaEndpoint::OnIceConnectionChange):
+ (WebCore::LibWebRTCMediaEndpoint::OnIceGatheringChange):
+ (WebCore::LibWebRTCMediaEndpoint::OnIceCandidate):
+ (WebCore::LibWebRTCMediaEndpoint::OnIceCandidatesRemoved):
+ (WebCore::LibWebRTCMediaEndpoint::createSessionDescriptionSucceeded):
+ (WebCore::LibWebRTCMediaEndpoint::createSessionDescriptionFailed):
+ (WebCore::LibWebRTCMediaEndpoint::setLocalSessionDescriptionSucceeded):
+ (WebCore::LibWebRTCMediaEndpoint::setLocalSessionDescriptionFailed):
+ (WebCore::LibWebRTCMediaEndpoint::setRemoteSessionDescriptionSucceeded):
+ (WebCore::LibWebRTCMediaEndpoint::setRemoteSessionDescriptionFailed):
+ * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h: Added.
+ * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp: Added.
+ (WebCore::createLibWebRTCPeerConnectionBackend):
+ (WebCore::libWebRTCProvider):
+ (WebCore::LibWebRTCPeerConnectionBackend::LibWebRTCPeerConnectionBackend):
+ (WebCore::configurationFromMediaEndpointConfiguration):
+ (WebCore::LibWebRTCPeerConnectionBackend::setConfiguration):
+ (WebCore::LibWebRTCPeerConnectionBackend::getStats):
+ (WebCore::LibWebRTCPeerConnectionBackend::doSetLocalDescription):
+ (WebCore::LibWebRTCPeerConnectionBackend::doSetRemoteDescription):
+ (WebCore::LibWebRTCPeerConnectionBackend::doCreateOffer):
+ (WebCore::LibWebRTCPeerConnectionBackend::doCreateAnswer):
+ (WebCore::LibWebRTCPeerConnectionBackend::doStop):
+ (WebCore::LibWebRTCPeerConnectionBackend::doAddIceCandidate):
+ (WebCore::LibWebRTCPeerConnectionBackend::markAsNeedingNegotiation):
+ (WebCore::LibWebRTCPeerConnectionBackend::createReceiver):
+ (WebCore::LibWebRTCPeerConnectionBackend::createDataChannelHandler):
+ * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h: Added.
+ * WebCore.xcodeproj/project.pbxproj:
+
2017-01-26 Chris Dumez <[email protected]>
Crash when navigating back to a page in PacheCache when one of its frames has been removed
Added: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp (0 => 211255)
--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp 2017-01-27 06:09:41 UTC (rev 211255)
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2017 Apple Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LibWebRTCMediaEndpoint.h"
+
+#if USE(LIBWEBRTC)
+
+#include "EventNames.h"
+#include "LibWebRTCPeerConnectionBackend.h"
+#include "LibWebRTCProvider.h"
+#include "LibWebRTCUtils.h"
+#include "MediaStreamEvent.h"
+#include "NotImplemented.h"
+#include "PlatformStrategies.h"
+#include "RTCDataChannel.h"
+#include "RTCDataChannelEvent.h"
+#include "RTCIceCandidate.h"
+#include "RTCPeerConnection.h"
+#include "RTCSessionDescription.h"
+#include "RTCTrackEvent.h"
+#include "RealtimeIncomingAudioSource.h"
+#include "RealtimeIncomingVideoSource.h"
+#include <webrtc/api/peerconnectionfactory.h>
+#include <webrtc/base/physicalsocketserver.h>
+#include <webrtc/p2p/base/basicpacketsocketfactory.h>
+#include <webrtc/p2p/client/basicportallocator.h>
+#include <wtf/MainThread.h>
+
+#include "CoreMediaSoftLink.h"
+
+namespace WebCore {
+
+LibWebRTCMediaEndpoint::LibWebRTCMediaEndpoint(LibWebRTCPeerConnectionBackend& peerConnection, LibWebRTCProvider& client)
+ : m_peerConnectionBackend(peerConnection)
+ , m_backend(client.createPeerConnection(*this))
+ , m_createSessionDescriptionObserver(*this)
+ , m_setLocalSessionDescriptionObserver(*this)
+ , m_setRemoteSessionDescriptionObserver(*this)
+{
+ ASSERT(m_backend);
+}
+
+static inline const char* sessionDescriptionType(RTCSessionDescription::SdpType sdpType)
+{
+ switch (sdpType) {
+ case RTCSessionDescription::SdpType::Offer:
+ return "offer";
+ case RTCSessionDescription::SdpType::Pranswer:
+ return "pranswer";
+ case RTCSessionDescription::SdpType::Answer:
+ return "answer";
+ case RTCSessionDescription::SdpType::Rollback:
+ return "rollback";
+ }
+}
+
+void LibWebRTCMediaEndpoint::doSetLocalDescription(RTCSessionDescription& description)
+{
+ webrtc::SdpParseError error;
+ std::unique_ptr<webrtc::SessionDescriptionInterface> sessionDescription(webrtc::CreateSessionDescription(sessionDescriptionType(description.type()), description.sdp().utf8().data(), &error));
+
+ if (!sessionDescription) {
+ String errorMessage(error.description.data(), error.description.size());
+ m_peerConnectionBackend.setLocalDescriptionFailed(Exception { OperationError, WTFMove(errorMessage) });
+ return;
+ }
+ m_backend->SetLocalDescription(&m_setLocalSessionDescriptionObserver, sessionDescription.release());
+}
+
+void LibWebRTCMediaEndpoint::doSetRemoteDescription(RTCSessionDescription& description)
+{
+ webrtc::SdpParseError error;
+ std::unique_ptr<webrtc::SessionDescriptionInterface> sessionDescription(webrtc::CreateSessionDescription(sessionDescriptionType(description.type()), description.sdp().utf8().data(), &error));
+ if (!sessionDescription) {
+ String errorMessage(error.description.data(), error.description.size());
+ m_peerConnectionBackend.setRemoteDescriptionFailed(Exception { OperationError, WTFMove(errorMessage) });
+ return;
+ }
+ m_backend->SetRemoteDescription(&m_setRemoteSessionDescriptionObserver, sessionDescription.release());
+}
+
+void LibWebRTCMediaEndpoint::addPendingIceCandidates()
+{
+ while (m_pendingCandidates.size())
+ m_backend->AddIceCandidate(m_pendingCandidates.takeLast().release());
+}
+
+static inline std::string streamId(RTCPeerConnection& connection)
+{
+ auto& senders = connection.getSenders();
+ if (senders.size()) {
+ for (RTCRtpSender& sender : senders) {
+ auto* track = sender.track();
+ if (track) {
+ ASSERT(sender.mediaStreamIds().size() == 1);
+ return std::string(sender.mediaStreamIds().first().utf8().data());
+ }
+ }
+ }
+ return "av_label";
+}
+
+void LibWebRTCMediaEndpoint::doCreateOffer()
+{
+ m_isInitiator = true;
+ auto& senders = m_peerConnectionBackend.connection().getSenders();
+ if (senders.size()) {
+ // FIXME: We only support one stream for the moment.
+ auto stream = peerConnectionFactory().CreateLocalMediaStream(streamId(m_peerConnectionBackend.connection()));
+ for (RTCRtpSender& sender : senders) {
+ auto* track = sender.track();
+ if (track) {
+ ASSERT(sender.mediaStreamIds().size() == 1);
+ auto& source = track->source();
+ if (source.type() == RealtimeMediaSource::Audio) {
+ auto trackSource = RealtimeOutgoingAudioSource::create(source);
+ auto rtcTrack = peerConnectionFactory().CreateAudioTrack(track->id().utf8().data(), trackSource.ptr());
+ trackSource->setTrack(rtc::scoped_refptr<webrtc::AudioTrackInterface>(rtcTrack));
+ m_audioSources.append(WTFMove(trackSource));
+ stream->AddTrack(WTFMove(rtcTrack));
+ } else {
+ m_videoSources.append(RealtimeOutgoingVideoSource::create(source));
+ stream->AddTrack(peerConnectionFactory().CreateVideoTrack(track->id().utf8().data(), m_videoSources.last().ptr()));
+ }
+ }
+ }
+ m_backend->AddStream(stream);
+ }
+ m_backend->CreateOffer(&m_createSessionDescriptionObserver, nullptr);
+}
+
+void LibWebRTCMediaEndpoint::doCreateAnswer()
+{
+ m_isInitiator = false;
+
+ auto& senders = m_peerConnectionBackend.connection().getSenders();
+ if (senders.size()) {
+ // FIXME: We only support one stream for the moment.
+ auto stream = peerConnectionFactory().CreateLocalMediaStream(streamId(m_peerConnectionBackend.connection()));
+ for (RTCRtpSender& sender : senders) {
+ auto* track = sender.track();
+ if (track) {
+ ASSERT(sender.mediaStreamIds().size() == 1);
+ auto& source = track->source();
+ if (source.type() == RealtimeMediaSource::Audio) {
+ auto trackSource = RealtimeOutgoingAudioSource::create(source);
+ auto rtcTrack = peerConnectionFactory().CreateAudioTrack(track->id().utf8().data(), trackSource.ptr());
+ trackSource->setTrack(rtc::scoped_refptr<webrtc::AudioTrackInterface>(rtcTrack));
+ m_audioSources.append(WTFMove(trackSource));
+ stream->AddTrack(WTFMove(rtcTrack));
+ } else {
+ m_videoSources.append(RealtimeOutgoingVideoSource::create(source));
+ stream->AddTrack(peerConnectionFactory().CreateVideoTrack(track->id().utf8().data(), m_videoSources.last().ptr()));
+ }
+ }
+ }
+ m_backend->AddStream(stream);
+ }
+ m_backend->CreateAnswer(&m_createSessionDescriptionObserver, nullptr);
+}
+
+void LibWebRTCMediaEndpoint::getStats(MediaStreamTrack* track, PeerConnection::StatsPromise&& promise)
+{
+ auto collector = StatsCollector::create(*this, WTFMove(promise), track);
+ m_backend->GetStats(collector.ptr());
+ m_statsCollectors.append(WTFMove(collector));
+}
+
+LibWebRTCMediaEndpoint::StatsCollector::StatsCollector(LibWebRTCMediaEndpoint& endpoint, PeerConnection::StatsPromise&& promise, MediaStreamTrack* track)
+ : m_endpoint(endpoint)
+ , m_promise(WTFMove(promise))
+{
+ if (track)
+ m_id = track->id();
+}
+
+void LibWebRTCMediaEndpoint::StatsCollector::OnStatsDelivered(const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report)
+{
+ callOnMainThread([this, report, protector = makeRef(m_endpoint)] {
+ // FIXME: Fulfill promise with the report
+ UNUSED_PARAM(report);
+ m_promise.reject(TypeError, ASCIILiteral("Stats API is not yet implemented"));
+
+ m_endpoint.m_statsCollectors.removeFirstMatching([this](const Ref<StatsCollector>& collector) {
+ return this == collector.ptr();
+ });
+ });
+}
+
+static PeerConnectionStates::SignalingState signalingState(webrtc::PeerConnectionInterface::SignalingState state)
+{
+ switch (state) {
+ case webrtc::PeerConnectionInterface::kStable:
+ return PeerConnectionStates::SignalingState::Stable;
+ case webrtc::PeerConnectionInterface::kHaveLocalOffer:
+ return PeerConnectionStates::SignalingState::HaveLocalOffer;
+ case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer:
+ return PeerConnectionStates::SignalingState::HaveLocalPrAnswer;
+ case webrtc::PeerConnectionInterface::kHaveRemoteOffer:
+ return PeerConnectionStates::SignalingState::HaveRemoteOffer;
+ case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer:
+ return PeerConnectionStates::SignalingState::HaveRemotePrAnswer;
+ case webrtc::PeerConnectionInterface::kClosed:
+ return PeerConnectionStates::SignalingState::Closed;
+ }
+}
+
+void LibWebRTCMediaEndpoint::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState rtcState)
+{
+ auto state = signalingState(rtcState);
+ callOnMainThread([protectedThis = makeRef(*this), state] {
+ if (protectedThis->isStopped())
+ return;
+ protectedThis->m_peerConnectionBackend.updateSignalingState(state);
+ });
+}
+
+static inline String trackId(webrtc::MediaStreamTrackInterface& videoTrack)
+{
+ return String(videoTrack.id().data(), videoTrack.id().size());
+}
+
+static inline Ref<MediaStreamTrack> createMediaStreamTrack(ScriptExecutionContext& context, Ref<RealtimeMediaSource>&& remoteSource)
+{
+ String trackId = remoteSource->id();
+ return MediaStreamTrack::create(context, MediaStreamTrackPrivate::create(WTFMove(remoteSource), WTFMove(trackId)));
+}
+
+void LibWebRTCMediaEndpoint::addStream(webrtc::MediaStreamInterface& stream)
+{
+ MediaStreamTrackVector tracks;
+ for (auto& videoTrack : stream.GetVideoTracks()) {
+ ASSERT(videoTrack);
+ String id = trackId(*videoTrack);
+ auto remoteSource = RealtimeIncomingVideoSource::create(WTFMove(videoTrack), WTFMove(id));
+ tracks.append(createMediaStreamTrack(*m_peerConnectionBackend.connection().scriptExecutionContext(), WTFMove(remoteSource)));
+ }
+ for (auto& audioTrack : stream.GetAudioTracks()) {
+ ASSERT(audioTrack);
+ String id = trackId(*audioTrack);
+ auto remoteSource = RealtimeIncomingAudioSource::create(WTFMove(audioTrack), WTFMove(id));
+ tracks.append(createMediaStreamTrack(*m_peerConnectionBackend.connection().scriptExecutionContext(), WTFMove(remoteSource)));
+ }
+
+ auto newStream = MediaStream::create(*m_peerConnectionBackend.connection().scriptExecutionContext(), WTFMove(tracks));
+ m_peerConnectionBackend.connection().fireEvent(MediaStreamEvent::create(eventNames().addstreamEvent, false, false, newStream.copyRef()));
+
+ Vector<RefPtr<MediaStream>> streams;
+ streams.append(newStream.copyRef());
+ for (auto& track : newStream->getTracks())
+ m_peerConnectionBackend.connection().fireEvent(RTCTrackEvent::create(eventNames().trackEvent, false, false, nullptr, track.get(), Vector<RefPtr<MediaStream>>(streams), nullptr));
+}
+
+void LibWebRTCMediaEndpoint::OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream)
+{
+ callOnMainThread([protectedThis = makeRef(*this), stream = WTFMove(stream)] {
+ if (protectedThis->isStopped())
+ return;
+ ASSERT(stream);
+ protectedThis->addStream(*stream.get());
+ });
+}
+
+void LibWebRTCMediaEndpoint::OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface>)
+{
+ ASSERT_NOT_REACHED();
+}
+
+void LibWebRTCMediaEndpoint::OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel)
+{
+ callOnMainThread([protectedThis = makeRef(*this), dataChannel = WTFMove(dataChannel)] {
+ if (protectedThis->isStopped())
+ return;
+ protectedThis->addDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface>(dataChannel));
+ });
+}
+
+void LibWebRTCMediaEndpoint::stop()
+{
+ ASSERT(m_backend);
+ m_backend->Close();
+ m_backend = nullptr;
+}
+
+void LibWebRTCMediaEndpoint::OnRenegotiationNeeded()
+{
+ notImplemented();
+}
+
+static inline PeerConnectionStates::IceConnectionState iceConnectionState(webrtc::PeerConnectionInterface::IceConnectionState state)
+{
+ switch (state) {
+ case webrtc::PeerConnectionInterface::kIceConnectionNew:
+ return PeerConnectionStates::IceConnectionState::New;
+ case webrtc::PeerConnectionInterface::kIceConnectionChecking:
+ return PeerConnectionStates::IceConnectionState::Checking;
+ case webrtc::PeerConnectionInterface::kIceConnectionConnected:
+ return PeerConnectionStates::IceConnectionState::Connected;
+ case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
+ return PeerConnectionStates::IceConnectionState::Completed;
+ case webrtc::PeerConnectionInterface::kIceConnectionFailed:
+ return PeerConnectionStates::IceConnectionState::Failed;
+ case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
+ return PeerConnectionStates::IceConnectionState::Disconnected;
+ case webrtc::PeerConnectionInterface::kIceConnectionClosed:
+ return PeerConnectionStates::IceConnectionState::Closed;
+ case webrtc::PeerConnectionInterface::kIceConnectionMax:
+ ASSERT_NOT_REACHED();
+ return PeerConnectionStates::IceConnectionState::New;
+ }
+}
+
+void LibWebRTCMediaEndpoint::OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState state)
+{
+ auto connectionState = iceConnectionState(state);
+ callOnMainThread([protectedThis = makeRef(*this), connectionState] {
+ if (protectedThis->isStopped())
+ return;
+ if (protectedThis->m_peerConnectionBackend.connection().internalIceConnectionState() != connectionState)
+ protectedThis->m_peerConnectionBackend.connection().updateIceConnectionState(connectionState);
+ });
+}
+
+void LibWebRTCMediaEndpoint::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState state)
+{
+ if (state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
+ callOnMainThread([protectedThis = makeRef(*this)] {
+ if (protectedThis->isStopped())
+ return;
+ protectedThis->m_peerConnectionBackend.doneGatheringCandidates();
+ });
+ }
+}
+
+void LibWebRTCMediaEndpoint::OnIceCandidate(const webrtc::IceCandidateInterface *rtcCandidate)
+{
+ ASSERT(rtcCandidate);
+
+ std::string sdp;
+ rtcCandidate->ToString(&sdp);
+ String candidateSDP(sdp.data(), sdp.size());
+
+ auto mid = rtcCandidate->sdp_mid();
+ String candidateMid(mid.data(), mid.size());
+
+ callOnMainThread([protectedThis = makeRef(*this), mid = WTFMove(candidateMid), sdp = WTFMove(candidateSDP)] {
+ if (protectedThis->isStopped())
+ return;
+ protectedThis->m_peerConnectionBackend.fireICECandidateEvent(RTCIceCandidate::create(String(sdp), String(mid), 0));
+ });
+}
+
+void LibWebRTCMediaEndpoint::OnIceCandidatesRemoved(const std::vector<cricket::Candidate>&)
+{
+ ASSERT_NOT_REACHED();
+}
+
+void LibWebRTCMediaEndpoint::createSessionDescriptionSucceeded(webrtc::SessionDescriptionInterface* description)
+{
+ std::string sdp;
+ description->ToString(&sdp);
+ String sdpString(sdp.data(), sdp.size());
+
+ callOnMainThread([protectedThis = makeRef(*this), sdp = WTFMove(sdpString)] {
+ if (protectedThis->isStopped())
+ return;
+ if (protectedThis->m_isInitiator)
+ protectedThis->m_peerConnectionBackend.createOfferSucceeded(String(sdp));
+ else
+ protectedThis->m_peerConnectionBackend.createAnswerSucceeded(String(sdp));
+ });
+}
+
+void LibWebRTCMediaEndpoint::createSessionDescriptionFailed(const std::string& errorMessage)
+{
+ String error(errorMessage.data(), errorMessage.size());
+ callOnMainThread([protectedThis = makeRef(*this), error = WTFMove(error)] {
+ if (protectedThis->isStopped())
+ return;
+ if (protectedThis->m_isInitiator)
+ protectedThis->m_peerConnectionBackend.createOfferFailed(Exception { OperationError, String(error) });
+ else
+ protectedThis->m_peerConnectionBackend.createAnswerFailed(Exception { OperationError, String(error) });
+ });
+}
+
+void LibWebRTCMediaEndpoint::setLocalSessionDescriptionSucceeded()
+{
+ callOnMainThread([protectedThis = makeRef(*this)] {
+ if (protectedThis->isStopped())
+ return;
+ protectedThis->m_peerConnectionBackend.setLocalDescriptionSucceeded();
+ });
+}
+
+void LibWebRTCMediaEndpoint::setLocalSessionDescriptionFailed(const std::string& errorMessage)
+{
+ String error(errorMessage.data(), errorMessage.size());
+ callOnMainThread([protectedThis = makeRef(*this), error = WTFMove(error)] {
+ if (protectedThis->isStopped())
+ return;
+ protectedThis->m_peerConnectionBackend.setLocalDescriptionFailed(Exception { OperationError, String(error) });
+ });
+}
+
+void LibWebRTCMediaEndpoint::setRemoteSessionDescriptionSucceeded()
+{
+ callOnMainThread([protectedThis = makeRef(*this)] {
+ if (protectedThis->isStopped())
+ return;
+ protectedThis->m_peerConnectionBackend.setRemoteDescriptionSucceeded();
+ });
+}
+
+void LibWebRTCMediaEndpoint::setRemoteSessionDescriptionFailed(const std::string& errorMessage)
+{
+ String error(errorMessage.data(), errorMessage.size());
+ callOnMainThread([protectedThis = makeRef(*this), error = WTFMove(error)] {
+ if (protectedThis->isStopped())
+ return;
+ protectedThis->m_peerConnectionBackend.setRemoteDescriptionFailed(Exception { OperationError, String(error) });
+ });
+}
+
+} // namespace WebCore
+
+#endif // USE(LIBWEBRTC)
Added: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h (0 => 211255)
--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h 2017-01-27 06:09:41 UTC (rev 211255)
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2017 Apple Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if USE(LIBWEBRTC)
+
+#include "LibWebRTCUtils.h"
+#include "PeerConnectionBackend.h"
+#include "RealtimeOutgoingAudioSource.h"
+#include "RealtimeOutgoingVideoSource.h"
+
+#include <webrtc/api/jsep.h>
+#include <webrtc/api/peerconnectionfactory.h>
+#include <webrtc/api/peerconnectioninterface.h>
+#include <webrtc/api/rtcstatscollector.h>
+
+#include <wtf/ThreadSafeRefCounted.h>
+
+namespace webrtc {
+class CreateSessionDescriptionObserver;
+class DataChannelInterface;
+class IceCandidateInterface;
+class MediaStreamInterface;
+class PeerConnectionObserver;
+class SessionDescriptionInterface;
+class SetSessionDescriptionObserver;
+}
+
+namespace WebCore {
+
+class LibWebRTCProvider;
+class LibWebRTCPeerConnectionBackend;
+class MediaStreamTrack;
+class RTCSessionDescription;
+
+class LibWebRTCMediaEndpoint : public ThreadSafeRefCounted<LibWebRTCMediaEndpoint>, private webrtc::PeerConnectionObserver {
+public:
+ static Ref<LibWebRTCMediaEndpoint> create(LibWebRTCPeerConnectionBackend& peerConnection, LibWebRTCProvider& client) { return adoptRef(*new LibWebRTCMediaEndpoint(peerConnection, client)); }
+ virtual ~LibWebRTCMediaEndpoint() { }
+
+ webrtc::PeerConnectionInterface& backend() const { ASSERT(m_backend); return *m_backend.get(); }
+ void doSetLocalDescription(RTCSessionDescription&);
+ void doSetRemoteDescription(RTCSessionDescription&);
+ void doCreateOffer();
+ void doCreateAnswer();
+ void getStats(MediaStreamTrack*, PeerConnection::StatsPromise&&);
+
+ void storeIceCandidate(std::unique_ptr<webrtc::IceCandidateInterface>&& candidate) { m_pendingCandidates.append(WTFMove(candidate)); }
+ void addPendingIceCandidates();
+
+ void stop();
+
+private:
+ LibWebRTCMediaEndpoint(LibWebRTCPeerConnectionBackend&, LibWebRTCProvider&);
+
+ // webrtc::PeerConnectionObserver API
+ void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState) final;
+ void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface>) final;
+ void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface>) final;
+ void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface>) final;
+ void OnRenegotiationNeeded() final;
+ void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState) final;
+ void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState) final;
+ void OnIceCandidate(const webrtc::IceCandidateInterface*) final;
+ void OnIceCandidatesRemoved(const std::vector<cricket::Candidate>&) final;
+
+ void createSessionDescriptionSucceeded(webrtc::SessionDescriptionInterface*);
+ void createSessionDescriptionFailed(const std::string&);
+ void setLocalSessionDescriptionSucceeded();
+ void setLocalSessionDescriptionFailed(const std::string&);
+ void setRemoteSessionDescriptionSucceeded();
+ void setRemoteSessionDescriptionFailed(const std::string&);
+ void addStream(webrtc::MediaStreamInterface&);
+ void addDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface>&&);
+
+ bool isStopped() const { return !m_backend; }
+
+ int AddRef() const { ref(); return static_cast<int>(refCount()); }
+ int Release() const { deref(); return static_cast<int>(refCount()); }
+
+ class CreateSessionDescriptionObserver final : public webrtc::CreateSessionDescriptionObserver {
+ public:
+ explicit CreateSessionDescriptionObserver(LibWebRTCMediaEndpoint &endpoint) : m_endpoint(endpoint) { }
+
+ void OnSuccess(webrtc::SessionDescriptionInterface* sessionDescription) final { m_endpoint.createSessionDescriptionSucceeded(sessionDescription); }
+ void OnFailure(const std::string& error) final { m_endpoint.createSessionDescriptionFailed(error); }
+
+ int AddRef() const { return m_endpoint.AddRef(); }
+ int Release() const { return m_endpoint.Release(); }
+
+ private:
+ LibWebRTCMediaEndpoint& m_endpoint;
+ };
+
+ class SetLocalSessionDescriptionObserver final : public webrtc::SetSessionDescriptionObserver {
+ public:
+ explicit SetLocalSessionDescriptionObserver(LibWebRTCMediaEndpoint &endpoint) : m_endpoint(endpoint) { }
+
+ void OnSuccess() final { m_endpoint.setLocalSessionDescriptionSucceeded(); }
+ void OnFailure(const std::string& error) final { m_endpoint.setLocalSessionDescriptionFailed(error); }
+
+ int AddRef() const { return m_endpoint.AddRef(); }
+ int Release() const { return m_endpoint.Release(); }
+
+ private:
+ LibWebRTCMediaEndpoint& m_endpoint;
+ };
+
+ class SetRemoteSessionDescriptionObserver final : public webrtc::SetSessionDescriptionObserver {
+ public:
+ explicit SetRemoteSessionDescriptionObserver(LibWebRTCMediaEndpoint &endpoint) : m_endpoint(endpoint) { }
+
+ void OnSuccess() final { m_endpoint.setRemoteSessionDescriptionSucceeded(); }
+ void OnFailure(const std::string& error) final { m_endpoint.setRemoteSessionDescriptionFailed(error); }
+
+ int AddRef() const { return m_endpoint.AddRef(); }
+ int Release() const { return m_endpoint.Release(); }
+
+ private:
+ LibWebRTCMediaEndpoint& m_endpoint;
+ };
+
+ class StatsCollector final : public RefCounted<StatsCollector>, public webrtc::RTCStatsCollectorCallback {
+ public:
+ static Ref<StatsCollector> create(LibWebRTCMediaEndpoint& endpoint, PeerConnection::StatsPromise&& promise, MediaStreamTrack* track) { return adoptRef(* new StatsCollector(endpoint, WTFMove(promise), track)); }
+ private:
+ StatsCollector(LibWebRTCMediaEndpoint&, PeerConnection::StatsPromise&&, MediaStreamTrack*);
+
+ void OnStatsDelivered(const rtc::scoped_refptr<const webrtc::RTCStatsReport>&) final;
+
+ int AddRef() const final { ref(); return static_cast<int>(refCount()); }
+ int Release() const final { deref(); return static_cast<int>(refCount()); }
+
+ LibWebRTCMediaEndpoint& m_endpoint;
+ PeerConnection::StatsPromise m_promise;
+ String m_id;
+ };
+
+ LibWebRTCPeerConnectionBackend& m_peerConnectionBackend;
+ rtc::scoped_refptr<webrtc::PeerConnectionInterface> m_backend;
+
+ CreateSessionDescriptionObserver m_createSessionDescriptionObserver;
+ SetLocalSessionDescriptionObserver m_setLocalSessionDescriptionObserver;
+ SetRemoteSessionDescriptionObserver m_setRemoteSessionDescriptionObserver;
+
+ bool m_isInitiator { false };
+
+ Vector<std::unique_ptr<webrtc::IceCandidateInterface>> m_pendingCandidates;
+ Vector<Ref<RealtimeOutgoingAudioSource>> m_audioSources;
+ Vector<Ref<RealtimeOutgoingVideoSource>> m_videoSources;
+ Vector<Ref<StatsCollector>> m_statsCollectors;
+};
+
+} // namespace WebCore
+
+#endif // USE(LIBWEBRTC)
Added: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp (0 => 211255)
--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp 2017-01-27 06:09:41 UTC (rev 211255)
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2017 Apple Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LibWebRTCPeerConnectionBackend.h"
+
+#if USE(LIBWEBRTC)
+
+#include "Document.h"
+#include "IceCandidate.h"
+#include "LibWebRTCMediaEndpoint.h"
+#include "MediaEndpointConfiguration.h"
+#include "Page.h"
+#include "RTCIceCandidate.h"
+#include "RTCPeerConnection.h"
+#include "RTCRtpReceiver.h"
+#include "RTCSessionDescription.h"
+#include "RealtimeIncomingAudioSource.h"
+#include "RealtimeIncomingVideoSource.h"
+
+namespace WebCore {
+
+static std::unique_ptr<PeerConnectionBackend> createLibWebRTCPeerConnectionBackend(RTCPeerConnection& peerConnection)
+{
+ return std::make_unique<LibWebRTCPeerConnectionBackend>(peerConnection);
+}
+
+CreatePeerConnectionBackend PeerConnectionBackend::create = createLibWebRTCPeerConnectionBackend;
+
+static inline LibWebRTCProvider& libWebRTCProvider(RTCPeerConnection& peerConnection)
+{
+ ASSERT(peerConnection.scriptExecutionContext()->isDocument());
+ auto* page = static_cast<Document*>(peerConnection.scriptExecutionContext())->page();
+ return page->libWebRTCProvider();
+}
+
+LibWebRTCPeerConnectionBackend::LibWebRTCPeerConnectionBackend(RTCPeerConnection& peerConnection)
+ : PeerConnectionBackend(peerConnection)
+ , m_endpoint(LibWebRTCMediaEndpoint::create(*this, libWebRTCProvider(peerConnection)))
+{
+}
+
+static webrtc::PeerConnectionInterface::RTCConfiguration configurationFromMediaEndpointConfiguration(MediaEndpointConfiguration&& configuration)
+{
+ webrtc::PeerConnectionInterface::RTCConfiguration rtcConfiguration(webrtc::PeerConnectionInterface::RTCConfigurationType::kAggressive);
+
+ if (configuration.iceTransportPolicy == PeerConnectionStates::IceTransportPolicy::Relay)
+ rtcConfiguration.type = webrtc::PeerConnectionInterface::kRelay;
+
+ if (configuration.bundlePolicy == PeerConnectionStates::BundlePolicy::MaxBundle)
+ rtcConfiguration.bundle_policy = webrtc::PeerConnectionInterface::kBundlePolicyMaxBundle;
+ else if (configuration.bundlePolicy == PeerConnectionStates::BundlePolicy::MaxCompat)
+ rtcConfiguration.bundle_policy = webrtc::PeerConnectionInterface::kBundlePolicyMaxCompat;
+
+ for (auto& server : configuration.iceServers) {
+ webrtc::PeerConnectionInterface::IceServer iceServer;
+ iceServer.username = server.username.utf8().data();
+ iceServer.password = server.credential.utf8().data();
+ for (auto& url : server.urls)
+ iceServer.urls.push_back({ url.string().utf8().data() });
+ rtcConfiguration.servers.push_back(WTFMove(iceServer));
+ }
+
+ return rtcConfiguration;
+}
+
+void LibWebRTCPeerConnectionBackend::setConfiguration(MediaEndpointConfiguration&& configuration)
+{
+ m_endpoint->backend().SetConfiguration(configurationFromMediaEndpointConfiguration(WTFMove(configuration)));
+}
+
+void LibWebRTCPeerConnectionBackend::getStats(MediaStreamTrack* track, PeerConnection::StatsPromise&& promise)
+{
+ m_endpoint->getStats(track, WTFMove(promise));
+}
+
+void LibWebRTCPeerConnectionBackend::doSetLocalDescription(RTCSessionDescription& description)
+{
+ m_endpoint->doSetLocalDescription(description);
+ if (!m_isLocalDescriptionSet) {
+ if (m_isRemoteDescriptionSet)
+ m_endpoint->addPendingIceCandidates();
+ m_isLocalDescriptionSet = true;
+ }
+}
+
+void LibWebRTCPeerConnectionBackend::doSetRemoteDescription(RTCSessionDescription& description)
+{
+ m_endpoint->doSetRemoteDescription(description);
+ if (!m_isRemoteDescriptionSet) {
+ if (m_isLocalDescriptionSet)
+ m_endpoint->addPendingIceCandidates();
+ m_isRemoteDescriptionSet = true;
+ }
+}
+
+void LibWebRTCPeerConnectionBackend::doCreateOffer(RTCOfferOptions&&)
+{
+ m_endpoint->doCreateOffer();
+}
+
+void LibWebRTCPeerConnectionBackend::doCreateAnswer(RTCAnswerOptions&&)
+{
+ if (!m_isRemoteDescriptionSet) {
+ createAnswerFailed(Exception { INVALID_STATE_ERR, "No remote description set" });
+ return;
+ }
+ m_endpoint->doCreateAnswer();
+}
+
+void LibWebRTCPeerConnectionBackend::doStop()
+{
+ m_endpoint->stop();
+}
+
+void LibWebRTCPeerConnectionBackend::doAddIceCandidate(RTCIceCandidate& candidate)
+{
+ if (!m_isRemoteDescriptionSet) {
+ addIceCandidateFailed(Exception { INVALID_STATE_ERR, "No remote description set" });
+ return;
+ }
+
+ webrtc::SdpParseError error;
+ int sdpMLineIndex = candidate.sdpMLineIndex() ? candidate.sdpMLineIndex().value() : 0;
+ std::unique_ptr<webrtc::IceCandidateInterface> rtcCandidate(webrtc::CreateIceCandidate(candidate.sdpMid().utf8().data(), sdpMLineIndex, candidate.candidate().utf8().data(), &error));
+
+ if (!rtcCandidate) {
+ String message(error.description.data(), error.description.size());
+ addIceCandidateFailed(Exception { OperationError, WTFMove(message) });
+ return;
+ }
+
+ // libwebrtc does not like that ice candidates are set before the description.
+ if (!m_isLocalDescriptionSet || !m_isRemoteDescriptionSet)
+ m_endpoint->storeIceCandidate(WTFMove(rtcCandidate));
+ else if (!m_endpoint->backend().AddIceCandidate(rtcCandidate.get())) {
+ ASSERT_NOT_REACHED();
+ addIceCandidateFailed(Exception { OperationError, ASCIILiteral("Failed to apply the received candidate") });
+ return;
+ }
+ addIceCandidateSucceeded();
+}
+
+void LibWebRTCPeerConnectionBackend::markAsNeedingNegotiation()
+{
+ // FIXME: Implement this
+}
+
+Ref<RTCRtpReceiver> LibWebRTCPeerConnectionBackend::createReceiver(const String&, const String& trackKind, const String& trackId)
+{
+ // FIXME: We need to create a source that will get fueled once we will receive OnAddStream.
+ // For the moment, we create an empty one.
+ auto remoteTrackPrivate = (trackKind == "audio") ? MediaStreamTrackPrivate::create(RealtimeIncomingAudioSource::create(nullptr, String(trackId))) : MediaStreamTrackPrivate::create(RealtimeIncomingVideoSource::create(nullptr, String(trackId)));
+ auto remoteTrack = MediaStreamTrack::create(*m_peerConnection.scriptExecutionContext(), WTFMove(remoteTrackPrivate));
+
+ return RTCRtpReceiver::create(WTFMove(remoteTrack));
+}
+
+std::unique_ptr<RTCDataChannelHandler> LibWebRTCPeerConnectionBackend::createDataChannelHandler(const String& label, const RTCDataChannelInit& options)
+{
+ UNUSED_PARAM(label);
+ UNUSED_PARAM(options);
+ ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+} // namespace WebCore
+
+#endif // USE(LIBWEBRTC)
Added: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h (0 => 211255)
--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h 2017-01-27 06:09:41 UTC (rev 211255)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 Apple Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if USE(LIBWEBRTC)
+
+#include "PeerConnectionBackend.h"
+
+namespace WebCore {
+
+class LibWebRTCMediaEndpoint;
+class RTCRtpReceiver;
+class RTCSessionDescription;
+
+class LibWebRTCPeerConnectionBackend final : public PeerConnectionBackend {
+public:
+ explicit LibWebRTCPeerConnectionBackend(RTCPeerConnection&);
+
+private:
+ void doCreateOffer(RTCOfferOptions&&) final;
+ void doCreateAnswer(RTCAnswerOptions&&) final;
+ void doSetLocalDescription(RTCSessionDescription&) final;
+ void doSetRemoteDescription(RTCSessionDescription&) final;
+ void doAddIceCandidate(RTCIceCandidate&) final;
+ void doStop() final;
+ std::unique_ptr<RTCDataChannelHandler> createDataChannelHandler(const String&, const RTCDataChannelInit&) final;
+ void setConfiguration(MediaEndpointConfiguration&&) final;
+ void getStats(MediaStreamTrack*, PeerConnection::StatsPromise&&) final;
+ Ref<RTCRtpReceiver> createReceiver(const String& transceiverMid, const String& trackKind, const String& trackId) final;
+
+ // FIXME: API to implement for real
+ RefPtr<RTCSessionDescription> localDescription() const final { return nullptr; }
+ RefPtr<RTCSessionDescription> currentLocalDescription() const final { return nullptr; }
+ RefPtr<RTCSessionDescription> pendingLocalDescription() const final { return nullptr; }
+
+ RefPtr<RTCSessionDescription> remoteDescription() const final { return nullptr; }
+ RefPtr<RTCSessionDescription> currentRemoteDescription() const final { return nullptr; }
+ RefPtr<RTCSessionDescription> pendingRemoteDescription() const final { return nullptr; }
+
+
+ Vector<RefPtr<MediaStream>> getRemoteStreams() const final { return { }; }
+
+ void replaceTrack(RTCRtpSender&, RefPtr<MediaStreamTrack>&&, DOMPromise<void>&&) final { }
+
+ bool isNegotiationNeeded() const final { return false; }
+ void markAsNeedingNegotiation() final;
+ void clearNegotiationNeededState() final { }
+
+ void emulatePlatformEvent(const String&) final { }
+
+ friend LibWebRTCMediaEndpoint;
+ RTCPeerConnection& connection() { return m_peerConnection; }
+
+private:
+ Ref<LibWebRTCMediaEndpoint> m_endpoint;
+ bool m_isLocalDescriptionSet { false };
+ bool m_isRemoteDescriptionSet { false };
+};
+
+} // namespace WebCore
+
+#endif // USE(LIBWEBRTC)
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (211254 => 211255)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-01-27 05:36:19 UTC (rev 211254)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-01-27 06:09:41 UTC (rev 211255)
@@ -1563,6 +1563,10 @@
4170A2EA1D8C0CCA00318452 /* JSDOMWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4170A2E91D8C0CC000318452 /* JSDOMWrapper.cpp */; };
417253AA1354BBBC00360F2A /* MediaControlElements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 417253A81354BBBC00360F2A /* MediaControlElements.cpp */; };
417253AB1354BBBC00360F2A /* MediaControlElements.h in Headers */ = {isa = PBXBuildFile; fileRef = 417253A91354BBBC00360F2A /* MediaControlElements.h */; };
+ 417612AF1E3A994000C3D81D /* LibWebRTCMediaEndpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 417612AB1E3A993B00C3D81D /* LibWebRTCMediaEndpoint.cpp */; };
+ 417612B01E3A994000C3D81D /* LibWebRTCMediaEndpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 417612AC1E3A993B00C3D81D /* LibWebRTCMediaEndpoint.h */; };
+ 417612B11E3A994000C3D81D /* LibWebRTCPeerConnectionBackend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 417612AD1E3A993B00C3D81D /* LibWebRTCPeerConnectionBackend.cpp */; };
+ 417612B21E3A994000C3D81D /* LibWebRTCPeerConnectionBackend.h in Headers */ = {isa = PBXBuildFile; fileRef = 417612AE1E3A993B00C3D81D /* LibWebRTCPeerConnectionBackend.h */; };
417DA6D913734E6E007C57FB /* Internals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 417DA4CF13734326007C57FB /* Internals.cpp */; };
417DA6DA13734E6E007C57FB /* Internals.h in Headers */ = {isa = PBXBuildFile; fileRef = 417DA4CE13734326007C57FB /* Internals.h */; };
417DA71D13735DFA007C57FB /* JSInternals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 417DA71B13735DFA007C57FB /* JSInternals.cpp */; };
@@ -8740,6 +8744,10 @@
4170A2E91D8C0CC000318452 /* JSDOMWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMWrapper.cpp; sourceTree = "<group>"; };
417253A81354BBBC00360F2A /* MediaControlElements.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaControlElements.cpp; sourceTree = "<group>"; };
417253A91354BBBC00360F2A /* MediaControlElements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaControlElements.h; sourceTree = "<group>"; };
+ 417612AB1E3A993B00C3D81D /* LibWebRTCMediaEndpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCMediaEndpoint.cpp; path = libwebrtc/LibWebRTCMediaEndpoint.cpp; sourceTree = "<group>"; };
+ 417612AC1E3A993B00C3D81D /* LibWebRTCMediaEndpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCMediaEndpoint.h; path = libwebrtc/LibWebRTCMediaEndpoint.h; sourceTree = "<group>"; };
+ 417612AD1E3A993B00C3D81D /* LibWebRTCPeerConnectionBackend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCPeerConnectionBackend.cpp; path = libwebrtc/LibWebRTCPeerConnectionBackend.cpp; sourceTree = "<group>"; };
+ 417612AE1E3A993B00C3D81D /* LibWebRTCPeerConnectionBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCPeerConnectionBackend.h; path = libwebrtc/LibWebRTCPeerConnectionBackend.h; sourceTree = "<group>"; };
417DA4CE13734326007C57FB /* Internals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Internals.h; sourceTree = "<group>"; };
417DA4CF13734326007C57FB /* Internals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Internals.cpp; sourceTree = "<group>"; };
417DA6D013734E02007C57FB /* libWebCoreTestSupport.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libWebCoreTestSupport.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -15115,6 +15123,7 @@
07221B4617CEC32700848E51 /* mediastream */ = {
isa = PBXGroup;
children = (
+ 417612AA1E3A992300C3D81D /* libwebrtc */,
073794ED19EE364200E5A045 /* DOMURLMediaStream.cpp */,
15FCC9FD1B4DF85600E72326 /* DOMURLMediaStream.h */,
073794EE19EE364200E5A045 /* DOMURLMediaStream.idl */,
@@ -16664,6 +16673,17 @@
name = libwebrtc;
sourceTree = "<group>";
};
+ 417612AA1E3A992300C3D81D /* libwebrtc */ = {
+ isa = PBXGroup;
+ children = (
+ 417612AB1E3A993B00C3D81D /* LibWebRTCMediaEndpoint.cpp */,
+ 417612AC1E3A993B00C3D81D /* LibWebRTCMediaEndpoint.h */,
+ 417612AD1E3A993B00C3D81D /* LibWebRTCPeerConnectionBackend.cpp */,
+ 417612AE1E3A993B00C3D81D /* LibWebRTCPeerConnectionBackend.h */,
+ );
+ name = libwebrtc;
+ sourceTree = "<group>";
+ };
417DA4CD13734204007C57FB /* testing */ = {
isa = PBXGroup;
children = (
@@ -24977,6 +24997,7 @@
319848011A1D817B00A13318 /* AnimationEvent.h in Headers */,
49E912AD0EFAC906009D0CAF /* AnimationList.h in Headers */,
31DCD29D1AB4FBDE0072E817 /* AnimationTrigger.h in Headers */,
+ 417612B01E3A994000C3D81D /* LibWebRTCMediaEndpoint.h in Headers */,
0F580FAF149800D400FB5BD8 /* AnimationUtilities.h in Headers */,
93309DD7099E64920056E581 /* AppendNodeCommand.h in Headers */,
7C6579E31E00827000E3A27A /* ApplePayLineItem.h in Headers */,
@@ -27840,6 +27861,7 @@
A8EA800C0A19516E00A8EF5F /* StyleSheet.h in Headers */,
E4F9EEF3156DA00700D23E7E /* StyleSheetContents.h in Headers */,
A8EA800A0A19516E00A8EF5F /* StyleSheetList.h in Headers */,
+ 417612B21E3A994000C3D81D /* LibWebRTCPeerConnectionBackend.h in Headers */,
BC5EB5E50E81BF6D00B25965 /* StyleSurroundData.h in Headers */,
BC5EB8100E81F2CE00B25965 /* StyleTransformData.h in Headers */,
E4DEAA1817A93DC3000E0430 /* StyleTreeResolver.h in Headers */,
@@ -29169,6 +29191,7 @@
E1B4CD2510B322E200BFFD7E /* CredentialStorageMac.mm in Sources */,
2D481F00146B5C4C00AA7834 /* CrossfadeGeneratedImage.cpp in Sources */,
E1C416170F6563180092D2FB /* CrossOriginAccessControl.cpp in Sources */,
+ 417612B11E3A994000C3D81D /* LibWebRTCPeerConnectionBackend.cpp in Sources */,
41ABE67C1D0580E0006D862D /* CrossOriginPreflightChecker.cpp in Sources */,
E1C415DE0F655D7C0092D2FB /* CrossOriginPreflightResultCache.cpp in Sources */,
E16980491133644700894115 /* CRuntimeObject.cpp in Sources */,
@@ -30483,6 +30506,7 @@
B2FA3DBA0AB75A6F000E5AC4 /* JSSVGPathSegArcRel.cpp in Sources */,
B2FA3DBC0AB75A6F000E5AC4 /* JSSVGPathSegClosePath.cpp in Sources */,
B2FA3DBE0AB75A6F000E5AC4 /* JSSVGPathSegCurvetoCubicAbs.cpp in Sources */,
+ 417612AF1E3A994000C3D81D /* LibWebRTCMediaEndpoint.cpp in Sources */,
B2FA3DC00AB75A6F000E5AC4 /* JSSVGPathSegCurvetoCubicRel.cpp in Sources */,
B2FA3DC20AB75A6F000E5AC4 /* JSSVGPathSegCurvetoCubicSmoothAbs.cpp in Sources */,
B2FA3DC40AB75A6F000E5AC4 /* JSSVGPathSegCurvetoCubicSmoothRel.cpp in Sources */,