diff options
author | Benny Prijono <bennylp@teluu.com> | 2006-09-20 20:02:18 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2006-09-20 20:02:18 +0000 |
commit | fea1c2e2fd2629ec721f82a45046d19eddbda820 (patch) | |
tree | 48689e085b45d935fce06ba043b4f59d1157bac4 | |
parent | eba3cc35db92c66e1d99180060a02d008c68f7ca (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.h | 6 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/conference.c | 22 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/port.c | 15 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/sound_port.c | 29 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/wav_player.c | 14 | ||||
-rw-r--r-- | pjsip/include/pjsua-lib/pjsua.h | 2 |
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; }; |