]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Update the rtp endpoint so it gets a fixed configuration from var_event
authorMathieu Rene <mrene@avgs.ca>
Mon, 16 Jul 2012 22:31:13 +0000 (18:31 -0400)
committerMathieu Rene <mrene@avgs.ca>
Mon, 16 Jul 2012 22:31:13 +0000 (18:31 -0400)
src/mod/endpoints/mod_sofia/rtp.c

index 9deddf59227771a1eff7e9293c1f40d42d7beaff..a269ec6cc91565ae20b6d38d1507e47cecfb1033 100644 (file)
 #include <switch.h>
 #include "mod_sofia.h"
 
-#define kBINDADDRESS "bind_address"
 #define kLOCALADDR "local_addr"
 #define kLOCALPORT "local_port"
 #define kREMOTEADDR "remote_addr"
 #define kREMOTEPORT "remote_port"
 #define kCODEC "codec"
 #define kPTIME "ptime"
+#define kPT "pt"
 #define kRFC2833PT "rfc2833_pt"
 #define kMODE "mode"
+#define kRATE "rate"
 
 static struct {
     switch_memory_pool_t *pool;
@@ -53,10 +54,15 @@ typedef struct {
     switch_codec_t read_codec, write_codec;
     switch_frame_t read_frame;
     
+
+    
     switch_rtp_bug_flag_t rtp_bugs;
     switch_rtp_t *rtp_session;
     
-    const char *bind_address;
+    uint32_t timestamp_send;
+    
+    const char *local_address;
+    const char *remote_address;
     const char *codec;
     int ptime;
     
@@ -67,6 +73,8 @@ typedef struct {
     
     switch_port_t local_port;
     switch_port_t remote_port;
+    switch_payload_t agreed_pt; /*XXX*/
+    sofia_dtmf_t dtmf_type;
 
 } crtp_private_t;
 
@@ -100,7 +108,7 @@ void crtp_init(switch_loadable_module_interface_t *module_interface)
 {
     switch_endpoint_interface_t *endpoint_interface;
     //switch_api_interface_t *api_interface;
-    
+
     crtp.pool = module_interface->pool;
     endpoint_interface = switch_loadable_module_create_interface(module_interface, SWITCH_ENDPOINT_INTERFACE);
     endpoint_interface->interface_name = "rtp";
@@ -119,11 +127,30 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
 {
     switch_channel_t *channel;
     char name[128];
-    const char *dname = "PCMU";
-    uint32_t interval = 20;
-    crtp_private_t *tech_pvt = NULL;
-    //const char *l_sdp = switch_event_get_header(var_event, kLSDP);
-    //const char *codec_string = switch_event_get_header_nil(var_event, kCODECSTRING);
+    crtp_private_t *tech_pvt = NULL;    
+    
+    const char *err;
+    
+    const char  *local_addr = switch_event_get_header_nil(var_event, kLOCALADDR),
+                *szlocal_port = switch_event_get_header_nil(var_event, kLOCALPORT),
+                *remote_addr = switch_event_get_header_nil(var_event, kREMOTEADDR),
+                *szremote_port = switch_event_get_header_nil(var_event, kREMOTEPORT),
+                *codec  = switch_event_get_header_nil(var_event, kCODEC),
+                *szptime  = switch_event_get_header_nil(var_event, kPTIME),
+                *mode  = switch_event_get_header_nil(var_event, kMODE),
+                *szrfc2833_pt = switch_event_get_header_nil(var_event, kRFC2833PT),
+                *szrate = switch_event_get_header_nil(var_event, kRATE),
+                *szpt = switch_event_get_header_nil(var_event, kPT);
+    
+    
+    switch_port_t local_port = !zstr(szlocal_port) ? atoi(szlocal_port) : 0,
+                 remote_port = !zstr(szremote_port) ? atoi(szremote_port) : 0;
+    
+    int ptime  = !zstr(szptime) ? atoi(szptime) : 0,
+        rfc2833_pt = !zstr(szrfc2833_pt) ? atoi(szrfc2833_pt) : 0,
+        rate = !zstr(szrate) ? atoi(szrate) : 8000,
+        pt = !zstr(szpt) ? atoi(szpt) : 0;
+
 
     
     if (!(*new_session = switch_core_session_request(crtp.endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, 0, pool))) {
@@ -133,41 +160,45 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
     
     channel = switch_core_session_get_channel(*new_session);
     
-    
-    
     tech_pvt = switch_core_session_alloc(*new_session, sizeof *tech_pvt);
     tech_pvt->session = *new_session;
     tech_pvt->channel = channel;
-    tech_pvt->bind_address = switch_core_session_strdup(*new_session, switch_event_get_header_nil(var_event, kBINDADDRESS));
+    tech_pvt->local_address = switch_core_session_strdup(*new_session, local_addr);
+    tech_pvt->local_port = local_port;
+    tech_pvt->remote_address = switch_core_session_strdup(*new_session, remote_addr);
+    tech_pvt->remote_port = remote_port;
+    tech_pvt->ptime = ptime;
+    tech_pvt->agreed_pt = pt;
+    tech_pvt->dtmf_type = DTMF_2833; /* XXX */
+    
     switch_core_session_set_private(*new_session, tech_pvt);
     
     
-    snprintf(name, sizeof(name), "rtp/ctrl"); /* TODO add addresses */
+    snprintf(name, sizeof(name), "rtp/ctrl");
        switch_channel_set_name(channel, name);
     
     switch_channel_set_state(channel, CS_INIT);
 
        if (switch_core_codec_init(&tech_pvt->read_codec,
-                                                          dname,
+                                                          codec,
                                                           NULL,
-                                                          8000,
-                                                          interval,
+                                                          rate,
+                                                          ptime,
                                                           1,
-                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+                                                          /*SWITCH_CODEC_FLAG_ENCODE |*/ SWITCH_CODEC_FLAG_DECODE,
                                                           NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
         goto fail;
        } else {
                if (switch_core_codec_init(&tech_pvt->write_codec,
-                                                                  dname,
+                                                                  codec,
                                                                   NULL,
-                                                                  8000,
-                                                                  interval,
+                                                                  rate,
+                                                                  ptime,
                                                                   1,
-                                                                  SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+                                                                  SWITCH_CODEC_FLAG_ENCODE /*| SWITCH_CODEC_FLAG_DECODE*/,
                                                                   NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
-                       switch_core_codec_destroy(&tech_pvt->read_codec);
             goto fail;
                }
        }
@@ -178,7 +209,15 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
     }
     
     if (switch_core_session_set_write_codec(*new_session, &tech_pvt->write_codec) != SWITCH_STATUS_SUCCESS) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set write codec?\n");        
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set write codec?\n");
+        goto fail;
+    }
+    
+    if (!(tech_pvt->rtp_session = switch_rtp_new(local_addr, local_port, remote_addr, remote_port, tech_pvt->agreed_pt,
+                                           tech_pvt->read_codec.implementation->samples_per_packet, ptime * 1000,
+                                             flags, "soft", &err, switch_core_session_get_pool(*new_session)))) {
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't setup RTP session: [%s]\n", err);
+        goto fail;
     }
     
     if (switch_core_session_thread_launch(*new_session) != SWITCH_STATUS_SUCCESS) {
@@ -214,7 +253,7 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
     
     switch_channel_set_state(channel, CS_ROUTING);
     
-    return SWITCH_STATUS_SUCCESS;   
+    return SWITCH_STATUS_SUCCESS;
 }
 
 static switch_status_t channel_on_destroy(switch_core_session_t *session)
@@ -240,6 +279,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
 {
     crtp_private_t *tech_pvt;
     switch_channel_t *channel;
+    switch_status_t status;
     
     channel = switch_core_session_get_channel(session);
        assert(channel != NULL);
@@ -247,6 +287,31 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
        tech_pvt = switch_core_session_get_private(session);
        assert(tech_pvt != NULL);
     
+    if (!tech_pvt->rtp_session) {
+        goto cng;
+    }
+    
+    if (switch_rtp_has_dtmf(tech_pvt->rtp_session)) {
+        switch_dtmf_t dtmf = { 0 };
+        switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, &dtmf);
+        switch_channel_queue_dtmf(channel, &dtmf);
+    }
+    
+    tech_pvt->read_frame.flags = SFF_NONE;
+    status = switch_rtp_zerocopy_read_frame(tech_pvt->rtp_session, &tech_pvt->read_frame, flags);
+
+    if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
+        goto cng;
+    }
+    
+done:
+    *frame = &tech_pvt->read_frame;
+    return SWITCH_STATUS_SUCCESS;
+    
+cng:
+    *frame = &tech_pvt->read_frame;
+    tech_pvt->read_frame.flags |= SFF_CNG;
+    tech_pvt->read_frame.datalen = 0;
     
     return SWITCH_STATUS_SUCCESS;
 }
@@ -255,6 +320,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
 {
     crtp_private_t *tech_pvt;
     switch_channel_t *channel;
+    int frames = 0, bytes = 0, samples = 0;
     
     channel = switch_core_session_get_channel(session);
        assert(channel != NULL);
@@ -263,8 +329,20 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
        assert(tech_pvt != NULL);
     
     
-    return SWITCH_STATUS_SUCCESS;
+    if (!switch_test_flag(frame, SFF_CNG) && !switch_test_flag(frame, SFF_PROXY_PACKET)) {
+               if (tech_pvt->read_codec.implementation->encoded_bytes_per_packet) {
+                       bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_packet;
+                       frames = ((int) frame->datalen / bytes);
+               } else
+                       frames = 1;
+        
+               samples = frames * tech_pvt->read_codec.implementation->samples_per_packet;
+       }
+    
+    tech_pvt->timestamp_send += samples;
+       switch_rtp_write_frame(tech_pvt->rtp_session, frame);
 
+    return SWITCH_STATUS_SUCCESS;
 }
 
 static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
@@ -274,8 +352,20 @@ static switch_status_t channel_send_dtmf(switch_core_session_t *session, const s
        tech_pvt = switch_core_session_get_private(session);
        assert(tech_pvt != NULL);
     
+    switch(tech_pvt->dtmf_type) {
+        case DTMF_2833:
+        {
+            switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Enqueuing RFC2833 DTMF %c of length %d\n", dtmf->digit, dtmf->duration);
+            return switch_rtp_queue_rfc2833(tech_pvt->rtp_session, dtmf);
+        }
+        case DTMF_NONE:
+        default:
+               {
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Discarding DTMF %c of length %d, DTMF type is NONE\n", dtmf->digit, dtmf->duration);
+               }
+    }
     
-       return SWITCH_STATUS_SUCCESS;
+    return SWITCH_STATUS_SUCCESS;
 }
 
 static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)