From b09d58c3233240172a9d89f7b18850cca1769428 Mon Sep 17 00:00:00 2001 From: MelwareDE Date: Fri, 8 May 2009 13:03:31 +0000 Subject: [PATCH] Use direct access to vocoder without RTP framing. Preserve implementation using RTP framing --- chan_capi.c | 125 +++++++++++++++++++++++++++++++++------------- chan_capi.h | 1 + chan_capi_rtp.c | 4 ++ chan_capi_utils.c | 21 ++++++++ 4 files changed, 117 insertions(+), 34 deletions(-) diff --git a/chan_capi.c b/chan_capi.c index 157e472..e57c344 100644 --- a/chan_capi.c +++ b/chan_capi.c @@ -203,6 +203,7 @@ static int pbx_capi_indicate(struct ast_channel *c, int condition, const void *d static int pbx_capi_indicate(struct ast_channel *c, int condition); #endif static struct capi_pvt* get_active_plci (struct ast_channel *c); +static _cstruct diva_get_b1_conf (struct capi_pvt *i); static void clear_channel_fax_loop (struct ast_channel *c, struct capi_pvt *i); /* @@ -232,6 +233,11 @@ static struct { /* (_cstruct) "\x04\x01\x00\x00\x02", */ (_cstruct) "\x06\x01\x00\x58\x02\x32\x00", (_cstruct) "\x00" + }, + { 0x1f, 1, 0, /* 3 */ + NULL, + NULL, + NULL } }; @@ -1512,7 +1518,7 @@ static int pbx_capi_call(struct ast_channel *c, char *idest, int timeout) b_protocol_table[i->bproto].b1protocol, b_protocol_table[i->bproto].b2protocol, b_protocol_table[i->bproto].b3protocol, - b_protocol_table[i->bproto].b1configuration, + diva_get_b1_conf (i), b_protocol_table[i->bproto].b2configuration, b_protocol_table[i->bproto].b3configuration, /* BC */ @@ -1536,6 +1542,42 @@ static int pbx_capi_call(struct ast_channel *c, char *idest, int timeout) return 0; } +static _cstruct diva_get_b1_conf (struct capi_pvt *i) { + _cstruct b1conf = b_protocol_table[i->bproto].b1configuration; + + if (i->bproto == CC_BPROTO_VOCODER) { + switch(i->codec) { + case AST_FORMAT_ALAW: + b1conf = (_cstruct)"\x06\x08\x04\x03\x00\xa0\x00"; + break; + case AST_FORMAT_ULAW: + b1conf = (_cstruct)"\x06\x00\x04\x03\x00\xa0\x00"; + break; + case AST_FORMAT_GSM: + b1conf = (_cstruct)"\x06\x03\x04\x0f\x00\xa0\x00"; + break; + case AST_FORMAT_G723_1: + b1conf = (_cstruct)"\x06\x04\x04\x01\x00\xa0\x00"; + break; + case AST_FORMAT_G726: + b1conf = (_cstruct)"\x06\x02\x04\x0f\x00\xa0\x00"; + break; + case AST_FORMAT_ILBC: /* 30 mSec 240 samples */ + b1conf = (_cstruct)"\x06\x1b\x04\x03\x00\xf0\x00"; + break; + case AST_FORMAT_G729A: + b1conf = (_cstruct)"\x06\x12\x04\x0f\x00\xa0\x00"; + break; + default: + cc_log(LOG_ERROR, "%s: format %s(%d) invalid.\n", + i->vname, ast_getformatname(i->codec), i->codec); + break; + } + } + + return (b1conf); +} + /* * answer a capi call */ @@ -1546,6 +1588,7 @@ static int capi_send_answer(struct ast_channel *c, _cstruct b3conf) const char *dnid; const char *connectednumber; unsigned char *facilityarray = NULL; + _cstruct b1conf; if (i->state == CAPI_STATE_DISCONNECTED) { cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: Not answering disconnected call.\n", @@ -1576,6 +1619,8 @@ static int capi_send_answer(struct ast_channel *c, _cstruct b3conf) b3conf = b_protocol_table[i->bproto].b3configuration; } + b1conf = diva_get_b1_conf (i); + cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: Answering for %s\n", i->vname, dnid); @@ -1594,7 +1639,7 @@ static int capi_send_answer(struct ast_channel *c, _cstruct b3conf) b_protocol_table[i->bproto].b1protocol, b_protocol_table[i->bproto].b2protocol, b_protocol_table[i->bproto].b3protocol, - b_protocol_table[i->bproto].b1configuration, + b1conf, b_protocol_table[i->bproto].b2configuration, b3conf, capi_set_global_configuration(i), @@ -1622,7 +1667,7 @@ static int pbx_capi_answer(struct ast_channel *c) struct capi_pvt *i = CC_CHANNEL_PVT(c); int ret; - i->bproto = CC_BPROTO_TRANSPARENT; + i->bproto = ((i->bproto == CC_BPROTO_VOCODER) && (i->codec != 0)) ? i->bproto : CC_BPROTO_TRANSPARENT; if (i->rtp) { if (!capi_tcap_is_digital(i->transfercapability)) @@ -2146,7 +2191,9 @@ static struct ast_channel *capi_new(struct capi_pvt *i, int state) tmp->pickupgroup = i->pickupgroup; tmp->nativeformats = capi_capability; i->bproto = CC_BPROTO_TRANSPARENT; + if ((i->rtpcodec = (capi_controllers[i->controller]->rtpcodec & i->capability))) { +#if 0 /* VOCODER */ if (capi_alloc_rtp(i)) { /* error on rtp alloc */ i->rtpcodec = 0; @@ -2155,6 +2202,10 @@ static struct ast_channel *capi_new(struct capi_pvt *i, int state) tmp->nativeformats = i->rtpcodec; i->bproto = CC_BPROTO_RTP; } +#else + tmp->nativeformats = i->rtpcodec; + i->bproto = CC_BPROTO_VOCODER; +#endif } fmt = ast_best_codec(tmp->nativeformats); i->codec = fmt; @@ -2169,7 +2220,7 @@ static struct ast_channel *capi_new(struct capi_pvt *i, int state) i->vname, ast_getformatname(fmt), ast_getformatname_multiple(alloca(80), 80, tmp->nativeformats), - (i->rtp) ? " (RTP)" : ""); + (i->bproto == CC_BPROTO_VOCODER) ? "VOCODER" : ((i->rtp) ? " (RTP)" : "")); if (!ast_strlen_zero(i->cid)) { if (tmp->cid.cid_num) { @@ -3802,44 +3853,48 @@ static void capidev_handle_data_b3_indication(_cmsg *CMSG, unsigned int PLCI, un i->B3q += b3len; } - if ((i->doES == 1) && (!capi_tcap_is_digital(i->transfercapability))) { - for (j = 0; j < b3len; j++) { - *(b3buf + j) = capi_reversebits[*(b3buf + j)]; - if (capi_capability == AST_FORMAT_ULAW) { - rxavg += abs(capiULAW2INT[ capi_reversebits[*(b3buf + j)]]); - } else { - rxavg += abs(capiALAW2INT[ capi_reversebits[*(b3buf + j)]]); - } - } - rxavg = rxavg / j; - for (j = 0; j < ECHO_EFFECTIVE_TX_COUNT; j++) { - txavg += i->txavg[j]; - } - txavg = txavg / j; - - if ( (txavg / ECHO_TXRX_RATIO) > rxavg) { - if (capi_capability == AST_FORMAT_ULAW) { - memset(b3buf, 255, b3len); - } else { - memset(b3buf, 85, b3len); - } - cc_verbose(6, 1, VERBOSE_PREFIX_3 "%s: SUPPRESSING ECHO rx=%d, tx=%d\n", - i->vname, rxavg, txavg); - } - } else { - if ((i->rxgain == 1.0) || (capi_tcap_is_digital(i->transfercapability))) { + if (i->bproto != CC_BPROTO_VOCODER) { + if ((i->doES == 1) && (!capi_tcap_is_digital(i->transfercapability))) { for (j = 0; j < b3len; j++) { - *(b3buf + j) = capi_reversebits[*(b3buf + j)]; + *(b3buf + j) = capi_reversebits[*(b3buf + j)]; + if (capi_capability == AST_FORMAT_ULAW) { + rxavg += abs(capiULAW2INT[ capi_reversebits[*(b3buf + j)]]); + } else { + rxavg += abs(capiALAW2INT[ capi_reversebits[*(b3buf + j)]]); + } + } + rxavg = rxavg / j; + for (j = 0; j < ECHO_EFFECTIVE_TX_COUNT; j++) { + txavg += i->txavg[j]; + } + txavg = txavg / j; + + if ( (txavg / ECHO_TXRX_RATIO) > rxavg) { + if (capi_capability == AST_FORMAT_ULAW) { + memset(b3buf, 255, b3len); + } else { + memset(b3buf, 85, b3len); + } + cc_verbose(6, 1, VERBOSE_PREFIX_3 "%s: SUPPRESSING ECHO rx=%d, tx=%d\n", + i->vname, rxavg, txavg); } } else { - for (j = 0; j < b3len; j++) { - *(b3buf + j) = capi_reversebits[i->g.rxgains[*(b3buf + j)]]; + if ((i->rxgain == 1.0) || (capi_tcap_is_digital(i->transfercapability))) { + for (j = 0; j < b3len; j++) { + *(b3buf + j) = capi_reversebits[*(b3buf + j)]; + } + } else { + for (j = 0; j < b3len; j++) { + *(b3buf + j) = capi_reversebits[i->g.rxgains[*(b3buf + j)]]; + } } } + fr.subclass = capi_capability; + } else { + fr.subclass = i->codec; } fr.frametype = AST_FRAME_VOICE; - fr.subclass = capi_capability; fr.FRAME_DATA_PTR = b3buf; fr.datalen = b3len; fr.samples = b3len; @@ -6747,6 +6802,8 @@ static char *show_bproto(int bproto) return " fax "; case CC_BPROTO_RTP: return " rtp "; + case CC_BPROTO_VOCODER: + return " vocoder "; } return " ??? "; } diff --git a/chan_capi.h b/chan_capi.h index 4548694..ec348f8 100644 --- a/chan_capi.h +++ b/chan_capi.h @@ -139,6 +139,7 @@ static inline unsigned int read_capi_dword(void *m) #define CC_BPROTO_TRANSPARENT 0 #define CC_BPROTO_FAXG3 1 #define CC_BPROTO_RTP 2 +#define CC_BPROTO_VOCODER 3 /* FAX Resolutions */ #define FAX_STANDARD_RESOLUTION 0 diff --git a/chan_capi_rtp.c b/chan_capi_rtp.c index 2d6805b..e76d1c4 100644 --- a/chan_capi_rtp.c +++ b/chan_capi_rtp.c @@ -391,6 +391,10 @@ void voice_over_ip_profile(struct cc_capi_controller *cp) cp->rtpcodec |= AST_FORMAT_G729A; cc_verbose(3, 0, "G.729"); } + if (payload1 & (1U << 27)) { + cp->rtpcodec |= AST_FORMAT_ILBC; + cc_verbose(3, 0, "iLBC"); + } cc_verbose(3, 0, "\n"); } diff --git a/chan_capi_utils.c b/chan_capi_utils.c index a7cecf7..47e56c8 100644 --- a/chan_capi_utils.c +++ b/chan_capi_utils.c @@ -1387,6 +1387,27 @@ int capi_write_frame(struct capi_pvt *i, struct ast_frame *f) return 0; } + if (i->bproto == CC_BPROTO_VOCODER) { + buf = &(i->send_buffer[(i->send_buffer_handle % CAPI_MAX_B3_BLOCKS) * + (CAPI_MAX_B3_BLOCK_SIZE + AST_FRIENDLY_OFFSET)]); + i->send_buffer_handle++; + + memcpy (buf, f->FRAME_DATA_PTR, f->datalen); + + error = capi_sendf(NULL, 0, CAPI_DATA_B3_REQ, i->NCCI, get_capi_MessageNumber(), + "dwww", buf, f->datalen, i->send_buffer_handle, 0); + if (likely(error == 0)) { + cc_mutex_lock(&i->lock); + i->B3count++; + i->B3q -= f->datalen; + if (i->B3q < 0) + i->B3q = 0; + cc_mutex_unlock(&i->lock); + } + + return 0; + } + if ((!i->smoother) || (ast_smoother_feed(i->smoother, f) != 0)) { cc_log(LOG_ERROR, "%s: failed to fill smoother\n", i->vname); return 0;