39#include <glibmm/error.h>
40#include <glibmm/signalproxy.h>
42#include <gst/gsterror.h>
43#include <gst/sdp/gstsdpmessage.h>
44#include <gstreamermm/pipeline.h>
47#include <gst/webrtc/webrtc.h>
49using namespace resipgst;
57#define RESIPROCATE_SUBSYSTEM ReconSubsystem::RECON
73#define GST_RTP_CAPS_OPUS "application/x-rtp,media=audio,encoding-name=OPUS,clock-rate=48000,payload=96"
74#define GST_RTP_CAPS_VP8 "application/x-rtp,media=video,encoding-name=VP8,clock-rate=90000,payload=97"
77#define GST_RTP_CAPS_PCMA "application/x-rtp,media=audio,encoding-name=PCMA,clock-rate=8000,payload=8"
78#define GST_RTP_CAPS_H264 "application/x-rtp,media=video,encoding-name=H264,clock-rate=90000,payload=120"
84 std::function<void()> &func = *
static_cast<std::function<
void()
>*>(u);
98 auto _u =
static_cast<std::function<
void(GstPromise* , gpointer)
>*>(u);
99 std::function<void(GstPromise*, gpointer)> &func = *_u;
111 RemoteParticipant(partHandle, conversationManager, dum, remoteParticipantDialogSet),
113 mIceGatheringDone(false),
114 mRemoveExtraMediaDescriptors(false),
115 mSipRtpEndpoint(true),
116 mReuseSdpAnswer(false),
117 mWSAcceptsKeyframeRequests(true),
119 mWaitingAnswer(false),
120 mWebRTCOutgoing(getDialogSet().getConversationProfile()->mediaEndpointMode() ==
ConversationProfile::WebRTC)
122 InfoLog(<<
"GstRemoteParticipant created (UAC), handle=" <<
mHandle);
135 mIceGatheringDone(false),
136 mRemoveExtraMediaDescriptors(false),
137 mSipRtpEndpoint(true),
138 mReuseSdpAnswer(false),
139 mWSAcceptsKeyframeRequests(true),
141 mWaitingAnswer(false),
142 mWebRTCOutgoing(getDialogSet().getConversationProfile()->mediaEndpointMode() ==
ConversationProfile::WebRTC)
144 InfoLog(<<
"GstRemoteParticipant created (UAS or forked leg), handle=" <<
mHandle);
150GstRemoteParticipant::initRtpManager()
155 mRtpManager = make_shared<GstRtpManager>(
"0.0.0.0");
212GstRemoteParticipant::linkOutgoingPipeline(
unsigned int streamId, RefPtr<Bin> bin,
const Glib::RefPtr<Gst::Caps> caps)
214 RefPtr<Pad> src = bin->get_static_pad(
"src");
216 RefPtr<Caps> padCaps = Caps::create_from_string(
"application/x-rtp");
217 RefPtr<Gst::PadTemplate> tmpl = PadTemplate::create(
"send_rtp_sink_%u", PAD_SINK, PAD_REQUEST, padCaps);
218 ostringstream padName;
219 padName <<
"sink_" << streamId;
220 DebugLog(<<
"linking to " << padName.str());
229 bool isWebRTC = isWebRTCSession();
241 CritLog(<<
"failed to get request pad " << padName.str());
257 RefPtr<Gst::EventCaps> capsEvent = Gst::EventCaps::create(caps);
258 RefPtr<Gst::Element> queueOut = RefPtr<Element>::cast_dynamic(bin->get_child(
"queueOut"));
259 queueOut->get_static_pad(
"sink")->send_event(capsEvent);
286GstRemoteParticipant::prepareStream(
unsigned int streamId,
bool loopbackMode)
288 GstRtpSession::CapsVector capsV =
mRtpSession->getOutgoingCaps();
290 if(capsV.size() > streamId && capsV[streamId])
292 caps = capsV[streamId];
297 ErrLog(<<
"caps not specified");
301 RefPtr<Pad> mediaSink =
mRtpSession->getOutgoingPads()[streamId];
303 MediaTypeName mediaTypeName = getMediaTypeName(caps);
321 RefPtr<Element> testSrc = buildTestSource(mediaTypeName);
324 testSrc->get_static_pad(
"src")->link(mediaSink);
330GstRemoteParticipant::initEndpointIfRequired(
bool isWebRTC)
334 DebugLog(<<
"mPipeline already exists");
340 mIceGatheringDone =
true;
344 mIceGatheringDone =
false;
361 GstWebRTCBundlePolicy bundlePolicy = GST_WEBRTC_BUNDLE_POLICY_MAX_COMPAT;
362 GValue val = G_VALUE_INIT;
363 g_value_init (&val, G_TYPE_ENUM);
364 g_value_set_enum (&val, bundlePolicy);
374 if(natTraversalMode ==
"Bind" && !stunServerName.
empty() && stunServerPort > 0)
376 Data stunUrl =
"stun://" + stunServerName +
":" + stunServerPort;
377 InfoLog(<<
"using STUN config: " << stunUrl);
382#ifdef GST_TURN_PASSWORD
391 Glib::ustring turnUrl = u.str();
393 InfoLog(<<
"using TURN config: " << turnUrl);
411 bool loopbackMode = !isWebRTC;
413 unsigned int streamCount =
mRtpSession->getOutgoingCaps().size();
417 InfoLog(<<
"creating streams for SDP offer");
425 InfoLog(<<
"creating streams for SDP answer");
426 for(
unsigned int streamId = 0; streamId < streamCount; streamId++)
428 prepareStream(streamId, loopbackMode);
434 bus->add_watch(sigc::mem_fun(*
this, &GstRemoteParticipant::onGstBusMessage));
436 DebugLog(<<
"mPipeline and mRtpTransportElement created");
491GstRemoteParticipant::isWebRTCSession()
const
498GstRemoteParticipant::onMediaSourceAdded(
const RefPtr<Pad>&
pad)
500 Glib::ustring padName =
pad->get_name();
501 DebugLog(<<
"onMediaSourceAdded: on-pad-added, padName: " << padName <<
" stream ID: " <<
pad->get_stream_id().raw());
502 if(
pad->get_direction() == PAD_SRC)
504 RefPtr<Caps> caps =
pad->get_current_caps();
511 MediaTypeName mediaTypeName = deduceKeyForPadName(padName);
512 int streamId = getStreamIdFromPadName(padName);
515 ErrLog(<<
"unable to find encoder for " << padName);
519 auto sink =
mRtpSession->getOutgoingPads()[streamId];
523 ErrLog(<<
"no encoder configured for stream " << streamId);
527 bool loopback = !isWebRTCSession();
532 if(sink->is_linked())
534 StackLog(<<
"unlinking existing src");
535 RefPtr<Pad> src = sink->get_peer();
536 if(src->unlink(sink))
545 ErrLog(<<
"failed to unlink existing src");
552 StackLog(<<
"attempting loopback configuration");
553 RefPtr<Element> proxy;
554 if(mediaTypeName ==
"video")
556 proxy = Gst::VideoConvert::create();
558 else if(mediaTypeName ==
"audio")
560 proxy = Gst::AudioConvert::create();
564 CritLog(<<
"unexpected streamKey: " << mediaTypeName);
569 proxy->get_static_pad(
"src")->link(sink);
570 pad->link(proxy->get_static_pad(
"sink"));
571 proxy->sync_state_with_parent();
577 DebugLog(<<
"completed connection from incoming to outgoing stream");
582 ErrLog(<<
"not doing loopback for WebRTC");
610 StackLog(<<
"not a source pad: " << padName);
615GstRemoteParticipant::createIncomingPipeline(RefPtr<Pad>
pad)
617 DebugLog(<<
"createIncomingPipeline: " <<
pad->get_name());
619 return RefPtr<Bin>();
621 MediaTypeName mediaType = getMediaTypeName(
pad->get_current_caps());
622 if(mediaType.empty())
624 mediaType = deduceKeyForPadName(
pad->get_name());
637 if(mediaType ==
"video")
648GstRemoteParticipant::debugGraph()
651 storeGstreamerGraph(bin,
"reCon-gst-graph");
655GstRemoteParticipant::createAndConnectElements(
bool isWebRTC, std::function<
void()> cConnected, CallbackSdpReady sdpReady)
660 createAndConnectElementsWebRTC(cConnected, sdpReady);
664 createAndConnectElementsStandard(cConnected, sdpReady);
669GstRemoteParticipant::createAndConnectElementsStandard(std::function<
void()> cConnected, CallbackSdpReady sdpReady)
674 mMediaBin->signal_pad_added().connect(sigc::mem_fun(*
this, &GstRemoteParticipant::onMediaSourceAdded));
732 DebugLog(<<
"going to STATE_PLAYING");
733 StateChangeReturn ret =
mPipeline->set_state(STATE_PLAYING);
734 if (ret == STATE_CHANGE_FAILURE)
736 ErrLog(<<
"pipeline fail");
738 sdpReady(
false,
nullptr);
748GstRemoteParticipant::createAndConnectElementsWebRTC(std::function<
void()> cConnected, CallbackSdpReady sdpReady)
752 Glib::signal_any<void>(
mRtpTransportElement,
"on-negotiation-needed").connect([
this, cConnected]()
754 DebugLog(<<
"onNegotiationNeeded invoked");
766 Glib::signal_any<void,guint,gchararray>(
mRtpTransportElement,
"on-ice-candidate").connect([
this](guint mline_index, gchararray candidate)
768 DebugLog(<<
"cOnIceCandidate invoked");
773 Glib::signal_any<void,GParamSpec*>(
mRtpTransportElement,
"notify::ice-gathering-state").connect_notify([
this, sdpReady](GParamSpec * pspec)
775 DebugLog(<<
"cIceGatheringStateNotify invoked");
776 GstWebRTCICEGatheringState ice_gather_state;
779 const Data& newState = lookupGstreamerStateName(iCEGatheringStates, ice_gather_state);
780 DebugLog(<<
"ICE gathering state: " << newState);
782 if(ice_gather_state == GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE)
784 GstWebRTCSessionDescription *_gstwebrtcsdp =
nullptr;
789 ErrLog(<<
"failed to obtain local-description");
790 sdpReady(
false,
nullptr);
794 std::unique_ptr<SdpContents> _sdp(createSdpContentsFromGstreamer(_gstwebrtcsdp));
795 gst_webrtc_session_description_free (_gstwebrtcsdp);
799 sdpReady(
true, std::move(_sdp));
804 StateChangeReturn ret =
mPipeline->set_state(STATE_READY);
805 if (ret == STATE_CHANGE_FAILURE)
807 ErrLog(<<
"pipeline fail");
809 sdpReady(
false,
nullptr);
812 Glib::signal_any<void,GParamSpec*>(
mRtpTransportElement,
"notify::ice-connection-state").connect_notify([
this](GParamSpec * pspec)
814 GstWebRTCICEConnectionState ice_connection_state;
817 const Data& newState = lookupGstreamerStateName(iCEConnectionStates, ice_connection_state);
818 DebugLog(<<
"ICE connection state: " << newState);
819 if(ice_connection_state == GST_WEBRTC_ICE_CONNECTION_STATE_CONNECTED)
826 Glib::signal_any<void,GParamSpec*>(
mRtpTransportElement,
"notify::signaling-state").connect_notify([
this](GParamSpec * pspec)
828 ErrLog(<<
"signaling-state");
829 GstWebRTCSignalingState signaling_state;
832 const Data& newState = lookupGstreamerStateName(signalingStates, signaling_state);
833 DebugLog(<<
"signaling state: " << newState);
836 mMediaBin->signal_pad_added().connect(sigc::mem_fun(*
this, &GstRemoteParticipant::onMediaSourceAdded));
859 DebugLog(<<
"going to STATE_PLAYING");
860 ret =
mPipeline->set_state(STATE_PLAYING);
861 if (ret == STATE_CHANGE_FAILURE)
863 ErrLog(<<
"pipeline fail");
865 sdpReady(
false,
nullptr);
929GstRemoteParticipant::setLocalDescription(GstWebRTCSessionDescription* gstwebrtcdesc)
935GstRemoteParticipant::setRemoteDescription(GstWebRTCSessionDescription* gstwebrtcdesc)
941GstRemoteParticipant::initRtpSession(
bool isWebRTC)
948 shared_ptr<flowmanager::HEPRTCPEventLoggingHandler> handler =
949 std::dynamic_pointer_cast<flowmanager::HEPRTCPEventLoggingHandler>(
954 handler->getHepAgent());
962 bool useExistingSdp =
false;
970 bool isWebRTC =
false;
972 initRtpSession(isWebRTC);
988 bool firstUseEndpoint = initEndpointIfRequired(isWebRTC);
990 std::function<void(GstPromise * _promise, gpointer user_data)> cOnOfferReady =
991 [
this, holdSdp, sdpReady](GstPromise * _promise, gpointer user_data){
993 DebugLog(<<
"cOnOfferReady invoked");
994 GstWebRTCSessionDescription *_gstwebrtcoffer =
nullptr;
996 if(gst_promise_wait(_promise) != GST_PROMISE_RESULT_REPLIED)
1003 Gst::Structure reply((GstStructure*)gst_promise_get_reply (_promise));
1004 gst_structure_get (reply.gobj(),
"offer",
1005 GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &_gstwebrtcoffer, NULL);
1006 if(!_gstwebrtcoffer)
1008 Glib::Error __error;
1009 reply.get_field<Glib::Error>(
"error", __error);
1010 ErrLog(<<
"failed to get SDP offer: " << __error.what());
1011 gst_promise_unref (_promise);
1012 sdpReady(
false,
nullptr);
1015 gst_promise_unref (_promise);
1017 setLocalDescription(_gstwebrtcoffer);
1020 std::shared_ptr<SdpContents> _offer(createSdpContentsFromGstreamer(_gstwebrtcoffer));
1021 gst_webrtc_session_description_free (_gstwebrtcoffer);
1032 std::function<void()> cConnected = [
this, cOnOfferReady, sdpReady, isWebRTC]{
1044 GstPromise *promise;
1045 std::function<void(GstPromise * _promise, gpointer user_data)> *_cOnOfferReady =
1046 new std::function<void(GstPromise * _promise, gpointer user_data)>(cOnOfferReady);
1047 promise = gst_promise_new_with_change_func (
promise_stub, _cOnOfferReady,
1053 bool sendAudio =
true;
1054 bool sendVideo =
true;
1055 std::unique_ptr<SdpContents> offer(
dynamic_cast<SdpContents*
>(
mRtpSession->buildOffer(sendAudio, sendVideo)->clone()));
1058 DebugLog(<<
"built offer: " << *offer);
1060 sdpReady(
true, std::move(offer));
1064 if(firstUseEndpoint)
1066 CallbackSdpReady _sdpReady = [
this, sdpReady](
bool sdpOk, std::unique_ptr<resip::SdpContents> sdp)
1070 sdpReady(
false, std::move(sdp));
1074 sdpReady(
true, std::move(sdp));
1077 createAndConnectElements(isWebRTC, cConnected, _sdpReady);
1087 std::ostringstream offerMangledBuf;
1090 std::shared_ptr<std::string> offerMangledStr = std::make_shared<std::string>(offerMangledBuf.str());
1097 ErrLog(<<
"something went wrong: " << e.what());
1098 sdpReady(
false,
nullptr);
1103GstRemoteParticipant::onGstBusMessage(
const RefPtr<Gst::Bus>&,
const RefPtr<Gst::Message>& message)
1105 switch(message->get_message_type())
1107 case Gst::MESSAGE_EOS:
1108 ErrLog(<<
"End of stream");
1111 case Gst::MESSAGE_ERROR:
1114 std::string debug_message;
1115 RefPtr<MessageError>::cast_static(message)->parse(error, debug_message);
1116 ErrLog(<<
"Error: " << error.what() << std::endl << debug_message);
1120 case Gst::MESSAGE_STATE_CHANGED:
1123 case Gst::MESSAGE_NEW_CLOCK:
1126 case Gst::MESSAGE_STREAM_STATUS:
1131 ErrLog(<<
"unhandled Bus Message: " << message->get_message_type());
1139GstRemoteParticipant::buildSdpAnswer(
const SdpContents& offer, CallbackSdpReady sdpReady)
1141 bool requestSent =
false;
1143 std::shared_ptr<SdpContents> offerMangled(
dynamic_cast<SdpContents*
>(offer.
clone()));
1147 DebugLog(<<
"more than 2 media descriptors, removing the last");
1148 offerMangled->session().media().pop_back();
1155 bool isWebRTC = offerMangled->session().isWebRTC();
1156 DebugLog(<<
"peer is " << (isWebRTC ?
"WebRTC":
"not WebRTC"));
1158 initRtpSession(isWebRTC);
1173 std::shared_ptr<GstWebRTCSessionDescription> gstwebrtcoffer;
1176 gstwebrtcoffer = createGstWebRTCSessionDescriptionFromSdpContents(GST_WEBRTC_SDP_TYPE_OFFER, *offerMangled);
1179 ErrLog(<<
"failed to convert offer to GstWebRTCSessionDescription");
1180 sdpReady(
false,
nullptr);
1186 std::shared_ptr<SdpContents> answer =
mRtpSession->buildAnswer(offerMangled);
1188 DebugLog(<<
"built answer: " << *answer);
1191 bool firstUseEndpoint = initEndpointIfRequired(isWebRTC);
1193 std::function<void(GstPromise* _promise, gpointer user_data)> cAnswerCreated =
1194 [
this, sdpReady](GstPromise * _promise, gpointer user_data)
1196 DebugLog(<<
"cAnswerCreated invoked");
1198 if(gst_promise_wait(_promise) != GST_PROMISE_RESULT_REPLIED)
1203 GstWebRTCSessionDescription *_gstwebrtcanswer = NULL;
1206 Gst::Structure reply((GstStructure*)gst_promise_get_reply (_promise));
1210 gst_structure_get (reply.gobj(),
"answer",
1211 GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &_gstwebrtcanswer, NULL);
1212 if(!_gstwebrtcanswer)
1214 Glib::Error __error;
1215 reply.get_field<Glib::Error>(
"error", __error);
1216 ErrLog(<<
"failed to get SDP answer: " << __error.what());
1217 gst_promise_unref (_promise);
1218 sdpReady(
false,
nullptr);
1221 gst_promise_unref (_promise);
1223 setLocalDescription(_gstwebrtcanswer);
1225 std::unique_ptr<SdpContents> _answer(createSdpContentsFromGstreamer(_gstwebrtcanswer));
1226 gst_webrtc_session_description_free (_gstwebrtcanswer);
1236 std::function<void()> cConnected = [
this, isWebRTC, cAnswerCreated, gstwebrtcoffer, offerMangled, sdpReady]() {
1240 DebugLog(<<
"submitting SDP offer to Gstreamer element");
1241 GstPromise *_promise =
nullptr;
1243 setRemoteDescription(gstwebrtcoffer.get());
1245 std::function<void(GstPromise * _promise, gpointer user_data)> *_cAnswerCreated =
1246 new std::function<void(GstPromise * _promise, gpointer user_data)>(cAnswerCreated);
1247 _promise = gst_promise_new_with_change_func (
promise_stub, _cAnswerCreated,
1258 sdpReady(
true, std::move(answer));
1264 DebugLog(<<
"request SDP answer from Gstreamer");
1268 CallbackSdpReady _sdpReady = [
this, offerMangled, sdpReady](
bool sdpOk, std::unique_ptr<resip::SdpContents> sdp)
1272 sdpReady(
false, std::move(sdp));
1277 sdpReady(
true, std::move(sdp));
1280 if(firstUseEndpoint)
1282 createAndConnectElements(isWebRTC, cConnected, _sdpReady);
1357 ErrLog(<<
"something went wrong: " << e.what());
1358 requestSent =
false;
1363 sdpReady(
false,
nullptr);
1376 std::shared_ptr<SdpContents> remoteSdp =
getRemoteSdp();
1382 if(!remoteDirection.
recv())
1393 DebugLog(<<
"remoteSdp has changed, sending to Gstreamer");
1395 if(isWebRTCSession())
1397 std::shared_ptr<GstWebRTCSessionDescription> gstwebrtcanswer =
1398 createGstWebRTCSessionDescriptionFromSdpContents(GST_WEBRTC_SDP_TYPE_ANSWER, *remoteSdp);
1399 if(!gstwebrtcanswer)
1401 ErrLog(<<
"failed to convert offer to GstWebRTCSessionDescription");
1405 setRemoteDescription(gstwebrtcanswer.get());
1423 for(
int i = 1000; i <= 5000; i+=1000)
1425 std::chrono::milliseconds _i = std::chrono::milliseconds(i);
1426 std::chrono::milliseconds __i = std::chrono::milliseconds(i + 500);
1494 auto now = std::chrono::steady_clock::now();
1497 DebugLog(<<
"keyframe request ignored, too soon");
1500 mLastLocalKeyframeRequest = now;
1501 InfoLog(<<
"onMediaControlEvent: sending to Gst");
1508 WarningLog(<<
"rejecting MediaControlEvent due to config option mWSAcceptsKeyframeRequests");
1514GstRemoteParticipant::onRemoteIceCandidate(
const resip::Data& candidate,
unsigned int lineIndex,
const resip::Data& mid)
1523 DebugLog(<<
"onTrickleIce: sending to Gst");
1527 for(
auto m = trickleIce.
media().cbegin(); m != trickleIce.
media().cend(); m++)
1529 if(m->exists(
"mid"))
1531 const Data& mid = m->getValues(
"mid").front();
1533 if(m->exists(
"candidate"))
1535 for(
const auto& c : m->getValues(
"candidate"))
1537 onRemoteIceCandidate(c, mLineIndex, mid);
1543 WarningLog(<<
"mid is missing for Medium in SDP fragment: " << trickleIce);
1553 DebugLog(<<
"requestKeyframe from local encoder");
1555 Gst::Structure gSTForceKeyUnit(
"GstForceKeyUnit",
1556 "all-headers",
true);
1561 RefPtr<Pad>
pad = *it;
1565 RefPtr<Pad> peer =
pad->get_peer();
1566 RefPtr<Caps> caps =
pad->get_current_caps();
1569 if(caps->get_structure(0).has_field(
"media"))
1572 caps->get_structure(0).get_field(
"media", mediaName);
1573 StackLog(<<
"mediaName: " << mediaName);
1574 if(mediaName ==
"video")
1576 RefPtr<Gst::Event> _e = Glib::wrap(gst_event_new_custom(GST_EVENT_CUSTOM_UPSTREAM,
1577 gSTForceKeyUnit.gobj_copy()));
1578 peer->send_event(_e);
1584 DebugLog(<<
"no peer or no caps for this pad");
void promise_stub(GstPromise *promise, void *u)
void voidStub(GstElement *webrtcbin, void *u)
void sendCapsEvent(RefPtr< Bin > bin, RefPtr< Caps > caps)
static const Data pad("\0\0\0\0\0\0\0", 7)
#define WarningLog(args_)
#define resip_assert(x)
This file needs to work for both C and C++ code.
This class is one of two main classes of concern to an application using the UserAgent library.
virtual void requestKeyframeFromPeer(ParticipantHandle partHandle, std::chrono::duration< double > durationMs)
MediaStackAdapter & getMediaStackAdapter()
virtual void requestKeyframe(ParticipantHandle partHandle, std::chrono::duration< double > durationMs)
std::shared_ptr< resip::ConfigParse > getConfig()
This class extends the resip UserProfile to include Conversation Manager specific settings.
This class is used to manage membership of participants.
This is the base class for a GstRemoteParticipant, GstLocalParticipant and a GstMediaResourceParticip...
GstMediaStackAdapter & mGstMediaStackAdapter
virtual int getMediaConnectionId()
bool mWSAcceptsKeyframeRequests
virtual void applyBridgeMixWeights() override
resip::SdpContents * mLastRemoteSdp
virtual void buildSdpOffer(bool holdSdp, CallbackSdpReady sdpReady, bool preferExistingSdp=false)
virtual bool onMediaControlEvent(resip::MediaControlContents::MediaControl &mediaControl)
virtual void requestKeyframe() override
virtual ~GstRemoteParticipant()
Glib::RefPtr< Gst::Element > mRtpTransportElement
virtual void removeFromConversation(Conversation *conversation) override
Glib::RefPtr< Gst::Element > mMediaBin
virtual void waitingMode()
GstRemoteParticipant(ParticipantHandle partHandle, ConversationManager &conversationManager, GstMediaStackAdapter &gstreamerMediaStackAdapter, resip::DialogUsageManager &dum, RemoteParticipantDialogSet &remoteParticipantDialogSet)
virtual int getConnectionPortOnBridge()
virtual void adjustRTPStreams(bool sendingOffer=false)
virtual int getMediaConnectionId()
bool mRemoveExtraMediaDescriptors
virtual bool mediaStackPortAvailable()
std::shared_ptr< resipgst::GstRtpSession > mRtpSession
std::shared_ptr< resipgst::GstRtpManager > mRtpManager
virtual bool onTrickleIce(resip::TrickleIceContents &trickleIce) override
virtual GstRemoteParticipantDialogSet & getGstDialogSet()
virtual void addToConversation(Conversation *conversation, unsigned int inputGain=100, unsigned int outputGain=100) override
Glib::RefPtr< Gst::Pipeline > mPipeline
This is the base class for a RemoteParticipant, LocalParticipant and a MediaResourceParticipant.
virtual void unregisterFromAllConversations()
ParticipantHandle mHandle
ConversationManager & mConversationManager
This class is used by Invite DialogSets.
virtual std::shared_ptr< resip::SdpContents > getProposedSdp()
This class represent a remote participant.
void setProposedSdp(const resip::SdpContents &sdp)
void setRemoteSdp(const resip::SdpContents &sdp, bool answer=false)
virtual std::chrono::duration< double > getKeyframeRequestInterval() const
virtual void onLocalIceCandidate(const resip::Data &candidate, unsigned int lineIndex, const resip::Data &mid)
std::function< void(bool sdpOk, std::unique_ptr< resip::SdpContents > sdp)> CallbackSdpReady
void setLocalSdp(const resip::SdpContents &sdp)
void setLocalSdpGathering(const resip::SdpContents &sdp)
virtual void addToConversation(Conversation *conversation, unsigned int inputGain=100, unsigned int outputGain=100) override
std::shared_ptr< resip::SdpContents > getLocalSdp()
virtual void removeFromConversation(Conversation *conversation) override
std::shared_ptr< resip::SdpContents > getRemoteSdp()
virtual void requestKeyframeFromPeer()
void setRemoteHold(bool remoteHold)
RemoteParticipantDialogSet & getDialogSet()
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
const char * c_str() const
Returns a null-terminated string representing.
bool empty() const noexcept
Checks whether the Data is empty.
int convertInt() const
Takes the contents of the Data and converts them to an integer.
Provides an interface to process and generate SDP bodies (MIME content-type application/sdp).
virtual Contents * clone() const
duplicate an SdpContents object
const SdpContents::Session::MediumContainer & media() const
unsigned int ParticipantHandle
dcm! – add UnusedChecking(_enum) below;