mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-30 02:26:23 +00:00
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
This commit is contained in:
@@ -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)
|
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 ? bridge_channel->tech_pvt : NULL;
|
||||||
struct holding_channel *hc = bridge_channel->tech_pvt;
|
|
||||||
|
|
||||||
/* 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 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) {
|
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 we aren't an announcer, we never have any business writing anything. */
|
||||||
if (!ast_test_flag(&hc->holding_roles, HOLDING_ROLE_ANNOUNCER)) {
|
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) {
|
* Ok, so we are the announcer. Write the frame to all other
|
||||||
if (bridge_channel == cur || !cur->tech_pvt) {
|
* channels if any.
|
||||||
continue;
|
*/
|
||||||
}
|
ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
|
||||||
|
|
||||||
ast_bridge_channel_queue_frame(cur, frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
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);
|
return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
|
||||||
|
|
||||||
if (!other) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The bridging core takes care of freeing the passed in frame. */
|
|
||||||
ast_bridge_channel_queue_frame(other, frame);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ast_bridge_technology native_rtp_bridge = {
|
static struct ast_bridge_technology native_rtp_bridge = {
|
||||||
|
@@ -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)
|
static int simple_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
|
||||||
{
|
{
|
||||||
struct ast_bridge_channel *other;
|
return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ast_bridge_technology simple_bridge = {
|
static struct ast_bridge_technology simple_bridge = {
|
||||||
|
@@ -445,29 +445,6 @@ static void softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_ch
|
|||||||
ast_free(sc);
|
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)
|
static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct ast_frame *frame)
|
||||||
{
|
{
|
||||||
struct ast_bridge_channel *cur;
|
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);
|
video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan);
|
||||||
if (video_src_priority == 1) {
|
if (video_src_priority == 1) {
|
||||||
/* Pass to me and everyone else. */
|
/* Pass to me and everyone else. */
|
||||||
softmix_pass_everyone_else(bridge, NULL, frame);
|
ast_bridge_queue_everyone_else(bridge, NULL, frame);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
|
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 num_src = ast_bridge_number_video_src(bridge);
|
||||||
int echo = num_src > 1 ? 0 : 1;
|
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) {
|
} else if (video_src_priority == 2) {
|
||||||
softmix_pass_video_top_priority(bridge, frame);
|
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 bridge_channel Which channel is writing the frame.
|
||||||
* \param frame What is being written.
|
* \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. */
|
/* BUGBUG need to look at channel roles to determine what to do with control frame. */
|
||||||
/*! \todo BUGBUG softmix_bridge_write_control() not written */
|
/*! \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 bridge_channel Which channel is writing the frame.
|
||||||
* \param frame What is being written.
|
* \param frame What is being written.
|
||||||
*
|
*
|
||||||
* \retval 0 on success
|
* \retval 0 Frame accepted into the bridge.
|
||||||
* \retval -1 on failure
|
* \retval -1 Frame needs to be deferred.
|
||||||
*
|
*
|
||||||
* \note On entry, bridge is already locked.
|
* \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;
|
int res = 0;
|
||||||
|
|
||||||
if (!bridge->tech_pvt || !bridge_channel->tech_pvt) {
|
if (!bridge->tech_pvt || (bridge_channel && !bridge_channel->tech_pvt)) {
|
||||||
return -1;
|
/* "Accept" the frame and discard it. */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (frame->frametype) {
|
switch (frame->frametype) {
|
||||||
case AST_FRAME_DTMF_BEGIN:
|
case AST_FRAME_DTMF_BEGIN:
|
||||||
case AST_FRAME_DTMF_END:
|
case AST_FRAME_DTMF_END:
|
||||||
softmix_pass_everyone_else(bridge, bridge_channel, frame);
|
res = ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
|
||||||
break;
|
break;
|
||||||
case AST_FRAME_VOICE:
|
case AST_FRAME_VOICE:
|
||||||
softmix_bridge_write_voice(bridge, bridge_channel, frame);
|
if (bridge_channel) {
|
||||||
|
softmix_bridge_write_voice(bridge, bridge_channel, frame);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case AST_FRAME_VIDEO:
|
case AST_FRAME_VIDEO:
|
||||||
softmix_bridge_write_video(bridge, bridge_channel, frame);
|
if (bridge_channel) {
|
||||||
|
softmix_bridge_write_video(bridge, bridge_channel, frame);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case AST_FRAME_CONTROL:
|
case AST_FRAME_CONTROL:
|
||||||
softmix_bridge_write_control(bridge, bridge_channel, frame);
|
res = softmix_bridge_write_control(bridge, bridge_channel, frame);
|
||||||
break;
|
break;
|
||||||
case AST_FRAME_BRIDGE_ACTION:
|
case AST_FRAME_BRIDGE_ACTION:
|
||||||
softmix_pass_everyone_else(bridge, bridge_channel, frame);
|
res = ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ast_debug(3, "Frame type %d unsupported\n", frame->frametype);
|
ast_debug(3, "Frame type %d unsupported\n", frame->frametype);
|
||||||
res = -1;
|
/* "Accept" the frame and discard it. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1064,6 +1064,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);
|
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.
|
* \brief Write a frame to the specified bridge_channel.
|
||||||
* \since 12.0.0
|
* \since 12.0.0
|
||||||
|
@@ -124,8 +124,10 @@ struct ast_bridge_technology {
|
|||||||
/*!
|
/*!
|
||||||
* \brief Write a frame into the bridging technology instance for a bridge.
|
* \brief Write a frame into the bridging technology instance for a bridge.
|
||||||
*
|
*
|
||||||
* \retval 0 on success
|
* \note The bridge must be tolerant of bridge_channel being NULL.
|
||||||
* \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.
|
* \note On entry, bridge is already locked.
|
||||||
*/
|
*/
|
||||||
|
@@ -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);
|
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)
|
void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel)
|
||||||
{
|
{
|
||||||
/* Restore original formats of the channel as they came in */
|
/* Restore original formats of the channel as they came in */
|
||||||
|
Reference in New Issue
Block a user