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