From patchwork Thu May 15 08:29:10 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Erlbeck X-Patchwork-Id: 349095 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from ganesha.gnumonks.org (ganesha.gnumonks.org [IPv6:2001:780:45:1d:225:90ff:fe52:c662]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 5FE4F1400DA for ; Thu, 15 May 2014 18:45:57 +1000 (EST) Received: from localhost ([127.0.0.1] helo=ganesha.gnumonks.org) by ganesha.gnumonks.org with esmtp (Exim 4.72) (envelope-from ) id 1WkrIR-0000Bd-38; Thu, 15 May 2014 10:45:47 +0200 Received: from mail.sysmocom.de ([144.76.43.93]) by ganesha.gnumonks.org with esmtp (Exim 4.72) (envelope-from ) id 1WkrDh-0007xB-DF for openbsc@lists.osmocom.org; Thu, 15 May 2014 10:41:02 +0200 Received: from sysmocom-tmp.home (24-134-58-61-dynip.superkabel.de [24.134.58.61]) by mail.sysmocom.de (Postfix) with ESMTPSA id 2D03158F01; Thu, 15 May 2014 08:40:53 +0000 (UTC) From: Jacob Erlbeck To: openbsc@lists.osmocom.org Subject: [PATCH 02/11] mgcp: Add audio info fields to struct mgcp_rtp_end Date: Thu, 15 May 2014 10:29:10 +0200 Message-Id: <1400142559-26788-2-git-send-email-jerlbeck@sysmocom.de> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1400142559-26788-1-git-send-email-jerlbeck@sysmocom.de> References: <1399891147-31419-1-git-send-email-jerlbeck@sysmocom.de> <1400142559-26788-1-git-send-email-jerlbeck@sysmocom.de> X-Spam-Score: 0.2 (/) X-Spam-Report: SpamASsassin versoin 3.3.1 on ganesha.gnumonks.org summary: Content analysis details: (0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.1 TW_CF BODY: Odd Letter Triples with CF 0.1 TW_MG BODY: Odd Letter Triples with MG 0.1 TW_GC BODY: Odd Letter Triples with GC Cc: Jacob Erlbeck X-BeenThere: openbsc@lists.osmocom.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Development of the OpenBSC GSM base station controller List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: openbsc-bounces@lists.osmocom.org Errors-To: openbsc-bounces@lists.osmocom.org 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 #include #include +#include #include #include @@ -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;