summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_voicemail.c24
-rw-r--r--formats/format_g729.c2
-rw-r--r--include/asterisk/sdp_state.h4
-rw-r--r--include/asterisk/stream.h28
-rw-r--r--main/pbx_app.c7
-rw-r--r--main/sdp_state.c56
-rw-r--r--main/stream.c35
-rw-r--r--tests/test_stream.c227
8 files changed, 353 insertions, 30 deletions
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 8f50e1106..a95168013 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -13134,10 +13134,25 @@ static void imap_logout(const char *mailbox_id)
return;
}
+ ast_mutex_lock(&vms->lock);
vms->mailstream = mail_close(vms->mailstream);
+ ast_mutex_unlock(&vms->lock);
+
vmstate_delete(vms);
}
+static void imap_close_subscribed_mailboxes(void)
+{
+ struct mwi_sub *mwi_sub;
+
+ AST_RWLIST_RDLOCK(&mwi_subs);
+ AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
+ if (!ast_strlen_zero(mwi_sub->mailbox)) {
+ imap_logout(mwi_sub->mailbox);
+ }
+ }
+ AST_RWLIST_UNLOCK(&mwi_subs);
+}
#endif
static int handle_unsubscribe(void *datap)
@@ -13591,7 +13606,11 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
strcpy(listen_control_restart_key, DEFAULT_LISTEN_CONTROL_RESTART_KEY);
strcpy(listen_control_stop_key, DEFAULT_LISTEN_CONTROL_STOP_KEY);
- /* Free all the users structure */
+#ifdef IMAP_STORAGE
+ imap_close_subscribed_mailboxes();
+#endif
+
+ /* Free all the users structure */
free_vm_users();
/* Free all the zones structure */
@@ -14985,6 +15004,9 @@ static int unload_module(void)
ast_unload_realtime("voicemail");
ast_unload_realtime("voicemail_data");
+#ifdef IMAP_STORAGE
+ imap_close_subscribed_mailboxes();
+#endif
free_vm_users();
free_vm_zones();
return res;
diff --git a/formats/format_g729.c b/formats/format_g729.c
index 1e523062e..91dc855f1 100644
--- a/formats/format_g729.c
+++ b/formats/format_g729.c
@@ -19,7 +19,7 @@
/*! \file
*
* \brief Save to raw, headerless G729 data.
- * \note This is not an encoder/decoder. The codec fo g729 is only
+ * \note This is not an encoder/decoder. The codec for g729 is only
* available with a commercial license from Digium, due to patent
* restrictions. Check http://www.digium.com for information.
* \arg Extensions: g729
diff --git a/include/asterisk/sdp_state.h b/include/asterisk/sdp_state.h
index c2122fbce..b8209e1d5 100644
--- a/include/asterisk/sdp_state.h
+++ b/include/asterisk/sdp_state.h
@@ -146,6 +146,10 @@ const void *ast_sdp_state_get_local_sdp_impl(struct ast_sdp_state *sdp_state);
* \param sdp_state
* \param sdp
*
+ * \note It is assumed that the passed in SDP has been checked for sanity
+ * already. e.g., There are no syntax errors, a c= line is reachable for
+ * each m= line, etc...
+ *
* \retval 0 Success
* \retval non-0 Failure
*
diff --git a/include/asterisk/stream.h b/include/asterisk/stream.h
index fcee3e47b..00169a3f1 100644
--- a/include/asterisk/stream.h
+++ b/include/asterisk/stream.h
@@ -359,6 +359,25 @@ int ast_stream_topology_set_stream(struct ast_stream_topology *topology,
unsigned int position, struct ast_stream *stream);
/*!
+ * \brief Delete a specified stream from the given topology.
+ * \since 15.0.0
+ *
+ * \param topology The topology of streams.
+ * \param position The topology position to delete.
+ *
+ * \note Deleting a stream will completely remove it from the topology
+ * as if it never existed in it. i.e., Any following stream positions
+ * will shift down so there is no gap.
+ *
+ * \retval 0 on success.
+ * \retval -1 on failure.
+ *
+ * \return Nothing
+ */
+int ast_stream_topology_del_stream(struct ast_stream_topology *topology,
+ unsigned int position);
+
+/*!
* \brief A helper function that, given a format capabilities structure,
* creates a topology and separates the media types in format_cap into
* separate streams.
@@ -382,8 +401,11 @@ struct ast_stream_topology *ast_stream_topology_create_from_format_cap(
struct ast_format_cap *cap);
/*!
- * \brief A helper function that, given a stream topology, creates a format
- * capabilities structure containing all formats from all streams.
+ * \brief Create a format capabilities structure representing the topology.
+ *
+ * \details
+ * A helper function that, given a stream topology, creates a format
+ * capabilities structure containing all formats from all active streams.
*
* \param topology The topology of streams
*
@@ -398,7 +420,7 @@ struct ast_format_cap *ast_format_cap_from_stream_topology(
struct ast_stream_topology *topology);
/*!
- * \brief Gets the first stream of a specific type from the topology
+ * \brief Gets the first active stream of a specific type from the topology
*
* \param topology The topology of streams
* \param type The media type
diff --git a/main/pbx_app.c b/main/pbx_app.c
index e0609db70..ec6bc7589 100644
--- a/main/pbx_app.c
+++ b/main/pbx_app.c
@@ -394,6 +394,11 @@ int ast_unregister_application(const char *app)
struct ast_app *cur;
int cmp;
+ /* Anticipate need for conlock in unreference_cached_app(), in order to avoid
+ * possible deadlock with pbx_extension_helper()/pbx_findapp()
+ */
+ ast_rdlock_contexts();
+
AST_RWLIST_WRLOCK(&apps);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
cmp = strcasecmp(app, cur->name);
@@ -416,6 +421,8 @@ int ast_unregister_application(const char *app)
AST_RWLIST_TRAVERSE_SAFE_END;
AST_RWLIST_UNLOCK(&apps);
+ ast_unlock_contexts();
+
return cur ? 0 : -1;
}
diff --git a/main/sdp_state.c b/main/sdp_state.c
index 00f147f47..0f06bf9e3 100644
--- a/main/sdp_state.c
+++ b/main/sdp_state.c
@@ -875,6 +875,7 @@ static void update_ice(const struct ast_sdp_state *state, struct ast_rtp_instanc
{
struct ast_rtp_engine_ice *ice;
const struct ast_sdp_a_line *attr;
+ const struct ast_sdp_a_line *attr_rtcp_mux;
unsigned int attr_i;
/* If ICE support is not enabled or available exit early */
@@ -902,10 +903,12 @@ static void update_ice(const struct ast_sdp_state *state, struct ast_rtp_instanc
return;
}
- if (ast_sdp_m_find_attribute(remote_m_line, "ice-lite", -1)) {
+ if (ast_sdp_find_attribute(remote_sdp, "ice-lite", -1)) {
ice->ice_lite(rtp);
}
+ attr_rtcp_mux = ast_sdp_m_find_attribute(remote_m_line, "rtcp-mux", -1);
+
/* Find all of the candidates */
for (attr_i = 0; attr_i < ast_sdp_m_get_a_count(remote_m_line); ++attr_i) {
char foundation[32];
@@ -931,9 +934,9 @@ static void update_ice(const struct ast_sdp_state *state, struct ast_rtp_instanc
continue;
}
- if (ast_sdp_options_get_rtcp_mux(options)
- && ast_sdp_m_find_attribute(remote_m_line, "rtcp-mux", -1)
- && candidate.id > 1) {
+ if (candidate.id > 1
+ && attr_rtcp_mux
+ && ast_sdp_options_get_rtcp_mux(options)) {
/* Remote side may have offered RTP and RTCP candidates. However, if we're using RTCP MUX,
* then we should ignore RTCP candidates.
*/
@@ -997,11 +1000,32 @@ static void update_rtp_after_merge(const struct ast_sdp_state *state,
const struct ast_sdp *remote_sdp,
const struct ast_sdp_m_line *remote_m_line)
{
+ struct ast_sdp_c_line *c_line;
+ struct ast_sockaddr *addrs;
+
if (!rtp) {
/* This is a dummy stream */
return;
}
+ c_line = remote_m_line->c_line;
+ if (!c_line) {
+ c_line = remote_sdp->c_line;
+ }
+ /*
+ * There must be a c= line somewhere but that would be an error by
+ * the far end that should have been caught by a validation check
+ * before we processed the SDP.
+ */
+ ast_assert(c_line != NULL);
+
+ if (ast_sockaddr_resolve(&addrs, c_line->address, PARSE_PORT_FORBID, AST_AF_UNSPEC) > 0) {
+ /* Apply connection information to the RTP instance */
+ ast_sockaddr_set_port(addrs, remote_m_line->port);
+ ast_rtp_instance_set_remote_address(rtp->instance, addrs);
+ ast_free(addrs);
+ }
+
if (ast_sdp_options_get_rtcp_mux(options)
&& ast_sdp_m_find_attribute(remote_m_line, "rtcp-mux", -1)) {
ast_rtp_instance_set_prop(rtp->instance, AST_RTP_PROPERTY_RTCP,
@@ -1011,9 +1035,7 @@ static void update_rtp_after_merge(const struct ast_sdp_state *state,
AST_RTP_INSTANCE_RTCP_STANDARD);
}
- if (ast_sdp_options_get_ice(options) == AST_SDP_ICE_ENABLED_STANDARD) {
- update_ice(state, rtp->instance, options, remote_sdp, remote_m_line);
- }
+ update_ice(state, rtp->instance, options, remote_sdp, remote_m_line);
}
/*!
@@ -1066,12 +1088,19 @@ static void update_udptl_after_merge(const struct ast_sdp_state *state, struct s
}
}
- c_line = remote_sdp->c_line;
- if (remote_m_line->c_line) {
- c_line = remote_m_line->c_line;
+ c_line = remote_m_line->c_line;
+ if (!c_line) {
+ c_line = remote_sdp->c_line;
}
+ /*
+ * There must be a c= line somewhere but that would be an error by
+ * the far end that should have been caught by a validation check
+ * before we processed the SDP.
+ */
+ ast_assert(c_line != NULL);
if (ast_sockaddr_resolve(&addrs, c_line->address, PARSE_PORT_FORBID, AST_AF_UNSPEC) > 0) {
+ /* Apply connection information to the UDPTL instance */
ast_sockaddr_set_port(addrs, remote_m_line->port);
ast_udptl_set_peer(udptl->instance, addrs);
ast_free(addrs);
@@ -1734,13 +1763,16 @@ static struct ast_sdp *sdp_create_from_state(const struct ast_sdp_state *sdp_sta
if (!c_line) {
goto error;
}
-
s_line = ast_sdp_s_alloc(options->sdpsession);
if (!s_line) {
goto error;
}
+ t_line = ast_sdp_t_alloc(0, 0);
+ if (!t_line) {
+ goto error;
+ }
- sdp = ast_sdp_alloc(o_line, c_line, s_line, NULL);
+ sdp = ast_sdp_alloc(o_line, c_line, s_line, t_line);
if (!sdp) {
goto error;
}
diff --git a/main/stream.c b/main/stream.c
index fb146931d..20179f331 100644
--- a/main/stream.c
+++ b/main/stream.c
@@ -349,6 +349,29 @@ int ast_stream_topology_set_stream(struct ast_stream_topology *topology,
return AST_VECTOR_REPLACE(&topology->streams, position, stream);
}
+int ast_stream_topology_del_stream(struct ast_stream_topology *topology,
+ unsigned int position)
+{
+ struct ast_stream *stream;
+
+ ast_assert(topology != NULL);
+
+ if (AST_VECTOR_SIZE(&topology->streams) <= position) {
+ return -1;
+ }
+
+ stream = AST_VECTOR_REMOVE_ORDERED(&topology->streams, position);
+ ast_stream_free(stream);
+
+ /* Fix up higher stream position indices */
+ for (; position < AST_VECTOR_SIZE(&topology->streams); ++position) {
+ stream = AST_VECTOR_GET(&topology->streams, position);
+ stream->position = position;
+ }
+
+ return 0;
+}
+
struct ast_stream_topology *ast_stream_topology_create_from_format_cap(
struct ast_format_cap *cap)
{
@@ -414,9 +437,11 @@ struct ast_format_cap *ast_format_cap_from_stream_topology(
}
for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
- struct ast_stream *stream = AST_VECTOR_GET(&topology->streams, i);
+ struct ast_stream *stream;
- if (!stream->formats) {
+ stream = AST_VECTOR_GET(&topology->streams, i);
+ if (!stream->formats
+ || stream->state == AST_STREAM_STATE_REMOVED) {
continue;
}
@@ -435,9 +460,11 @@ struct ast_stream *ast_stream_topology_get_first_stream_by_type(
ast_assert(topology != NULL);
for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
- struct ast_stream *stream = AST_VECTOR_GET(&topology->streams, i);
+ struct ast_stream *stream;
- if (stream->type == type) {
+ stream = AST_VECTOR_GET(&topology->streams, i);
+ if (stream->type == type
+ && stream->state != AST_STREAM_STATE_REMOVED) {
return stream;
}
}
diff --git a/tests/test_stream.c b/tests/test_stream.c
index a2a970181..fdb988584 100644
--- a/tests/test_stream.c
+++ b/tests/test_stream.c
@@ -529,6 +529,146 @@ AST_TEST_DEFINE(stream_topology_set_stream)
return AST_TEST_PASS;
}
+static int check_stream_positions(struct ast_test *test, const struct ast_stream_topology *topology)
+{
+ const struct ast_stream *stream;
+ int idx;
+ int pos;
+ enum ast_media_type type;
+
+ for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx) {
+ stream = ast_stream_topology_get_stream(topology, idx);
+ pos = ast_stream_get_position(stream);
+ if (idx != pos) {
+ type = ast_stream_get_type(stream);
+ ast_test_status_update(test, "Failed: '%s' stream says it is at position %d instead of %d\n",
+ ast_codec_media_type2str(type), pos, idx);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+AST_TEST_DEFINE(stream_topology_del_stream)
+{
+ RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
+ struct ast_stream *stream;
+ enum ast_media_type type;
+ int idx;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "stream_topology_del_stream";
+ info->category = "/main/stream/";
+ info->summary = "stream topology stream delete unit test";
+ info->description =
+ "Test that deleting streams at a specific position in a topology works";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ topology = ast_stream_topology_alloc();
+ if (!topology) {
+ ast_test_status_update(test, "Failed to create media stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ /* Create streams */
+ for (type = AST_MEDIA_TYPE_UNKNOWN; type < AST_MEDIA_TYPE_END; ++type) {
+ stream = ast_stream_alloc(ast_codec_media_type2str(type), type);
+ if (!stream) {
+ ast_test_status_update(test, "Failed to create '%s' stream for testing stream topology\n",
+ ast_codec_media_type2str(type));
+ return AST_TEST_FAIL;
+ }
+ if (ast_stream_topology_append_stream(topology, stream) == -1) {
+ ast_test_status_update(test, "Failed to append '%s' stream to topology\n",
+ ast_codec_media_type2str(type));
+ ast_stream_free(stream);
+ return AST_TEST_FAIL;
+ }
+ }
+
+ /* Check initial stream positions and types for sanity. */
+ type = AST_MEDIA_TYPE_UNKNOWN;
+ for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx, ++type) {
+ stream = ast_stream_topology_get_stream(topology, idx);
+ if (type != ast_stream_get_type(stream)) {
+ ast_test_status_update(test, "Initial topology types failed: Expected:%s Got:%s\n",
+ ast_codec_media_type2str(type),
+ ast_codec_media_type2str(ast_stream_get_type(stream)));
+ return AST_TEST_FAIL;
+ }
+ }
+ if (check_stream_positions(test, topology)) {
+ ast_test_status_update(test, "Initial topology positions failed.\n");
+ return AST_TEST_FAIL;
+ }
+
+ /* Try to delete outside of topology size */
+ if (!ast_stream_topology_del_stream(topology, ast_stream_topology_get_count(topology))) {
+ ast_test_status_update(test, "Deleting stream outside of topology succeeded!\n");
+ return AST_TEST_FAIL;
+ }
+
+ /* Try to delete the last topology stream */
+ if (ast_stream_topology_del_stream(topology, ast_stream_topology_get_count(topology) - 1)) {
+ ast_test_status_update(test, "Failed deleting last stream of topology.\n");
+ return AST_TEST_FAIL;
+ }
+ if (check_stream_positions(test, topology)) {
+ ast_test_status_update(test, "Last stream delete topology positions failed.\n");
+ return AST_TEST_FAIL;
+ }
+ stream = ast_stream_topology_get_stream(topology, ast_stream_topology_get_count(topology) - 1);
+ type = ast_stream_get_type(stream);
+ if (type != AST_MEDIA_TYPE_END - 2) {
+ ast_test_status_update(test, "Last stream delete types failed: Expected:%s Got:%s\n",
+ ast_codec_media_type2str(AST_MEDIA_TYPE_END - 2),
+ ast_codec_media_type2str(type));
+ return AST_TEST_FAIL;
+ }
+
+ /* Try to delete the second stream in the topology */
+ if (ast_stream_topology_del_stream(topology, 1)) {
+ ast_test_status_update(test, "Failed deleting second stream in topology.\n");
+ return AST_TEST_FAIL;
+ }
+ if (check_stream_positions(test, topology)) {
+ ast_test_status_update(test, "Second stream delete topology positions failed.\n");
+ return AST_TEST_FAIL;
+ }
+ stream = ast_stream_topology_get_stream(topology, 1);
+ type = ast_stream_get_type(stream);
+ if (type != AST_MEDIA_TYPE_UNKNOWN + 2) {
+ ast_test_status_update(test, "Second stream delete types failed: Expected:%s Got:%s\n",
+ ast_codec_media_type2str(AST_MEDIA_TYPE_UNKNOWN + 2),
+ ast_codec_media_type2str(type));
+ return AST_TEST_FAIL;
+ }
+
+ /* Try to delete the first stream in the topology */
+ if (ast_stream_topology_del_stream(topology, 0)) {
+ ast_test_status_update(test, "Failed deleting first stream in topology.\n");
+ return AST_TEST_FAIL;
+ }
+ if (check_stream_positions(test, topology)) {
+ ast_test_status_update(test, "First stream delete topology positions failed.\n");
+ return AST_TEST_FAIL;
+ }
+ stream = ast_stream_topology_get_stream(topology, 0);
+ type = ast_stream_get_type(stream);
+ if (type != AST_MEDIA_TYPE_UNKNOWN + 2) {
+ ast_test_status_update(test, "First stream delete types failed: Expected:%s Got:%s\n",
+ ast_codec_media_type2str(AST_MEDIA_TYPE_UNKNOWN + 2),
+ ast_codec_media_type2str(type));
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
AST_TEST_DEFINE(stream_topology_create_from_format_cap)
{
RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
@@ -615,7 +755,12 @@ AST_TEST_DEFINE(stream_topology_create_from_format_cap)
AST_TEST_DEFINE(stream_topology_get_first_stream_by_type)
{
RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
- struct ast_stream *first_stream, *second_stream, *third_stream, *fourth_stream;
+ struct ast_stream *first_stream;
+ struct ast_stream *second_stream;
+ struct ast_stream *third_stream;
+ struct ast_stream *fourth_stream;
+ struct ast_stream *fifth_stream;
+ struct ast_stream *sixth_stream;
switch (cmd) {
case TEST_INIT:
@@ -640,6 +785,7 @@ AST_TEST_DEFINE(stream_topology_get_first_stream_by_type)
ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
return AST_TEST_FAIL;
}
+ ast_stream_set_state(first_stream, AST_STREAM_STATE_REMOVED);
if (ast_stream_topology_append_stream(topology, first_stream) == -1) {
ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
@@ -659,9 +805,9 @@ AST_TEST_DEFINE(stream_topology_get_first_stream_by_type)
return AST_TEST_FAIL;
}
- third_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
+ third_stream = ast_stream_alloc("audio3", AST_MEDIA_TYPE_AUDIO);
if (!third_stream) {
- ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
+ ast_test_status_update(test, "Failed to create a third audio stream for testing stream topology\n");
return AST_TEST_FAIL;
}
@@ -671,11 +817,12 @@ AST_TEST_DEFINE(stream_topology_get_first_stream_by_type)
return AST_TEST_FAIL;
}
- fourth_stream = ast_stream_alloc("video2", AST_MEDIA_TYPE_VIDEO);
+ fourth_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
if (!fourth_stream) {
- ast_test_status_update(test, "Failed to create a second video stream for testing stream topology\n");
+ ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
return AST_TEST_FAIL;
}
+ ast_stream_set_state(fourth_stream, AST_STREAM_STATE_REMOVED);
if (ast_stream_topology_append_stream(topology, fourth_stream) == -1) {
ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
@@ -683,12 +830,36 @@ AST_TEST_DEFINE(stream_topology_get_first_stream_by_type)
return AST_TEST_FAIL;
}
- if (ast_stream_topology_get_first_stream_by_type(topology, AST_MEDIA_TYPE_AUDIO) != first_stream) {
+ fifth_stream = ast_stream_alloc("video2", AST_MEDIA_TYPE_VIDEO);
+ if (!fifth_stream) {
+ ast_test_status_update(test, "Failed to create a second video stream for testing stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_append_stream(topology, fifth_stream) == -1) {
+ ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
+ ast_stream_free(fifth_stream);
+ return AST_TEST_FAIL;
+ }
+
+ sixth_stream = ast_stream_alloc("video3", AST_MEDIA_TYPE_VIDEO);
+ if (!sixth_stream) {
+ ast_test_status_update(test, "Failed to create a third video stream for testing stream topology\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_append_stream(topology, sixth_stream) == -1) {
+ ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
+ ast_stream_free(sixth_stream);
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_stream_topology_get_first_stream_by_type(topology, AST_MEDIA_TYPE_AUDIO) != second_stream) {
ast_test_status_update(test, "Retrieved first audio stream from topology but it is not the correct one\n");
return AST_TEST_FAIL;
}
- if (ast_stream_topology_get_first_stream_by_type(topology, AST_MEDIA_TYPE_VIDEO) != third_stream) {
+ if (ast_stream_topology_get_first_stream_by_type(topology, AST_MEDIA_TYPE_VIDEO) != fifth_stream) {
ast_test_status_update(test, "Retrieved first video stream from topology but it is not the correct one\n");
return AST_TEST_FAIL;
}
@@ -1778,6 +1949,8 @@ AST_TEST_DEFINE(format_cap_from_stream_topology)
RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
RAII_VAR(struct ast_format_cap *, stream_caps, NULL, ao2_cleanup);
struct ast_stream_topology *topology;
+ struct ast_stream *stream;
+ struct ast_format_cap *new_cap;
switch (cmd) {
case TEST_INIT:
@@ -1798,12 +1971,12 @@ AST_TEST_DEFINE(format_cap_from_stream_topology)
}
if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
- ast_test_status_update(test, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
+ ast_test_status_update(test, "Failed to append ulaw format to capabilities\n");
return AST_TEST_FAIL;
}
if (ast_format_cap_append(caps, ast_format_h264, 0)) {
- ast_test_status_update(test, "Failed to append an h264 format to capabilities for channel nativeformats\n");
+ ast_test_status_update(test, "Failed to append h264 format to capabilities\n");
return AST_TEST_FAIL;
}
@@ -1813,6 +1986,40 @@ AST_TEST_DEFINE(format_cap_from_stream_topology)
return AST_TEST_FAIL;
}
+ /*
+ * Append declined stream with formats that should not be included
+ * in combined topology caps.
+ */
+ stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
+ if (!stream) {
+ ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
+ ast_stream_topology_free(topology);
+ return AST_TEST_FAIL;
+ }
+ ast_stream_set_state(stream, AST_STREAM_STATE_REMOVED);
+ new_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!new_cap) {
+ ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
+ ast_stream_free(stream);
+ ast_stream_topology_free(topology);
+ return AST_TEST_FAIL;
+ }
+ if (ast_format_cap_append(new_cap, ast_format_alaw, 0)) {
+ ast_test_status_update(test, "Failed to append alaw format to capabilities\n");
+ ao2_cleanup(new_cap);
+ ast_stream_free(stream);
+ ast_stream_topology_free(topology);
+ return AST_TEST_FAIL;
+ }
+ ast_stream_set_formats(stream, new_cap);
+ ao2_cleanup(new_cap);
+ if (ast_stream_topology_append_stream(topology, stream) == -1) {
+ ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
+ ast_stream_free(stream);
+ ast_stream_topology_free(topology);
+ return AST_TEST_FAIL;
+ }
+
stream_caps = ast_format_cap_from_stream_topology(topology);
if (!stream_caps) {
ast_test_status_update(test, "Failed to create a format capabilities from a stream topology\n");
@@ -1933,6 +2140,7 @@ static int unload_module(void)
AST_TEST_UNREGISTER(stream_topology_clone);
AST_TEST_UNREGISTER(stream_topology_append_stream);
AST_TEST_UNREGISTER(stream_topology_set_stream);
+ AST_TEST_UNREGISTER(stream_topology_del_stream);
AST_TEST_UNREGISTER(stream_topology_create_from_format_cap);
AST_TEST_UNREGISTER(stream_topology_get_first_stream_by_type);
AST_TEST_UNREGISTER(stream_topology_create_from_channel_nativeformats);
@@ -1961,6 +2169,7 @@ static int load_module(void)
AST_TEST_REGISTER(stream_topology_clone);
AST_TEST_REGISTER(stream_topology_append_stream);
AST_TEST_REGISTER(stream_topology_set_stream);
+ AST_TEST_REGISTER(stream_topology_del_stream);
AST_TEST_REGISTER(stream_topology_create_from_format_cap);
AST_TEST_REGISTER(stream_topology_get_first_stream_by_type);
AST_TEST_REGISTER(stream_topology_create_from_channel_nativeformats);