summaryrefslogtreecommitdiff
path: root/pjmedia
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-07-31 15:19:36 +0000
committerBenny Prijono <bennylp@teluu.com>2006-07-31 15:19:36 +0000
commitce9088d8978fdd457158ec0ea4c8e11e10b2960f (patch)
tree956aa5ec9405841bd1b2a12627591eaa37549235 /pjmedia
parent38d6c045a1d0ebb665a4c7213897330a6b8af7de (diff)
- Added iLBC codec (experimental) with the following features:
- configurable default decoder mode (20 or 30), - encoder mode follows the mode specified in SDP fmtp from the remote's SDP, - silence detector uses pjmedia's, - PLC uses iLBC's PLC, - perceptual enhancement (penh) is configurable via codec param, as usual. - iLBC mode is configurable in pjsua with --ilbc-mode option. - Added packet lost simulation in pjmedia's UDP transport and in pjsua (with --rx-drop-pct and --tx-drop-pct options). - Increase default buffer count in DirectSound to 32 frames to make it more resilient to CPU disruption. - Specify and parse fmtp mode in SDP for codecs that need it. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@637 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r--pjmedia/build/Makefile16
-rw-r--r--pjmedia/build/pjmedia_codec.dsp205
-rw-r--r--pjmedia/include/pjmedia-codec.h1
-rw-r--r--pjmedia/include/pjmedia-codec/config.h8
-rw-r--r--pjmedia/include/pjmedia-codec/types.h3
-rw-r--r--pjmedia/include/pjmedia/codec.h4
-rw-r--r--pjmedia/include/pjmedia/errno.h10
-rw-r--r--pjmedia/include/pjmedia/transport_udp.h22
-rw-r--r--pjmedia/src/pjmedia-codec/speex_codec.c2
-rw-r--r--pjmedia/src/pjmedia/dsound.c2
-rw-r--r--pjmedia/src/pjmedia/endpoint.c19
-rw-r--r--pjmedia/src/pjmedia/errno.c2
-rw-r--r--pjmedia/src/pjmedia/session.c65
-rw-r--r--pjmedia/src/pjmedia/transport_udp.c48
14 files changed, 398 insertions, 9 deletions
diff --git a/pjmedia/build/Makefile b/pjmedia/build/Makefile
index 7e183502..c0465f10 100644
--- a/pjmedia/build/Makefile
+++ b/pjmedia/build/Makefile
@@ -11,7 +11,7 @@ export SOUND_OBJS = $(PORTAUDIO_OBJS)
# E.g., to exclude Speex, we need to exclude SPEEX_OBJS from CODEC_OBJS, AND specify
# "#define PJMEDIA_HAS_SPEEX_CODEC 0" in pj/config_site.h.
#
-export CODEC_OBJS = $(GSM_OBJS) $(SPEEX_OBJS)
+export CODEC_OBJS = $(GSM_OBJS) $(SPEEX_OBJS) $(ILBC_OBJS)
include ../../build/common.mak
@@ -106,11 +106,23 @@ SPEEX_OBJS := speex_codec.o \
speex/stereo.o speex/vbr.o speex/vq.o speex/window.o
SPEEX_CFLAGS := -DHAVE_CONFIG_H=1 -I../src/pjmedia-codec
+ILBC_OBJS := ilbc.o \
+ ilbc/FrameClassify.o ilbc/LPCdecode.o ilbc/LPCencode.o \
+ ilbc/StateConstructW.o ilbc/StateSearchW.o ilbc/anaFilter.o \
+ ilbc/constants.o ilbc/createCB.o ilbc/doCPLC.o \
+ ilbc/enhancer.o ilbc/filter.o ilbc/gainquant.o \
+ ilbc/getCBvec.o ilbc/helpfun.o ilbc/hpInput.o \
+ ilbc/hpOutput.o ilbc/iCBConstruct.o ilbc/iCBSearch.o \
+ ilbc/iLBC_decode.o ilbc/iLBC_encode.o ilbc/lsf.o \
+ ilbc/packing.o ilbc/syntFilter.o
+ILBC_CFLAGS :=
+
export PJMEDIA_CODEC_SRCDIR = ../src/pjmedia-codec
export PJMEDIA_CODEC_OBJS += l16.o \
$(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
$(CODEC_OBJS)
-export PJMEDIA_CODEC_CFLAGS += $(_CFLAGS) $(GSM_CFLAGS) $(SPEEX_CFLAGS)
+export PJMEDIA_CODEC_CFLAGS += $(_CFLAGS) $(GSM_CFLAGS) $(SPEEX_CFLAGS) \
+ $(ILBC_CFLAGS)
###############################################################################
diff --git a/pjmedia/build/pjmedia_codec.dsp b/pjmedia/build/pjmedia_codec.dsp
index a1bd308a..42490a1c 100644
--- a/pjmedia/build/pjmedia_codec.dsp
+++ b/pjmedia/build/pjmedia_codec.dsp
@@ -100,6 +100,10 @@ SOURCE="..\src\pjmedia-codec\gsm.c"
# End Source File
# Begin Source File
+SOURCE="..\src\pjmedia-codec\ilbc.c"
+# End Source File
+# Begin Source File
+
SOURCE="..\src\pjmedia-codec\l16.c"
!IF "$(CFG)" == "pjmedia_codec - Win32 Release"
@@ -138,6 +142,10 @@ SOURCE="..\include\pjmedia-codec\gsm.h"
# End Source File
# Begin Source File
+SOURCE="..\include\pjmedia-codec\ilbc.h"
+# End Source File
+# Begin Source File
+
SOURCE="..\include\pjmedia-codec\l16.h"
# End Source File
# Begin Source File
@@ -663,5 +671,202 @@ SOURCE="..\src\pjmedia-codec\speex\window.c"
# End Source File
# End Group
# End Group
+# Begin Group "iLBC Codec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\anaFilter.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\anaFilter.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\constants.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\constants.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\createCB.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\createCB.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\doCPLC.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\doCPLC.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\enhancer.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\enhancer.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\filter.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\filter.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\FrameClassify.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\FrameClassify.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\gainquant.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\gainquant.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\getCBvec.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\getCBvec.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\helpfun.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\helpfun.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\hpInput.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\hpInput.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\hpOutput.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\hpOutput.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\iCBConstruct.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\iCBConstruct.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\iCBSearch.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\iCBSearch.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\iLBC_decode.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\iLBC_decode.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\iLBC_define.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\iLBC_encode.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\iLBC_encode.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\iLBC_test.c"
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\LPCdecode.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\LPCdecode.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\LPCencode.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\LPCencode.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\lsf.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\lsf.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\packing.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\packing.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\StateConstructW.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\StateConstructW.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\StateSearchW.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\StateSearchW.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\syntFilter.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjmedia-codec\ilbc\syntFilter.h"
+# End Source File
+# End Group
# End Target
# End Project
diff --git a/pjmedia/include/pjmedia-codec.h b/pjmedia/include/pjmedia-codec.h
index 3658cb10..f220fd1f 100644
--- a/pjmedia/include/pjmedia-codec.h
+++ b/pjmedia/include/pjmedia-codec.h
@@ -27,6 +27,7 @@
#include <pjmedia-codec/l16.h>
#include <pjmedia-codec/gsm.h>
#include <pjmedia-codec/speex.h>
+#include <pjmedia-codec/ilbc.h>
#endif /* __PJMEDIA_CODEC_PJMEDIA_CODEC_H__ */
diff --git a/pjmedia/include/pjmedia-codec/config.h b/pjmedia/include/pjmedia-codec/config.h
index 2006528d..85bd7785 100644
--- a/pjmedia/include/pjmedia-codec/config.h
+++ b/pjmedia/include/pjmedia-codec/config.h
@@ -46,5 +46,13 @@
#endif
+/**
+ * Unless specified otherwise, iLBC codec is included by default.
+ */
+#ifndef PJMEDIA_HAS_ILBC_CODEC
+# define PJMEDIA_HAS_ILBC_CODEC 1
+#endif
+
+
#endif /* __PJMEDIA_CODEC_CONFIG_H__ */
diff --git a/pjmedia/include/pjmedia-codec/types.h b/pjmedia/include/pjmedia-codec/types.h
index a738fb68..18c7bfab 100644
--- a/pjmedia/include/pjmedia-codec/types.h
+++ b/pjmedia/include/pjmedia-codec/types.h
@@ -48,7 +48,8 @@ enum
PJMEDIA_RTP_PT_L16_32KHZ_MONO, /**< L16 @ 32KHz, mono */
PJMEDIA_RTP_PT_L16_32KHZ_STEREO, /**< L16 @ 32KHz, stereo */
PJMEDIA_RTP_PT_L16_48KHZ_MONO, /**< L16 @ 48KHz, mono */
- PJMEDIA_RTP_PT_L16_48KHZ_STEREO /**< L16 @ 48KHz, stereo */
+ PJMEDIA_RTP_PT_L16_48KHZ_STEREO, /**< L16 @ 48KHz, stereo */
+ PJMEDIA_RTP_PT_ILBC /**< iLBC (13.3/15.2Kbps) */
};
diff --git a/pjmedia/include/pjmedia/codec.h b/pjmedia/include/pjmedia/codec.h
index 844f8865..dd611f2f 100644
--- a/pjmedia/include/pjmedia/codec.h
+++ b/pjmedia/include/pjmedia/codec.h
@@ -271,11 +271,11 @@ typedef struct pjmedia_codec_param
pj_uint8_t frm_per_pkt; /**< Number of frames per packet. */
unsigned vad:1; /**< Voice Activity Detector. */
unsigned cng:1; /**< Comfort Noise Generator. */
- unsigned lpf:1; /**< Low pass filter */
- unsigned hpf:1; /**< High pass filter */
unsigned penh:1; /**< Perceptual Enhancement */
unsigned plc:1; /**< Packet loss concealment */
unsigned reserved:1; /**< Reserved, must be zero. */
+ pj_uint8_t enc_fmtp_mode; /**< Mode param in fmtp (def:0) */
+ pj_uint8_t dec_fmtp_mode; /**< Mode param in fmtp (def:0) */
} setting;
} pjmedia_codec_param;
diff --git a/pjmedia/include/pjmedia/errno.h b/pjmedia/include/pjmedia/errno.h
index c9c6bae2..03608f9f 100644
--- a/pjmedia/include/pjmedia/errno.h
+++ b/pjmedia/include/pjmedia/errno.h
@@ -298,6 +298,16 @@ PJ_BEGIN_DECL
* Invalid codec frame length.
*/
#define PJMEDIA_CODEC_EFRMINLEN (PJMEDIA_ERRNO_START+84) /* 220084 */
+/**
+ * @hideinitializer
+ * Invalid PCM frame length.
+ */
+#define PJMEDIA_CODEC_EPCMFRMINLEN (PJMEDIA_ERRNO_START+85) /* 220085 */
+/**
+ * @hideinitializer
+ * Invalid mode.
+ */
+#define PJMEDIA_CODEC_EINMODE (PJMEDIA_ERRNO_START+86) /* 220086 */
/************************************************************
diff --git a/pjmedia/include/pjmedia/transport_udp.h b/pjmedia/include/pjmedia/transport_udp.h
index 860ea7e3..5a348d32 100644
--- a/pjmedia/include/pjmedia/transport_udp.h
+++ b/pjmedia/include/pjmedia/transport_udp.h
@@ -144,8 +144,30 @@ PJ_DECL(pj_status_t) pjmedia_transport_udp_attach(pjmedia_endpt *endpt,
/**
+ * Simulate packet lost in the specified direction (for testing purposes).
+ * When enabled, the transport will randomly drop packets to the specified
+ * direction.
+ *
+ * @param tp The UDP media transport.
+ * @param dir Media direction to which packets will be randomly dropped.
+ * @param pct_lost Percent lost (0-100). Set to zero to disable packet
+ * lost simulation.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_transport_udp_simulate_lost(pjmedia_transport *tp,
+ pjmedia_dir dir,
+ unsigned pct_lost);
+
+
+
+/**
* Close UDP transport. Application can also use the "destroy" member of
* media transport interface to close the UDP transport.
+ *
+ * @param tp The UDP media transport.
+ *
+ * @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_transport_udp_close(pjmedia_transport *tp);
diff --git a/pjmedia/src/pjmedia-codec/speex_codec.c b/pjmedia/src/pjmedia-codec/speex_codec.c
index b434ee85..e4dda97a 100644
--- a/pjmedia/src/pjmedia-codec/speex_codec.c
+++ b/pjmedia/src/pjmedia-codec/speex_codec.c
@@ -408,8 +408,6 @@ static pj_status_t spx_default_attr (pjmedia_codec_factory *factory,
/* Default flags. */
attr->setting.cng = 1;
attr->setting.plc = 1;
- attr->setting.hpf = 1;
- attr->setting.lpf =1 ;
attr->setting.penh =1 ;
attr->setting.vad = 1;
diff --git a/pjmedia/src/pjmedia/dsound.c b/pjmedia/src/pjmedia/dsound.c
index e452fa55..bf29299e 100644
--- a/pjmedia/src/pjmedia/dsound.c
+++ b/pjmedia/src/pjmedia/dsound.c
@@ -44,7 +44,7 @@
#define BYTES_PER_SAMPLE (BITS_PER_SAMPLE/8)
#define MAX_PACKET_BUFFER_COUNT 32
-#define DEFAULT_BUFFER_COUNT 16
+#define DEFAULT_BUFFER_COUNT 32
#define MAX_HARDWARE 16
diff --git a/pjmedia/src/pjmedia/endpoint.c b/pjmedia/src/pjmedia/endpoint.c
index 5e098c45..eb9d8947 100644
--- a/pjmedia/src/pjmedia/endpoint.c
+++ b/pjmedia/src/pjmedia/endpoint.c
@@ -346,19 +346,22 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt,
}
#endif
- /* Add format and rtpmap for each codec */
+ /* Add format, rtpmap, and fmtp (when applicable) for each codec */
for (i=0; i<endpt->codec_mgr.codec_cnt; ++i) {
pjmedia_codec_info *codec_info;
pjmedia_sdp_rtpmap rtpmap;
char tmp_param[3];
pjmedia_sdp_attr *attr;
+ pjmedia_codec_param codec_param;
pj_str_t *fmt;
if (endpt->codec_mgr.codec_desc[i].prio == PJMEDIA_CODEC_PRIO_DISABLED)
break;
codec_info = &endpt->codec_mgr.codec_desc[i].info;
+ pjmedia_codec_mgr_get_default_param(&endpt->codec_mgr, codec_info,
+ &codec_param);
fmt = &m->desc.fmt[m->desc.fmt_count++];
fmt->ptr = pj_pool_alloc(pool, 8);
@@ -390,6 +393,20 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt,
pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
m->attr[m->attr_count++] = attr;
+ /* Add fmtp mode where applicable */
+ if (codec_param.setting.dec_fmtp_mode != 0) {
+ const pj_str_t fmtp = { "fmtp", 4 };
+ attr = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_attr));
+
+ attr->name = fmtp;
+ attr->value.ptr = pj_pool_alloc(pool, 32);
+ attr->value.slen =
+ pj_ansi_snprintf( attr->value.ptr, 32,
+ ":%d mode=%d",
+ codec_info->pt,
+ codec_param.setting.dec_fmtp_mode);
+ m->attr[m->attr_count++] = attr;
+ }
}
/* Add sendrecv attribute. */
diff --git a/pjmedia/src/pjmedia/errno.c b/pjmedia/src/pjmedia/errno.c
index 3d62e067..9305cd65 100644
--- a/pjmedia/src/pjmedia/errno.c
+++ b/pjmedia/src/pjmedia/errno.c
@@ -89,6 +89,8 @@ static const struct
PJ_BUILD_ERR( PJMEDIA_CODEC_EFRMTOOSHORT, "Codec frame is too short" ),
PJ_BUILD_ERR( PJMEDIA_CODEC_EPCMTOOSHORT, "PCM frame is too short" ),
PJ_BUILD_ERR( PJMEDIA_CODEC_EFRMINLEN, "Invalid codec frame length" ),
+ PJ_BUILD_ERR( PJMEDIA_CODEC_EPCMFRMINLEN, "Invalid PCM frame length" ),
+ PJ_BUILD_ERR( PJMEDIA_CODEC_EINMODE, "Invalid codec mode (no fmtp?)" ),
/* Media errors. */
PJ_BUILD_ERR( PJMEDIA_EINVALIDIP, "Invalid remote media (IP) address" ),
diff --git a/pjmedia/src/pjmedia/session.c b/pjmedia/src/pjmedia/session.c
index b629219c..870576de 100644
--- a/pjmedia/src/pjmedia/session.c
+++ b/pjmedia/src/pjmedia/session.c
@@ -58,6 +58,55 @@ static const pj_str_t STR_RECVONLY = { "recvonly", 8 };
/*
+ * Get fmtp mode parameter associated with the codec.
+ */
+static pj_status_t get_fmtp_mode(const pjmedia_sdp_media *m,
+ const pj_str_t *fmt,
+ int *p_mode)
+{
+ const pjmedia_sdp_attr *attr;
+ pjmedia_sdp_fmtp fmtp;
+ const pj_str_t str_mode = { "mode=", 5 };
+ char *pos;
+
+ /* Get "fmtp" attribute for the format */
+ attr = pjmedia_sdp_media_find_attr2(m, "fmtp", fmt);
+ if (attr == NULL)
+ return -1;
+
+ /* Parse "fmtp" attribute */
+ if (pjmedia_sdp_attr_get_fmtp(attr, &fmtp) != PJ_SUCCESS)
+ return -1;
+
+ /* Look for "mode=" string in the fmtp */
+ while (fmtp.fmt_param.slen >= str_mode.slen + 1) {
+ if (pj_strnicmp(&fmtp.fmt_param, &str_mode, str_mode.slen)==0) {
+ /* Found "mode=" string */
+ break;
+ }
+
+ fmtp.fmt_param.ptr++;
+ fmtp.fmt_param.slen--;
+ }
+
+ if (fmtp.fmt_param.slen < str_mode.slen + 1) {
+ /* "mode=" param not found */
+ return -1;
+ }
+
+ /* Get the mode */
+ pos = fmtp.fmt_param.ptr + str_mode.slen;
+ *p_mode = 0;
+ while (pj_isdigit(*pos)) {
+ *p_mode = *p_mode * 10 + (*pos - '0');
+ ++pos;
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+/*
* Create stream info from SDP media line.
*/
PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp(
@@ -75,6 +124,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp(
const pjmedia_sdp_conn *local_conn;
const pjmedia_sdp_conn *rem_conn;
pjmedia_sdp_rtpmap *rtpmap;
+ int local_fmtp_mode = 0, rem_fmtp_mode = 0;
unsigned i, pt;
pj_status_t status;
@@ -270,6 +320,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp(
si->tx_pt = pt;
} else {
+
attr = pjmedia_sdp_media_find_attr(local_m, &ID_RTPMAP,
&local_m->desc.fmt[0]);
if (attr == NULL)
@@ -304,6 +355,9 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp(
si->fmt.channel_cnt = 1;
}
+ /* Get fmtp mode= param in local SDP, if any */
+ get_fmtp_mode(local_m, &local_m->desc.fmt[0], &local_fmtp_mode);
+
/* Determine payload type for outgoing channel, by finding
* dynamic payload type in remote SDP that matches the answer.
*/
@@ -330,6 +384,10 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp(
{
/* Found matched codec. */
si->tx_pt = rpt;
+
+ /* Get fmtp mode param in remote SDP, if any */
+ get_fmtp_mode(rem_m, &rtpmap->pt, &rem_fmtp_mode);
+
break;
}
}
@@ -345,6 +403,13 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp(
if (status != PJ_SUCCESS)
return status;
+ /* Set fmtp mode for both local and remote */
+ if (local_fmtp_mode != 0)
+ si->param->setting.dec_fmtp_mode = (pj_int8_t)local_fmtp_mode;
+ if (rem_fmtp_mode != 0)
+ si->param->setting.enc_fmtp_mode = (pj_int8_t)rem_fmtp_mode;
+
+
/* Get incomming payload type for telephone-events */
si->rx_event_pt = -1;
for (i=0; i<local_m->attr_count; ++i) {
diff --git a/pjmedia/src/pjmedia/transport_udp.c b/pjmedia/src/pjmedia/transport_udp.c
index edfabbb9..4928c0ce 100644
--- a/pjmedia/src/pjmedia/transport_udp.c
+++ b/pjmedia/src/pjmedia/transport_udp.c
@@ -21,6 +21,7 @@
#include <pj/errno.h>
#include <pj/ioqueue.h>
#include <pj/log.h>
+#include <pj/rand.h>
#include <pj/string.h>
@@ -58,6 +59,9 @@ struct transport_udp
const void*,
pj_ssize_t);
+ unsigned tx_drop_pct; /**< Percent of tx pkts to drop. */
+ unsigned rx_drop_pct; /**< Percent of rx pkts to drop. */
+
pj_sock_t rtp_sock; /**< RTP socket */
pj_sockaddr_in rtp_addr_name; /**< Published RTP address. */
pj_ioqueue_key_t *rtp_key; /**< RTP socket key in ioqueue */
@@ -371,6 +375,17 @@ static void on_rx_rtp( pj_ioqueue_key_t *key,
cb = udp->rtp_cb;
user_data = udp->user_data;
+ /* Simulate packet lost on RX direction */
+ if (udp->rx_drop_pct) {
+ if ((pj_rand() % 100) <= (int)udp->rx_drop_pct) {
+ PJ_LOG(5,(udp->base.name,
+ "RX RTP packet dropped because of pkt lost "
+ "simulation"));
+ goto read_next_packet;
+ }
+ }
+
+
if (udp->attached && cb)
(*cb)(user_data, udp->rtp_pkt, bytes_read);
@@ -425,6 +440,7 @@ static void on_rx_rtp( pj_ioqueue_key_t *key,
}
}
+read_next_packet:
bytes_read = sizeof(udp->rtp_pkt);
udp->rtp_addrlen = sizeof(pj_sockaddr_in);
status = pj_ioqueue_recvfrom(udp->rtp_key, &udp->rtp_read_op,
@@ -581,6 +597,17 @@ static pj_status_t transport_send_rtp( pjmedia_transport *tp,
/* Check that the size is supported */
PJ_ASSERT_RETURN(size <= RTP_LEN, PJ_ETOOBIG);
+ /* Simulate packet lost on TX direction */
+ if (udp->tx_drop_pct) {
+ if ((pj_rand() % 100) <= (int)udp->tx_drop_pct) {
+ PJ_LOG(5,(udp->base.name,
+ "TX RTP packet dropped because of pkt lost "
+ "simulation"));
+ return PJ_SUCCESS;
+ }
+ }
+
+
id = udp->rtp_write_op_id;
pw = &udp->rtp_pending_write[id];
@@ -628,3 +655,24 @@ static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
return status;
}
+
+PJ_DEF(pj_status_t) pjmedia_transport_udp_simulate_lost(pjmedia_transport *tp,
+ pjmedia_dir dir,
+ unsigned pct_lost)
+{
+ struct transport_udp *udp = (struct transport_udp*)tp;
+
+ PJ_ASSERT_RETURN(tp &&
+ (dir==PJMEDIA_DIR_ENCODING||dir==PJMEDIA_DIR_DECODING) &&
+ pct_lost <= 100, PJ_EINVAL);
+
+ if (dir == PJMEDIA_DIR_ENCODING)
+ udp->tx_drop_pct = pct_lost;
+ else if (dir == PJMEDIA_DIR_DECODING)
+ udp->rx_drop_pct = pct_lost;
+ else
+ return PJ_EINVAL;
+
+ return PJ_SUCCESS;
+}
+