Use q<ms> option to peload.
+/* 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)
/* port sends message to the endpoint
*/
void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
port_enablekeypad(portlist, message_type, param);
break;
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);
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);
+/* 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)
/* JOIN sends messages to the endpoint
*/
void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
join_dtmf(portlist, message_type, param);
break;
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);
}
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);
}
+ 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);
}
default:
PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
}
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_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);
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);
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_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);
/* epoint */
void new_state(int state);
if (!call->hdlc)
call->hdlc = 1;
break;
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");
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);
newparam.setup.capainfo.hlc = INFO_HLC_NONE;
newparam.setup.capainfo.exthlc = INFO_HLC_NONE;
send_message(MESSAGE_SETUP, call->ref, &newparam);
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;
/* change to outgoing setup state */
call->state = CHAN_LCR_STATE_OUT_SETUP;
/* 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.
*/
/* 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();
- 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);
- printf("FIXME");
- exit(0);
+ printf("FIXME");
+ exit(0);
- } 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;
call1->bridge_call = call2;
call2->bridge_call = call1;
apply_opt(call, (char *)argv[0]);
#endif
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");
else
CERROR(NULL, ast, "lcr_config app not called by chan_lcr channel.\n");
" 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"
" 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"
" 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"
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 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 */
/* flags for bchannel mode */
char queue_string[64];
/* queue for asterisk */
p_m_txdata = 0;
p_m_delay = 0;
p_m_tx_dejitter = 0;
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;
p_m_echo = 0;
p_m_tone = 0;
p_m_rxoff = 0;
* levels
there are two levels:
* 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
* 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:
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| |
+--------------------+----------------------+
+--------------------+----------------------+
|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 |
+--------------------+----------------------+
+--------------------+----------------------+
|TTTTTTTTTTTTTTTTTTTTRRRRR |
+--------------------+----------------------+
/* to send data, tone must be on */
if ((p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on) /* what tones? */
/* 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? */
&& (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;
unsigned char buf[MISDN_HEADER_LEN+tosend];
struct mISDNhead *frm = (struct mISDNhead *)buf;
unsigned char *p = buf+MISDN_HEADER_LEN;
- 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;
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);
- 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;
PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
message_crypt(epoint_id, message_id, param);
return 1;
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;
}
}
/* dejitter on bridge */
}
}
/* dejitter on bridge */
+ if (p_bridge && !p_m_disable_dejitter)
tx_dejitter = 1;
if (p_m_tx_dejitter != tx_dejitter) {
p_m_tx_dejitter = tx_dejitter;
tx_dejitter = 1;
if (p_m_tx_dejitter != tx_dejitter) {
p_m_tx_dejitter = tx_dejitter;
- * enque data from upper buffer
+ * enque data from remote port
*/
int PmISDN::bridge_rx(unsigned char *data, int length)
{
*/
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;
struct mISDNhead *hh = (struct mISDNhead *)buf;
int ret;
* if transmit buffer in DSP module is empty,
* preload it to DSP_LOAD to prevent jitter gaps.
*/
* 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;
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);
if (ret <= 0)
PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_sock[p_m_b_index].fd);
+ 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
*/
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 */
return -EINVAL;
/* make and send frame */
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 */
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 */
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 */
/*
* load transmit buffer to avoid gaps at the beginning due to jitter
/*
* 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_LOAD 1024 // samples
-#define ISDN_MAXLOAD 2048 // samples
/* give sendmail program. if not inside $PATH, give absolute path here (e.g. "/usr/sbin/sendmail")
*/
/* give sendmail program. if not inside $PATH, give absolute path here (e.g. "/usr/sbin/sendmail")
*/
unsigned int bridge_id; /* MESSAGE_BRIDGE */
struct param_traffic traffic; /* MESSAGE_TRAFFIC */
struct param_3pty threepty; /* MESSAGE_TRAFFIC */
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 */
};
enum { /* message flow */
MESSAGE_BRIDGE, /* control port bridge */
MESSAGE_TRAFFIC, /* exchange bchannel traffic */
MESSAGE_3PTY, /* 3PTY call invoke */
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[] = { \
};
#define MESSAGES static const char *messages_txt[] = { \
"MESSAGE_BRIDGE", \
"MESSAGE_TRAFFIC", \
"MESSAGE_3PTY", \
"MESSAGE_BRIDGE", \
"MESSAGE_TRAFFIC", \
"MESSAGE_3PTY", \
+ "MESSAGE_DISABLE_DEJITTER", \