Title: [211255] trunk/Source/WebCore
Revision
211255
Author
[email protected]
Date
2017-01-26 22:09:41 -0800 (Thu, 26 Jan 2017)

Log Message

[WebRTC] Implement WebRTC PeerConnection backend based on libwebrtc
https://bugs.webkit.org/show_bug.cgi?id=167289

Patch by Youenn Fablet <[email protected]> on 2017-01-26
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:

Modified Paths

Added Paths

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 */,
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to