stream: Add stream topology to channel

Adds topology set and get to channel.

ASTERISK-26790

Change-Id: Ic379ea82a9486fc79dbd8c4d95c29fa3b46424f4
changes/39/4939/9
George Joseph 8 years ago
parent 6c4657e28e
commit bf2f091bbb

@ -884,6 +884,10 @@ enum {
* world
*/
AST_CHAN_TP_INTERNAL = (1 << 2),
/*!
* \brief Channels with this particular technology support multiple simultaneous streams
*/
AST_CHAN_TP_MULTISTREAM = (1 << 3),
};
/*! \brief ast_channel flags */
@ -4734,4 +4738,34 @@ enum ast_channel_error ast_channel_errno(void);
*/
int ast_channel_get_intercept_mode(void);
/*!
* \brief Retrieve the topology of streams on a channel
*
* \param chan The channel to get the stream topology of
*
* \pre chan is locked
*
* \retval non-NULL success
* \retval NULL failure
*/
struct ast_stream_topology *ast_channel_get_stream_topology(
const struct ast_channel *chan);
/*!
* \brief Set the topology of streams on a channel
*
* \param chan The channel to set the stream topology on
* \param topology The stream topology to set
*
* \pre chan is locked
*
* \note If topology is NULL a new empty topology will be created
* and returned.
*
* \retval non-NULL Success
* \retval NULL failure
*/
struct ast_stream_topology *ast_channel_set_stream_topology(
struct ast_channel *chan, struct ast_stream_topology *topology);
#endif /* _ASTERISK_CHANNEL_H */

@ -27,3 +27,7 @@ int ast_channel_internal_setup_topics(struct ast_channel *chan);
void ast_channel_internal_errno_set(enum ast_channel_error error);
enum ast_channel_error ast_channel_internal_errno(void);
void ast_channel_internal_set_stream_topology(struct ast_channel *chan,
struct ast_stream_topology *topology);
void ast_channel_internal_swap_stream_topology(struct ast_channel *chan1,
struct ast_channel *chan2);

@ -316,4 +316,19 @@ int ast_stream_topology_set_stream(struct ast_stream_topology *topology,
struct ast_stream_topology *ast_stream_topology_create_from_format_cap(
struct ast_format_cap *cap);
/*!
* \brief Gets the first stream of a specific type from the topology
*
* \param topology The topology of streams
* \param type The media type
*
* \retval non-NULL success
* \retval NULL failure
*
* \since 15
*/
struct ast_stream *ast_stream_topology_get_first_stream_by_type(
const struct ast_stream_topology *topology,
enum ast_media_type type);
#endif /* _AST_STREAM_H */

@ -73,6 +73,7 @@
#include "asterisk/test.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/max_forwards.h"
#include "asterisk/stream.h"
/*** DOCUMENTATION
***/
@ -806,6 +807,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
struct ast_timer *timer;
struct timeval now;
const struct ast_channel_tech *channel_tech;
struct ast_stream_topology *topology;
/* If shutting down, don't allocate any new channels */
if (ast_shutting_down()) {
@ -886,6 +888,11 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
return ast_channel_unref(tmp);
}
if (!(topology = ast_stream_topology_create())) {
return ast_channel_unref(tmp);
}
ast_channel_internal_set_stream_topology(tmp, topology);
/* Always watch the alertpipe */
ast_channel_set_fd(tmp, AST_ALERT_FD, ast_channel_internal_alert_readfd(tmp));
/* And timing pipe */
@ -7074,6 +7081,8 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
ast_channel_tech(clonechan)->type, ast_channel_name(clonechan));
}
ast_channel_internal_swap_stream_topology(original, clonechan);
/*
* Now, at this point, the "clone" channel is totally F'd up.
* We mark it as a zombie so nothing tries to touch it.

@ -46,6 +46,7 @@
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_endpoints.h"
#include "asterisk/stringfields.h"
#include "asterisk/stream.h"
#include "asterisk/test.h"
/*!
@ -221,6 +222,8 @@ struct ast_channel {
struct stasis_cp_single *topics; /*!< Topic for all channel's events */
struct stasis_forward *endpoint_forward; /*!< Subscription for event forwarding to endpoint's topic */
struct stasis_forward *endpoint_cache_forward; /*!< Subscription for cache updates to endpoint's topic */
struct ast_stream_topology *stream_topology; /*!< Stream topology */
struct ast_stream *default_streams[AST_MEDIA_TYPE_END]; /*!< Default streams indexed by media type */
};
/*! \brief The monotonically increasing integer counter for channel uniqueids */
@ -825,10 +828,57 @@ struct ast_format_cap *ast_channel_nativeformats(const struct ast_channel *chan)
{
return chan->nativeformats;
}
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
static void channel_set_default_streams(struct ast_channel *chan)
{
enum ast_media_type type;
ast_assert(chan != NULL);
for (type = AST_MEDIA_TYPE_UNKNOWN; type < AST_MEDIA_TYPE_END; type++) {
if (chan->stream_topology) {
chan->default_streams[type] =
ast_stream_topology_get_first_stream_by_type(chan->stream_topology, type);
} else {
chan->default_streams[type] = NULL;
}
}
}
void ast_channel_internal_set_stream_topology(struct ast_channel *chan,
struct ast_stream_topology *topology)
{
ast_stream_topology_destroy(chan->stream_topology);
chan->stream_topology = topology;
channel_set_default_streams(chan);
}
void ast_channel_nativeformats_set(struct ast_channel *chan,
struct ast_format_cap *value)
{
ast_assert(chan != NULL);
ao2_replace(chan->nativeformats, value);
/* If chan->stream_topology is NULL, the channel is being destroyed
* and topology is destroyed.
*/
if (!chan->stream_topology) {
return;
}
if (!chan->tech || !(chan->tech->properties & AST_CHAN_TP_MULTISTREAM) || !value) {
struct ast_stream_topology *new_topology;
if (!value) {
new_topology = ast_stream_topology_create();
} else {
new_topology = ast_stream_topology_create_from_format_cap(value);
}
ast_channel_internal_set_stream_topology(chan, new_topology);
}
}
struct ast_framehook_list *ast_channel_framehooks(const struct ast_channel *chan)
{
return chan->framehooks;
@ -1637,6 +1687,8 @@ void ast_channel_internal_cleanup(struct ast_channel *chan)
stasis_cp_single_unsubscribe(chan->topics);
chan->topics = NULL;
ast_channel_internal_set_stream_topology(chan, NULL);
}
void ast_channel_internal_finalize(struct ast_channel *chan)
@ -1729,3 +1781,52 @@ enum ast_channel_error ast_channel_internal_errno(void)
return *error_code;
}
struct ast_stream_topology *ast_channel_get_stream_topology(
const struct ast_channel *chan)
{
ast_assert(chan != NULL);
return chan->stream_topology;
}
struct ast_stream_topology *ast_channel_set_stream_topology(struct ast_channel *chan,
struct ast_stream_topology *topology)
{
struct ast_stream_topology *new_topology;
ast_assert(chan != NULL);
/* A non-MULTISTREAM channel can't manipulate topology directly */
ast_assert(chan->tech != NULL && (chan->tech->properties & AST_CHAN_TP_MULTISTREAM));
/* Unless the channel is being destroyed, we always want a topology on
* it even if its empty.
*/
if (!topology) {
new_topology = ast_stream_topology_create();
} else {
new_topology = topology;
}
if (new_topology) {
ast_channel_internal_set_stream_topology(chan, new_topology);
}
return new_topology;
}
void ast_channel_internal_swap_stream_topology(struct ast_channel *chan1,
struct ast_channel *chan2)
{
struct ast_stream_topology *tmp_topology;
ast_assert(chan1 != NULL && chan2 != NULL);
tmp_topology = chan1->stream_topology;
chan1->stream_topology = chan2->stream_topology;
chan2->stream_topology = tmp_topology;
channel_set_default_streams(chan1);
channel_set_default_streams(chan2);
}

@ -337,3 +337,22 @@ struct ast_stream_topology *ast_stream_topology_create_from_format_cap(
return topology;
}
struct ast_stream *ast_stream_topology_get_first_stream_by_type(
const struct ast_stream_topology *topology,
enum ast_media_type type)
{
int i;
ast_assert(topology != NULL);
for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
struct ast_stream *stream = AST_VECTOR_GET(&topology->streams, i);
if (stream->type == type) {
return stream;
}
}
return NULL;
}

@ -825,12 +825,12 @@ static struct ast_channel *test_vm_api_create_mock_channel(void)
}
ast_channel_set_writeformat(mock_channel, ast_format_gsm);
native_formats = ast_channel_nativeformats(mock_channel);
ast_format_cap_append(native_formats, ast_channel_writeformat(mock_channel), 0);
ast_channel_set_rawwriteformat(mock_channel, ast_format_gsm);
ast_channel_set_readformat(mock_channel, ast_format_gsm);
ast_channel_set_rawreadformat(mock_channel, ast_format_gsm);
ast_channel_tech_set(mock_channel, &mock_channel_tech);
native_formats = ast_channel_nativeformats(mock_channel);
ast_format_cap_append(native_formats, ast_channel_writeformat(mock_channel), 0);
ast_channel_unlock(mock_channel);

Loading…
Cancel
Save