Browse Source

add util library, make Makefile suitable for inclusion

master
Martin Dørum 3 years ago
parent
commit
cc42f86dd4
4 changed files with 282 additions and 18 deletions
  1. 2
    1
      .gitignore
  2. 45
    17
      Makefile
  3. 71
    0
      include/rtcutil/Conductor.h
  4. 164
    0
      util/Conductor.cc

+ 2
- 1
.gitignore View File

@@ -1,4 +1,5 @@
/include
/include/webrtc
/libs
/depot_tools
/webrtc-checkout
/build

+ 45
- 17
Makefile View File

@@ -1,4 +1,5 @@
WEBRTC_DIR ?= .
WEBRTC_BASE ?= .
WEBRTC_DIR ?= $(WEBRTC_BASE)
WEBRTC_VERSION ?= m79
WEBRTC_OUT ?= Release
WEBRTC_GN_ARGS ?= \
@@ -11,18 +12,29 @@ WEBRTC_GN_ARGS ?= \
WEBRTC_TARGETS ?= default $(WEBRTC_TARGETS_EXTRA)
WEBRTC_LIBS ?= libwebrtc.a $(WEBRTC_LIBS_EXTRA)
WEBRTC_INCLUDES = \
api audio base common_audio common_video logging media modules p2p pc \
rtc_base rtc_tools video common_types.h \
api audio base call common_audio common_video logging media modules p2p pc \
system_wrappers rtc_base rtc_tools video third_party common_types.h \
$(WEBRTC_INCLUDES_EXTRA)

SETPATH = PATH=$(WEBRTC_DIR)/depot_tools:"$$PATH"
WEBRTC_PLATFORM ?= POSIX

WEBRTC_FLAGS ?= \
-I$(WEBRTC_BASE)/include -I$(WEBRTC_BASE)/include/webrtc \
-I$(WEBRTC_BASE)/include/webrtc/third_party/abseil-cpp \
-DWEBRTC_$(WEBRTC_PLATFORM)

WEBRTC_SETPATH = PATH=$(WEBRTC_DIR)/depot_tools:"$$PATH"
RTC_STAMP_DEPOT = $(WEBRTC_DIR)/depot_tools/.stamp
RTC_STAMP_REPO = $(WEBRTC_DIR)/webrtc-checkout/.stamp
RTC_STAMP_VERSION = $(WEBRTC_DIR)/webrtc-checkout/.stamps/stamp-$(WEBRTC_VERSION)
RTC_STAMP_COMPILE = $(WEBRTC_DIR)/webrtc-checkout/src/out/$(WEBRTC_OUT)/.stamp
RTC_STAMP_INCLUDES = include/webrtc/.stamp
RTC_STAMP_INCLUDES = $(WEBRTC_BASE)/include/webrtc/.stamp

all: include/webrtc/.stamp $(patsubst %,libs/%,$(WEBRTC_LIBS))
.PHONY: rtcall
rtcall:
$(WEBRTC_BASE)/include/webrtc/.stamp \
$(patsubst %,$(WEBRTC_BASE)/libs/%,$(WEBRTC_LIBS)) \
$(WEBRTC_BASE)/libs/libutil.a

# Get depot_tools, which contains all the tools required to work with Google software
$(RTC_STAMP_DEPOT):
@@ -35,7 +47,7 @@ $(RTC_STAMP_REPO): $(RTC_STAMP_DEPOT)
rm -rf $(WEBRTC_DIR)/webrtc-checkout && mkdir $(WEBRTC_DIR)/webrtc-checkout
#
# Fetch webrtc, thit will take time...
cd $(WEBRTC_DIR)/webrtc-checkout && $(SETPATH) fetch --nohooks --no-history webrtc
cd $(WEBRTC_DIR)/webrtc-checkout && $(WEBRTC_SETPATH) fetch --nohooks --no-history webrtc
touch $@

# Check out the correct WebRTC branch/commit
@@ -44,13 +56,13 @@ $(RTC_STAMP_VERSION): $(RTC_STAMP_REPO)
cd $(WEBRTC_DIR)/webrtc-checkout/src && git checkout branch-heads/$(WEBRTC_VERSION)
#
# Sync webrtc, this will take time...
cd $(WEBRTC_DIR)/webrtc-checkout/src && $(SETPATH) gclient sync -D --nohooks
cd $(WEBRTC_DIR)/webrtc-checkout/src && $(WEBRTC_SETPATH) gclient sync -D --nohooks
touch $@

# Compile
$(RTC_STAMP_COMPILE):
cd $(WEBRTC_DIR)/webrtc-checkout/src && $(SETPATH) gn gen out/$(WEBRTC_OUT) --args='$(WEBRTC_GN_ARGS)'
cd $(WEBRTC_DIR)/webrtc-checkout/src && $(SETPATH) ninja -C out/$(WEBRTC_OUT) $(WEBRTC_TARGETS)
cd $(WEBRTC_DIR)/webrtc-checkout/src && $(WEBRTC_SETPATH) gn gen out/$(WEBRTC_OUT) --args='$(WEBRTC_GN_ARGS)'
cd $(WEBRTC_DIR)/webrtc-checkout/src && $(WEBRTC_SETPATH) ninja -C out/$(WEBRTC_OUT) $(WEBRTC_TARGETS)
touch $@

# Includes
@@ -62,15 +74,31 @@ $(RTC_STAMP_INCLUDES): $(RTC_STAMP_VERSION)
touch $@

# Libraries
libs/%.a: $(WEBRTC_DIR)/webrtc-checkout/src/out/$(WEBRTC_OUT)/obj/%.a
$(WEBRTC_BASE)/libs/%.a: $(WEBRTC_DIR)/webrtc-checkout/src/out/$(WEBRTC_OUT)/obj/%.a
@mkdir -p $(@D)
cp $< $@

.PHONY: clean
clean:
# Util
$(WEBRTC_BASE)/libs/libutil.a: $(WEBRTC_BASE)/build/util/Conductor.cc.o
@mkdir -p $(@D)
ar cr $@ $^
$(WEBRTC_BASE)/build/%.cc.o: $(WEBRTC_BASE)/%.cc $(RTC_STAMP_INCLUDES) $(wildcard $(WEBRTC_BASE)/util/*.h)
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(WEBRTC_FLAGS) -c $< -o $@

.PHONY: rtcclean
rtcclean:
rm -rf include libs build

.PHONY: rtccleanall
rtccleanall: rtcclean
rm -rf $(WEBRTC_DIR)/depot_tools $(WEBRTC_DIR)/webrtc-checkout
rm -rf include libs
cd $(WEBRTC_DIR)/webrtc-checkout/src && $(WEBRTC_SETPATH) gn clean out/$(WEBRTC_OUT)

.PHONY: gn-clean
gn-clean:
cd $(WEBRTC_DIR)/webrtc-checkout/src && $(SETPATH) gn clean out/$(WEBRTC_OUT)
.PHONY: mockstamps
rtcmockstamps:
mkdir -p $(dir $(RTC_STAMP_DEPOT)) && touch $(RTC_STAMP_DEPOT)
mkdir -p $(dir $(RTC_STAMP_REPO)) && touch $(RTC_STAMP_REPO)
mkdir -p $(dir $(RTC_STAMP_VERSION)) && touch $(RTC_STAMP_VERSION)
mkdir -p $(dir $(RTC_STAMP_COMPILE)) && touch $(RTC_STAMP_COMPILE)
mkdir -p $(dir $(RTC_STAMP_INCLUDES)) && touch $(RTC_STAMP_INCLUDES)

+ 71
- 0
include/rtcutil/Conductor.h View File

@@ -0,0 +1,71 @@
#include <webrtc/api/peer_connection_interface.h>
#include <memory>

namespace rtcutil {

class ConductorObserver {
public:
enum class ErrorType {
WARNING,
RECEIVE_OFFER,
RECEIVE_ICE_CANDIDATE,
CREATE_ANSWER,
};

virtual void onError(ErrorType type, std::string err);

virtual void onIceCandidate(std::string mid, int index, std::string sdp) = 0;
virtual void onAnswer(std::string sdp) = 0;
virtual void onRemoteTrack(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track);
virtual void removeRemoteTrack(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track);
};

class Conductor:
public webrtc::PeerConnectionObserver,
public webrtc::CreateSessionDescriptionObserver {
public:
Conductor(ConductorObserver &observer): observer_(observer) {}

void receiveOffer(const std::string &sdp);
void receiveOffer(std::unique_ptr<webrtc::SessionDescriptionInterface> offer);
void receiveIceCandidate(std::string mid, int index, std::string sdp);

void ensurePeerConnection();

protected:
// PeerConnectionObserver
void OnAddTrack(
rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> &streams) override;
void OnRemoveTrack(
rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) override;
void OnIceCandidate(const webrtc::IceCandidateInterface *candidate) override;

void OnSignalingChange(
webrtc::PeerConnectionInterface::SignalingState new_state) override {}
void OnDataChannel(
rtc::scoped_refptr<webrtc::DataChannelInterface> channel) override {}
void OnRenegotiationNeeded() override {}
void OnIceConnectionChange(
webrtc::PeerConnectionInterface::IceConnectionState new_state) override {}
void OnIceGatheringChange(
webrtc::PeerConnectionInterface::IceGatheringState new_state) override {}
void OnIceConnectionReceivingChange(bool receiving) override {}

// CreateSessionDescriptionObserver
void OnSuccess(webrtc::SessionDescriptionInterface* desc) override;
void OnFailure(webrtc::RTCError error) override;

// Overridables for consumers
virtual rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
doCreatePeerConnectionFactory();
virtual rtc::scoped_refptr<webrtc::PeerConnectionInterface>
doCreatePeerConnection(webrtc::PeerConnectionFactoryInterface &factory);
virtual void doAddTracks(webrtc::PeerConnectionInterface &conn) {};

ConductorObserver &observer_;
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_conn_factory_;
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_conn_;
};

}

+ 164
- 0
util/Conductor.cc View File

@@ -0,0 +1,164 @@
#include "Conductor.h"

#include <webrtc/api/create_peerconnection_factory.h>
#include <webrtc/api/audio_codecs/builtin_audio_encoder_factory.h>
#include <webrtc/api/audio_codecs/builtin_audio_decoder_factory.h>
#include <webrtc/api/video_codecs/builtin_video_encoder_factory.h>
#include <webrtc/api/video_codecs/builtin_video_decoder_factory.h>
#include <webrtc/pc/video_track_source.h>
#include <stdio.h>
#include <stdlib.h>

namespace rtcutil {

void ConductorObserver::onError(ErrorType type, std::string err) {
if (type == ErrorType::WARNING) {
fprintf(stderr, "Warning: %s\n", err.c_str());
} else {
fprintf(stderr, "Error: %s\n", err.c_str());
abort();
}
}

class SetSessionDescriptionObserver: public webrtc::SetSessionDescriptionObserver {
public:
SetSessionDescriptionObserver(ConductorObserver &observer): observer_(observer) {}

static SetSessionDescriptionObserver* Create(ConductorObserver &observer) {
return new rtc::RefCountedObject<SetSessionDescriptionObserver>(observer);
}

virtual void OnSuccess() {}
virtual void OnFailure(webrtc::RTCError error) {
observer_.onError(ConductorObserver::ErrorType::RECEIVE_OFFER,
error.message());
}

private:
ConductorObserver &observer_;
};

void Conductor::receiveOffer(const std::string &sdp) {
webrtc::SdpParseError error;
std::unique_ptr<webrtc::SessionDescriptionInterface> desc =
webrtc::CreateSessionDescription(webrtc::SdpType::kOffer, sdp, &error);
if (!desc.get()) {
observer_.onError(ConductorObserver::ErrorType::RECEIVE_OFFER,
std::move(error.description));
return;
}

receiveOffer(std::move(desc));
}

void Conductor::receiveOffer(std::unique_ptr<webrtc::SessionDescriptionInterface> offer) {
ensurePeerConnection();

peer_conn_->SetRemoteDescription(
SetSessionDescriptionObserver::Create(observer_),
offer.release());

peer_conn_->CreateAnswer(
this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
}

void Conductor::receiveIceCandidate(std::string mid, int index, std::string sdp) {
webrtc::SdpParseError error;
std::unique_ptr<webrtc::IceCandidateInterface> candidate(
webrtc::CreateIceCandidate(mid, index, sdp, &error));
if (!candidate.get()) {
observer_.onError(ConductorObserver::ErrorType::WARNING,
std::move(error.description));
return;
}

if (!peer_conn_->AddIceCandidate(candidate.get())) {
observer_.onError(ConductorObserver::ErrorType::WARNING,
"Failed to apply the received candidate");
return;
}
}

void Conductor::ensurePeerConnection() {
if (peer_conn_factory_.get())
return;

peer_conn_factory_ = doCreatePeerConnectionFactory();
peer_conn_ = doCreatePeerConnection(*peer_conn_factory_);
}

void Conductor::OnAddTrack(
rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> &streams) {
observer_.onRemoteTrack(std::move(receiver->track()));
}

void Conductor::OnRemoveTrack(
rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) {
observer_.removeRemoteTrack(std::move(receiver->track()));
}

void Conductor::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
std::string sdp;
if (!candidate->ToString(&sdp)) {
observer_.onError(ConductorObserver::ErrorType::WARNING,
"Failed to serialize candidate");
return;
}

observer_.onIceCandidate(
std::move(candidate->sdp_mid()),
candidate->sdp_mline_index(),
std::move(sdp));
}

rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
Conductor::doCreatePeerConnectionFactory() {
return webrtc::CreatePeerConnectionFactory(
nullptr /* network_thread */, nullptr /* worker_thread */,
nullptr /* signaling_thread */, nullptr /* default_adm */,
webrtc::CreateBuiltinAudioEncoderFactory(),
webrtc::CreateBuiltinAudioDecoderFactory(),
webrtc::CreateBuiltinVideoEncoderFactory(),
webrtc::CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
nullptr /* audio_processing */);
}

rtc::scoped_refptr<webrtc::PeerConnectionInterface>
Conductor::doCreatePeerConnection(webrtc::PeerConnectionFactoryInterface &factory) {
webrtc::PeerConnectionInterface::RTCConfiguration config;
config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;

webrtc::PeerConnectionInterface::IceServer server;
const char *uri = getenv("WEBRTC_CONNECT");
if (uri) {
server.uri = uri;
} else {
server.uri = "stun:stun.l.google.com:19302";
}
config.servers.push_back(server);

rtc::scoped_refptr<webrtc::PeerConnectionInterface> conn =
factory.CreatePeerConnection(
config, nullptr, nullptr, this);

doAddTracks(*conn);

return conn;
}

void Conductor::OnSuccess(webrtc::SessionDescriptionInterface *desc) {
peer_conn_->SetLocalDescription(
SetSessionDescriptionObserver::Create(observer_), desc);

std::string sdp;
desc->ToString(&sdp);
observer_.onAnswer(std::move(sdp));
}

void Conductor::OnFailure(webrtc::RTCError error) {
observer_.onError(ConductorObserver::ErrorType::WARNING,
error.message());
}

}

Loading…
Cancel
Save