- 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: https://svn.pjsip.org/repos/pjproject/trunk@637 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
Benny Prijono 2006-07-31 15:19:36 +00:00
parent d345a65007
commit 00cae61f5e
19 changed files with 499 additions and 20 deletions

View File

@ -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)
###############################################################################

View File

@ -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

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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) */
};

View File

@ -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;

View File

@ -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 */
/************************************************************

View File

@ -143,9 +143,31 @@ PJ_DECL(pj_status_t) pjmedia_transport_udp_attach(pjmedia_endpt *endpt,
pjmedia_transport **p_tp);
/**
* 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);

View File

@ -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;

View File

@ -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

View File

@ -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. */

View File

@ -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" ),

View File

@ -57,6 +57,55 @@ static const pj_str_t STR_SENDONLY = { "sendonly", 8 };
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.
*/
@ -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) {

View File

@ -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;
}

View File

@ -123,9 +123,13 @@ static void usage(void)
puts (" --auto-play Automatically play the file (to incoming calls only)");
puts (" --auto-loop Automatically loop incoming RTP to outgoing RTP");
puts (" --rtp-port=N Base port to try for RTP (default=4000)");
puts (" --quality=N Specify media quality (0-10, default=10)");
puts (" --quality=N Specify media quality (0-10, default=6)");
puts (" --ptime=MSEC Override codec ptime to MSEC (default=specific)");
puts (" --no-vad Disable VAD/silence detector (default=vad enabled)");
puts (" --ilbc-mode=MODE Set iLBC codec mode (20 or 30, default is 20)");
puts (" --rx-drop-pct=PCT Drop PCT percent of RX RTP (for pkt lost sim, default: 0)");
puts (" --tx-drop-pct=PCT Drop PCT percent of TX RTP (for pkt lost sim, default: 0)");
puts ("");
puts ("Buddy List (can be more than one):");
@ -255,8 +259,9 @@ static pj_status_t parse_args(int argc, char *argv[],
OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE,
OPT_AUTO_ANSWER, OPT_AUTO_HANGUP, OPT_AUTO_PLAY, OPT_AUTO_LOOP,
OPT_AUTO_CONF, OPT_CLOCK_RATE,
OPT_PLAY_FILE, OPT_RTP_PORT, OPT_ADD_CODEC,
OPT_PLAY_FILE, OPT_RTP_PORT, OPT_ADD_CODEC, OPT_ILBC_MODE,
OPT_COMPLEXITY, OPT_QUALITY, OPT_PTIME, OPT_NO_VAD,
OPT_RX_DROP_PCT, OPT_TX_DROP_PCT,
OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS,
OPT_DURATION, OPT_NO_TCP, OPT_NO_UDP,
};
@ -298,6 +303,9 @@ static pj_status_t parse_args(int argc, char *argv[],
{ "quality", 1, 0, OPT_QUALITY},
{ "ptime", 1, 0, OPT_PTIME},
{ "no-vad", 0, 0, OPT_NO_VAD},
{ "ilbc-mode", 1, 0, OPT_ILBC_MODE},
{ "rx-drop-pct",1, 0, OPT_RX_DROP_PCT},
{ "tx-drop-pct",1, 0, OPT_TX_DROP_PCT},
{ "next-account",0,0, OPT_NEXT_ACCOUNT},
{ "next-cred", 0, 0, OPT_NEXT_CRED},
{ "max-calls", 1, 0, OPT_MAX_CALLS},
@ -624,6 +632,33 @@ static pj_status_t parse_args(int argc, char *argv[],
}
break;
case OPT_ILBC_MODE:
cfg->media_cfg.ilbc_mode = my_atoi(pj_optarg);
if (cfg->media_cfg.ilbc_mode!=20 && cfg->media_cfg.ilbc_mode!=30) {
PJ_LOG(1,(THIS_FILE,
"Error: invalid --ilbc-mode (expecting 20 or 30"));
return -1;
}
break;
case OPT_RX_DROP_PCT:
cfg->media_cfg.rx_drop_pct = my_atoi(pj_optarg);
if (cfg->media_cfg.rx_drop_pct > 100) {
PJ_LOG(1,(THIS_FILE,
"Error: invalid --rx-drop-pct (expecting <= 100"));
return -1;
}
break;
case OPT_TX_DROP_PCT:
cfg->media_cfg.tx_drop_pct = my_atoi(pj_optarg);
if (cfg->media_cfg.tx_drop_pct > 100) {
PJ_LOG(1,(THIS_FILE,
"Error: invalid --tx-drop-pct (expecting <= 100"));
return -1;
}
break;
case OPT_AUTO_ANSWER:
cfg->auto_answer = my_atoi(pj_optarg);
if (cfg->auto_answer < 100 || cfg->auto_answer > 699) {

View File

@ -2087,7 +2087,7 @@ struct pjsua_media_config
* The media quality also sets speex codec quality/complexity to the
* number.
*
* Default: 5.
* Default: 6.
*/
unsigned quality;
@ -2104,6 +2104,30 @@ struct pjsua_media_config
* Default: 0 (no (meaning VAD is enabled))
*/
pj_bool_t no_vad;
/**
* iLBC mode (20 or 30).
*
* Default: 20
*/
unsigned ilbc_mode;
/**
* Percentage of RTP packet to drop in TX direction
* (to simulate packet lost).
*
* Default: 0
*/
unsigned tx_drop_pct;
/**
* Percentage of RTP packet to drop in RX direction
* (to simulate packet lost).
*
* Default: 0
*/
unsigned rx_drop_pct;
};
@ -2120,7 +2144,8 @@ PJ_INLINE(void) pjsua_media_config_default(pjsua_media_config *cfg)
cfg->max_media_ports = 32;
cfg->has_ioqueue = PJ_TRUE;
cfg->thread_cnt = 1;
cfg->quality = 5;
cfg->quality = 6;
cfg->ilbc_mode = 20;
}

View File

@ -941,6 +941,7 @@ PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id,
}
/* Create SDP */
PJ_UNUSED_ARG(unhold);
PJ_TODO(create_active_inactive_sdp_based_on_unhold_arg);
status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt, call->inv->pool,
1, &call->skinfo, &sdp);
@ -1853,8 +1854,8 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv,
/* Override ptime, if this option is specified. */
if (pjsua_var.media_cfg.ptime != 0) {
sess_info.stream_info[0].param->setting.frm_per_pkt =
pjsua_var.media_cfg.ptime / sess_info.stream_info[0].param->info.frm_ptime;
sess_info.stream_info[0].param->setting.frm_per_pkt = (pj_uint8_t)
(pjsua_var.media_cfg.ptime / sess_info.stream_info[0].param->info.frm_ptime);
if (sess_info.stream_info[0].param->setting.frm_per_pkt == 0)
sess_info.stream_info[0].param->setting.frm_per_pkt = 1;
}

View File

@ -1114,7 +1114,7 @@ PJ_DEF(pj_status_t) pjsua_transport_close( pjsua_transport_id id,
/* To be done!! */
PJ_UNUSED_ARG(force);
PJ_TODO(pjsua_transport_close);

View File

@ -85,6 +85,17 @@ pj_status_t pjsua_media_subsys_init(const pjsua_media_config *cfg)
}
#endif /* PJMEDIA_HAS_SPEEX_CODEC */
#if PJMEDIA_HAS_ILBC_CODEC
/* Register iLBC. */
status = pjmedia_codec_ilbc_init( pjsua_var.med_endpt,
pjsua_var.media_cfg.ilbc_mode);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Error initializing iLBC codec",
status);
return status;
}
#endif /* PJMEDIA_HAS_ILBC_CODEC */
#if PJMEDIA_HAS_GSM_CODEC
/* Register GSM */
status = pjmedia_codec_gsm_init(pjsua_var.med_endpt);
@ -484,6 +495,15 @@ pjsua_media_transports_create(const pjsua_transport_config *app_cfg)
status);
goto on_error;
}
pjmedia_transport_udp_simulate_lost(pjsua_var.calls[i].med_tp,
PJMEDIA_DIR_ENCODING,
pjsua_var.media_cfg.tx_drop_pct);
pjmedia_transport_udp_simulate_lost(pjsua_var.calls[i].med_tp,
PJMEDIA_DIR_DECODING,
pjsua_var.media_cfg.rx_drop_pct);
}
PJSUA_UNLOCK();
@ -660,7 +680,7 @@ PJ_DEF(pj_status_t) pjsua_player_create( const pj_str_t *filename,
status = pjmedia_wav_player_port_create(pjsua_var.pool, path,
pjsua_var.mconf_cfg.samples_per_frame *
1000 / pjsua_var.media_cfg.clock_rate,
0, 0, &port);
options, 0, &port);
if (status != PJ_SUCCESS) {
PJSUA_UNLOCK();
pjsua_perror(THIS_FILE, "Unable to open file for playback", status);
@ -758,6 +778,15 @@ PJ_DEF(pj_status_t) pjsua_recorder_create( const pj_str_t *filename,
pjmedia_port *port;
pj_status_t status;
/* Don't support max_size at present */
PJ_ASSERT_RETURN(max_size == 0, PJ_EINVAL);
/* Don't support file format at present */
PJ_ASSERT_RETURN(file_format == 0, PJ_EINVAL);
/* Don't support encoding at present */
PJ_ASSERT_RETURN(encoding == NULL, PJ_EINVAL);
if (pjsua_var.rec_cnt >= PJ_ARRAY_SIZE(pjsua_var.recorder))
return PJ_ETOOMANY;
@ -782,7 +811,7 @@ PJ_DEF(pj_status_t) pjsua_recorder_create( const pj_str_t *filename,
pjsua_var.mconf_cfg.channel_count,
pjsua_var.mconf_cfg.samples_per_frame,
pjsua_var.mconf_cfg.bits_per_sample,
0, 0, &port);
options, 0, &port);
if (status != PJ_SUCCESS) {
PJSUA_UNLOCK();
pjsua_perror(THIS_FILE, "Unable to open file for recording", status);
@ -1092,8 +1121,8 @@ PJ_DEF(pj_status_t) pjsua_codec_get_param( const pj_str_t *codec_id,
PJ_DEF(pj_status_t) pjsua_codec_set_param( const pj_str_t *id,
const pjmedia_codec_param *param)
{
PJ_UNUSED_ARG(id);
PJ_UNUSED_ARG(param);
PJ_TODO(set_codec_param);
return PJ_SUCCESS;
}