[pjsip] Accoustic echo cancelation

Alexandre Gonçalves alexandre at silvagoncalves.com
Mon Apr 11 11:16:08 EDT 2016


Yes it does. The device is handsfree.

Thanks.

*Alexandre Gonçalves*

............................................................................................................................
Email: alexandre at silvagoncalves.com

2016-04-11 16:09 GMT+01:00 Bill Gardner <billg at wavearts.com>:

> Hi Alexandre,
>
> I don't know what the problem is, but you shouldn't need to create a
> separate EC object. pjsua_init will create an echo canceller and connect it
> to the sound port.
>
> Does the call work without EC?
>
> Regards,
>
> Bill
>
> On 4/11/2016 10:33 AM, Alexandre Gonçalves wrote:
>
> Hello,
>
> I've made a small C application to run on a linux machine, based on
> "Simple PJSUA" example.
>
> What I need to add is echo cancellation, and I tryed to do it like the
> code attached:
>
> But according to the logs I get it seems that something is missing. I
> suspect it's the manipulation of the capture and playback frames, but I
> have no idea how to do it!
>
>
> #include <pjsua-lib/pjsua.h>
> #define THIS_FILE "APP"
>
> #define SIP_DOMAIN "raspbx"
> #define SIP_USER "511"
> #define SIP_PASSWD "aaa511"
> #define SIP_REALM "asterisk"
> #define SIP_SCHEME "digest"
>
>
>
> pjmedia_echo_state *ec;
> pjmedia_frame play_frame, rec_frame;
>
> /* Callback called by the library upon receiving incoming call */
> static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
>         pjsip_rx_data *rdata) {
>     pjsua_call_info ci;
>
>     PJ_UNUSED_ARG(acc_id);
>     PJ_UNUSED_ARG(rdata);
>
>     pjsua_call_get_info(call_id, &ci);
>
>     PJ_LOG(2, (THIS_FILE, "Incoming call from %.*s!!",
>             (int) ci.remote_info.slen,
>             ci.remote_info.ptr));
>
>     /* Automatically answer incoming calls with 200/OK */
>     pjsua_call_answer(call_id, 200, NULL, NULL);
> }
>
> /* Callback called by the library when call's state has changed */
> static void on_call_state(pjsua_call_id call_id, pjsip_event *e) {
>     pjsua_call_info ci;
>
>     PJ_UNUSED_ARG(e);
>
>     pjsua_call_get_info(call_id, &ci);
>     PJ_LOG(2, (THIS_FILE, "Call %d state=%.*s", call_id,
>             (int) ci.state_text.slen,
>             ci.state_text.ptr));
>
> }
>
> /* Callback called by the library when call's media state has changed */
> static void on_call_media_state(pjsua_call_id call_id) {
>     pjsua_call_info ci;
>
>     pjsua_call_get_info(call_id, &ci);
>
>     if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
>         // When media is active, connect call to sound device.
>         pjsua_conf_connect(ci.conf_slot, 0);
>         pjsua_conf_connect(0, ci.conf_slot);
>     }
> }
>
> /* Display error and exit application */
> static void error_exit(const char *title, pj_status_t status) {
>     pjsua_perror(THIS_FILE, title, status);
>     pjsua_destroy();
>     exit(1);
> }
>
> /*
>  * main()
>  *
>  * argv[1] may contain URL to call.
>  */
> int main(int argc, char *argv[]) {
>     pjsua_acc_id acc_id;
>     pj_status_t status;
>
>
>
>     /* Create pjsua first! */
>     status = pjsua_create();
>     if (status != PJ_SUCCESS) error_exit("Error in pjsua_create()",
> status);
>
>
>     /* Init pjsua */
>     {
>         pjsua_config cfg;
>         pjsua_logging_config log_cfg;
>         pjsua_media_config media_cfg;
>
>         pjsua_config_default(&cfg);
>         cfg.cb.on_incoming_call = &on_incoming_call;
>         cfg.cb.on_call_media_state = &on_call_media_state;
>         cfg.cb.on_call_state = &on_call_state;
>         cfg.max_calls = 1;
>
>         pjsua_logging_config_default(&log_cfg);
>         log_cfg.console_level = 6;
>
>         pjsua_media_config_default(&media_cfg);
>         media_cfg.ec_options = PJMEDIA_ECHO_DEFAULT;
>         media_cfg.ec_tail_len = 250;
>
>
>         status = pjsua_init(&cfg, &log_cfg, &media_cfg);
>         // status = pjsua_init(&cfg, &log_cfg, NULL);
>
>         if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()",
> status);
>
>         pj_pool_t *pool = pjsua_pool_create("my_echo", 1000, 1000);
>         status = pjmedia_echo_create(pool, 16000, 320, 500, 500,
> PJMEDIA_ECHO_DEFAULT, &ec);
>         play_frame.buf = pj_pool_alloc(pool, 320);
>         rec_frame.buf = pj_pool_alloc(pool, 320);
>
>     }
>
>     /* Add UDP transport. */
>     {
>         pjsua_transport_config cfg;
>
>         pjsua_transport_config_default(&cfg);
>         cfg.port = 5060;
>         status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
>         if (status != PJ_SUCCESS) error_exit("Error creating transport",
> status);
>     }
>
>     /* Initialization is done, now start pjsua */
>     status = pjsua_start();
>     if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status);
>
>     /* Register to SIP server by creating SIP account. */
>     {
>         pjsua_acc_config cfg;
>
>         pjsua_acc_config_default(&cfg);
>         cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
>         cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
>         cfg.cred_count = 1;
>         cfg.cred_info[0].realm = pj_str(SIP_REALM);
>         cfg.cred_info[0].scheme = pj_str(SIP_SCHEME);
>         cfg.cred_info[0].username = pj_str(SIP_USER);
>         cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
>         cfg.cred_info[0].data = pj_str(SIP_PASSWD);
>
>         status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
>         if (status != PJ_SUCCESS) error_exit("Error adding account",
> status);
>     }
>
>     if (argc > 1) {
>         pj_str_t uri = pj_str(argv[1]);
>         status = pjsua_call_make_call(acc_id, &uri, 0, NULL, NULL, NULL);
>         if (status != PJ_SUCCESS) error_exit("Error making call", status);
>     }
>
>
>     char option[10];
>     while (1) {
>
>         if (fgets(option, sizeof (option), stdin) == NULL) {
>             puts("EOF while reading stdin, will quit now..");
>             break;
>         }
>
>         if (option[0] == 'q')
>             break;
>
>     }
>
>     /* Destroy pjsua */
>     pjsua_destroy();
>
>     return 0;
> }
>
>
> The logs:
>
> 16:10:45.203          speex !warning: No playback frame available (your
> application is buggy and/or got xruns)
> 16:10:45.207          speex !warning: Auto-filling the buffer (your
> application is buggy and/or got xruns)
> 16:10:45.216          speex !warning: internal playback buffer corruption?
> 16:10:45.221          speex !warning: Auto-filling the buffer (your
> application is buggy and/or got xruns)
> 16:10:45.279          speex  warning: Had to discard a playback frame
> (your application is buggy and/or got xruns)
> 16:10:45.393          speex  warning: Auto-filling the buffer (your
> application is buggy and/or got xruns)
> 16:10:45.462          speex  warning: Had to discard a playback frame
> (your application is buggy and/or got xruns)
> 16:10:45.522          speex  warning: Auto-filling the buffer (your
> application is buggy and/or got xruns)
> 16:10:45.562          speex  warning: Had to discard a playback frame
> (your application is buggy and/or got xruns)
>
>
> Pjsip version: 2.4
>
>
> Can anyone help out?
>
>
> Thanks.
>
>
>
>
> *Alexandre Gonçalves*
>
>
> ............................................................................................................................
> Email:  <alexandre at silvagoncalves.com>alexandre at silvagoncalves.com
>
>
> _______________________________________________
> Visit our blog: http://blog.pjsip.org
>
> pjsip mailing listpjsip at lists.pjsip.orghttp://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
>
>
>
> _______________________________________________
> Visit our blog: http://blog.pjsip.org
>
> pjsip mailing list
> pjsip at lists.pjsip.org
> http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/attachments/20160411/64142949/attachment-0002.html>


More information about the pjsip mailing list