diff options
author | Benny Prijono <bennylp@teluu.com> | 2006-07-31 15:19:36 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2006-07-31 15:19:36 +0000 |
commit | ce9088d8978fdd457158ec0ea4c8e11e10b2960f (patch) | |
tree | 956aa5ec9405841bd1b2a12627591eaa37549235 /pjmedia | |
parent | 38d6c045a1d0ebb665a4c7213897330a6b8af7de (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/Makefile | 16 | ||||
-rw-r--r-- | pjmedia/build/pjmedia_codec.dsp | 205 | ||||
-rw-r--r-- | pjmedia/include/pjmedia-codec.h | 1 | ||||
-rw-r--r-- | pjmedia/include/pjmedia-codec/config.h | 8 | ||||
-rw-r--r-- | pjmedia/include/pjmedia-codec/types.h | 3 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/codec.h | 4 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/errno.h | 10 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/transport_udp.h | 22 | ||||
-rw-r--r-- | pjmedia/src/pjmedia-codec/speex_codec.c | 2 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/dsound.c | 2 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/endpoint.c | 19 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/errno.c | 2 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/session.c | 65 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/transport_udp.c | 48 |
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; +} + |