diff options
author | Richard Mudgett <rmudgett@digium.com> | 2013-06-21 22:39:27 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2013-06-21 22:39:27 +0000 |
commit | 1267c91315f6850483022b4535beadbc0069b22e (patch) | |
tree | 17236bfa946838220112a3d80fb86913f0b70aa8 | |
parent | c14cdede125902fb5c59c92745ae10d6c1e57d33 (diff) |
Extract a useful routine from the softmix bridge technology.
* Extract a useful routine from the softmix bridge technology for other
technologies. Make other technologies use it if they can.
* Made native and 1-1 bridges write to all parties if the bridge channel
writing the frame into the bridge is NULL. Softmix will also do the same
for frame types that make sense.
* Tweak the bridge write routine return value meaning and adjust the
bridge technologies to match.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@392514 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r-- | bridges/bridge_holding.c | 22 | ||||
-rw-r--r-- | bridges/bridge_native_rtp.c | 11 | ||||
-rw-r--r-- | bridges/bridge_simple.c | 13 | ||||
-rw-r--r-- | bridges/bridge_softmix.c | 58 | ||||
-rw-r--r-- | include/asterisk/bridging.h | 16 | ||||
-rw-r--r-- | include/asterisk/bridging_technology.h | 6 | ||||
-rw-r--r-- | main/bridging.c | 16 |
7 files changed, 69 insertions, 73 deletions
diff --git a/bridges/bridge_holding.c b/bridges/bridge_holding.c index fe0a7303f..bd288c9bd 100644 --- a/bridges/bridge_holding.c +++ b/bridges/bridge_holding.c @@ -255,27 +255,25 @@ static void holding_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_ch static int holding_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) { - struct ast_bridge_channel *cur; - struct holding_channel *hc = bridge_channel->tech_pvt; + struct holding_channel *hc = bridge_channel ? bridge_channel->tech_pvt : NULL; /* If there is no tech_pvt, then the channel failed to allocate one when it joined and is borked. Don't listen to him. */ if (!hc) { - return -1; + /* "Accept" the frame and discard it. */ + return 0; } /* If we aren't an announcer, we never have any business writing anything. */ if (!ast_test_flag(&hc->holding_roles, HOLDING_ROLE_ANNOUNCER)) { - return -1; + /* "Accept" the frame and discard it. */ + return 0; } - /* Ok, so we are the announcer and there are one or more people available to receive our writes. Let's do it. */ - AST_LIST_TRAVERSE(&bridge->channels, cur, entry) { - if (bridge_channel == cur || !cur->tech_pvt) { - continue; - } - - ast_bridge_channel_queue_frame(cur, frame); - } + /* + * Ok, so we are the announcer. Write the frame to all other + * channels if any. + */ + ast_bridge_queue_everyone_else(bridge, bridge_channel, frame); return 0; } diff --git a/bridges/bridge_native_rtp.c b/bridges/bridge_native_rtp.c index 120a509c1..4436f706a 100644 --- a/bridges/bridge_native_rtp.c +++ b/bridges/bridge_native_rtp.c @@ -389,16 +389,7 @@ static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) { - struct ast_bridge_channel *other = ast_bridge_channel_peer(bridge_channel); - - if (!other) { - return -1; - } - - /* The bridging core takes care of freeing the passed in frame. */ - ast_bridge_channel_queue_frame(other, frame); - - return 0; + return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame); } static struct ast_bridge_technology native_rtp_bridge = { diff --git a/bridges/bridge_simple.c b/bridges/bridge_simple.c index 3e53b31c0..49e3a35ac 100644 --- a/bridges/bridge_simple.c +++ b/bridges/bridge_simple.c @@ -68,18 +68,7 @@ static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chann static int simple_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) { - struct ast_bridge_channel *other; - - /* Find the channel we actually want to write to */ - other = ast_bridge_channel_peer(bridge_channel); - if (!other) { - return -1; - } - - /* The bridging core takes care of freeing the passed in frame. */ - ast_bridge_channel_queue_frame(other, frame); - - return 0; + return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame); } static struct ast_bridge_technology simple_bridge = { diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c index 8698ff451..cf891c668 100644 --- a/bridges/bridge_softmix.c +++ b/bridges/bridge_softmix.c @@ -445,29 +445,6 @@ static void softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_ch ast_free(sc); } -/*! - * \internal - * \brief Pass the given frame to everyone else. - * \since 12.0.0 - * - * \param bridge What bridge to distribute frame. - * \param bridge_channel Channel to optionally not pass frame to. (NULL to pass to everyone) - * \param frame Frame to pass. - * - * \return Nothing - */ -static void softmix_pass_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) -{ - struct ast_bridge_channel *cur; - - AST_LIST_TRAVERSE(&bridge->channels, cur, entry) { - if (cur == bridge_channel) { - continue; - } - ast_bridge_channel_queue_frame(cur, frame); - } -} - static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct ast_frame *frame) { struct ast_bridge_channel *cur; @@ -507,7 +484,7 @@ static void softmix_bridge_write_video(struct ast_bridge *bridge, struct ast_bri video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan); if (video_src_priority == 1) { /* Pass to me and everyone else. */ - softmix_pass_everyone_else(bridge, NULL, frame); + ast_bridge_queue_everyone_else(bridge, NULL, frame); } break; case AST_BRIDGE_VIDEO_MODE_TALKER_SRC: @@ -522,7 +499,7 @@ static void softmix_bridge_write_video(struct ast_bridge *bridge, struct ast_bri int num_src = ast_bridge_number_video_src(bridge); int echo = num_src > 1 ? 0 : 1; - softmix_pass_everyone_else(bridge, echo ? NULL : bridge_channel, frame); + ast_bridge_queue_everyone_else(bridge, echo ? NULL : bridge_channel, frame); } else if (video_src_priority == 2) { softmix_pass_video_top_priority(bridge, frame); } @@ -612,12 +589,14 @@ static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bri * \param bridge_channel Which channel is writing the frame. * \param frame What is being written. * - * \return Nothing + * \retval 0 Frame accepted into the bridge. + * \retval -1 Frame needs to be deferred. */ -static void softmix_bridge_write_control(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) +static int 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 */ + return 0; } /*! @@ -629,8 +608,8 @@ static void softmix_bridge_write_control(struct ast_bridge *bridge, struct ast_b * \param bridge_channel Which channel is writing the frame. * \param frame What is being written. * - * \retval 0 on success - * \retval -1 on failure + * \retval 0 Frame accepted into the bridge. + * \retval -1 Frame needs to be deferred. * * \note On entry, bridge is already locked. */ @@ -638,30 +617,35 @@ static int softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_cha { int res = 0; - if (!bridge->tech_pvt || !bridge_channel->tech_pvt) { - return -1; + if (!bridge->tech_pvt || (bridge_channel && !bridge_channel->tech_pvt)) { + /* "Accept" the frame and discard it. */ + return 0; } switch (frame->frametype) { case AST_FRAME_DTMF_BEGIN: case AST_FRAME_DTMF_END: - softmix_pass_everyone_else(bridge, bridge_channel, frame); + res = ast_bridge_queue_everyone_else(bridge, bridge_channel, frame); break; case AST_FRAME_VOICE: - softmix_bridge_write_voice(bridge, bridge_channel, frame); + if (bridge_channel) { + softmix_bridge_write_voice(bridge, bridge_channel, frame); + } break; case AST_FRAME_VIDEO: - softmix_bridge_write_video(bridge, bridge_channel, frame); + if (bridge_channel) { + softmix_bridge_write_video(bridge, bridge_channel, frame); + } break; case AST_FRAME_CONTROL: - softmix_bridge_write_control(bridge, bridge_channel, frame); + res = softmix_bridge_write_control(bridge, bridge_channel, frame); break; case AST_FRAME_BRIDGE_ACTION: - softmix_pass_everyone_else(bridge, bridge_channel, frame); + res = ast_bridge_queue_everyone_else(bridge, bridge_channel, frame); break; default: ast_debug(3, "Frame type %d unsupported\n", frame->frametype); - res = -1; + /* "Accept" the frame and discard it. */ break; } diff --git a/include/asterisk/bridging.h b/include/asterisk/bridging.h index 3f817f4f1..850245827 100644 --- a/include/asterisk/bridging.h +++ b/include/asterisk/bridging.h @@ -1065,6 +1065,22 @@ void ast_bridge_update_linkedids(struct ast_bridge *bridge, struct ast_bridge_ch void ast_bridge_update_accountcodes(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap); /*! + * \brief Queue the given frame to everyone else. + * \since 12.0.0 + * + * \param bridge What bridge to distribute frame. + * \param bridge_channel Channel to optionally not pass frame to. (NULL to pass to everyone) + * \param frame Frame to pass. + * + * \note This is intended to be called by bridge hooks and + * bridge technologies. + * + * \retval 0 Frame written to at least one channel. + * \retval -1 Frame written to no channels. + */ +int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame); + +/*! * \brief Write a frame to the specified bridge_channel. * \since 12.0.0 * diff --git a/include/asterisk/bridging_technology.h b/include/asterisk/bridging_technology.h index 33bdf2584..bc4326384 100644 --- a/include/asterisk/bridging_technology.h +++ b/include/asterisk/bridging_technology.h @@ -124,8 +124,10 @@ struct ast_bridge_technology { /*! * \brief Write a frame into the bridging technology instance for a bridge. * - * \retval 0 on success - * \retval -1 on failure + * \note The bridge must be tolerant of bridge_channel being NULL. + * + * \retval 0 Frame accepted into the bridge. + * \retval -1 Frame needs to be deferred. * * \note On entry, bridge is already locked. */ diff --git a/main/bridging.c b/main/bridging.c index 98a72f379..0530424ff 100644 --- a/main/bridging.c +++ b/main/bridging.c @@ -421,6 +421,22 @@ int ast_bridge_channel_queue_control_data(struct ast_bridge_channel *bridge_chan return ast_bridge_channel_queue_frame(bridge_channel, &frame); } +int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) +{ + struct ast_bridge_channel *cur; + int not_written = -1; + + AST_LIST_TRAVERSE(&bridge->channels, cur, entry) { + if (cur == bridge_channel) { + continue; + } + if (!ast_bridge_channel_queue_frame(cur, frame)) { + not_written = 0; + } + } + return not_written; +} + void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel) { /* Restore original formats of the channel as they came in */ |