<p>Jenkins2 <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/5814">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  Kevin Harwell: Looks good to me, approved
  Jenkins2: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">stream: Add ast_stream_topology_del_stream() and unit test.<br><br>Change-Id: If07e3c716a2e3ff85ae905c17572ea6ec3cdc1f9<br>---<br>M include/asterisk/stream.h<br>M main/stream.c<br>M tests/test_stream.c<br>3 files changed, 184 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/include/asterisk/stream.h b/include/asterisk/stream.h<br>index fcee3e4..14d624f 100644<br>--- a/include/asterisk/stream.h<br>+++ b/include/asterisk/stream.h<br>@@ -359,6 +359,25 @@<br>    unsigned int position, struct ast_stream *stream);<br> <br> /*!<br>+ * \brief Delete a specified stream from the given topology.<br>+ * \since 15.0.0<br>+ *<br>+ * \param topology The topology of streams.<br>+ * \param position The topology position to delete.<br>+ *<br>+ * \note Deleting a stream will completely remove it from the topology<br>+ * as if it never existed in it.  i.e., Any following stream positions<br>+ * will shift down so there is no gap.<br>+ *<br>+ * \retval 0 on success.<br>+ * \retval -1 on failure.<br>+ *<br>+ * \return Nothing<br>+ */<br>+int ast_stream_topology_del_stream(struct ast_stream_topology *topology,<br>+        unsigned int position);<br>+<br>+/*!<br>  * \brief A helper function that, given a format capabilities structure,<br>  * creates a topology and separates the media types in format_cap into<br>  * separate streams.<br>diff --git a/main/stream.c b/main/stream.c<br>index fb14693..b617744 100644<br>--- a/main/stream.c<br>+++ b/main/stream.c<br>@@ -349,6 +349,29 @@<br>        return AST_VECTOR_REPLACE(&topology->streams, position, stream);<br> }<br> <br>+int ast_stream_topology_del_stream(struct ast_stream_topology *topology,<br>+    unsigned int position)<br>+{<br>+   struct ast_stream *stream;<br>+<br>+        ast_assert(topology != NULL);<br>+<br>+     if (AST_VECTOR_SIZE(&topology->streams) <= position) {<br>+             return -1;<br>+   }<br>+<br>+ stream = AST_VECTOR_REMOVE_ORDERED(&topology->streams, position);<br>+     ast_stream_free(stream);<br>+<br>+  /* Fix up higher stream position indices */<br>+  for (; position < AST_VECTOR_SIZE(&topology->streams); ++position) {<br>+               stream = AST_VECTOR_GET(&topology->streams, position);<br>+                stream->position = position;<br>+      }<br>+<br>+ return 0;<br>+}<br>+<br> struct ast_stream_topology *ast_stream_topology_create_from_format_cap(<br>    struct ast_format_cap *cap)<br> {<br>diff --git a/tests/test_stream.c b/tests/test_stream.c<br>index a2a9701..cf3d2e3 100644<br>--- a/tests/test_stream.c<br>+++ b/tests/test_stream.c<br>@@ -529,6 +529,146 @@<br>   return AST_TEST_PASS;<br> }<br> <br>+static int check_stream_positions(struct ast_test *test, const struct ast_stream_topology *topology)<br>+{<br>+      const struct ast_stream *stream;<br>+     int idx;<br>+     int pos;<br>+     enum ast_media_type type;<br>+<br>+ for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx) {<br>+             stream = ast_stream_topology_get_stream(topology, idx);<br>+              pos = ast_stream_get_position(stream);<br>+               if (idx != pos) {<br>+                    type = ast_stream_get_type(stream);<br>+                  ast_test_status_update(test, "Failed: '%s' stream says it is at position %d instead of %d\n",<br>+                              ast_codec_media_type2str(type), pos, idx);<br>+                   return -1;<br>+           }<br>+    }<br>+    return 0;<br>+}<br>+<br>+AST_TEST_DEFINE(stream_topology_del_stream)<br>+{<br>+   RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);<br>+    struct ast_stream *stream;<br>+   enum ast_media_type type;<br>+    int idx;<br>+<br>+  switch (cmd) {<br>+       case TEST_INIT:<br>+              info->name = "stream_topology_del_stream";<br>+              info->category = "/main/stream/";<br>+               info->summary = "stream topology stream delete unit test";<br>+              info->description =<br>+                       "Test that deleting streams at a specific position in a topology works";<br>+           return AST_TEST_NOT_RUN;<br>+     case TEST_EXECUTE:<br>+           break;<br>+       }<br>+<br>+ topology = ast_stream_topology_alloc();<br>+      if (!topology) {<br>+             ast_test_status_update(test, "Failed to create media stream topology\n");<br>+          return AST_TEST_FAIL;<br>+        }<br>+<br>+ /* Create streams */<br>+ for (type = AST_MEDIA_TYPE_UNKNOWN; type < AST_MEDIA_TYPE_END; ++type) {<br>+          stream = ast_stream_alloc(ast_codec_media_type2str(type), type);<br>+             if (!stream) {<br>+                       ast_test_status_update(test, "Failed to create '%s' stream for testing stream topology\n",<br>+                         ast_codec_media_type2str(type));<br>+                     return AST_TEST_FAIL;<br>+                }<br>+            if (ast_stream_topology_append_stream(topology, stream) == -1) {<br>+                     ast_test_status_update(test, "Failed to append '%s' stream to topology\n",<br>+                         ast_codec_media_type2str(type));<br>+                     ast_stream_free(stream);<br>+                     return AST_TEST_FAIL;<br>+                }<br>+    }<br>+<br>+ /* Check initial stream positions and types for sanity. */<br>+   type = AST_MEDIA_TYPE_UNKNOWN;<br>+       for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx, ++type) {<br>+             stream = ast_stream_topology_get_stream(topology, idx);<br>+              if (type != ast_stream_get_type(stream)) {<br>+                   ast_test_status_update(test, "Initial topology types failed: Expected:%s Got:%s\n",<br>+                                ast_codec_media_type2str(type),<br>+                              ast_codec_media_type2str(ast_stream_get_type(stream)));<br>+                      return AST_TEST_FAIL;<br>+                }<br>+    }<br>+    if (check_stream_positions(test, topology)) {<br>+                ast_test_status_update(test, "Initial topology positions failed.\n");<br>+              return AST_TEST_FAIL;<br>+        }<br>+<br>+ /* Try to delete outside of topology size */<br>+ if (!ast_stream_topology_del_stream(topology, ast_stream_topology_get_count(topology))) {<br>+            ast_test_status_update(test, "Deleting stream outside of topology succeeded!\n");<br>+          return AST_TEST_FAIL;<br>+        }<br>+<br>+ /* Try to delete the last topology stream */<br>+ if (ast_stream_topology_del_stream(topology, ast_stream_topology_get_count(topology) - 1)) {<br>+         ast_test_status_update(test, "Failed deleting last stream of topology.\n");<br>+                return AST_TEST_FAIL;<br>+        }<br>+    if (check_stream_positions(test, topology)) {<br>+                ast_test_status_update(test, "Last stream delete topology positions failed.\n");<br>+           return AST_TEST_FAIL;<br>+        }<br>+    stream = ast_stream_topology_get_stream(topology, ast_stream_topology_get_count(topology) - 1);<br>+      type = ast_stream_get_type(stream);<br>+  if (type != AST_MEDIA_TYPE_END - 2) {<br>+                ast_test_status_update(test, "Last stream delete types failed: Expected:%s Got:%s\n",<br>+                      ast_codec_media_type2str(AST_MEDIA_TYPE_END - 2),<br>+                    ast_codec_media_type2str(type));<br>+             return AST_TEST_FAIL;<br>+        }<br>+<br>+ /* Try to delete the second stream in the topology */<br>+        if (ast_stream_topology_del_stream(topology, 1)) {<br>+           ast_test_status_update(test, "Failed deleting second stream in topology.\n");<br>+              return AST_TEST_FAIL;<br>+        }<br>+    if (check_stream_positions(test, topology)) {<br>+                ast_test_status_update(test, "Second stream delete topology positions failed.\n");<br>+         return AST_TEST_FAIL;<br>+        }<br>+    stream = ast_stream_topology_get_stream(topology, 1);<br>+        type = ast_stream_get_type(stream);<br>+  if (type != AST_MEDIA_TYPE_UNKNOWN + 2) {<br>+            ast_test_status_update(test, "Second stream delete types failed: Expected:%s Got:%s\n",<br>+                    ast_codec_media_type2str(AST_MEDIA_TYPE_UNKNOWN + 2),<br>+                        ast_codec_media_type2str(type));<br>+             return AST_TEST_FAIL;<br>+        }<br>+<br>+ /* Try to delete the first stream in the topology */<br>+ if (ast_stream_topology_del_stream(topology, 0)) {<br>+           ast_test_status_update(test, "Failed deleting first stream in topology.\n");<br>+               return AST_TEST_FAIL;<br>+        }<br>+    if (check_stream_positions(test, topology)) {<br>+                ast_test_status_update(test, "First stream delete topology positions failed.\n");<br>+          return AST_TEST_FAIL;<br>+        }<br>+    stream = ast_stream_topology_get_stream(topology, 0);<br>+        type = ast_stream_get_type(stream);<br>+  if (type != AST_MEDIA_TYPE_UNKNOWN + 2) {<br>+            ast_test_status_update(test, "First stream delete types failed: Expected:%s Got:%s\n",<br>+                     ast_codec_media_type2str(AST_MEDIA_TYPE_UNKNOWN + 2),<br>+                        ast_codec_media_type2str(type));<br>+             return AST_TEST_FAIL;<br>+        }<br>+<br>+ return AST_TEST_PASS;<br>+}<br>+<br> AST_TEST_DEFINE(stream_topology_create_from_format_cap)<br> {<br>    RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);<br>@@ -1933,6 +2073,7 @@<br>      AST_TEST_UNREGISTER(stream_topology_clone);<br>   AST_TEST_UNREGISTER(stream_topology_append_stream);<br>   AST_TEST_UNREGISTER(stream_topology_set_stream);<br>+     AST_TEST_UNREGISTER(stream_topology_del_stream);<br>      AST_TEST_UNREGISTER(stream_topology_create_from_format_cap);<br>  AST_TEST_UNREGISTER(stream_topology_get_first_stream_by_type);<br>        AST_TEST_UNREGISTER(stream_topology_create_from_channel_nativeformats);<br>@@ -1961,6 +2102,7 @@<br>        AST_TEST_REGISTER(stream_topology_clone);<br>     AST_TEST_REGISTER(stream_topology_append_stream);<br>     AST_TEST_REGISTER(stream_topology_set_stream);<br>+       AST_TEST_REGISTER(stream_topology_del_stream);<br>        AST_TEST_REGISTER(stream_topology_create_from_format_cap);<br>    AST_TEST_REGISTER(stream_topology_get_first_stream_by_type);<br>  AST_TEST_REGISTER(stream_topology_create_from_channel_nativeformats);<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/5814">change 5814</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/5814"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: If07e3c716a2e3ff85ae905c17572ea6ec3cdc1f9 </div>
<div style="display:none"> Gerrit-Change-Number: 5814 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Richard Mudgett <rmudgett@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Richard Mudgett <rmudgett@digium.com> </div>