From c8c2f23926a066d277ece3548bc2319aface3d70 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Thu, 15 Dec 2011 06:45:23 +0000 Subject: Close #1279: Implemented custom SDP format match for G.722.1 and AMR-NB/WB. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3911 74dad513-b988-da41-8d7b-12977e46ad98 --- build.symbian/pjmedia.mmp | 2 + pjmedia/build/Makefile | 3 +- pjmedia/build/pjmedia_codec.vcproj | 362 +++++++++++++----------- pjmedia/include/pjmedia-codec/amr_sdp_match.h | 61 ++++ pjmedia/include/pjmedia-codec/g7221_sdp_match.h | 59 ++++ pjmedia/src/pjmedia-codec/amr_sdp_match.c | 176 ++++++++++++ pjmedia/src/pjmedia-codec/g7221.c | 10 + pjmedia/src/pjmedia-codec/g7221_sdp_match.c | 91 ++++++ pjmedia/src/pjmedia-codec/ipp_codecs.c | 34 +++ pjmedia/src/pjmedia-codec/opencore_amrnb.c | 12 +- pjmedia/src/pjmedia-codec/passthrough.c | 17 +- pjmedia/src/pjmedia/sdp_neg.c | 262 ----------------- 12 files changed, 651 insertions(+), 438 deletions(-) create mode 100644 pjmedia/include/pjmedia-codec/amr_sdp_match.h create mode 100644 pjmedia/include/pjmedia-codec/g7221_sdp_match.h create mode 100644 pjmedia/src/pjmedia-codec/amr_sdp_match.c create mode 100644 pjmedia/src/pjmedia-codec/g7221_sdp_match.c diff --git a/build.symbian/pjmedia.mmp b/build.symbian/pjmedia.mmp index 5b84e639..f20b01aa 100644 --- a/build.symbian/pjmedia.mmp +++ b/build.symbian/pjmedia.mmp @@ -91,6 +91,8 @@ SOURCE wsola.c // SOURCEPATH ..\pjmedia\src\pjmedia-codec SOURCE audio_codecs.c +SOURCE amr_sdp_match.c +SOURCE g7221_sdp_match.c // diff --git a/pjmedia/build/Makefile b/pjmedia/build/Makefile index afe6546a..3357efb8 100644 --- a/pjmedia/build/Makefile +++ b/pjmedia/build/Makefile @@ -113,7 +113,8 @@ export PJMEDIA_CODEC_SRCDIR = ../src/pjmedia-codec export PJMEDIA_CODEC_OBJS += audio_codecs.o ffmpeg_codecs.o \ h263_packetizer.o h264_packetizer.o \ $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \ - ipp_codecs.o $(CODEC_OBJS) + ipp_codecs.o $(CODEC_OBJS) \ + g7221_sdp_match.o amr_sdp_match.o export PJMEDIA_CODEC_CFLAGS += $(_CFLAGS) $(GSM_CFLAGS) $(SPEEX_CFLAGS) \ $(ILBC_CFLAGS) $(IPP_CFLAGS) $(G7221_CFLAGS) diff --git a/pjmedia/build/pjmedia_codec.vcproj b/pjmedia/build/pjmedia_codec.vcproj index 516c011e..043b3143 100644 --- a/pjmedia/build/pjmedia_codec.vcproj +++ b/pjmedia/build/pjmedia_codec.vcproj @@ -223,12 +223,11 @@ /> + + @@ -320,7 +328,7 @@ /> @@ -386,7 +394,7 @@ /> + + - - @@ -576,7 +584,7 @@ /> + + @@ -700,7 +716,7 @@ /> @@ -766,7 +782,7 @@ /> + + @@ -890,7 +914,7 @@ /> - - + + @@ -1080,7 +1104,7 @@ /> @@ -1146,7 +1170,7 @@ /> @@ -1278,7 +1302,7 @@ /> - - @@ -1476,7 +1492,7 @@ /> @@ -1542,7 +1558,7 @@ /> @@ -1608,7 +1624,7 @@ /> @@ -1674,7 +1690,7 @@ /> @@ -1740,7 +1756,7 @@ /> @@ -1806,7 +1822,7 @@ /> - - @@ -1938,7 +1946,7 @@ /> @@ -2004,7 +2012,7 @@ /> @@ -2070,7 +2078,7 @@ /> @@ -2136,7 +2144,7 @@ /> @@ -2202,7 +2210,7 @@ /> @@ -2268,7 +2276,7 @@ /> - - @@ -2400,7 +2400,7 @@ /> @@ -2466,7 +2466,7 @@ /> + + @@ -2780,6 +2784,10 @@ RelativePath="..\src\pjmedia-codec\g7221.c" > + + @@ -3061,6 +3069,10 @@ RelativePath="..\include\pjmedia-codec\amr_helper.h" > + + @@ -3081,6 +3093,10 @@ RelativePath="..\include\pjmedia-codec\g7221.h" > + + diff --git a/pjmedia/include/pjmedia-codec/amr_sdp_match.h b/pjmedia/include/pjmedia-codec/amr_sdp_match.h new file mode 100644 index 00000000..73e5ecd7 --- /dev/null +++ b/pjmedia/include/pjmedia-codec/amr_sdp_match.h @@ -0,0 +1,61 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_CODEC_AMR_SDP_MATCH_H__ +#define __PJMEDIA_CODEC_AMR_SDP_MATCH_H__ + + +/** + * @file g7221_sdp_match.h + * @brief Special SDP format match for AMR-NB and AMR-WB. + */ + +#include + +PJ_BEGIN_DECL + + +/* Match AMR-NB and AMR-WB format in the SDP media offer and answer. This + * function will match some AMR settings in the SDP format parameters, i.e: + * octet-align, crc, robust-sorting, interleaving. Note that, for answerer, + * if octet-align mode needs to be adaptable to offerer setting, application + * should set #PJMEDIA_SDP_NEG_FMT_MATCH_ALLOW_MODIFY_ANSWER in the option. + * + * @param pool The memory pool. + * @param offer The SDP media offer. + * @param o_fmt_idx Index of the AMR format in the SDP media offer. + * @param answer The SDP media answer. + * @param a_fmt_idx Index of the AMR format in the SDP media answer. + * @param option The format matching option, see + * #pjmedia_sdp_neg_fmt_match_flag. + * + * @return PJ_SUCCESS when the formats in offer and answer match. + */ +PJ_DECL(pj_status_t) pjmedia_codec_amr_match_sdp( pj_pool_t *pool, + pjmedia_sdp_media *offer, + unsigned o_fmt_idx, + pjmedia_sdp_media *answer, + unsigned a_fmt_idx, + unsigned option); + + +PJ_END_DECL + + +#endif /* __PJMEDIA_CODEC_AMR_SDP_MATCH_H__ */ diff --git a/pjmedia/include/pjmedia-codec/g7221_sdp_match.h b/pjmedia/include/pjmedia-codec/g7221_sdp_match.h new file mode 100644 index 00000000..a4dca0bd --- /dev/null +++ b/pjmedia/include/pjmedia-codec/g7221_sdp_match.h @@ -0,0 +1,59 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_CODEC_G7221_SDP_MATCH_H__ +#define __PJMEDIA_CODEC_G7221_SDP_MATCH_H__ + + +/** + * @file g7221_sdp_match.h + * @brief Special SDP format match for G722.1. + */ + +#include + +PJ_BEGIN_DECL + +/** + * Match G.722.1 format in the SDP media offer and answer. This function + * will match G.722.1 bitrate setting in the SDP format parameter of + * offer and answer. + * + * @param pool The memory pool. + * @param offer The SDP media offer. + * @param o_fmt_idx Index of the G.722.1 format in the SDP media offer. + * @param answer The SDP media answer. + * @param a_fmt_idx Index of the G.722.1 format in the SDP media answer. + * @param option The format matching option, see + * #pjmedia_sdp_neg_fmt_match_flag. + * + * @return PJ_SUCCESS when the formats in offer and answer match. + */ +PJ_DECL(pj_status_t) pjmedia_codec_g7221_match_sdp( pj_pool_t *pool, + pjmedia_sdp_media *offer, + unsigned o_fmt_idx, + pjmedia_sdp_media *answer, + unsigned a_fmt_idx, + unsigned option); + + +PJ_END_DECL + + +#endif /* __PJMEDIA_CODEC_G7221_SDP_MATCH_H__ */ diff --git a/pjmedia/src/pjmedia-codec/amr_sdp_match.c b/pjmedia/src/pjmedia-codec/amr_sdp_match.c new file mode 100644 index 00000000..5eb02185 --- /dev/null +++ b/pjmedia/src/pjmedia-codec/amr_sdp_match.c @@ -0,0 +1,176 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include + + +#define GET_FMTP_IVAL_BASE(ival, base, fmtp, param, default_val) \ + do { \ + pj_str_t s; \ + char *p; \ + p = pj_stristr(&fmtp.fmt_param, ¶m); \ + if (!p) { \ + ival = default_val; \ + break; \ + } \ + pj_strset(&s, p + param.slen, fmtp.fmt_param.slen - \ + (p - fmtp.fmt_param.ptr) - param.slen); \ + ival = pj_strtoul2(&s, NULL, base); \ + } while (0) + +#define GET_FMTP_IVAL(ival, fmtp, param, default_val) \ + GET_FMTP_IVAL_BASE(ival, 10, fmtp, param, default_val) + + +/* Toggle AMR octet-align setting in the fmtp. */ +static pj_status_t amr_toggle_octet_align(pj_pool_t *pool, + pjmedia_sdp_media *media, + unsigned fmt_idx) +{ + pjmedia_sdp_attr *attr; + pjmedia_sdp_fmtp fmtp; + const pj_str_t STR_OCTET_ALIGN = {"octet-align=", 12}; + + enum { MAX_FMTP_STR_LEN = 160 }; + + attr = pjmedia_sdp_media_find_attr2(media, "fmtp", + &media->desc.fmt[fmt_idx]); + /* Check if the AMR media format has FMTP attribute */ + if (attr) { + char *p; + pj_status_t status; + + status = pjmedia_sdp_attr_get_fmtp(attr, &fmtp); + if (status != PJ_SUCCESS) + return status; + + /* Check if the fmtp has octet-align field. */ + p = pj_stristr(&fmtp.fmt_param, &STR_OCTET_ALIGN); + if (p) { + /* It has, just toggle the value */ + unsigned octet_align; + pj_str_t s; + + pj_strset(&s, p + STR_OCTET_ALIGN.slen, fmtp.fmt_param.slen - + (p - fmtp.fmt_param.ptr) - STR_OCTET_ALIGN.slen); + octet_align = pj_strtoul(&s); + *(p + STR_OCTET_ALIGN.slen) = (char)(octet_align? '0' : '1'); + } else { + /* It doesn't, append octet-align field */ + char buf[MAX_FMTP_STR_LEN]; + + pj_ansi_snprintf(buf, MAX_FMTP_STR_LEN, "%.*s;octet-align=1", + (int)fmtp.fmt_param.slen, fmtp.fmt_param.ptr); + attr->value = pj_strdup3(pool, buf); + } + } else { + /* Add new attribute for the AMR media format with octet-align + * field set. + */ + char buf[MAX_FMTP_STR_LEN]; + + attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr); + attr->name = pj_str("fmtp"); + pj_ansi_snprintf(buf, MAX_FMTP_STR_LEN, "%.*s octet-align=1", + (int)media->desc.fmt[fmt_idx].slen, + media->desc.fmt[fmt_idx].ptr); + attr->value = pj_strdup3(pool, buf); + media->attr[media->attr_count++] = attr; + } + + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pjmedia_codec_amr_match_sdp( pj_pool_t *pool, + pjmedia_sdp_media *offer, + unsigned o_fmt_idx, + pjmedia_sdp_media *answer, + unsigned a_fmt_idx, + unsigned option) +{ + /* Negotiated format-param field-names constants. */ + const pj_str_t STR_OCTET_ALIGN = {"octet-align=", 12}; + const pj_str_t STR_CRC = {"crc=", 4}; + const pj_str_t STR_ROBUST_SORTING = {"robust-sorting=", 15}; + const pj_str_t STR_INTERLEAVING = {"interleaving=", 13}; + + /* Negotiated params and their default values. */ + unsigned a_octet_align = 0, o_octet_align = 0; + unsigned a_crc = 0, o_crc = 0; + unsigned a_robust_sorting = 0, o_robust_sorting = 0; + unsigned a_interleaving = 0, o_interleaving = 0; + + const pjmedia_sdp_attr *attr_ans; + const pjmedia_sdp_attr *attr_ofr; + pjmedia_sdp_fmtp fmtp; + pj_status_t status; + + /* Parse offerer FMTP */ + attr_ofr = pjmedia_sdp_media_find_attr2(offer, "fmtp", + &offer->desc.fmt[o_fmt_idx]); + if (attr_ofr) { + status = pjmedia_sdp_attr_get_fmtp(attr_ofr, &fmtp); + if (status != PJ_SUCCESS) + return status; + + GET_FMTP_IVAL(o_octet_align, fmtp, STR_OCTET_ALIGN, 0); + GET_FMTP_IVAL(o_crc, fmtp, STR_CRC, 0); + GET_FMTP_IVAL(o_robust_sorting, fmtp, STR_ROBUST_SORTING, 0); + GET_FMTP_IVAL(o_interleaving, fmtp, STR_INTERLEAVING, 0); + } + + /* Parse answerer FMTP */ + attr_ans = pjmedia_sdp_media_find_attr2(answer, "fmtp", + &answer->desc.fmt[a_fmt_idx]); + if (attr_ans) { + status = pjmedia_sdp_attr_get_fmtp(attr_ans, &fmtp); + if (status != PJ_SUCCESS) + return status; + + GET_FMTP_IVAL(a_octet_align, fmtp, STR_OCTET_ALIGN, 0); + GET_FMTP_IVAL(a_crc, fmtp, STR_CRC, 0); + GET_FMTP_IVAL(a_robust_sorting, fmtp, STR_ROBUST_SORTING, 0); + GET_FMTP_IVAL(a_interleaving, fmtp, STR_INTERLEAVING, 0); + } + + /* First, match crc, robust-sorting, interleaving settings */ + if (a_crc != o_crc || + a_robust_sorting != o_robust_sorting || + a_interleaving != o_interleaving) + { + return PJMEDIA_SDP_EFORMATNOTEQUAL; + } + + /* Match octet-align setting */ + if (a_octet_align != o_octet_align) { + /* Check if answer can be modified to match to the offer */ + if (option & PJMEDIA_SDP_NEG_FMT_MATCH_ALLOW_MODIFY_ANSWER) { + status = amr_toggle_octet_align(pool, answer, a_fmt_idx); + return status; + } else { + return PJMEDIA_SDP_EFORMATNOTEQUAL; + } + } + + return PJ_SUCCESS; +} diff --git a/pjmedia/src/pjmedia-codec/g7221.c b/pjmedia/src/pjmedia-codec/g7221.c index 44ecabc9..c5f81211 100644 --- a/pjmedia/src/pjmedia-codec/g7221.c +++ b/pjmedia/src/pjmedia-codec/g7221.c @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include #include #include @@ -246,6 +247,7 @@ PJ_DEF(pj_status_t) pjmedia_codec_g7221_init( pjmedia_endpt *endpt ) { pjmedia_codec_mgr *codec_mgr; codec_mode *mode; + pj_str_t codec_name; pj_status_t status; if (codec_factory.pool != NULL) { @@ -337,6 +339,14 @@ PJ_DEF(pj_status_t) pjmedia_codec_g7221_init( pjmedia_endpt *endpt ) goto on_error; } + /* Register format match callback. */ + pj_cstr(&codec_name, CODEC_TAG); + status = pjmedia_sdp_neg_register_fmt_match_cb( + &codec_name, + &pjmedia_codec_g7221_match_sdp); + if (status != PJ_SUCCESS) + goto on_error; + /* Register codec factory to endpoint. */ status = pjmedia_codec_mgr_register_factory(codec_mgr, &codec_factory.base); diff --git a/pjmedia/src/pjmedia-codec/g7221_sdp_match.c b/pjmedia/src/pjmedia-codec/g7221_sdp_match.c new file mode 100644 index 00000000..a9cc17dc --- /dev/null +++ b/pjmedia/src/pjmedia-codec/g7221_sdp_match.c @@ -0,0 +1,91 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include + + +#define GET_FMTP_IVAL_BASE(ival, base, fmtp, param, default_val) \ + do { \ + pj_str_t s; \ + char *p; \ + p = pj_stristr(&fmtp.fmt_param, ¶m); \ + if (!p) { \ + ival = default_val; \ + break; \ + } \ + pj_strset(&s, p + param.slen, fmtp.fmt_param.slen - \ + (p - fmtp.fmt_param.ptr) - param.slen); \ + ival = pj_strtoul2(&s, NULL, base); \ + } while (0) + +#define GET_FMTP_IVAL(ival, fmtp, param, default_val) \ + GET_FMTP_IVAL_BASE(ival, 10, fmtp, param, default_val) + + + +PJ_DEF(pj_status_t) pjmedia_codec_g7221_match_sdp(pj_pool_t *pool, + pjmedia_sdp_media *offer, + unsigned o_fmt_idx, + pjmedia_sdp_media *answer, + unsigned a_fmt_idx, + unsigned option) +{ + const pjmedia_sdp_attr *attr_ans; + const pjmedia_sdp_attr *attr_ofr; + pjmedia_sdp_fmtp fmtp; + unsigned a_bitrate, o_bitrate; + const pj_str_t bitrate = {"bitrate=", 8}; + pj_status_t status; + + PJ_UNUSED_ARG(pool); + PJ_UNUSED_ARG(option); + + /* Parse offer */ + attr_ofr = pjmedia_sdp_media_find_attr2(offer, "fmtp", + &offer->desc.fmt[o_fmt_idx]); + if (!attr_ofr) + return PJMEDIA_SDP_EINFMTP; + + status = pjmedia_sdp_attr_get_fmtp(attr_ofr, &fmtp); + if (status != PJ_SUCCESS) + return status; + + GET_FMTP_IVAL(o_bitrate, fmtp, bitrate, 0); + + /* Parse answer */ + attr_ans = pjmedia_sdp_media_find_attr2(answer, "fmtp", + &answer->desc.fmt[a_fmt_idx]); + if (!attr_ans) + return PJMEDIA_SDP_EINFMTP; + + status = pjmedia_sdp_attr_get_fmtp(attr_ans, &fmtp); + if (status != PJ_SUCCESS) + return status; + + GET_FMTP_IVAL(a_bitrate, fmtp, bitrate, 0); + + /* Compare bitrate in answer and offer. */ + if (a_bitrate != o_bitrate) + return PJMEDIA_SDP_EFORMATNOTEQUAL; + + return PJ_SUCCESS; +} diff --git a/pjmedia/src/pjmedia-codec/ipp_codecs.c b/pjmedia/src/pjmedia-codec/ipp_codecs.c index 5f939d08..8072e6ce 100644 --- a/pjmedia/src/pjmedia-codec/ipp_codecs.c +++ b/pjmedia/src/pjmedia-codec/ipp_codecs.c @@ -18,6 +18,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include +#include #include #include #include @@ -665,6 +667,7 @@ PJ_DEF(pj_status_t) pjmedia_codec_g7221_set_pcm_shift(int val) PJ_DEF(pj_status_t) pjmedia_codec_ipp_init( pjmedia_endpt *endpt ) { pjmedia_codec_mgr *codec_mgr; + pj_str_t codec_name; pj_status_t status; if (ipp_factory.pool != NULL) { @@ -695,6 +698,37 @@ PJ_DEF(pj_status_t) pjmedia_codec_ipp_init( pjmedia_endpt *endpt ) goto on_error; } + /* Register format match callback. */ +#if PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1 + pj_cstr(&codec_name, "G7221"); + status = pjmedia_sdp_neg_register_fmt_match_cb( + &codec_name, + &pjmedia_codec_g7221_match_sdp); + if (status != PJ_SUCCESS) + goto on_error; +#endif + +#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR + pj_cstr(&codec_name, "AMR"); + status = pjmedia_sdp_neg_register_fmt_match_cb( + &codec_name, + &pjmedia_codec_amr_match_sdp); + if (status != PJ_SUCCESS) + goto on_error; +#endif + +#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMRWB + pj_cstr(&codec_name, "AMR-WB"); + status = pjmedia_sdp_neg_register_fmt_match_cb( + &codec_name, + &pjmedia_codec_amr_match_sdp); + if (status != PJ_SUCCESS) + goto on_error; +#endif + + /* Suppress compile warning */ + PJ_UNUSED_ARG(codec_name); + /* Register codec factory to endpoint. */ status = pjmedia_codec_mgr_register_factory(codec_mgr, &ipp_factory.base); diff --git a/pjmedia/src/pjmedia-codec/opencore_amrnb.c b/pjmedia/src/pjmedia-codec/opencore_amrnb.c index eba53215..fdc68cdd 100644 --- a/pjmedia/src/pjmedia-codec/opencore_amrnb.c +++ b/pjmedia/src/pjmedia-codec/opencore_amrnb.c @@ -1,4 +1,4 @@ -/* $Id */ +/* $Id$ */ /* * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2011 Dan Arrhenius @@ -22,6 +22,7 @@ * AMR-NB codec implementation with OpenCORE AMRNB library */ #include +#include #include #include #include @@ -166,6 +167,7 @@ static pjmedia_codec_amrnb_config def_config = PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_init( pjmedia_endpt *endpt ) { pjmedia_codec_mgr *codec_mgr; + pj_str_t codec_name; pj_status_t status; if (amr_codec_factory.pool != NULL) @@ -188,6 +190,14 @@ PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_init( pjmedia_endpt *endpt ) goto on_error; } + /* Register format match callback. */ + pj_cstr(&codec_name, "AMR"); + status = pjmedia_sdp_neg_register_fmt_match_cb( + &codec_name, + &pjmedia_codec_amr_match_sdp); + if (status != PJ_SUCCESS) + goto on_error; + /* Register codec factory to endpoint. */ status = pjmedia_codec_mgr_register_factory(codec_mgr, &amr_codec_factory.base); diff --git a/pjmedia/src/pjmedia-codec/passthrough.c b/pjmedia/src/pjmedia-codec/passthrough.c index 8fdd8271..ef34bd19 100644 --- a/pjmedia/src/pjmedia-codec/passthrough.c +++ b/pjmedia/src/pjmedia-codec/passthrough.c @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include #include #include @@ -316,6 +317,7 @@ static pj_status_t parse_amr(codec_private_t *codec_data, void *pkt, PJ_DEF(pj_status_t) pjmedia_codec_passthrough_init( pjmedia_endpt *endpt ) { pjmedia_codec_mgr *codec_mgr; + pj_str_t codec_name; pj_status_t status; if (codec_factory.pool != NULL) { @@ -346,6 +348,19 @@ PJ_DEF(pj_status_t) pjmedia_codec_passthrough_init( pjmedia_endpt *endpt ) goto on_error; } + /* Register format match callback. */ +#if PJMEDIA_HAS_PASSTROUGH_CODEC_AMR + pj_cstr(&codec_name, "AMR"); + status = pjmedia_sdp_neg_register_fmt_match_cb( + &codec_name, + &pjmedia_codec_amr_match_sdp); + if (status != PJ_SUCCESS) + goto on_error; +#endif + + /* Suppress compile warning */ + PJ_UNUSED_ARG(codec_name); + /* Register codec factory to endpoint. */ status = pjmedia_codec_mgr_register_factory(codec_mgr, &codec_factory.base); @@ -382,7 +397,7 @@ PJ_DEF(pj_status_t) pjmedia_codec_passthrough_init2( unsigned j; for (j = 0; j < setting->fmt_cnt && !enabled; ++j) { - if (codec_desc[i].fmt_id == setting->fmts[j].id) + if ((pj_uint32_t)codec_desc[i].fmt_id == setting->fmts[j].id) enabled = PJ_TRUE; } diff --git a/pjmedia/src/pjmedia/sdp_neg.c b/pjmedia/src/pjmedia/sdp_neg.c index f98f9004..fbc88c88 100644 --- a/pjmedia/src/pjmedia/sdp_neg.c +++ b/pjmedia/src/pjmedia/sdp_neg.c @@ -52,24 +52,6 @@ static const char *state_str[] = "STATE_DONE", }; -#define GET_FMTP_IVAL_BASE(ival, base, fmtp, param, default_val) \ - do { \ - pj_str_t s; \ - char *p; \ - p = pj_stristr(&fmtp.fmt_param, ¶m); \ - if (!p) { \ - ival = default_val; \ - break; \ - } \ - pj_strset(&s, p + param.slen, fmtp.fmt_param.slen - \ - (p - fmtp.fmt_param.ptr) - param.slen); \ - ival = pj_strtoul2(&s, NULL, base); \ - } while (0) - -#define GET_FMTP_IVAL(ival, fmtp, param, default_val) \ - GET_FMTP_IVAL_BASE(ival, 10, fmtp, param, default_val) - - /* Definition of customized SDP format negotiation callback */ struct fmt_match_cb_t { @@ -610,189 +592,6 @@ static void update_media_direction(pj_pool_t *pool, } } -/* Matching G722.1 bitrates between offer and answer. - */ -static pj_bool_t match_g7221( const pjmedia_sdp_media *offer, - unsigned o_fmt_idx, - const pjmedia_sdp_media *answer, - unsigned a_fmt_idx) -{ - const pjmedia_sdp_attr *attr_ans; - const pjmedia_sdp_attr *attr_ofr; - pjmedia_sdp_fmtp fmtp; - unsigned a_bitrate, o_bitrate; - const pj_str_t bitrate = {"bitrate=", 8}; - - /* Parse offer */ - attr_ofr = pjmedia_sdp_media_find_attr2(offer, "fmtp", - &offer->desc.fmt[o_fmt_idx]); - if (!attr_ofr) - return PJ_FALSE; - - if (pjmedia_sdp_attr_get_fmtp(attr_ofr, &fmtp) != PJ_SUCCESS) - return PJ_FALSE; - - GET_FMTP_IVAL(o_bitrate, fmtp, bitrate, 0); - - /* Parse answer */ - attr_ans = pjmedia_sdp_media_find_attr2(answer, "fmtp", - &answer->desc.fmt[a_fmt_idx]); - if (!attr_ans) - return PJ_FALSE; - - if (pjmedia_sdp_attr_get_fmtp(attr_ans, &fmtp) != PJ_SUCCESS) - return PJ_FALSE; - - GET_FMTP_IVAL(a_bitrate, fmtp, bitrate, 0); - - /* Compare bitrate in answer and offer. */ - return (a_bitrate == o_bitrate); -} - -/* Negotiate AMR format params between offer and answer. Format params - * to be matched are: octet-align, crc, robust-sorting, interleaving, - * and channels (channels is negotiated by rtpmap line negotiation). - * Note: For answerer, octet-align mode setting is adaptable to offerer - * setting. In the case that octet-align mode need to be adjusted, - * pt_need_adapt will be set to the format ID. - * - */ -static pj_bool_t match_amr( const pjmedia_sdp_media *offer, - unsigned o_fmt_idx, - const pjmedia_sdp_media *answer, - unsigned a_fmt_idx, - pj_bool_t answerer, - pj_str_t *pt_need_adapt) -{ - /* Negotiated format-param field-names constants. */ - const pj_str_t STR_OCTET_ALIGN = {"octet-align=", 12}; - const pj_str_t STR_CRC = {"crc=", 4}; - const pj_str_t STR_ROBUST_SORTING = {"robust-sorting=", 15}; - const pj_str_t STR_INTERLEAVING = {"interleaving=", 13}; - - /* Negotiated params and their default values. */ - unsigned a_octet_align = 0, o_octet_align = 0; - unsigned a_crc = 0, o_crc = 0; - unsigned a_robust_sorting = 0, o_robust_sorting = 0; - unsigned a_interleaving = 0, o_interleaving = 0; - - const pjmedia_sdp_attr *attr_ans; - const pjmedia_sdp_attr *attr_ofr; - pjmedia_sdp_fmtp fmtp; - pj_bool_t match; - - /* Parse offerer FMTP */ - attr_ofr = pjmedia_sdp_media_find_attr2(offer, "fmtp", - &offer->desc.fmt[o_fmt_idx]); - if (attr_ofr) { - if (pjmedia_sdp_attr_get_fmtp(attr_ofr, &fmtp) != PJ_SUCCESS) - /* Invalid fmtp format. */ - return PJ_FALSE; - - GET_FMTP_IVAL(o_octet_align, fmtp, STR_OCTET_ALIGN, 0); - GET_FMTP_IVAL(o_crc, fmtp, STR_CRC, 0); - GET_FMTP_IVAL(o_robust_sorting, fmtp, STR_ROBUST_SORTING, 0); - GET_FMTP_IVAL(o_interleaving, fmtp, STR_INTERLEAVING, 0); - } - - /* Parse answerer FMTP */ - attr_ans = pjmedia_sdp_media_find_attr2(answer, "fmtp", - &answer->desc.fmt[a_fmt_idx]); - if (attr_ans) { - if (pjmedia_sdp_attr_get_fmtp(attr_ans, &fmtp) != PJ_SUCCESS) - /* Invalid fmtp format. */ - return PJ_FALSE; - - GET_FMTP_IVAL(a_octet_align, fmtp, STR_OCTET_ALIGN, 0); - GET_FMTP_IVAL(a_crc, fmtp, STR_CRC, 0); - GET_FMTP_IVAL(a_robust_sorting, fmtp, STR_ROBUST_SORTING, 0); - GET_FMTP_IVAL(a_interleaving, fmtp, STR_INTERLEAVING, 0); - } - - if (answerer) { - match = a_crc == o_crc && - a_robust_sorting == o_robust_sorting && - a_interleaving == o_interleaving; - - /* If answerer octet-align setting doesn't match to the offerer's, - * set pt_need_adapt to this media format ID to signal the caller - * that this format ID needs to be adjusted. - */ - if (a_octet_align != o_octet_align && match) { - pj_assert(pt_need_adapt != NULL); - *pt_need_adapt = answer->desc.fmt[a_fmt_idx]; - } - } else { - match = (a_octet_align == o_octet_align && - a_crc == o_crc && - a_robust_sorting == o_robust_sorting && - a_interleaving == o_interleaving); - } - - return match; -} - - -/* Toggle AMR octet-align setting in the fmtp. - */ -static pj_status_t amr_toggle_octet_align(pj_pool_t *pool, - pjmedia_sdp_media *media, - unsigned fmt_idx) -{ - pjmedia_sdp_attr *attr; - pjmedia_sdp_fmtp fmtp; - const pj_str_t STR_OCTET_ALIGN = {"octet-align=", 12}; - - enum { MAX_FMTP_STR_LEN = 160 }; - - attr = pjmedia_sdp_media_find_attr2(media, "fmtp", - &media->desc.fmt[fmt_idx]); - /* Check if the AMR media format has FMTP attribute */ - if (attr) { - char *p; - pj_status_t status; - - status = pjmedia_sdp_attr_get_fmtp(attr, &fmtp); - if (status != PJ_SUCCESS) - return status; - - /* Check if the fmtp has octet-align field. */ - p = pj_stristr(&fmtp.fmt_param, &STR_OCTET_ALIGN); - if (p) { - /* It has, just toggle the value */ - unsigned octet_align; - pj_str_t s; - - pj_strset(&s, p + STR_OCTET_ALIGN.slen, fmtp.fmt_param.slen - - (p - fmtp.fmt_param.ptr) - STR_OCTET_ALIGN.slen); - octet_align = pj_strtoul(&s); - *(p + STR_OCTET_ALIGN.slen) = (char)(octet_align? '0' : '1'); - } else { - /* It doesn't, append octet-align field */ - char buf[MAX_FMTP_STR_LEN]; - - pj_ansi_snprintf(buf, MAX_FMTP_STR_LEN, "%.*s;octet-align=1", - (int)fmtp.fmt_param.slen, fmtp.fmt_param.ptr); - attr->value = pj_strdup3(pool, buf); - } - } else { - /* Add new attribute for the AMR media format with octet-align - * field set. - */ - char buf[MAX_FMTP_STR_LEN]; - - attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr); - attr->name = pj_str("fmtp"); - pj_ansi_snprintf(buf, MAX_FMTP_STR_LEN, "%.*s octet-align=1", - (int)media->desc.fmt[fmt_idx].slen, - media->desc.fmt[fmt_idx].ptr); - attr->value = pj_strdup3(pool, buf); - media->attr[media->attr_count++] = attr; - } - - return PJ_SUCCESS; -} - /* Update single local media description to after receiving answer * from remote. @@ -930,22 +729,6 @@ static pj_status_t process_m_answer( pj_pool_t *pool, (pj_stricmp(&or_.param, &ar.param)==0 || (ar.param.slen==1 && *ar.param.ptr=='1'))) { - /* Further check for G7221, negotiate bitrate. */ - if (pj_stricmp2(&or_.enc_name, "G7221") == 0) - { - if (match_g7221(offer, i, answer, j)) - break; - } else - - /* Further check for AMR, negotiate fmtp. */ - if (pj_stricmp2(&or_.enc_name, "AMR") == 0 || - pj_stricmp2(&or_.enc_name, "AMR-WB") == 0) - { - if (match_amr(offer, i, answer, j, PJ_FALSE, - NULL)) - break; - } else - /* Call custom format matching callbacks */ if (custom_fmt_match(pool, &or_.enc_name, offer, i, answer, j, 0) == @@ -1217,7 +1000,6 @@ static pj_status_t match_offer(pj_pool_t *pool, pj_str_t pt_offer[PJMEDIA_MAX_SDP_FMT]; pjmedia_sdp_media *answer; const pjmedia_sdp_media *master, *slave; - pj_str_t pt_amr_need_adapt = {NULL, 0}; /* If offer has zero port, just clone the offer */ if (offer->desc.port == 0) { @@ -1354,29 +1136,7 @@ static pj_status_t match_offer(pj_pool_t *pool, PJ_SUCCESS) { continue; - } else - - /* Further check for G7221, negotiate bitrate */ - if (pj_stricmp2(&or_.enc_name, "G7221") == 0 && - !match_g7221(master, i, slave, j)) - { - continue; - } else - - /* Further check for AMR, negotiate fmtp */ - if (pj_stricmp2(&or_.enc_name, "AMR")==0 || - pj_stricmp2(&or_.enc_name, "AMR-WB")==0) - { - unsigned o_med_idx, a_med_idx; - - o_med_idx = prefer_remote_codec_order? i:j; - a_med_idx = prefer_remote_codec_order? j:i; - if (!match_amr(offer, o_med_idx, - preanswer, a_med_idx, - PJ_TRUE, &pt_amr_need_adapt)) - continue; } - found_matching_codec = 1; } else { found_matching_telephone_event = 1; @@ -1453,10 +1213,6 @@ static pj_status_t match_offer(pj_pool_t *pool, } pj_assert(j != answer->desc.fmt_count); str_swap(&answer->desc.fmt[i], &answer->desc.fmt[j]); - - /* For AMR/AMRWB format, adapt octet-align setting if required. */ - if (!pj_strcmp(&pt_amr_need_adapt, &pt_answer[i])) - amr_toggle_octet_align(pool, answer, i); } /* Remove unwanted local formats. */ @@ -1783,24 +1539,6 @@ PJ_DEF(pj_status_t) pjmedia_sdp_neg_fmt_match(pj_pool_t *pool, return PJMEDIA_SDP_EFORMATNOTEQUAL; } - /* Further check for G7221, negotiate bitrate. */ - if (pj_stricmp2(&o_rtpmap.enc_name, "G7221") == 0) { - if (match_g7221(offer, o_fmt_idx, answer, a_fmt_idx)) - return PJ_SUCCESS; - else - return PJMEDIA_SDP_EFORMATNOTEQUAL; - } else - /* Further check for AMR, negotiate fmtp. */ - if (pj_stricmp2(&o_rtpmap.enc_name, "AMR") == 0 || - pj_stricmp2(&o_rtpmap.enc_name, "AMR-WB") == 0) - { - if (match_amr(offer, o_fmt_idx, answer, a_fmt_idx, PJ_FALSE, NULL)) - return PJ_SUCCESS; - else - return PJMEDIA_SDP_EFORMATNOTEQUAL; - } - PJ_TODO(replace_hardcoded_fmt_match_in_sdp_neg_with_custom_fmt_match_cb); - return custom_fmt_match(pool, &o_rtpmap.enc_name, offer, o_fmt_idx, answer, a_fmt_idx, option); } -- cgit v1.2.3