/*! \brief Frame hook that is called to intercept hold/unhold */ static struct ast_frame *native_rtp_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data) { RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup); struct native_rtp_bridge_data *native_data = data; if (!f || (event != AST_FRAMEHOOK_EVENT_WRITE)) { return f; } bridge = ast_channel_get_bridge(chan); if (bridge) { /* native_rtp_bridge_start/stop are not being called from bridging core so we need to lock the bridge prior to calling these functions Unfortunately that means unlocking the channel, but as it should not be modified this should be okay... hopefully... unless this channel is being moved around right now and is in the process of having this framehook removed (which is fine). To ensure we then don't stop or start when we shouldn't we consult the data provided. If this framehook has been detached then the detached variable will be set. This is safe to check as it is only manipulated with the bridge lock held. */ ast_channel_unlock(chan); ast_bridge_lock(bridge); if (!native_data->detached) { if (f->subclass.integer == AST_CONTROL_HOLD) { native_rtp_bridge_stop(bridge, chan); } else if ((f->subclass.integer == AST_CONTROL_UNHOLD) || (f->subclass.integer == AST_CONTROL_UPDATE_RTP_PEER)) { native_rtp_bridge_start(bridge, chan); } } ast_bridge_unlock(bridge); ast_channel_lock(chan); } return f; }
static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) { native_rtp_bridge_framehook_detach(bridge_channel); native_rtp_bridge_stop(bridge, NULL); }