summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-09-20 20:02:18 +0000
committerBenny Prijono <bennylp@teluu.com>2006-09-20 20:02:18 +0000
commitfea1c2e2fd2629ec721f82a45046d19eddbda820 (patch)
tree48689e085b45d935fce06ba043b4f59d1157bac4
parenteba3cc35db92c66e1d99180060a02d008c68f7ca (diff)
Automatically suspend AEC when nothing is connected to the sound port in the bridge, and resume as soon as frames are transmitted.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@731 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjmedia/include/pjmedia/sound_port.h6
-rw-r--r--pjmedia/src/pjmedia/conference.c22
-rw-r--r--pjmedia/src/pjmedia/port.c15
-rw-r--r--pjmedia/src/pjmedia/sound_port.c29
-rw-r--r--pjmedia/src/pjmedia/wav_player.c14
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h2
6 files changed, 63 insertions, 25 deletions
diff --git a/pjmedia/include/pjmedia/sound_port.h b/pjmedia/include/pjmedia/sound_port.h
index c65a11dc..a1378320 100644
--- a/pjmedia/include/pjmedia/sound_port.h
+++ b/pjmedia/include/pjmedia/sound_port.h
@@ -220,6 +220,12 @@ PJ_DECL(pj_status_t) pjmedia_snd_port_get_ec_tail(pjmedia_snd_port *snd_port,
unsigned *p_length);
+/**
+ * Enable or disable echo canceller. By default the EC is enabled after it
+ * was created, so there is no need to enable the EC after creating it.
+ * This function is only useful to disable the echo canceller temporarily,
+ * for example during idle period, to prevent EC from using
+ */
/**
* Connect a port to the sound device port. If the sound device port has a
diff --git a/pjmedia/src/pjmedia/conference.c b/pjmedia/src/pjmedia/conference.c
index a0743b6a..df623f1f 100644
--- a/pjmedia/src/pjmedia/conference.c
+++ b/pjmedia/src/pjmedia/conference.c
@@ -1266,12 +1266,15 @@ static pj_status_t read_port( pjmedia_conf *conf,
* Write the mixed signal to the port.
*/
static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport,
- pj_uint32_t timestamp)
+ pj_uint32_t timestamp,
+ pjmedia_frame_type *frm_type)
{
pj_int16_t *buf;
unsigned j;
pj_status_t status;
+ *frm_type = PJMEDIA_FRAME_TYPE_AUDIO;
+
/* If port is muted or nobody is transmitting to this port,
* transmit NULL frame.
*/
@@ -1292,10 +1295,12 @@ static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport,
}
cport->tx_level = 0;
+ *frm_type = PJMEDIA_FRAME_TYPE_NONE;
return PJ_SUCCESS;
} else if (cport->tx_setting != PJMEDIA_PORT_ENABLE) {
cport->tx_level = 0;
+ *frm_type = PJMEDIA_FRAME_TYPE_NONE;
return PJ_SUCCESS;
}
@@ -1486,6 +1491,7 @@ static pj_status_t get_frame(pjmedia_port *this_port,
pjmedia_frame *frame)
{
pjmedia_conf *conf = this_port->port_data.pdata;
+ pjmedia_frame_type speaker_frame_type = PJMEDIA_FRAME_TYPE_NONE;
unsigned ci, cj, i, j;
TRACE_((THIS_FILE, "- clock -"));
@@ -1683,6 +1689,7 @@ static pj_status_t get_frame(pjmedia_port *this_port,
*/
for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) {
struct conf_port *conf_port = conf->ports[i];
+ pjmedia_frame_type frm_type;
pj_status_t status;
if (!conf_port)
@@ -1691,7 +1698,8 @@ static pj_status_t get_frame(pjmedia_port *this_port,
/* Var "ci" is to count how many ports have been visited. */
++ci;
- status = write_port( conf, conf_port, frame->timestamp.u32.lo);
+ status = write_port( conf, conf_port, frame->timestamp.u32.lo,
+ &frm_type);
if (status != PJ_SUCCESS) {
/* bennylp: why do we need this????
One thing for sure, put_frame()/write_port() may return
@@ -1708,6 +1716,12 @@ static pj_status_t get_frame(pjmedia_port *this_port,
*/
continue;
}
+
+ /* Set the type of frame to be returned to sound playback
+ * device.
+ */
+ if (i == 0)
+ speaker_frame_type = frm_type;
}
/* Return sound playback frame. */
@@ -1722,7 +1736,7 @@ static pj_status_t get_frame(pjmedia_port *this_port,
}
/* MUST set frame type */
- frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
+ frame->type = speaker_frame_type;
pj_mutex_unlock(conf->mutex);
@@ -1744,6 +1758,8 @@ static pj_status_t get_frame_pasv(pjmedia_port *this_port,
pjmedia_frame *frame)
{
pj_assert(0);
+ PJ_UNUSED_ARG(this_port);
+ PJ_UNUSED_ARG(frame);
return -1;
}
diff --git a/pjmedia/src/pjmedia/port.c b/pjmedia/src/pjmedia/port.c
index f1baa98a..2c511a0c 100644
--- a/pjmedia/src/pjmedia/port.c
+++ b/pjmedia/src/pjmedia/port.c
@@ -62,9 +62,13 @@ PJ_DEF(pj_status_t) pjmedia_port_get_frame( pjmedia_port *port,
pjmedia_frame *frame )
{
PJ_ASSERT_RETURN(port && frame, PJ_EINVAL);
- PJ_ASSERT_RETURN(port->get_frame, PJ_EINVALIDOP);
- return port->get_frame(port, frame);
+ if (port->get_frame)
+ return port->get_frame(port, frame);
+ else {
+ frame->type = PJMEDIA_FRAME_TYPE_NONE;
+ return PJ_EINVALIDOP;
+ }
}
@@ -75,10 +79,11 @@ PJ_DEF(pj_status_t) pjmedia_port_put_frame( pjmedia_port *port,
const pjmedia_frame *frame )
{
PJ_ASSERT_RETURN(port && frame, PJ_EINVAL);
- PJ_ASSERT_RETURN(port->put_frame, PJ_EINVALIDOP);
-
- return port->put_frame(port, frame);
+ if (port->put_frame)
+ return port->put_frame(port, frame);
+ else
+ return PJ_EINVALIDOP;
}
diff --git a/pjmedia/src/pjmedia/sound_port.c b/pjmedia/src/pjmedia/sound_port.c
index dc8dd3a9..9bc48117 100644
--- a/pjmedia/src/pjmedia/sound_port.c
+++ b/pjmedia/src/pjmedia/sound_port.c
@@ -34,7 +34,8 @@
#endif
//#define SIMULATE_LOST_PCT 20
-#define AEC_TAIL 128 /* default AEC length in ms */
+#define AEC_TAIL 128 /* default AEC length in ms */
+#define AEC_SUSPEND_LIMIT 5 /* seconds of no activity */
#define THIS_FILE "sound_port.c"
@@ -58,6 +59,11 @@ struct pjmedia_snd_port
pjmedia_echo_state *ec_state;
unsigned aec_tail_len;
+
+ pj_bool_t ec_suspended;
+ unsigned ec_suspend_count;
+ unsigned ec_suspend_limit;
+
pjmedia_plc *plc;
unsigned clock_rate;
@@ -116,6 +122,11 @@ static pj_status_t play_cb(/* in */ void *user_data,
pjmedia_plc_save(snd_port->plc, output);
if (snd_port->ec_state) {
+ if (snd_port->ec_suspended) {
+ snd_port->ec_suspended = PJ_FALSE;
+ PJ_LOG(4,(THIS_FILE, "EC activated"));
+ }
+ snd_port->ec_suspend_count = 0;
pjmedia_echo_playback(snd_port->ec_state, output);
}
@@ -124,6 +135,14 @@ static pj_status_t play_cb(/* in */ void *user_data,
no_frame:
+ if (!snd_port->ec_suspended) {
+ ++snd_port->ec_suspend_count;
+ if (snd_port->ec_suspend_count > snd_port->ec_suspend_limit) {
+ snd_port->ec_suspended = PJ_TRUE;
+ PJ_LOG(4,(THIS_FILE, "EC suspended because of inactivity"));
+ }
+ }
+
/* Apply PLC */
if (snd_port->plc) {
@@ -164,7 +183,7 @@ static pj_status_t rec_cb(/* in */ void *user_data,
return PJ_SUCCESS;
/* Cancel echo */
- if (snd_port->ec_state) {
+ if (snd_port->ec_state && !snd_port->ec_suspended) {
pjmedia_echo_capture(snd_port->ec_state, input, 0);
}
@@ -253,6 +272,10 @@ static pj_status_t start_sound_device( pj_pool_t *pool,
}
}
+ /* Inactivity limit before EC is suspended. */
+ snd_port->ec_suspend_limit = AEC_SUSPEND_LIMIT *
+ (snd_port->clock_rate /
+ snd_port->samples_per_frame);
/* Start sound stream. */
status = pjmedia_snd_stream_start(snd_port->snd_stream);
@@ -454,6 +477,8 @@ PJ_DEF(pj_status_t) pjmedia_snd_port_set_ec( pjmedia_snd_port *snd_port,
tail_ms, options, &snd_port->ec_state);
if (status != PJ_SUCCESS)
snd_port->ec_state = NULL;
+ else
+ snd_port->ec_suspended = PJ_FALSE;
} else {
PJ_LOG(4,(THIS_FILE, "Echo canceller is now disabled in the "
"sound port"));
diff --git a/pjmedia/src/pjmedia/wav_player.c b/pjmedia/src/pjmedia/wav_player.c
index 79d1209d..02333c4b 100644
--- a/pjmedia/src/pjmedia/wav_player.c
+++ b/pjmedia/src/pjmedia/wav_player.c
@@ -70,8 +70,6 @@ struct file_port
};
-static pj_status_t file_put_frame(pjmedia_port *this_port,
- const pjmedia_frame *frame);
static pj_status_t file_get_frame(pjmedia_port *this_port,
pjmedia_frame *frame);
static pj_status_t file_on_destroy(pjmedia_port *this_port);
@@ -91,7 +89,6 @@ static struct file_port *create_file_port(pj_pool_t *pool)
pjmedia_port_info_init(&port->base.info, &name, SIGNATURE,
8000, 1, 16, 80);
- port->base.put_frame = &file_put_frame;
port->base.get_frame = &file_get_frame;
port->base.on_destroy = &file_on_destroy;
@@ -469,17 +466,6 @@ pjmedia_wav_player_set_eof_cb( pjmedia_port *port,
/*
- * Put frame to file.
- */
-static pj_status_t file_put_frame(pjmedia_port *this_port,
- const pjmedia_frame *frame)
-{
- PJ_UNUSED_ARG(this_port);
- PJ_UNUSED_ARG(frame);
- return PJ_EINVALIDOP;
-}
-
-/*
* Get frame from file.
*/
static pj_status_t file_get_frame(pjmedia_port *this_port,
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index 1af7e98b..0a106f47 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -2187,7 +2187,7 @@ struct pjsua_media_config
/**
* Echo canceller tail length, in miliseconds.
*
- * Default: 128 (PJSUA_DEFAULT_EC_TAIL_LEN)
+ * Default: PJSUA_DEFAULT_EC_TAIL_LEN
*/
unsigned ec_tail_len;
};