Browse code

SBC: RTP relay mode switching

Václav Kubart authored on 14/09/2012 09:30:20
Showing 4 changed files
... ...
@@ -2,15 +2,11 @@
2 2
 #define __EXTENDED_CC_INTERFACE
3 3
 
4 4
 #include "CallLeg.h"
5
+#include "sbc_events.h"
5 6
 
6 7
 class SBCCallLeg;
7 8
 class SBCCallProfile;
8 9
 
9
-/** This ID should be used by all CC modules that produce B2B events. Because
10
- * CC modules are developped indepenedently it is not possible to synchronize
11
- * their B2B event IDs so only this one should be used. */
12
-#define CC_B2B_EVENT_ID (LAST_B2B_CALL_LEG_EVENT_ID + 1)
13
-
14 10
 struct InitialInviteHandlerParams
15 11
 {
16 12
   string remote_party;
... ...
@@ -1422,12 +1422,31 @@ bool SBCCallLeg::reinvite(const AmSdp &sdp, unsigned &request_cseq)
1422 1422
 
1423 1423
 void SBCCallLeg::changeRtpMode(RTPRelayMode new_mode)
1424 1424
 {
1425
+  if (new_mode == rtp_relay_mode) return; // requested mode is set already
1426
+
1427
+  if (getCallStatus() != CallLeg::Connected /*other_id.empty()*/) {
1428
+    ERROR("BUG: changeRtpMode supported for established calls only\n");
1429
+    return;
1430
+  }
1431
+
1425 1432
   // we don't need to send reINVITE from here, expecting caller knows what is he
1426 1433
   // doing (it is probably processing or generating its own reINVITE)
1427 1434
   // Switch from RTP_Direct to RTP_Relay is safe (no audio loss), the other can
1428 1435
   // be lossy because already existing media object would be destroyed.
1429 1436
   // FIXME: use AmB2BMedia in all RTP relay modes to avoid these problems?
1430
-  ERROR("BUG: not implemented yet\n");
1437
+  switch (rtp_relay_mode) {
1438
+    case RTP_Relay:
1439
+      clearRtpReceiverRelay();
1440
+      break;
1441
+
1442
+    case RTP_Direct:
1443
+      // create new blablabla
1444
+      setMediaSession(new AmB2BMedia(a_leg ? this: NULL, a_leg ? NULL : this));
1445
+      break;
1446
+  }
1447
+
1448
+  relayEvent(new ChangeRtpModeEvent(new_mode, getMediaSession()));
1449
+  setRtpRelayMode(new_mode);
1431 1450
 }
1432 1451
 
1433 1452
 void SBCCallLeg::initCCModules(const AmSipRequest &original_invite)
... ...
@@ -1436,3 +1455,29 @@ void SBCCallLeg::initCCModules(const AmSipRequest &original_invite)
1436 1455
     (*i)->init(this, original_invite);
1437 1456
   }
1438 1457
 }
1458
+
1459
+void SBCCallLeg::onB2BEvent(B2BEvent* ev)
1460
+{
1461
+  if (ev->event_id == ChangeRtpModeEventId) {
1462
+    INFO("*** B2B request to change RTP mode\n");
1463
+    ChangeRtpModeEvent *e = dynamic_cast<ChangeRtpModeEvent*>(ev);
1464
+    if (e) {
1465
+      if (e->new_mode == rtp_relay_mode) return; // requested mode is set already
1466
+
1467
+      switch (rtp_relay_mode) {
1468
+        case RTP_Relay:
1469
+          clearRtpReceiverRelay();
1470
+          break;
1471
+
1472
+        case RTP_Direct:
1473
+          // create new blablabla
1474
+          setMediaSession(e->media);
1475
+          media_session->changeSession(a_leg, this);
1476
+          break;
1477
+      }
1478
+      setRtpRelayMode(e->new_mode);
1479
+    }
1480
+  }
1481
+
1482
+  CallLeg::onB2BEvent(ev);
1483
+}
... ...
@@ -3,6 +3,7 @@
3 3
 
4 4
 #include "SBC.h"
5 5
 #include "ExtendedCCInterface.h"
6
+#include "sbc_events.h"
6 7
 
7 8
 class PayloadIdMapping
8 9
 {
... ...
@@ -106,6 +107,7 @@ class SBCCallLeg : public CallLeg, public CredentialHolder
106 107
   ~SBCCallLeg();
107 108
 
108 109
   void process(AmEvent* ev);
110
+  void onB2BEvent(B2BEvent* ev);
109 111
   void onBye(const AmSipRequest& req);
110 112
   void onInvite(const AmSipRequest& req);
111 113
   void onCancel(const AmSipRequest& cancel);
112 114
new file mode 100644
... ...
@@ -0,0 +1,30 @@
1
+#ifndef __SBC_EVENTS_H
2
+#define __SBC_EVENTS_H
3
+
4
+#include "CallLeg.h"
5
+
6
+enum {
7
+  ChangeRtpModeEventId = LAST_B2B_CALL_LEG_EVENT_ID + 1,
8
+
9
+  /** This ID should be used by all CC modules that produce B2B events. Because
10
+   * CC modules are developped indepenedently it is not possible to synchronize
11
+   * their B2B event IDs so only this one should be used. */
12
+  CCB2BEventId
13
+};
14
+
15
+/* we don't need to have 'reliable event' for this because we are always
16
+ * connected to SBCCallLeg, right? */
17
+struct ChangeRtpModeEvent: public B2BEvent
18
+{
19
+  AmB2BSession::RTPRelayMode new_mode;
20
+  AmB2BMedia *media; // avoid direct access to this
21
+
22
+  ChangeRtpModeEvent(AmB2BSession::RTPRelayMode _new_mode, AmB2BMedia *_media):
23
+    B2BEvent(ChangeRtpModeEventId), new_mode(_new_mode), media(_media)
24
+    { if (media) media->addReference(); }
25
+
26
+  virtual ~ChangeRtpModeEvent() { if (media && media->releaseReference()) delete media; }
27
+};
28
+
29
+
30
+#endif