Define prload of mISDN buffer by chan_lcr (required for fax)

Use q<ms> option to peload.
This commit is contained in:
Andreas Eversberg 2012-07-29 14:33:15 +02:00
parent 8b9bdad861
commit 3f7ef909c9
8 changed files with 108 additions and 54 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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"

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

3
main.h
View File

@ -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")
*/

View File

@ -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", \
};