This patch adds the fields channels, subtype_name, and audio_name to
the struct. The field audio_name contains the full string that has
been used for the last part of a SDP a=rtpmap line. The others contain
decoded parts of that string. If no a=rtpmap line has been given
(e.g. because dynamic payload types are not used), values are
assigned when the payload type matches one of the predefined ones
(GSM, G729, PCMA).

Sponsored-by: On-Waves ehf
---
 openbsc/include/openbsc/mgcp_internal.h |    3 ++
 openbsc/src/libmgcp/mgcp_protocol.c     |   82 +++++++++++++++++++++++--------
 2 files changed, 64 insertions(+), 21 deletions(-)

diff --git a/openbsc/include/openbsc/mgcp_internal.h 
b/openbsc/include/openbsc/mgcp_internal.h
index 56c280d..72ac8e9 100644
--- a/openbsc/include/openbsc/mgcp_internal.h
+++ b/openbsc/include/openbsc/mgcp_internal.h
@@ -81,11 +81,14 @@ struct mgcp_rtp_end {
        /* per endpoint data */
        int payload_type;
        uint32_t rate;
+       int channels;
        uint32_t frame_duration_num;
        uint32_t frame_duration_den;
        int  frames_per_packet;
        uint32_t packet_duration_ms;
        char *fmtp_extra;
+       char *audio_name;
+       char *subtype_name;
        int output_enabled;
 
        /* RTP patching */
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c 
b/openbsc/src/libmgcp/mgcp_protocol.c
index 0f8614c..3960c88 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -28,6 +28,7 @@
 #include <time.h>
 #include <limits.h>
 #include <unistd.h>
+#include <errno.h>
 
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/talloc.h>
@@ -77,6 +78,7 @@ char *strline_r(char *str, char **saveptr)
 #define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
 #define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
 #define DEFAULT_RTP_AUDIO_DEFAULT_RATE  8000
+#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
 
 static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end);
 
@@ -231,6 +233,8 @@ static struct msgb *create_response_with_sdp(struct 
mgcp_endpoint *endp,
 {
        const char *addr = endp->cfg->local_ip;
        const char *fmtp_extra = endp->bts_end.fmtp_extra;
+       const char *audio_name = endp->bts_end.audio_name;
+       int payload_type = endp->bts_end.payload_type;
        char sdp_record[4096];
        int len;
 
@@ -244,11 +248,12 @@ static struct msgb *create_response_with_sdp(struct 
mgcp_endpoint *endp,
                        "c=IN IP4 %s\r\n"
                        "t=0 0\r\n"
                        "m=audio %d RTP/AVP %d\r\n"
-                       "a=rtpmap:%d %s\r\n"
+                       "a=rtpmap:%d%s%s\r\n"
                        "%s%s",
                        endp->ci, endp->ci, addr, addr,
-                       endp->net_end.local_port, endp->bts_end.payload_type,
-                       endp->bts_end.payload_type, endp->tcfg->audio_name,
+                       endp->net_end.local_port, payload_type,
+                       payload_type,
+                       audio_name ? " " : "", audio_name ? audio_name : "",
                        fmtp_extra ? fmtp_extra : "", fmtp_extra ? "\r\n" : "");
 
        if (len < 0 || len >= sizeof(sdp_record))
@@ -514,6 +519,47 @@ static int parse_conn_mode(const char *msg, struct 
mgcp_endpoint *endp)
        return ret;
 }
 
+static int set_audio_info(void *ctx, struct mgcp_rtp_end *rtp,
+                         int payload_type, const char *audio_name)
+{
+       int rate = 8000;
+       int channels = 1;
+       char audio_codec[64];
+
+       talloc_free(rtp->subtype_name);
+       rtp->subtype_name = NULL;
+       talloc_free(rtp->audio_name);
+       rtp->audio_name = NULL;
+
+       rtp->payload_type = payload_type;
+
+       if (!audio_name) {
+               switch (payload_type) {
+               case 3: audio_name = "GSM/8000/1"; break;
+               case 8: audio_name = "PCMA/8000/1"; break;
+               case 18: audio_name = "G729/8000/1"; break;
+               default:
+                        rtp->rate = 8000;
+                        rtp->channels = 1;
+                        return 0;
+               }
+       }
+
+       if (sscanf(audio_name, "%63[^/]/%d/%d",
+                  audio_codec, &rate, &channels) < 2)
+               return -EINVAL;
+
+       rtp->rate = rate;
+       rtp->channels = channels;
+       rtp->subtype_name = talloc_strdup(ctx, audio_codec);
+       rtp->audio_name = talloc_strdup(ctx, audio_name);
+       if (channels != 1)
+               LOGP(DMGCP, LOGL_NOTICE,
+                    "Channels != 1 in SDP: '%s'\n", audio_name);
+
+       return 0;
+}
+
 static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end,
                         struct mgcp_port_range *range,
                         int (*alloc)(struct mgcp_endpoint *endp, int port))
@@ -600,29 +646,18 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, 
struct mgcp_parse_data *p)
                        break;
                case 'a': {
                        int payload;
-                       int rate;
-                       int channels = 1;
                        int ptime, ptime2 = 0;
                        char audio_name[64];
-                       char audio_codec[64];
 
                        if (audio_payload == -1)
                                break;
 
-                       if (sscanf(line, "a=rtpmap:%d %64s",
+                       if (sscanf(line, "a=rtpmap:%d %63s",
                                   &payload, audio_name) == 2) {
                                if (payload != audio_payload)
                                        break;
 
-                               if (sscanf(audio_name, "%[^/]/%d/%d",
-                                         audio_codec, &rate, &channels) < 2)
-                                       break;
-
-                               rtp->rate = rate;
-                               if (channels != 1)
-                                       LOGP(DMGCP, LOGL_NOTICE,
-                                            "Channels != 1 in SDP: '%s' on 
0x%x\n",
-                                            line, ENDPOINT_NUMBER(p->endp));
+                               set_audio_info(p->cfg, rtp, payload, 
audio_name);
                        } else if (sscanf(line, "a=ptime:%d-%d",
                                          &ptime, &ptime2) >= 1) {
                                if (ptime2 > 0 && ptime2 != ptime)
@@ -645,8 +680,8 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct 
mgcp_parse_data *p)
                                   &port, &audio_payload) == 2) {
                                rtp->rtp_port = htons(port);
                                rtp->rtcp_port = htons(port + 1);
-                               rtp->payload_type = audio_payload;
                                found_media = 1;
+                               set_audio_info(p->cfg, rtp, audio_payload, 
NULL);
                        }
                        break;
                }
@@ -826,7 +861,7 @@ mgcp_header_done:
        endp->allocated = 1;
 
        /* set up RTP media parameters */
-       endp->bts_end.payload_type = tcfg->audio_payload;
+       set_audio_info(p->cfg, &endp->bts_end, tcfg->audio_payload, 
tcfg->audio_name);
        endp->bts_end.fmtp_extra = talloc_strdup(tcfg->endpoints,
                                                tcfg->audio_fmtp_extra);
        if (have_sdp) {
@@ -1252,6 +1287,7 @@ static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end)
        end->frames_per_packet  = 0; /* unknown */
        end->packet_duration_ms = DEFAULT_RTP_AUDIO_PACKET_DURATION_MS;
        end->rate               = DEFAULT_RTP_AUDIO_DEFAULT_RATE;
+       end->channels           = DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS;
        end->output_enabled     = 0;
 }
 
@@ -1329,6 +1365,9 @@ static void send_msg(struct mgcp_endpoint *endp, int 
endpoint, int port,
 {
        char buf[2096];
        int len;
+       const char *fmtp_extra = endp->bts_end.fmtp_extra;
+       const char *audio_name = endp->bts_end.audio_name;
+       int payload_type = endp->bts_end.payload_type;
 
        /* hardcoded to AMR right now, we do not know the real type at this 
point */
        len = snprintf(buf, sizeof(buf),
@@ -1338,10 +1377,11 @@ static void send_msg(struct mgcp_endpoint *endp, int 
endpoint, int port,
                        "\r\n"
                        "c=IN IP4 %s\r\n"
                        "m=audio %d RTP/AVP %d\r\n"
-                       "a=rtpmap:%d %s\r\n",
+                       "a=rtpmap:%d%s%s\r\n",
                        msg, endpoint, mode, endp->cfg->source_addr,
-                       port, endp->tcfg->audio_payload,
-                       endp->tcfg->audio_payload, endp->tcfg->audio_name);
+                       port, payload_type,
+                       payload_type,
+                       audio_name ? " " : "", audio_name ? audio_name : "");
 
        if (len < 0)
                return;
-- 
1.7.9.5


Reply via email to