Index: rtp.c
===================================================================
RCS file: /usr/cvsroot/asterisk/rtp.c,v
retrieving revision 1.26
diff -u -r1.26 rtp.c
--- rtp.c       24 Feb 2003 14:39:44 -0000      1.26
+++ rtp.c       26 Feb 2003 11:25:08 -0000
@@ -283,28 +283,24 @@
 #endif 
        rtp->f.frametype = AST_FRAME_VOICE;
        rtp->f.subclass = rtp2ast(payloadtype);
-       if (rtp->f.subclass < 0) {
-               f = NULL;
-               if (payloadtype == 101) {
-                       /* It's special -- rfc2833 process it */
-                       f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + 
hdrlen, res - hdrlen);
-               } else if (payloadtype == 121) {
-                       /* CISCO proprietary DTMF bridge */
-                       f = process_type121(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + 
hdrlen, res - hdrlen);
-               } else if (payloadtype == 100) {
-                       /* CISCO's notso proprietary DTMF bridge */
-                       f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + 
hdrlen, res - hdrlen);
-               } else if (payloadtype == 13) {
-                       f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + 
hdrlen, res - hdrlen);
-               } else {
-                       ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", 
payloadtype);
-               }
-               if (f)
-                       return f;
-               else
-                       return &null_frame;
-       } else
-               rtp->lastrxformat = rtp->f.subclass;
+       // Check for special in-band data (DTMF or Comfort Noise):
+       if (rtp->f.subclass == AST_FORMAT_DTMF) {
+         /* It's special -- rfc2833 process it */
+         f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - 
hdrlen);
+         if (f) return f; else return &null_frame;
+       } else if (rtp->f.subclass == AST_FORMAT_DTMF_CISCO) {
+         /* CISCO proprietary DTMF bridge */
+         f = process_type121(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - 
hdrlen);
+         if (f) return f; else return &null_frame;
+       } else if (rtp->f.subclass == AST_FORMAT_CN) {
+         /* Comfort Noise */
+         f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - 
hdrlen);
+         if (f) return f; else return &null_frame;
+       } else if (rtp->f.subclass < 0) {
+         ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype);
+         return &null_frame;
+       }
+       rtp->lastrxformat = rtp->f.subclass;
 
        if (!rtp->lastrxts)
                rtp->lastrxts = timestamp;
@@ -360,48 +356,122 @@
        return &rtp->f;
 }
 
+// The following array defines the MIME type (and subtype) for each
+// defined "AST_FORMAT_..." value.
 static struct {
-       int rtp;
-       int ast;
-       char *label;
-} cmap[] = {
-       { 0, AST_FORMAT_ULAW, "PCMU" },
-       { 3, AST_FORMAT_GSM, "GSM" },
-       { 4, AST_FORMAT_G723_1, "G723" },
-       { 5, AST_FORMAT_ADPCM, "ADPCM" },
-       { 8, AST_FORMAT_ALAW, "PCMA" },
-       { 18, AST_FORMAT_G729A, "G729" },
+  int ast;
+  char* type;
+  char* subtype;
+} mimeTypes[] = {
+  {AST_FORMAT_G723_1, "audio", "G723"},
+  {AST_FORMAT_GSM, "audio", "GSM"},
+  {AST_FORMAT_ULAW, "audio", "PCMU"},
+  {AST_FORMAT_ALAW, "audio", "PCMA"},
+  {AST_FORMAT_MP3, "audio", "MPA"},
+  {AST_FORMAT_ADPCM, "audio", "DVI4"},
+  {AST_FORMAT_SLINEAR, "audio", "L16"},
+  {AST_FORMAT_LPC10, "audio", "LPC"},
+  {AST_FORMAT_G729A, "audio", "G729"},
+  {AST_FORMAT_SPEEX, "audio", "SPEEX"},
+  {AST_FORMAT_DTMF, "audio", "TELEPHONE-EVENT"},
+  {AST_FORMAT_DTMF_CISCO, "audio", "TELEPHONE-EVENT-CISCO"/*Fix this!*/},
+  {AST_FORMAT_CN, "audio", "CN"},
+  {AST_FORMAT_JPEG, "video", "JPEG"},
+  {AST_FORMAT_PNG, "video", "PNG"},
+  {AST_FORMAT_H261, "video", "H261"},
+  {AST_FORMAT_H263, "video", "H263"},
 };
 
-int rtp2ast(int id)
-{
-       int x;
-       for (x=0;x<sizeof(cmap) / sizeof(cmap[0]); x++) {
-               if (cmap[x].rtp == id)
-                       return cmap[x].ast;
-       }
-       return -1;
+#define MAX_RTP_PT 256
+
+// Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s:
+static int static_RTP_PT[MAX_RTP_PT] = {
+  [0] = AST_FORMAT_ULAW,
+  [3] = AST_FORMAT_GSM,
+  [4] = AST_FORMAT_G723_1,
+  [5] = AST_FORMAT_ADPCM, // 8 kHz
+  [6] = AST_FORMAT_ADPCM, // 16 kHz
+  [7] = AST_FORMAT_LPC10,
+  [8] = AST_FORMAT_ALAW,
+  [10] = AST_FORMAT_SLINEAR, // 2 channels
+  [11] = AST_FORMAT_SLINEAR, // 1 channel
+  [13] = AST_FORMAT_CN,
+  [14] = AST_FORMAT_MP3,
+  [16] = AST_FORMAT_ADPCM, // 11.025 kHz
+  [17] = AST_FORMAT_ADPCM, // 22.050 kHz
+  [18] = AST_FORMAT_G729A,
+  [26] = AST_FORMAT_JPEG,
+  [31] = AST_FORMAT_H261,
+  [34] = AST_FORMAT_H263,
+};
+
+// The set of RTP payload types that the current caller has requested:
+static int current_RTP_PT[MAX_RTP_PT];
+
+void rtp_pt_init() {
+  int i;
+  for (i = 0; i < MAX_RTP_PT; ++i) {
+    current_RTP_PT[i] = 0;
+  }
 }
 
-int ast2rtp(int id)
-{
-       int x;
-       for (x=0;x<sizeof(cmap) / sizeof(cmap[0]); x++) {
-               if (cmap[x].ast == id)
-                       return cmap[x].rtp;
-       }
-       return -1;
+// Make a note of a RTP payload type that was seen in a SDP "m=" line.
+// By default, use the well-known value for this type (although it may
+// still be set to a different value by a subsequent "a=rtpmap:" line):
+void rtp_set_m_type(int pt) {
+  if (pt < 0 || pt > MAX_RTP_PT) return; // bogus payload type
+
+  if (static_RTP_PT[pt] != 0) {
+    current_RTP_PT[pt] = static_RTP_PT[pt];
+  }
+} 
+
+// Make a note of a RTP payload type (with MIME type) that was seen in
+// a SDP "a=rtpmap:" line.
+void rtp_set_rtpmap_type(int pt, char* mimeType, char* mimeSubtype) {
+  int i;
+
+  if (pt < 0 || pt > MAX_RTP_PT) return; // bogus payload type
+
+  for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
+    if (strcmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
+       strcmp(mimeType, mimeTypes[i].type) == 0) {
+      current_RTP_PT[pt] = mimeTypes[i].ast;
+      return;
+    }
+  }
+} 
+
+// Return the union of all of the codecs that were set by rtp_set...() calls
+int rtp_get_current_codecs() {
+  int result = 0, pt;
+  for (pt = 0; pt < MAX_RTP_PT; ++pt) result |= current_RTP_PT[pt];
+
+  return result;
 }
 
-char *ast2rtpn(int id)
-{
-       int x;
-       for (x=0;x<sizeof(cmap) / sizeof(cmap[0]); x++) {
-               if (cmap[x].ast == id)
-                       return cmap[x].label;
-       }
-       return "";
+int rtp2ast(int pt) {
+  if (pt < 0 || pt > MAX_RTP_PT) return -1; // bogus payload type
+  return current_RTP_PT[pt];
+}
+
+int ast2rtp(int id) {
+  int pt;
+  for (pt = 0; pt < MAX_RTP_PT; ++pt) {
+    if (current_RTP_PT[pt] == id) return pt;
+  }
+  return -1;
 }
+
+char* ast2rtpn(int id) {
+  int i;
+
+  for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
+    if (mimeTypes[i].ast == id) return mimeTypes[i].subtype;
+  }
+  return "";
+}
+
 struct ast_rtp *ast_rtp_new(struct sched_context *sched, struct io_context *io)
 {
        struct ast_rtp *rtp;
Index: channels/chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.129
diff -u -r1.129 chan_sip.c
--- channels/chan_sip.c 24 Feb 2003 15:20:42 -0000      1.129
+++ channels/chan_sip.c 26 Feb 2003 11:25:10 -0000
@@ -974,21 +974,41 @@
        { "Via", "v" },
 };
 
-static char *get_sdp(struct sip_request *req, char *name)
-{
-       int x;
-       int len = strlen(name);
-       char *r;
-       for (x=0;x<req->lines;x++) {
-               if (!strncasecmp(req->line[x], name, len) && 
-                               (req->line[x][len] == '=')) {
-                                       r = req->line[x] + len + 1;
-                                       while(*r && (*r < 33))
-                                                       r++;
-                                       return r;
-               }
-       }
-       return "";
+static char* get_sdp_by_line(char* line, char *name, int nameLen) {
+  if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
+    char* r = line + nameLen + 1;
+    while (*r && (*r < 33)) ++r;
+    return r;
+  }
+
+  return "";
+}
+
+static char *get_sdp(struct sip_request *req, char *name) {
+  int x;
+  int len = strlen(name);
+  char *r;
+
+  for (x=0; x<req->lines; x++) {
+    r = get_sdp_by_line(req->line[x], name, len);
+    if (r[0] != '\0') return r;
+  }
+  return "";
+}
+
+static int sdpLineNum_iterator;
+void sdpLineNum_iterator_init() {
+  sdpLineNum_iterator = 0;
+}
+
+static char* get_sdp_iterate(struct sip_request *req, char *name) {
+  int len = strlen(name);
+  char *r;
+  while (sdpLineNum_iterator < req->lines) {
+    r = get_sdp_by_line(req->line[sdpLineNum_iterator++], name, len);
+    if (r[0] != '\0') return r;
+  }
+  return "";
 }
 
 static char *__get_header(struct sip_request *req, char *name, int *start)
@@ -1288,6 +1308,7 @@
 {
        char *m;
        char *c;
+       char *a;
        char host[258];
        int len = -1;
        int portno;
@@ -1329,21 +1350,38 @@
 #if 0
        printf("Peer RTP is at port %s:%d\n", inet_ntoa(sin.sin_addr), 
ntohs(sin.sin_port));
 #endif 
-       peercapability = 0;
+       // Scan through the RTP payload types specified in a "m=" line:
+       rtp_pt_init();
        codecs = m + len;
        while(strlen(codecs)) {
                if (sscanf(codecs, "%d %n", &codec, &len) != 1) {
                        ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
                        return -1;
                }
-#if 0
-               printf("Codec: %d\n", codec);
-#endif         
-               codec = rtp2ast(codec);
-               if (codec  > -1)
-                       peercapability |= codec;
+               rtp_set_m_type(codec);
                codecs += len;
        }
+
+       // Next, scan through each "a=rtpmap:" line, noting each
+       // specified RTP payload type (with corresponding MIME subtype):
+       sdpLineNum_iterator_init();
+       while ((a = get_sdp_iterate(req, "a"))[0] != '\0') {
+         char mimeSubtype[100];
+         int subtypeLen, i;
+         if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue;
+         // Note: should really look at the 'freq' and '#chans' params too
+         mimeSubtype[sizeof mimeSubtype - 1] = '\0'; // in case...
+         subtypeLen = strlen(mimeSubtype);
+         // Convert the MIME subtype to upper case, for ease of searching:
+         for (i = 0; i < subtypeLen; ++i) {
+           mimeSubtype[i] = toupper(mimeSubtype[i]);
+         }
+         rtp_set_rtpmap_type(codec, "audio", mimeSubtype);
+       }
+
+       // Now gather all of the codecs that were asked for:
+       peercapability = rtp_get_current_codecs();
+       capability |= AST_FORMAT_DTMF|AST_FORMAT_DTMF_CISCO; // include DTMF
        p->capability = capability & peercapability;
        if (sipdebug)
                ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
@@ -1722,13 +1760,17 @@
                                strcat(m, costr);
                                snprintf(costr, sizeof(costr), "a=rtpmap:%d 
%s/8000\r\n", codec, ast2rtpn(x));
                                strcat(a, costr);
+                               if (x == AST_FORMAT_DTMF ||
+                                   x == AST_FORMAT_DTMF_CISCO) {
+                                 /* Indicate we support DTMF only...  Not sure about 
16, but MSN supports it so dang it, we will too... */
+                                 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n",
+                                          codec);
+                                 strcat(a, costr);
+                               }
                        }
                }
        }
-       strcat(m, " 101\r\n");
-       strcat(a, "a=rtpmap:101 telephone-event/8000\r\n");
-       /* Indicate we support DTMF only...  Not sure about 16, but MSN supports it so 
dang it, we will too... */
-       strcat(a, "a=fmtp:101 0-16\r\n");
+       strcat(m, "\r\n");
        len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + 
strlen(a);
        snprintf(costr, sizeof(costr), "%d", len);
        add_header(resp, "Content-Type", "application/sdp");
Index: include/asterisk/frame.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/frame.h,v
retrieving revision 1.41
diff -u -r1.41 frame.h
--- include/asterisk/frame.h    5 Feb 2003 19:26:49 -0000       1.41
+++ include/asterisk/frame.h    26 Feb 2003 11:25:11 -0000
@@ -131,6 +131,12 @@
 #define AST_FORMAT_G729A       (1 << 8)
 /*! SpeeX Free Compression */
 #define AST_FORMAT_SPEEX       (1 << 9)
+/*! DTMF (in RTP) */
+#define AST_FORMAT_DTMF        (1 << 10)
+/*! Cisco's proprietary DTMF variant (in RTP) */
+#define AST_FORMAT_DTMF_CISCO  (1 << 11)
+/*! Comfort Noise (RFC 3389) (in RTP) */
+#define AST_FORMAT_CN  (1 << 12)
 /*! Maximum audio format */
 #define AST_FORMAT_MAX_AUDIO   (1 << 15)
 /*! JPEG Images */
Index: include/asterisk/rtp.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/rtp.h,v
retrieving revision 1.7
diff -u -r1.7 rtp.h
--- include/asterisk/rtp.h      15 Feb 2003 23:41:23 -0000      1.7
+++ include/asterisk/rtp.h      26 Feb 2003 11:25:11 -0000
@@ -61,6 +61,14 @@
 
 int ast_rtp_settos(struct ast_rtp *rtp, int tos);
 
+void rtp_pt_init(void);
+
+void rtp_set_m_type(int pt);
+
+void rtp_set_rtpmap_type(int pt, char* mimeType, char* mimeSubtype);
+
+int rtp_get_current_codecs(void);
+
 int ast2rtp(int id);
 
 int rtp2ast(int id);

Reply via email to