reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
LibWebRTCRemoteParticipant.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
6
8#include "Conversation.hxx"
9#include "UserAgent.hxx"
10#include "DtmfEvent.hxx"
11#include "ReconSubsystem.hxx"
12
13#include <rutil/Log.hxx>
14#include <rutil/Logger.hxx>
15#include <rutil/DnsUtil.hxx>
16#include <rutil/Random.hxx>
27
29
30#include <utility>
31
32using namespace recon;
33using namespace resip;
34using namespace std;
35
36#define RESIPROCATE_SUBSYSTEM ReconSubsystem::RECON
37
38/* Technically, there are a range of features that need to be implemented
39 to be fully (S)AVPF compliant.
40 However, it is speculated that (S)AVPF peers will communicate with legacy
41 systems that just fudge the RTP/SAVPF protocol in their SDP. Enabling
42 this define allows such behavior to be tested.
43
44 http://www.ietf.org/mail-archive/web/rtcweb/current/msg01145.html
45 "1) RTCWEB end-point will always signal AVPF or SAVPF. I signalling
46 gateway to legacy will change that by removing the F to AVP or SAVP."
47
48 http://www.ietf.org/mail-archive/web/rtcweb/current/msg04380.html
49*/
50//#define RTP_SAVPF_FUDGE
51
52// UAC
54 ConversationManager& conversationManager,
55 LibWebRTCMediaStackAdapter& libwebrtcMediaStackAdapter,
57 RemoteParticipantDialogSet& remoteParticipantDialogSet)
58: Participant(partHandle, ConversationManager::ParticipantType_Remote, conversationManager),
59 RemoteParticipant(partHandle, conversationManager, dum, remoteParticipantDialogSet),
60 LibWebRTCParticipant(partHandle, ConversationManager::ParticipantType_Remote, conversationManager, libwebrtcMediaStackAdapter),
61 mRemoveExtraMediaDescriptors(false),
62 mSipRtpEndpoint(true),
63 mReuseSdpAnswer(false),
64 mWSAcceptsKeyframeRequests(true),
65 mLastRemoteSdp(0),
66 mWaitingAnswer(false),
67 mWebRTCOutgoing(getDialogSet().getConversationProfile()->mediaEndpointMode() == ConversationProfile::WebRTC)
68{
69 InfoLog(<< "LibWebRTCRemoteParticipant created (UAC), handle=" << mHandle);
70}
71
72// UAS - or forked leg
74 LibWebRTCMediaStackAdapter& libwebrtcMediaStackAdapter,
76 RemoteParticipantDialogSet& remoteParticipantDialogSet)
77: Participant(ConversationManager::ParticipantType_Remote, conversationManager),
78 RemoteParticipant(conversationManager, dum, remoteParticipantDialogSet),
79 LibWebRTCParticipant(ConversationManager::ParticipantType_Remote, conversationManager, libwebrtcMediaStackAdapter),
80 mRemoveExtraMediaDescriptors(false),
81 mSipRtpEndpoint(true),
82 mReuseSdpAnswer(false),
83 mWSAcceptsKeyframeRequests(true),
84 mLastRemoteSdp(0),
85 mWaitingAnswer(false),
86 mWebRTCOutgoing(getDialogSet().getConversationProfile()->mediaEndpointMode() == ConversationProfile::WebRTC)
87{
88 InfoLog(<< "LibWebRTCRemoteParticipant created (UAS or forked leg), handle=" << mHandle);
89}
90
92{
93 // Note: Ideally this call would exist in the Participant Base class - but this call requires
94 // dynamic_casts and virtual methods to function correctly during destruction.
95 // If the call is placed in the base Participant class then these things will not
96 // function as desired because a classes type changes as the descructors unwind.
97 // See https://stackoverflow.com/questions/10979250/usage-of-this-in-destructor.
99
100 InfoLog(<< "LibWebRTCRemoteParticipant destroyed, handle=" << mHandle);
101}
102
103int
105{
106 if(getDialogSet().getActiveRemoteParticipantHandle() == mHandle)
107 {
108 return -1; // FIXME LibWebRTC
109 }
110 else
111 {
112 // If this is not active fork leg, then we don't want to effect the bridge mixer.
113 // Note: All forked endpoints/participants have the same connection port on the bridge
114 return -1;
115 }
116}
117
118int
123
124void
126{
127 // FIXME LibWebRTC - do we need to implement this?
128}
129
130// Special version of this call used only when a participant
131// is removed from a conversation. Required when sipXConversationMediaInterfaceMode
132// is used, in order to get a pointer to the bridge mixer
133// for a participant (ie. LocalParticipant) that has no currently
134// assigned conversations.
135void
137{
138 // FIXME LibWebRTC - do we need to implement this?
139}
140
141libwebrtc::BaseRtpEndpoint*
142LibWebRTCRemoteParticipant::newEndpoint()
143{
144 return mSipRtpEndpoint ?
145 dynamic_cast<libwebrtc::BaseRtpEndpoint*>(new libwebrtc::SipRtpEndpoint(mLibWebRTCMediaStackAdapter.mPipeline)) :
146 dynamic_cast<libwebrtc::BaseRtpEndpoint*>(new libwebrtc::RtpEndpoint(mLibWebRTCMediaStackAdapter.mPipeline));
147}
148
149bool
150LibWebRTCRemoteParticipant::initEndpointIfRequired(bool isWebRTC)
151{
152 if(mEndpoint)
153 {
154 return false;
155 }
156 if(isWebRTC)
157 {
158 // delay while ICE gathers candidates from STUN and TURN
159 mIceGatheringDone = false;
160 mEndpoint.reset(new libwebrtc::WebRtcEndpoint(mLibWebRTCMediaStackAdapter.mPipeline));
161 }
162 else
163 {
164 mIceGatheringDone = true;
165 mEndpoint.reset(newEndpoint());
166 }
167
168 //mMultiqueue.reset(new libwebrtc::GStreamerFilter(mLibWebRTCMediaStackAdapter.mPipeline, "videoconvert"));
169 //mMultiqueue.reset(new libwebrtc::PassThroughElement(mLibWebRTCMediaStackAdapter.mPipeline));
170 std::shared_ptr<resip::ConfigParse> cfg = mConversationManager.getConfig();
171 if(cfg)
172 {
173 const Data& holdVideo = mConversationManager.getConfig()->getConfigData("HoldVideo", "file:///tmp/test.mp4", true);
174 mPlayer.reset(new libwebrtc::PlayerEndpoint(mLibWebRTCMediaStackAdapter.mPipeline, holdVideo.c_str()));
175 }
176 mPassThrough.reset(new libwebrtc::PassThroughElement(mLibWebRTCMediaStackAdapter.mPipeline));
177
178 return true;
179}
180
181void
182LibWebRTCRemoteParticipant::doIceGathering(libwebrtc::ContinuationString sdpReady)
183{
184 std::shared_ptr<libwebrtc::WebRtcEndpoint> webRtc = std::static_pointer_cast<libwebrtc::WebRtcEndpoint>(mEndpoint);
185
186 std::shared_ptr<libwebrtc::EventContinuation> elEventIceCandidateFound =
187 std::make_shared<libwebrtc::EventContinuation>([this](std::shared_ptr<libwebrtc::Event> event){
188 DebugLog(<<"received event: " << *event);
189 std::shared_ptr<libwebrtc::OnIceCandidateFoundEvent> _event =
190 std::dynamic_pointer_cast<libwebrtc::OnIceCandidateFoundEvent>(event);
191 resip_assert(_event.get());
192
194 {
195 return;
196 }
197 // FIXME - if we are waiting for a previous INFO to be confirmed,
198 // aggregate the candidates into a vector and send them in bulk
199 auto ice = getLocalSdp()->session().makeIceFragment(Data(_event->getCandidate()),
200 _event->getLineIndex(), Data(_event->getId()));
201 if(ice.get())
202 {
203 StackLog(<<"about to send " << *ice);
204 info(*ice);
205 }
206 else
207 {
208 WarningLog(<<"failed to create ICE fragment for mid: " << _event->getId());
209 }
210 });
211
212 std::shared_ptr<libwebrtc::EventContinuation> elIceGatheringDone =
213 std::make_shared<libwebrtc::EventContinuation>([this, sdpReady](std::shared_ptr<libwebrtc::Event> event){
214 mIceGatheringDone = true;
215 mEndpoint->getLocalSessionDescriptor(sdpReady);
216 });
217
218 webRtc->addOnIceCandidateFoundListener(elEventIceCandidateFound, [=](){
219 webRtc->addOnIceGatheringDoneListener(elIceGatheringDone, [=](){
220 webRtc->gatherCandidates([]{
221 // FIXME - handle the case where it fails
222 // on success, we continue from the IceGatheringDone event handler
223 }); // gatherCandidates
224 });
225 });
226}
227
228void
229LibWebRTCRemoteParticipant::createAndConnectElements(libwebrtc::ContinuationVoid cConnected)
230{
231 // FIXME - implement listeners for some of the events currently using elEventDebug
232
233 std::shared_ptr<libwebrtc::EventContinuation> elError =
234 std::make_shared<libwebrtc::EventContinuation>([this](std::shared_ptr<libwebrtc::Event> event){
235 ErrLog(<<"Error from LibWebRTC MediaObject: " << *event);
236 });
237
238 std::shared_ptr<libwebrtc::EventContinuation> elEventDebug =
239 std::make_shared<libwebrtc::EventContinuation>([this](std::shared_ptr<libwebrtc::Event> event){
240 DebugLog(<<"received event: " << *event);
241 });
242
243 std::shared_ptr<libwebrtc::EventContinuation> elEventKeyframeRequired =
244 std::make_shared<libwebrtc::EventContinuation>([this](std::shared_ptr<libwebrtc::Event> event){
245 DebugLog(<<"received event: " << *event);
247 });
248
249 mEndpoint->create([=]{
250 mEndpoint->addErrorListener(elError, [=](){
251 mEndpoint->addConnectionStateChangedListener(elEventDebug, [=](){
252 mEndpoint->addMediaStateChangedListener(elEventDebug, [=](){
253 mEndpoint->addMediaTranscodingStateChangeListener(elEventDebug, [=](){
254 mEndpoint->addMediaFlowInStateChangeListener(elEventDebug, [=](){
255 mEndpoint->addMediaFlowOutStateChangeListener(elEventDebug, [=](){
256 mEndpoint->addKeyframeRequiredListener(elEventKeyframeRequired, [=](){
257 //mMultiqueue->create([this, cConnected]{
258 // mMultiqueue->connect([this, cConnected]{
259 mPlayer->create([this, cConnected]{
260 mPassThrough->create([this, cConnected]{
261 mEndpoint->connect([this, cConnected]{
262 mPassThrough->connect([this, cConnected]{
263 //mPlayer->play([this, cConnected]{
264 cConnected();
265 //mPlayer->connect(cConnected, *mEndpoint); // connect
266 //});
267 }, *mEndpoint);
268 }, *mPassThrough);
269 });
270 });
271 //}, *mEndpoint); // mEndpoint->connect
272 // }, *mEndpoint); // mMultiqueue->connect
273 //}); // mMultiqueue->create
274 }); // addKeyframeRequiredListener
275
276 });
277 });
278 });
279 });
280 });
281 });
282 }); // create
283}
284
285void
286LibWebRTCRemoteParticipant::buildSdpOffer(bool holdSdp, CallbackSdpReady sdpReady, bool preferExistingSdp)
287{
288 bool useExistingSdp = false;
289 if(getLocalSdp())
290 {
291 useExistingSdp = preferExistingSdp || mReuseSdpAnswer;
292 }
293
294 try
295 {
296 bool isWebRTC = mWebRTCOutgoing;
297 bool firstUseEndpoint = initEndpointIfRequired(isWebRTC);
298
299 libwebrtc::ContinuationString cOnOfferReady = [this, holdSdp, sdpReady](const std::string& offer){
300 StackLog(<<"offer FROM LibWebRTC: " << offer);
301 HeaderFieldValue hfv(offer.data(), offer.size());
302 Mime type("application", "sdp");
303 std::unique_ptr<SdpContents> _offer(new SdpContents(hfv, type));
304 _offer->session().transformLocalHold(holdSdp);
305 setProposedSdp(*_offer);
306 sdpReady(true, std::move(_offer));
307 };
308
309 libwebrtc::ContinuationVoid cConnected = [this, holdSdp, isWebRTC, sdpReady, cOnOfferReady]{
310 // FIXME - can we tell LibWebRTC to use holdSdp?
311 // We currently mangle the SDP after-the-fact in cOnOfferReady
312 mEndpoint->generateOffer([this, isWebRTC, sdpReady, cOnOfferReady](const std::string& offer){
313 mWaitingAnswer = true;
314 if(isWebRTC)
315 {
316 doIceGathering(cOnOfferReady);
317 }
318 else
319 {
320 cOnOfferReady(offer);
321 }
322 }); // generateOffer
323 };
324
325 if(firstUseEndpoint)
326 {
327 createAndConnectElements(cConnected);
328 }
329 else
330 {
331 if(!useExistingSdp)
332 {
333 cConnected();
334 }
335 else
336 {
337 std::ostringstream offerMangledBuf;
338 getLocalSdp()->session().transformLocalHold(isHolding());
339 offerMangledBuf << *getLocalSdp();
340 std::shared_ptr<std::string> offerMangledStr = std::make_shared<std::string>(offerMangledBuf.str());
341 cOnOfferReady(*offerMangledStr);
342 }
343 }
344 }
345 catch(exception& e)
346 {
347 ErrLog(<<"something went wrong: " << e.what());
348 sdpReady(false, nullptr);
349 }
350}
351
352void
353LibWebRTCRemoteParticipant::buildSdpAnswer(const SdpContents& offer, CallbackSdpReady sdpReady)
354{
355 bool requestSent = false;
356
357 std::shared_ptr<SdpContents> offerMangled = std::make_shared<SdpContents>(offer);
358 while(mRemoveExtraMediaDescriptors && offerMangled->session().media().size() > 2)
359 {
360 // FIXME hack to remove BFCP
361 DebugLog(<<"more than 2 media descriptors, removing the last");
362 offerMangled->session().media().pop_back();
363 }
364
365 try
366 {
367 // do some checks on the offer
368 // check for video, check for WebRTC
369 bool isWebRTC = offerMangled->session().isWebRTC();
370 DebugLog(<<"peer is " << (isWebRTC ? "WebRTC":"not WebRTC"));
371
372 if(!isWebRTC)
373 {
374 // RFC 4145 uses the attribute name "setup"
375 // We override the attribute name and use the legacy name "direction"
376 // from the drafts up to draft-ietf-mmusic-sdp-comedia-05.txt
377 // Tested with LibWebRTC and Cisco EX90
378 // https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-sdp-comedia-05
379 // https://datatracker.ietf.org/doc/html/rfc4145
380 offerMangled->session().transformCOMedia("active", "direction");
381 }
382
383 std::ostringstream offerMangledBuf;
384 offerMangledBuf << *offerMangled;
385 std::shared_ptr<std::string> offerMangledStr = std::make_shared<std::string>(offerMangledBuf.str());
386
387 StackLog(<<"offer TO LibWebRTC: " << *offerMangledStr);
388
389 bool firstUseEndpoint = initEndpointIfRequired(isWebRTC);
390
391 libwebrtc::ContinuationString cOnAnswerReady = [this, offerMangled, isWebRTC, sdpReady](const std::string& answer){
392 StackLog(<<"answer FROM LibWebRTC: " << answer);
393 HeaderFieldValue hfv(answer.data(), answer.size());
394 Mime type("application", "sdp");
395 std::unique_ptr<SdpContents> _answer(new SdpContents(hfv, type));
396 _answer->session().transformLocalHold(isHolding());
397 setLocalSdp(*_answer);
398 setRemoteSdp(*offerMangled);
399 sdpReady(true, std::move(_answer));
400 };
401
402 libwebrtc::ContinuationVoid cConnected = [this, offerMangled, offerMangledStr, isWebRTC, firstUseEndpoint, sdpReady, cOnAnswerReady]{
403 if(!firstUseEndpoint && mReuseSdpAnswer)
404 {
405 // FIXME - LibWebRTC should handle hold/resume
406 // but it fails with SDP_END_POINT_ALREADY_NEGOTIATED
407 // if we call processOffer more than once
408 std::ostringstream answerBuf;
409 answerBuf << *getLocalSdp();
410 std::shared_ptr<std::string> answerStr = std::make_shared<std::string>(answerBuf.str());
411 cOnAnswerReady(*answerStr);
412 return;
413 }
414 mEndpoint->processOffer([this, offerMangled, isWebRTC, sdpReady, cOnAnswerReady](const std::string& answer){
415 if(isWebRTC)
416 {
417 if(mTrickleIcePermitted && offerMangled->session().isTrickleIceSupported())
418 {
419 HeaderFieldValue hfv(answer.data(), answer.size());
420 Mime type("application", "sdp");
421 std::unique_ptr<SdpContents> _local(new SdpContents(hfv, type));
422 DebugLog(<<"storing incomplete webrtc answer");
423 setLocalSdp(*_local);
424 setRemoteSdp(*offerMangled);
425 ServerInviteSession* sis = dynamic_cast<ServerInviteSession*>(getInviteSessionHandle().get());
426 sis->provideAnswer(*_local);
427 sis->provisional(183, true);
428 //getDialogSet().provideAnswer(std::move(_local), getInviteSessionHandle(), false, true);
429 enableTrickleIce(); // now we are in early media phase, it is safe to send INFO
430
431 // FIXME - if we sent an SDP answer here,
432 // make sure we don't call provideAnswer again on 200 OK
433 }
434
435 doIceGathering(cOnAnswerReady);
436 }
437 else
438 {
439 cOnAnswerReady(answer);
440 }
441 }, *offerMangledStr); // processOffer
442 };
443
444 if(firstUseEndpoint)
445 {
446 createAndConnectElements(cConnected);
447 }
448 else
449 {
450 cConnected();
451 }
452
453 requestSent = true;
454 }
455 catch(exception& e)
456 {
457 ErrLog(<<"something went wrong: " << e.what()); // FIXME - add try/catch to Continuation
458 requestSent = false;
459 }
460
461 if(!requestSent)
462 {
463 sdpReady(false, nullptr);
464 }
465}
466
467void
469{
470 // FIXME LibWebRTC - implement, may need to break up this method into multiple parts
471 StackLog(<<"adjustRTPStreams");
472
473 std::shared_ptr<SdpContents> localSdp = sendingOffer ? getDialogSet().getProposedSdp() : getLocalSdp();
474 resip_assert(localSdp);
475
476 std::shared_ptr<SdpContents> remoteSdp = getRemoteSdp();
477 bool remoteSdpChanged = remoteSdp.get() != mLastRemoteSdp; // FIXME - better way to do this?
478 mLastRemoteSdp = remoteSdp.get();
479 if(remoteSdp)
480 {
481 const SdpContents::Session::Direction& remoteDirection = remoteSdp->session().getDirection();
482 if(!remoteDirection.recv())
483 {
484 setRemoteHold(true);
485 }
486 else
487 {
488 setRemoteHold(false);
489 }
490 if(remoteSdpChanged && mWaitingAnswer)
491 {
492 // FIXME - maybe this should not be in adjustRTPStreams
493 DebugLog(<<"remoteSdp has changed, sending to LibWebRTC");
494 mWaitingAnswer = false;
495 std::ostringstream answerBuf;
496 answerBuf << *remoteSdp;
497 mEndpoint->processAnswer([this](const std::string updatedOffer){
498 // FIXME - use updatedOffer
499 WarningLog(<<"LibWebRTC has processed the peer's SDP answer");
500 StackLog(<<"updatedOffer FROM LibWebRTC: " << updatedOffer);
501 HeaderFieldValue hfv(updatedOffer.data(), updatedOffer.size());
502 Mime type("application", "sdp");
503 std::unique_ptr<SdpContents> _updatedOffer(new SdpContents(hfv, type));
504 _updatedOffer->session().transformLocalHold(isHolding());
505 setLocalSdp(*_updatedOffer);
506 //c(true, std::move(_updatedOffer));
507 }, answerBuf.str());
508 }
509 for(int i = 1000; i <= 5000; i+=1000)
510 {
511 std::chrono::milliseconds _i = std::chrono::milliseconds(i);
512 std::chrono::milliseconds __i = std::chrono::milliseconds(i + 500);
515 }
516 }
517}
518
519void
520LibWebRTCRemoteParticipant::addToConversation(Conversation *conversation, unsigned int inputGain, unsigned int outputGain)
521{
522 RemoteParticipant::addToConversation(conversation, inputGain, outputGain);
523}
524
525void
530
531bool
533{
534 return true; // FIXME LibWebRTC - can we check with LibWebRTC somehow?
535}
536
537void
539{
540 std::shared_ptr<libwebrtc::MediaElement> e = getWaitingModeElement();
541 if(!e)
542 {
543 return;
544 }
545 e->connect([this]{
546 DebugLog(<<"connected in waiting mode, waiting for peer");
548 {
549 mPlayer->play([this]{}); // FIXME LibWebRTC async
550 }
551 else
552 {
553 mEndpoint->connect([this]{
555 }, *mPassThrough); // FIXME LibWebRTC async
556 }
558 }, *mEndpoint);
559}
560
561std::shared_ptr<libwebrtc::MediaElement>
563{
565 {
566 return dynamic_pointer_cast<libwebrtc::Endpoint>(mPlayer);
567 }
568 else
569 {
570 return mPassThrough;
571 }
572}
573
574bool
576{
578 {
579 auto now = std::chrono::steady_clock::now();
580 if(now < (mLastLocalKeyframeRequest + getKeyframeRequestInterval()))
581 {
582 DebugLog(<<"keyframe request ignored, too soon");
583 return false;
584 }
585 mLastLocalKeyframeRequest = now;
586 InfoLog(<<"onMediaControlEvent: sending to LibWebRTC");
587 // FIXME - check the content of the event
588 mEndpoint->sendPictureFastUpdate([this](){}); // FIXME LibWebRTC async, do we need to wait for LibWebRTC here?
589 return true;
590 }
591 else
592 {
593 WarningLog(<<"rejecting MediaControlEvent due to config option mWSAcceptsKeyframeRequests");
594 return false;
595 }
596}
597
598bool
600{
601 DebugLog(<<"onTrickleIce: sending to LibWebRTC");
602 // FIXME - did we already receive a suitable SDP for trickle ICE and send it to LibWebRTC?
603 // if not, LibWebRTC is not ready for the candidates
604 // FIXME - do we need to validate the ice-pwd password attribute here?
605 std::shared_ptr<libwebrtc::WebRtcEndpoint> webRtc = std::static_pointer_cast<libwebrtc::WebRtcEndpoint>(mEndpoint);
606 for(auto m = trickleIce.media().cbegin(); m != trickleIce.media().cend(); m++)
607 {
608 if(m->exists("mid"))
609 {
610 const Data& mid = m->getValues("mid").front();
611 const std::string _mid = mid.c_str();
612 unsigned int mLineIndex = mid.convertInt(); // FIXME - calculate from the full SDP
613 if(m->exists("candidate"))
614 {
615 auto candidates = m->getValues("candidate");
616 for(auto a = candidates.cbegin(); a != candidates.cend(); a++)
617 {
618 webRtc->addIceCandidate([this](){},
619 a->c_str(),
620 _mid,
621 mLineIndex);
622 }
623 }
624 }
625 else
626 {
627 WarningLog(<<"mid is missing for Medium in SDP fragment: " << trickleIce);
628 return false;
629 }
630 }
631 return true;
632}
633
634void
636{
637 WarningLog(<<"requestKeyframe not implemented for this media stack"); // FIXME
638}
639
640/* ====================================================================
641
642 Copyright (c) 2022, Software Freedom Institute https://softwarefreedom.institute
643 Copyright (c) 2022, Daniel Pocock https://danielpocock.com
644 Copyright (c) 2021, SIP Spectrum, Inc.
645 Copyright (c) 2007-2008, Plantronics, Inc.
646 All rights reserved.
647
648 Redistribution and use in source and binary forms, with or without
649 modification, are permitted provided that the following conditions are
650 met:
651
652 1. Redistributions of source code must retain the above copyright
653 notice, this list of conditions and the following disclaimer.
654
655 2. Redistributions in binary form must reproduce the above copyright
656 notice, this list of conditions and the following disclaimer in the
657 documentation and/or other materials provided with the distribution.
658
659 3. Neither the name of Plantronics nor the names of its contributors
660 may be used to endorse or promote products derived from this
661 software without specific prior written permission.
662
663 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
664 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
665 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
666 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
667 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
668 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
669 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
670 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
671 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
672 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
673 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
674
675 ==================================================================== */
#define DebugLog(args_)
Definition Logger.hxx:128
#define StackLog(args_)
Definition Logger.hxx:125
#define InfoLog(args_)
Definition Logger.hxx:131
#define WarningLog(args_)
Definition Logger.hxx:134
#define ErrLog(args_)
Definition Logger.hxx:137
#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)
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 class is one of two main classes of concern to an application using the UserAgent library.
This is the base class for a LibWebRTCRemoteParticipant, LibWebRTCLocalParticipant and a LibWebRTCMed...
LibWebRTCMediaStackAdapter & mLibWebRTCMediaStackAdapter
virtual LibWebRTCRemoteParticipantDialogSet & getLibWebRTCDialogSet()
LibWebRTCRemoteParticipant(ParticipantHandle partHandle, ConversationManager &conversationManager, LibWebRTCMediaStackAdapter &libwebrtcMediaStackAdapter, resip::DialogUsageManager &dum, RemoteParticipantDialogSet &remoteParticipantDialogSet)
std::shared_ptr< libwebrtc::PassThroughElement > mPassThrough
virtual void addToConversation(Conversation *conversation, unsigned int inputGain=100, unsigned int outputGain=100) override
virtual void adjustRTPStreams(bool sendingOffer=false)
std::shared_ptr< libwebrtc::PlayerEndpoint > mPlayer
virtual std::shared_ptr< libwebrtc::MediaElement > getWaitingModeElement()
virtual bool onTrickleIce(resip::TrickleIceContents &trickleIce) override
virtual bool onMediaControlEvent(resip::MediaControlContents::MediaControl &mediaControl)
virtual void removeFromConversation(Conversation *conversation) override
virtual void buildSdpOffer(bool holdSdp, CallbackSdpReady sdpReady, bool preferExistingSdp=false)
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
std::function< void(bool sdpOk, std::unique_ptr< resip::SdpContents > sdp)> CallbackSdpReady
void setLocalSdp(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 info(const resip::Contents &contents)
virtual void removeFromConversation(Conversation *conversation) override
std::shared_ptr< resip::SdpContents > getRemoteSdp()
void setRemoteHold(bool remoteHold)
RemoteParticipantDialogSet & getDialogSet()
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
int convertInt() const
Takes the contents of the Data and converts them to an integer.
Definition Data.cxx:1684
Represents the "media-type" element in the RFC 3261 grammar.
Definition Mime.hxx:20
Provides an interface to process and generate SDP bodies (MIME content-type application/sdp).
const SdpContents::Session::MediumContainer & media() const
unsigned int ParticipantHandle
dcm! – add UnusedChecking(_enum) below;