mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 20:20:07 +00:00
Fixes reliability issues with func_jitterbuffer's usage in the new ConfBridge application.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@317197 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -429,15 +429,20 @@ static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *brid
|
|||||||
bridge_channel->tech_args.silence_threshold :
|
bridge_channel->tech_args.silence_threshold :
|
||||||
DEFAULT_SOFTMIX_SILENCE_THRESHOLD;
|
DEFAULT_SOFTMIX_SILENCE_THRESHOLD;
|
||||||
char update_talking = -1; /* if this is set to 0 or 1, tell the bridge that the channel has started or stopped talking. */
|
char update_talking = -1; /* if this is set to 0 or 1, tell the bridge that the channel has started or stopped talking. */
|
||||||
|
int res = AST_BRIDGE_WRITE_SUCCESS;
|
||||||
|
|
||||||
/* Only accept audio frames, all others are unsupported */
|
/* Only accept audio frames, all others are unsupported */
|
||||||
if (frame->frametype == AST_FRAME_DTMF_END || frame->frametype == AST_FRAME_DTMF_BEGIN) {
|
if (frame->frametype == AST_FRAME_DTMF_END || frame->frametype == AST_FRAME_DTMF_BEGIN) {
|
||||||
softmix_pass_dtmf(bridge, bridge_channel, frame);
|
softmix_pass_dtmf(bridge, bridge_channel, frame);
|
||||||
return AST_BRIDGE_WRITE_SUCCESS;
|
goto no_audio;
|
||||||
} else if (frame->frametype != AST_FRAME_VOICE) {
|
} else if (frame->frametype != AST_FRAME_VOICE) {
|
||||||
return AST_BRIDGE_WRITE_UNSUPPORTED;
|
res = AST_BRIDGE_WRITE_UNSUPPORTED;
|
||||||
|
goto no_audio;
|
||||||
|
} else if (frame->datalen == 0) {
|
||||||
|
goto no_audio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we made it here, we are going to write the frame into the conference */
|
||||||
ast_mutex_lock(&sc->lock);
|
ast_mutex_lock(&sc->lock);
|
||||||
|
|
||||||
ast_dsp_silence(sc->dsp, frame, &totalsilence);
|
ast_dsp_silence(sc->dsp, frame, &totalsilence);
|
||||||
@@ -480,7 +485,20 @@ static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *brid
|
|||||||
ast_bridge_notify_talking(bridge, bridge_channel, update_talking);
|
ast_bridge_notify_talking(bridge, bridge_channel, update_talking);
|
||||||
}
|
}
|
||||||
|
|
||||||
return AST_BRIDGE_WRITE_SUCCESS;
|
return res;
|
||||||
|
|
||||||
|
no_audio:
|
||||||
|
/* Even though the frame is not being written into the conference because it is not audio,
|
||||||
|
* we should use this opportunity to check to see if a frame is ready to be written out from
|
||||||
|
* the conference to the channel. */
|
||||||
|
ast_mutex_lock(&sc->lock);
|
||||||
|
if (sc->have_frame) {
|
||||||
|
ast_write(bridge_channel->chan, &sc->write_frame);
|
||||||
|
sc->have_frame = 0;
|
||||||
|
}
|
||||||
|
ast_mutex_unlock(&sc->lock);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Function called when the channel's thread is poked */
|
/*! \brief Function called when the channel's thread is poked */
|
||||||
|
@@ -203,6 +203,7 @@ static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_fram
|
|||||||
struct jb_framedata *framedata = data;
|
struct jb_framedata *framedata = data;
|
||||||
struct timeval now_tv;
|
struct timeval now_tv;
|
||||||
unsigned long now;
|
unsigned long now;
|
||||||
|
int putframe = 0; /* signifies if audio frame was placed into the buffer or not */
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case AST_FRAMEHOOK_EVENT_READ:
|
case AST_FRAMEHOOK_EVENT_READ:
|
||||||
@@ -249,15 +250,31 @@ static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_fram
|
|||||||
if (res == AST_JB_IMPL_OK) {
|
if (res == AST_JB_IMPL_OK) {
|
||||||
frame = &ast_null_frame;
|
frame = &ast_null_frame;
|
||||||
}
|
}
|
||||||
|
putframe = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame->frametype == AST_FRAME_NULL) {
|
if (frame->frametype == AST_FRAME_NULL) {
|
||||||
int res;
|
int res;
|
||||||
long next = framedata->jb_impl->next(framedata->jb_obj);
|
long next = framedata->jb_impl->next(framedata->jb_obj);
|
||||||
|
|
||||||
|
/* If now is earlier than the next expected output frame
|
||||||
|
* from the jitterbuffer we may choose to pass on retrieving
|
||||||
|
* a frame during this read iteration. The only exception
|
||||||
|
* to this rule is when an audio frame is placed into the buffer
|
||||||
|
* and the time for the next frame to come out of the buffer is
|
||||||
|
* at least within the timer_interval of the next output frame. By
|
||||||
|
* doing this we are able to feed off the timing of the input frames
|
||||||
|
* and only rely on our jitterbuffer timer when frames are dropped.
|
||||||
|
* During testing, this hybrid form of timing gave more reliable results. */
|
||||||
if (now < next) {
|
if (now < next) {
|
||||||
return frame;
|
long int diff = next - now;
|
||||||
|
if (!putframe) {
|
||||||
|
return frame;
|
||||||
|
} else if (diff >= framedata->timer_interval) {
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = framedata->jb_impl->get(framedata->jb_obj, &frame, now, framedata->timer_interval);
|
res = framedata->jb_impl->get(framedata->jb_obj, &frame, now, framedata->timer_interval);
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case AST_JB_IMPL_OK:
|
case AST_JB_IMPL_OK:
|
||||||
|
Reference in New Issue
Block a user