summaryrefslogtreecommitdiff
path: root/pjmedia/src
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/src
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/src')
-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
6 files changed, 134 insertions, 4 deletions
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;
+}
+