From 3f7ef909c907a374a1760ffae0c01b49487f18d7 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 29 Jul 2012 14:33:15 +0200 Subject: [PATCH] Define prload of mISDN buffer by chan_lcr (required for fax) Use q option to peload. --- apppbx.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ apppbx.h | 2 ++ chan_lcr.c | 53 +++++++++++++++++++++++++---------------------------- chan_lcr.h | 2 +- mISDN.cpp | 53 +++++++++++++++++++++++++++++++---------------------- mISDN.h | 2 ++ main.h | 3 --- message.h | 3 +++ 8 files changed, 108 insertions(+), 54 deletions(-) diff --git a/apppbx.cpp b/apppbx.cpp index 0369bb9..d55424b 100644 --- a/apppbx.cpp +++ b/apppbx.cpp @@ -2471,6 +2471,19 @@ void EndpointAppPBX::port_enablekeypad(struct port_list *portlist, int message_t } +/* port MESSAGE_DISABLE_DEJITTER */ +void EndpointAppPBX::port_disable_dejitter(struct port_list *portlist, int message_type, union parameter *param) +{ + struct lcr_msg *message; + + logmessage(message_type, param, portlist->port_id, DIRECTION_IN); + + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_DISABLE_DEJITTER); + memcpy(&message->param, param, sizeof(union parameter)); + message_put(message); +} + + /* port sends message to the endpoint */ void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param) @@ -2657,6 +2670,11 @@ void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, uni port_enablekeypad(portlist, message_type, param); break; + case MESSAGE_DISABLE_DEJITTER: + PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming disable dejitter message (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id); + port_disable_dejitter(portlist, message_type, param); + break; + default: PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message_type); @@ -3181,6 +3199,19 @@ void EndpointAppPBX::join_dtmf(struct port_list *portlist, int message_type, uni } } +/* join MESSAGE_DISABLE_DEJITTER */ +void EndpointAppPBX::join_disable_dejitter(struct port_list *portlist, int message_type, union parameter *param) +{ + struct lcr_msg *message; + + while(portlist) { + message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISABLE_DEJITTER); + memcpy(&message->param, param, sizeof(union parameter)); + message_put(message); + portlist = portlist->next; + } +} + /* JOIN sends messages to the endpoint */ void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param) @@ -3352,6 +3383,12 @@ void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, uni join_dtmf(portlist, message_type, param); break; + /* JOIN sends a DISABLE_DEJITTER message */ + case MESSAGE_DISABLE_DEJITTER: + PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received disable dejitter.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id); + join_disable_dejitter(portlist, message_type, param); + break; + default: PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: #%d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message_type); } @@ -4432,6 +4469,13 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign end_trace(); break; + case MESSAGE_DISABLE_DEJITTER: + trace_header("DISBALE_DEJITTER", dir); + if (param->queue) + add_trace("queue", NULL, "%d", param->queue); + end_trace(); + break; + default: PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type); } diff --git a/apppbx.h b/apppbx.h index 1bbe8ba..e42651f 100644 --- a/apppbx.h +++ b/apppbx.h @@ -215,6 +215,7 @@ class EndpointAppPBX : public EndpointApp void port_suspend(struct port_list *portlist, int message_type, union parameter *param); void port_resume(struct port_list *portlist, int message_type, union parameter *param); void port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param); + void port_disable_dejitter(struct port_list *portlist, int message_type, union parameter *param); void ea_message_join(unsigned int join_id, int message, union parameter *param); void join_crypt(struct port_list *portlist, int message_type, union parameter *param); void join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param); @@ -229,6 +230,7 @@ class EndpointAppPBX : public EndpointApp void join_notify(struct port_list *portlist, int message_type, union parameter *param); void join_facility(struct port_list *portlist, int message_type, union parameter *param); void join_dtmf(struct port_list *portlist, int message_type, union parameter *param); + void join_disable_dejitter(struct port_list *portlist, int message_type, union parameter *param); /* epoint */ void new_state(int state); diff --git a/chan_lcr.c b/chan_lcr.c index 1c3500b..ee221b7 100644 --- a/chan_lcr.c +++ b/chan_lcr.c @@ -492,22 +492,13 @@ void apply_opt(struct chan_call *call, char *data) if (!call->hdlc) call->hdlc = 1; break; - case 't': - if (opt[1] != '\0') { - CERROR(call, call->ast, "Option 't' (no_dsp) expects no parameter.\n", opt); - break; - } - CDEBUG(call, call->ast, "Option 't' (no dsp).\n"); - if (!call->nodsp) - call->nodsp = 1; - break; case 'q': if (opt[1] == '\0') { CERROR(call, call->ast, "Option 'q' (queue) expects parameter.\n", opt); break; } CDEBUG(call, call->ast, "Option 'q' (queue).\n"); - call->nodsp_queue = atoi(opt+1); + call->tx_queue = atoi(opt+1); break; #if 0 case 'e': @@ -708,6 +699,11 @@ static void send_setup_to_lcr(struct chan_call *call) newparam.setup.capainfo.hlc = INFO_HLC_NONE; newparam.setup.capainfo.exthlc = INFO_HLC_NONE; send_message(MESSAGE_SETUP, call->ref, &newparam); + if (call->tx_queue) { + memset(&newparam, 0, sizeof(union parameter)); + newparam.queue = call->tx_queue * 8; + send_message(MESSAGE_DISABLE_DEJITTER, call->ref, &newparam); + } /* change to outgoing setup state */ call->state = CHAN_LCR_STATE_OUT_SETUP; @@ -3122,30 +3118,24 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1, /* join, if both call instances uses dsp ignore the case of fax detection here it may be benificial for ISDN fax machines or pass through. */ - if (!call1->nodsp && !call2->nodsp) { - CDEBUG(NULL, NULL, "Both calls use DSP, bridging via DSP.\n"); + CDEBUG(NULL, NULL, "Both calls use DSP, bridging via DSP.\n"); - /* get bridge id and join */ - bridge_id = new_bridge_id(); + /* get bridge id and join */ + bridge_id = new_bridge_id(); #if 0 - call1->bridge_id = bridge_id; - if (call1->bchannel) - bchannel_join(call1->bchannel, bridge_id); + call1->bridge_id = bridge_id; + if (call1->bchannel) + bchannel_join(call1->bchannel, bridge_id); - call2->bridge_id = bridge_id; - if (call2->bchannel) - bchannel_join(call2->bchannel, bridge_id); + call2->bridge_id = bridge_id; + if (call2->bchannel) + bchannel_join(call2->bchannel, bridge_id); #else - printf("FIXME"); - exit(0); + printf("FIXME"); + exit(0); #endif - } else - if (call1->nodsp && call2->nodsp) - CDEBUG(NULL, NULL, "Both calls use no DSP, bridging in channel driver.\n"); - else - CDEBUG(NULL, NULL, "One call uses no DSP, bridging in channel driver.\n"); call1->bridge_call = call2; call2->bridge_call = call1; @@ -3416,6 +3406,14 @@ static int lcr_config_exec(struct ast_channel *ast, void *data, char **argv) apply_opt(call, (char *)argv[0]); #endif + /* send options */ + if (call->tx_queue) { + union parameter newparam; + + memset(&newparam, 0, sizeof(union parameter)); + newparam.queue = call->tx_queue * 8; + send_message(MESSAGE_DISABLE_DEJITTER, call->ref, &newparam); + } else CERROR(NULL, ast, "lcr_config app not called by chan_lcr channel.\n"); @@ -3491,7 +3489,6 @@ int load_module(void) " d - Send display text on called phone, text is the optarg.\n" " n - Don't detect dtmf tones on called channel.\n" " h - Force data call (HDLC).\n" - " t - Disable mISDN_dsp features (required for fax application).\n" " q - Add queue to make fax stream seamless (required for fax app).\n" " Use queue size in miliseconds for optarg. (try 250)\n" " f - Adding fax detection. It it timeouts, mISDN_dsp is used.\n" diff --git a/chan_lcr.h b/chan_lcr.h index 345f769..da0bcbd 100644 --- a/chan_lcr.h +++ b/chan_lcr.h @@ -71,7 +71,7 @@ struct chan_call { int bf_len; /* blowfish crypt key */ struct ast_dsp *dsp; /* ast dsp processor for fax/tone detection */ struct ast_trans_pvt *trans; /* Codec translation path as fax/tone detection requires slin */ - int nodsp, nodsp_queue, hdlc, faxdetect; + int tx_queue, hdlc, faxdetect; /* flags for bchannel mode */ char queue_string[64]; /* queue for asterisk */ diff --git a/mISDN.cpp b/mISDN.cpp index 585ae82..546b39f 100644 --- a/mISDN.cpp +++ b/mISDN.cpp @@ -139,6 +139,8 @@ PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_setti p_m_txdata = 0; p_m_delay = 0; p_m_tx_dejitter = 0; + p_m_preload = ISDN_LOAD; + p_m_disable_dejitter = 0; p_m_echo = 0; p_m_tone = 0; p_m_rxoff = 0; @@ -879,31 +881,31 @@ times have no skew. * levels there are two levels: -ISDN_LOAD will give the load that have to be kept in dsp. -ISDN_MAXLOAD will give the maximum load before dropping. +p_m_preload will give the load that have to be kept in dsp. +ISDN_MAXLOAD (2*p_m_preload) will give the maximum load before dropping. * procedure for low priority data see txfromup() for procedure in short: remote data is ignored during high priority tones * procedure for high priority data -whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD +whenever load is below p_m_preload, load is filled up to p_m_preload if no more data is available, load becomes empty again. 'load' variable: -0 ISDN_LOAD ISDN_MAXLOAD +0 p_m_preload ISDN_MAXLOAD +--------------------+----------------------+ | | | +--------------------+----------------------+ -on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD: -0 ISDN_LOAD ISDN_MAXLOAD +on empty load or on load below p_m_preload, the load is inceased to p_m_preload: +0 p_m_preload ISDN_MAXLOAD +--------------------+----------------------+ |TTTTTTTTTTTTTTTTTTTT| | +--------------------+----------------------+ -on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD. -0 ISDN_LOAD ISDN_MAXLOAD +on empty load, remote-audio causes the load with the remote audio to be increased to p_m_preload. +0 p_m_preload ISDN_MAXLOAD +--------------------+----------------------+ |TTTTTTTTTTTTTTTTTTTTRRRRR | +--------------------+----------------------+ @@ -957,9 +959,9 @@ void PmISDN::load_tx(void) /* to send data, tone must be on */ if ((p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on) /* what tones? */ - && (p_m_load < ISDN_LOAD) /* not too much load? */ + && (p_m_load < p_m_preload) /* not too much load? */ && (p_state==PORT_STATE_CONNECT || p_m_mISDNport->tones || p_m_inband_send_on)) { /* connected or inband-tones? */ - int tosend = ISDN_LOAD - p_m_load, length; + int tosend = p_m_preload - p_m_load, length; unsigned char buf[MISDN_HEADER_LEN+tosend]; struct mISDNhead *frm = (struct mISDNhead *)buf; unsigned char *p = buf+MISDN_HEADER_LEN; @@ -1002,13 +1004,13 @@ void PmISDN::load_tx(void) } /* send data */ - if (ISDN_LOAD - p_m_load - tosend > 0) { + if (p_m_preload - p_m_load - tosend > 0) { frm->prim = PH_DATA_REQ; frm->id = 0; - ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+ISDN_LOAD-p_m_load-tosend, 0, NULL, 0); + ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+p_m_preload-p_m_load-tosend, 0, NULL, 0); if (ret <= 0) - PERROR("Failed to send to socket %d (samples = %d)\n", p_m_mISDNport->b_sock[p_m_b_index].fd, ISDN_LOAD-p_m_load-tosend); - p_m_load += ISDN_LOAD - p_m_load - tosend; + PERROR("Failed to send to socket %d (samples = %d)\n", p_m_mISDNport->b_sock[p_m_b_index].fd, p_m_preload-p_m_load-tosend); + p_m_load += p_m_preload - p_m_load - tosend; } } } @@ -1433,6 +1435,13 @@ int PmISDN::message_epoint(unsigned int epoint_id, int message_id, union paramet PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type); message_crypt(epoint_id, message_id, param); return 1; + + case MESSAGE_DISABLE_DEJITTER: + PDEBUG(DEBUG_ISDN, "PmISDN(%s) received de-jitter disable order.\n", p_name); + p_m_disable_dejitter = 1; + p_m_preload = param->queue; + update_rxoff(); + return 1; } return 0; @@ -1487,7 +1496,7 @@ void PmISDN::update_rxoff(void) } } /* dejitter on bridge */ - if (p_bridge) + if (p_bridge && !p_m_disable_dejitter) tx_dejitter = 1; if (p_m_tx_dejitter != tx_dejitter) { p_m_tx_dejitter = tx_dejitter; @@ -2143,11 +2152,11 @@ void mISDNport_close(struct mISDNport *mISDNport) /* - * enque data from upper buffer + * enque data from remote port */ int PmISDN::bridge_rx(unsigned char *data, int length) { - unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)]; + unsigned char buf[MISDN_HEADER_LEN+((length>p_m_preload)?length:p_m_preload)]; struct mISDNhead *hh = (struct mISDNhead *)buf; int ret; @@ -2166,21 +2175,21 @@ int PmISDN::bridge_rx(unsigned char *data, int length) * if transmit buffer in DSP module is empty, * preload it to DSP_LOAD to prevent jitter gaps. */ - if (p_m_load == 0 && ISDN_LOAD > 0) { + if ((!p_bridge || p_m_disable_dejitter) && p_m_load == 0 && p_m_preload > 0) { hh->prim = PH_DATA_REQ; hh->id = 0; - memset(buf+MISDN_HEADER_LEN, silence, ISDN_LOAD); - ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+ISDN_LOAD, 0, NULL, 0); + memset(buf+MISDN_HEADER_LEN, silence, p_m_preload); + ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+p_m_preload, 0, NULL, 0); if (ret <= 0) PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_sock[p_m_b_index].fd); - p_m_load += ISDN_LOAD; + p_m_load += p_m_preload; schedule_timer(&p_m_loadtimer, 0, PORT_TRANSMIT * 125); } /* drop if load would exceed ISDN_MAXLOAD * this keeps the delay not too high */ - if (p_m_load+length > ISDN_MAXLOAD) + if (p_m_load+length > (p_m_preload << 1)) return -EINVAL; /* make and send frame */ diff --git a/mISDN.h b/mISDN.h index 0803698..aad6f72 100644 --- a/mISDN.h +++ b/mISDN.h @@ -110,6 +110,8 @@ class PmISDN : public Port struct mISDNport *p_m_mISDNport; /* pointer to port */ int p_m_delay; /* use delay instead of dejitter */ int p_m_tx_dejitter; /* use dejitter on transmit data to DSP */ + int p_m_disable_dejitter; /* usefull to send fax via bridge */ + int p_m_preload; /* set to ISDN_LOAD, but may be changed later */ int p_m_tx_gain, p_m_rx_gain; /* volume shift (0 = no change) */ char p_m_pipeline[256]; /* filter pipeline */ int p_m_echo, p_m_conf; /* remote echo, conference number */ diff --git a/main.h b/main.h index 0c117e3..b16012d 100644 --- a/main.h +++ b/main.h @@ -85,11 +85,8 @@ void debug(const char *file, const char *function, int line, const char *prefix, /* * load transmit buffer to avoid gaps at the beginning due to jitter - * also the maximum load that will be kept in tx-buffer - * also the (minimum) number of data to transmit in a frame */ #define ISDN_LOAD 1024 // samples -#define ISDN_MAXLOAD 2048 // samples /* give sendmail program. if not inside $PATH, give absolute path here (e.g. "/usr/sbin/sendmail") */ diff --git a/message.h b/message.h index ab4ca7e..97bfddc 100644 --- a/message.h +++ b/message.h @@ -376,6 +376,7 @@ union parameter { unsigned int bridge_id; /* MESSAGE_BRIDGE */ struct param_traffic traffic; /* MESSAGE_TRAFFIC */ struct param_3pty threepty; /* MESSAGE_TRAFFIC */ + unsigned int queue; /* MESSAGE_DISABLE_DEJITTER */ }; enum { /* message flow */ @@ -431,6 +432,7 @@ enum { /* messages between entities */ MESSAGE_BRIDGE, /* control port bridge */ MESSAGE_TRAFFIC, /* exchange bchannel traffic */ MESSAGE_3PTY, /* 3PTY call invoke */ + MESSAGE_DISABLE_DEJITTER/* tell (mISDN) port not to dejitter */ }; #define MESSAGES static const char *messages_txt[] = { \ @@ -468,6 +470,7 @@ enum { /* messages between entities */ "MESSAGE_BRIDGE", \ "MESSAGE_TRAFFIC", \ "MESSAGE_3PTY", \ + "MESSAGE_DISABLE_DEJITTER", \ }; -- 2.13.6