Define prload of mISDN buffer by chan_lcr (required for fax)
Use q<ms> option to peload.
This commit is contained in:
parent
8b9bdad861
commit
3f7ef909c9
44
apppbx.cpp
44
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);
|
||||
}
|
||||
|
|
2
apppbx.h
2
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);
|
||||
|
|
53
chan_lcr.c
53
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"
|
||||
|
|
|
@ -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 */
|
||||
|
|
53
mISDN.cpp
53
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 */
|
||||
|
|
2
mISDN.h
2
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 */
|
||||
|
|
3
main.h
3
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")
|
||||
*/
|
||||
|
|
|
@ -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", \
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue