[asterisk-commits] rmudgett: branch rmudgett/bridge_phase r384007 - in /team/rmudgett/bridge_pha...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Mar 27 10:24:08 CDT 2013
Author: rmudgett
Date: Wed Mar 27 10:24:04 2013
New Revision: 384007
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=384007
Log:
Initial handling of control frames in new bridging.
* Refactored softmix_bridge_write().
Modified:
team/rmudgett/bridge_phase/bridges/bridge_holding.c
team/rmudgett/bridge_phase/bridges/bridge_simple.c
team/rmudgett/bridge_phase/bridges/bridge_softmix.c
team/rmudgett/bridge_phase/include/asterisk/bridging_technology.h
team/rmudgett/bridge_phase/main/abstract_jb.c
team/rmudgett/bridge_phase/main/bridging.c
Modified: team/rmudgett/bridge_phase/bridges/bridge_holding.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/bridges/bridge_holding.c?view=diff&rev=384007&r1=384006&r2=384007
==============================================================================
--- team/rmudgett/bridge_phase/bridges/bridge_holding.c (original)
+++ team/rmudgett/bridge_phase/bridges/bridge_holding.c Wed Mar 27 10:24:04 2013
@@ -278,11 +278,7 @@
}
if (other->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
-/* BUGBUG need to handle control frames in a bridge tech specific way here. Mostly just queue action to bridge channel. */
- if (!other->suspended
- || ast_is_deferrable_frame(frame)) {
- ast_bridge_channel_queue_frame(other, frame);
- }
+ ast_bridge_channel_queue_frame(other, frame);
}
}
Modified: team/rmudgett/bridge_phase/bridges/bridge_simple.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/bridges/bridge_simple.c?view=diff&rev=384007&r1=384006&r2=384007
==============================================================================
--- team/rmudgett/bridge_phase/bridges/bridge_simple.c (original)
+++ team/rmudgett/bridge_phase/bridges/bridge_simple.c Wed Mar 27 10:24:04 2013
@@ -83,11 +83,7 @@
/* The bridging core takes care of freeing the passed in frame. */
if (other->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
-/* BUGBUG need to handle control frames in a bridge tech specific way here. Mostly just queue action to bridge channel. */
- if (!other->suspended
- || ast_is_deferrable_frame(frame)) {
- ast_bridge_channel_queue_frame(other, frame);
- }
+ ast_bridge_channel_queue_frame(other, frame);
}
return 0;
Modified: team/rmudgett/bridge_phase/bridges/bridge_softmix.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/bridges/bridge_softmix.c?view=diff&rev=384007&r1=384006&r2=384007
==============================================================================
--- team/rmudgett/bridge_phase/bridges/bridge_softmix.c (original)
+++ team/rmudgett/bridge_phase/bridges/bridge_softmix.c Wed Mar 27 10:24:04 2013
@@ -468,8 +468,64 @@
}
}
-/*! \brief Function called when a channel writes a frame into the bridge */
-static int softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+/*!
+ * \internal
+ * \brief Determine what to do with a video frame.
+ * \since 12.0.0
+ *
+ * \param bridge Which bridge is getting the frame
+ * \param bridge_channel Which channel is writing the frame.
+ * \param frame What is being written.
+ *
+ * \return Nothing
+ */
+static void softmix_bridge_write_video(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+{
+ struct softmix_channel *sc = bridge_channel->tech_pvt;
+ int num_src;
+ int video_src_priority;
+
+ num_src = ast_bridge_number_video_src(bridge);
+ video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan);
+
+ /* Determine if the video frame should be distributed or not */
+ switch (bridge->video_mode.mode) {
+ case AST_BRIDGE_VIDEO_MODE_NONE:
+ break;
+ case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
+ if (video_src_priority == 1) {
+ softmix_pass_video_all(bridge, bridge_channel, frame, 1);
+ }
+ break;
+ case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
+ ast_mutex_lock(&sc->lock);
+ ast_bridge_update_talker_src_video_mode(bridge, bridge_channel->chan,
+ sc->video_talker.energy_average,
+ ast_format_get_video_mark(&frame->subclass.format));
+ ast_mutex_unlock(&sc->lock);
+ if (video_src_priority == 1) {
+ int echo = num_src > 1 ? 0 : 1;
+
+ softmix_pass_video_all(bridge, bridge_channel, frame, echo);
+ } else if (video_src_priority == 2) {
+ softmix_pass_video_top_priority(bridge, frame);
+ }
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Determine what to do with a voice frame.
+ * \since 12.0.0
+ *
+ * \param bridge Which bridge is getting the frame
+ * \param bridge_channel Which channel is writing the frame.
+ * \param frame What is being written.
+ *
+ * \return Nothing
+ */
+static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
{
struct softmix_channel *sc = bridge_channel->tech_pvt;
struct softmix_bridge_data *softmix_data = bridge->tech_pvt;
@@ -479,49 +535,8 @@
bridge_channel->tech_args.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. */
- int res = 0;
-
- /* Only accept audio frames, all others are unsupported */
- if (frame->frametype == AST_FRAME_DTMF_END || frame->frametype == AST_FRAME_DTMF_BEGIN) {
- softmix_pass_dtmf(bridge, bridge_channel, frame);
- return res;
- } else if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO) {
- /* Frame type unsupported. */
- res = -1;
- return res;
- } else if (frame->datalen == 0) {
- return res;
- }
-
- /* Determine if this video frame should be distributed or not */
- if (frame->frametype == AST_FRAME_VIDEO) {
- int num_src = ast_bridge_number_video_src(bridge);
- int video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan);
-
- switch (bridge->video_mode.mode) {
- case AST_BRIDGE_VIDEO_MODE_NONE:
- break;
- case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
- if (video_src_priority == 1) {
- softmix_pass_video_all(bridge, bridge_channel, frame, 1);
- }
- break;
- case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
- ast_mutex_lock(&sc->lock);
- ast_bridge_update_talker_src_video_mode(bridge, bridge_channel->chan, sc->video_talker.energy_average, ast_format_get_video_mark(&frame->subclass.format));
- ast_mutex_unlock(&sc->lock);
- if (video_src_priority == 1) {
- int echo = num_src > 1 ? 0 : 1;
- softmix_pass_video_all(bridge, bridge_channel, frame, echo);
- } else if (video_src_priority == 2) {
- softmix_pass_video_top_priority(bridge, frame);
- }
- break;
- }
- return res;
- }
-
- /* If we made it here, we are going to write the frame into the conference */
+
+ /* Write the frame into the conference */
ast_mutex_lock(&sc->lock);
ast_dsp_silence_with_energy(sc->dsp, frame, &totalsilence, &cur_energy);
@@ -569,6 +584,62 @@
if (update_talking != -1) {
ast_bridge_notify_talking(bridge_channel, update_talking);
+ }
+}
+
+/*!
+ * \internal
+ * \brief Determine what to do with a control frame.
+ * \since 12.0.0
+ *
+ * \param bridge Which bridge is getting the frame
+ * \param bridge_channel Which channel is writing the frame.
+ * \param frame What is being written.
+ *
+ * \return Nothing
+ */
+static void softmix_bridge_write_control(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+{
+/* BUGBUG need to look at channel roles to determine what to do with control frame. */
+ /*! \todo BUGBUG softmix_bridge_write_control() not written */
+}
+
+/*!
+ * \internal
+ * \brief Determine what to do with a frame written into the bridge.
+ * \since 12.0.0
+ *
+ * \param bridge Which bridge is getting the frame
+ * \param bridge_channel Which channel is writing the frame.
+ * \param frame What is being written.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
+ *
+ * \note On entry, bridge is already locked.
+ */
+static int softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+{
+ int res = 0;
+
+ switch (frame->frametype) {
+ case AST_FRAME_DTMF_BEGIN:
+ case AST_FRAME_DTMF_END:
+ softmix_pass_dtmf(bridge, bridge_channel, frame);
+ break;
+ case AST_FRAME_VOICE:
+ softmix_bridge_write_voice(bridge, bridge_channel, frame);
+ break;
+ case AST_FRAME_VIDEO:
+ softmix_bridge_write_video(bridge, bridge_channel, frame);
+ break;
+ case AST_FRAME_CONTROL:
+ softmix_bridge_write_control(bridge, bridge_channel, frame);
+ break;
+ default:
+ ast_debug(3, "Frame type %d unsupported\n", frame->frametype);
+ res = -1;
+ break;
}
return res;
Modified: team/rmudgett/bridge_phase/include/asterisk/bridging_technology.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/include/asterisk/bridging_technology.h?view=diff&rev=384007&r1=384006&r2=384007
==============================================================================
--- team/rmudgett/bridge_phase/include/asterisk/bridging_technology.h (original)
+++ team/rmudgett/bridge_phase/include/asterisk/bridging_technology.h Wed Mar 27 10:24:04 2013
@@ -83,6 +83,8 @@
*
* \retval 0 on success
* \retval -1 on failure
+ *
+ * \note On entry, bridge is already locked.
*/
int (*write)(struct ast_bridge *bridge, struct ast_bridge_channel *bridged_channel, struct ast_frame *frame);
/*! Formats that the bridge technology supports */
Modified: team/rmudgett/bridge_phase/main/abstract_jb.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/abstract_jb.c?view=diff&rev=384007&r1=384006&r2=384007
==============================================================================
--- team/rmudgett/bridge_phase/main/abstract_jb.c (original)
+++ team/rmudgett/bridge_phase/main/abstract_jb.c Wed Mar 27 10:24:04 2013
@@ -570,6 +570,7 @@
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
{
+/* BUGBUG convert this to use func_jitterbuffer then the channel jitterbuffer may be able to go away. */
memcpy(&ast_channel_jb(chan)->conf, conf, sizeof(*conf));
}
Modified: team/rmudgett/bridge_phase/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/bridging.c?view=diff&rev=384007&r1=384006&r2=384007
==============================================================================
--- team/rmudgett/bridge_phase/main/bridging.c (original)
+++ team/rmudgett/bridge_phase/main/bridging.c Wed Mar 27 10:24:04 2013
@@ -296,7 +296,10 @@
struct ast_frame *dup;
char nudge = 0;
-/* BUGBUG need to do something with media frames when channel is suspended. Likely just drop non-deferable frames. */
+ if (bridge_channel->suspended && !ast_is_deferrable_frame(fr)) {
+ /* Drop non-deferable frames when suspended. */
+ return 0;
+ }
dup = ast_frdup(fr);
if (!dup) {
@@ -614,32 +617,6 @@
return ready;
}
-/*! \brief Internal function used to determine whether a control frame should be dropped or not */
-static int bridge_drop_control_frame(int subclass)
-{
-/* BUGBUG I think this code should be removed. Let the bridging tech determine what to do with control frames. */
-#if 1
- /* Block all control frames. */
- return 1;
-#else
- switch (subclass) {
- case AST_CONTROL_READ_ACTION:
- case AST_CONTROL_CC:
- case AST_CONTROL_MCID:
- case AST_CONTROL_AOC:
- case AST_CONTROL_CONNECTED_LINE:
- case AST_CONTROL_REDIRECTING:
- return 1;
-
- case AST_CONTROL_ANSWER:
- case -1:
- return 1;
- default:
- return 0;
- }
-#endif
-}
-
void ast_bridge_notify_talking(struct ast_bridge_channel *bridge_channel, int started_talking)
{
struct ast_frame action = {
@@ -682,13 +659,6 @@
ast_frfree(frame);
return;
}
- if (bridge_drop_control_frame(frame->subclass.integer)) {
- ast_debug(1, "Dropping control frame %d from bridge channel %p(%s)\n",
- frame->subclass.integer, bridge_channel,
- ast_channel_name(bridge_channel->chan));
- ast_frfree(frame);
- return;
- }
break;
case AST_FRAME_DTMF_BEGIN:
frame = bridge_handle_dtmf(bridge_channel, frame);
@@ -706,10 +676,6 @@
break;
}
-/* BUGBUG looks like the place to handle the control frame exchange between 1-1 bridge participants is the bridge tech write callback. */
-/* BUGBUG make a 1-1 bridge write handler for control frames. */
-/* BUGBUG make bridge_channel thread run the CONNECTED_LINE and REDIRECTING interception macros. */
-/* BUGBUG should make AST_CONTROL_ANSWER do an ast_indicate(-1) to the bridge peer if it is not UP as well as a connected line update. */
/* BUGBUG bridge join or impart needs to do CONNECTED_LINE updates if the channels are being swapped and it is a 1-1 bridge. */
/* Simply write the frame out to the bridge technology. */
@@ -1714,10 +1680,82 @@
*/
static void bridge_channel_handle_control(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr)
{
+ struct ast_channel *chan;
+ struct ast_option_header *aoh;
+ int is_caller;
+ int intercept_failed;
+
+ chan = bridge_channel->chan;
switch (fr->subclass.integer) {
+ case AST_CONTROL_REDIRECTING:
+ is_caller = !ast_test_flag(ast_channel_flags(chan), AST_FLAG_OUTGOING);
+ bridge_channel_suspend(bridge_channel);
+ intercept_failed = ast_channel_redirecting_sub(NULL, chan, fr, 1)
+ && ast_channel_redirecting_macro(NULL, chan, fr, is_caller, 1);
+ bridge_channel_unsuspend(bridge_channel);
+ if (intercept_failed) {
+ ast_indicate_data(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);
+ }
+ break;
case AST_CONTROL_CONNECTED_LINE:
+ is_caller = !ast_test_flag(ast_channel_flags(chan), AST_FLAG_OUTGOING);
+ bridge_channel_suspend(bridge_channel);
+ intercept_failed = ast_channel_connected_line_sub(NULL, chan, fr, 1)
+ && ast_channel_connected_line_macro(NULL, chan, fr, is_caller, 1);
+ bridge_channel_unsuspend(bridge_channel);
+ if (intercept_failed) {
+ ast_indicate_data(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);
+ }
+ break;
+ case AST_CONTROL_HOLD:
+ case AST_CONTROL_UNHOLD:
+/*
+ * BUGBUG bridge_channels should remember sending/receiving an outstanding HOLD to/from the bridge
+ *
+ * When the sending channel is pulled from the bridge it needs to write into the bridge an UNHOLD before being pulled.
+ * When the receiving channel is pulled from the bridge it needs to generate its own UNHOLD.
+ * Something similar needs to be done for DTMF begin/end.
+ */
+ case AST_CONTROL_VIDUPDATE:
+ case AST_CONTROL_SRCUPDATE:
+ case AST_CONTROL_SRCCHANGE:
+ case AST_CONTROL_T38_PARAMETERS:
+/* BUGBUG may have to do something with a jitter buffer for these. */
+ ast_indicate_data(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);
+ break;
+ case AST_CONTROL_OPTION:
+ /*
+ * Forward option Requests, but only ones we know are safe These
+ * are ONLY sent by chan_iax2 and I'm not convinced that they
+ * are useful. I haven't deleted them entirely because I just am
+ * not sure of the ramifications of removing them.
+ */
+ aoh = fr->data.ptr;
+ if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
+ switch (ntohs(aoh->option)) {
+ case AST_OPTION_TONE_VERIFY:
+ case AST_OPTION_TDD:
+ case AST_OPTION_RELAXDTMF:
+ case AST_OPTION_AUDIO_MODE:
+ case AST_OPTION_DIGIT_DETECT:
+ case AST_OPTION_FAX_DETECT:
+ ast_channel_setoption(chan, ntohs(aoh->option), aoh->data,
+ fr->datalen - sizeof(*aoh), 0);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case AST_CONTROL_ANSWER:
+ if (ast_channel_state(chan) != AST_STATE_UP) {
+ ast_answer(chan);
+ } else {
+ ast_indicate(chan, -1);
+ }
break;
default:
+ ast_indicate_data(chan, fr->subclass.integer, fr->data.ptr, fr->datalen);
break;
}
/*! \todo BUGBUG bridge_channel_handle_control() not written */
More information about the asterisk-commits
mailing list