[Asterisk-code-review] stream: Add stream topology to channel (asterisk[master])
George Joseph
asteriskteam at digium.com
Wed Feb 15 19:29:53 CST 2017
George Joseph has submitted this change and it was merged. ( https://gerrit.asterisk.org/4939 )
Change subject: stream: Add stream topology to channel
......................................................................
stream: Add stream topology to channel
Adds topology set and get to channel.
ASTERISK-26790
Change-Id: Ic379ea82a9486fc79dbd8c4d95c29fa3b46424f4
---
M include/asterisk/channel.h
M include/asterisk/channel_internal.h
M include/asterisk/stream.h
M main/channel.c
M main/channel_internal_api.c
M main/stream.c
M tests/test_voicemail_api.c
7 files changed, 186 insertions(+), 4 deletions(-)
Approvals:
Mark Michelson: Looks good to me, approved
Anonymous Coward #1000019: Verified
Joshua Colp: Looks good to me, but someone else must approve
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index e5f792f..4170a8a 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -884,6 +884,10 @@
* 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 @@
*/
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 */
diff --git a/include/asterisk/channel_internal.h b/include/asterisk/channel_internal.h
index 2316e2f..3de2b14 100644
--- a/include/asterisk/channel_internal.h
+++ b/include/asterisk/channel_internal.h
@@ -27,3 +27,7 @@
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);
diff --git a/include/asterisk/stream.h b/include/asterisk/stream.h
index cffe6ea..9fb4660 100644
--- a/include/asterisk/stream.h
+++ b/include/asterisk/stream.h
@@ -316,4 +316,19 @@
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 */
diff --git a/main/channel.c b/main/channel.c
index 2349193..fa92508 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -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 @@
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()) {
@@ -885,6 +887,11 @@
if (needqueue && ast_channel_internal_alertpipe_init(tmp)) {
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));
@@ -7074,6 +7081,8 @@
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.
diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c
index a0cbe86..235b996 100644
--- a/main/channel_internal_api.c
+++ b/main/channel_internal_api.c
@@ -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 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 @@
{
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)
{
- ao2_replace(chan->nativeformats, value);
+ 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 @@
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 @@
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);
+}
diff --git a/main/stream.c b/main/stream.c
index 24844c4..5112c95 100644
--- a/main/stream.c
+++ b/main/stream.c
@@ -337,3 +337,22 @@
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;
+}
diff --git a/tests/test_voicemail_api.c b/tests/test_voicemail_api.c
index 802b6bf..e467572 100644
--- a/tests/test_voicemail_api.c
+++ b/tests/test_voicemail_api.c
@@ -825,12 +825,12 @@
}
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);
--
To view, visit https://gerrit.asterisk.org/4939
To unsubscribe, visit https://gerrit.asterisk.org/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ic379ea82a9486fc79dbd8c4d95c29fa3b46424f4
Gerrit-PatchSet: 9
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Owner: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Mark Michelson <mmichelson at digium.com>
More information about the asterisk-code-review
mailing list