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

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_rtp: Add unit tests for RTCP stats.<br><br>Added unit tests for RTCP video stats. These tests include NACK, REMB,<br>FIR/FUR/PLI, SR/RR/SDES, and packet loss statistics. The REMB and FIR<br>tests are currently disabled due to a bug. We expect to receive a<br>compound packet, but the code sends this out as a single packet, which<br>the browser accepts, but makes Asterisk upset.<br><br>While writing these tests, I noticed an issue with NACK as well. Where<br>it is handling a received NACK request, it was reading in only the first<br>8 bits of following packets that were also lost. This has been changed<br>to the correct value of 16 bits.<br><br>Also made a minor fix to the data buffer unit test.<br><br>Change-Id: I56107c7411003a247589bbb6086d25c54719901b<br>---<br>M include/asterisk/rtp_engine.h<br>M main/rtp_engine.c<br>M res/res_rtp_asterisk.c<br>M tests/test_data_buffer.c<br>A tests/test_res_rtp.c<br>5 files changed, 831 insertions(+), 6 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h</span><br><span>index 206ed63..57f29b4 100644</span><br><span>--- a/include/asterisk/rtp_engine.h</span><br><span>+++ b/include/asterisk/rtp_engine.h</span><br><span>@@ -589,6 +589,26 @@</span><br><span>       const char *(*get_fingerprint)(struct ast_rtp_instance *instance);</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Structure that represents the test functionality for res_rtp_asterisk unit tests */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_rtp_engine_test {</span><br><span style="color: hsl(120, 100%, 40%);">+     /*! Drops RTP packets while this has a value greater than 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+        int packets_to_drop;</span><br><span style="color: hsl(120, 100%, 40%);">+  /*! Sends a SR/RR instead of RTP the next time RTP would be sent */</span><br><span style="color: hsl(120, 100%, 40%);">+   int send_report;</span><br><span style="color: hsl(120, 100%, 40%);">+      /*! Set to 1 whenever SDES is received */</span><br><span style="color: hsl(120, 100%, 40%);">+     int sdes_received;</span><br><span style="color: hsl(120, 100%, 40%);">+    /*! Get the number of packets in the receive buffer for a RTP instance */</span><br><span style="color: hsl(120, 100%, 40%);">+     size_t (*recv_buffer_count)(struct ast_rtp_instance *instance);</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! Get the maximum number of packets the receive buffer can hold for a RTP instance */</span><br><span style="color: hsl(120, 100%, 40%);">+       size_t (*recv_buffer_max)(struct ast_rtp_instance *instance);</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Get the number of packets in the send buffer for a RTP instance */</span><br><span style="color: hsl(120, 100%, 40%);">+        size_t (*send_buffer_count)(struct ast_rtp_instance *instance);</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! Set the schedid for RTCP */</span><br><span style="color: hsl(120, 100%, 40%);">+       void (*set_schedid)(struct ast_rtp_instance *instance, int id);</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Structure that represents an RTP stack (engine) */</span><br><span> struct ast_rtp_engine {</span><br><span>   /*! Name of the RTP engine, used when explicitly requested */</span><br><span>@@ -670,6 +690,10 @@</span><br><span>         struct ast_rtp_engine_ice *ice;</span><br><span>      /*! Callback to pointer for optional DTLS SRTP support */</span><br><span>    struct ast_rtp_engine_dtls *dtls;</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+      /*! Callback to pointer for test callbacks for RTP/RTCP unit tests */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_rtp_engine_test *test;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>    /*! Callback to enable an RTP extension (returns non-zero if supported) */</span><br><span>   int (*extension_enable)(struct ast_rtp_instance *instance, enum ast_rtp_extension extension);</span><br><span>        /*! Linked list information */</span><br><span>@@ -2513,6 +2537,18 @@</span><br><span>  */</span><br><span> struct ast_rtp_engine_ice *ast_rtp_instance_get_ice(struct ast_rtp_instance *instance);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Obtain a pointer to the test callbacks on an RTP instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param instance the RTP instance</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval test callbacks if present</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL if not present</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_rtp_engine_test *ast_rtp_instance_get_test(struct ast_rtp_instance *instance);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span>  * \brief Obtain a pointer to the DTLS support present on an RTP instance</span><br><span>  *</span><br><span>@@ -2686,6 +2722,70 @@</span><br><span>  */</span><br><span> struct stasis_message_type *ast_rtp_rtcp_received_type(void);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the maximum size of the receive buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param instance The RTP instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval The recv_buffer max size if it exists, else 0</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+size_t ast_rtp_instance_get_recv_buffer_max(struct ast_rtp_instance *instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the current size of the receive buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param instance The RTP instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval The recv_buffer size if it exists, else 0</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+size_t ast_rtp_instance_get_recv_buffer_count(struct ast_rtp_instance *instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the current size of the send buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param instance The RTP instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval The send_buffer size if it exists, else 0</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+size_t ast_rtp_instance_get_send_buffer_count(struct ast_rtp_instance *instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Set the schedid for RTCP</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param instance The RTP instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param id The number to set schedid to</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_rtp_instance_set_schedid(struct ast_rtp_instance *instance, int id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Set the number of packets to drop on RTP read</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param instance The RTP instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param num The number of packets to drop</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_rtp_instance_drop_packets(struct ast_rtp_instance *instance, int num);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Sends a SR/RR report the next time RTP would be sent</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param instance The RTP instance</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_rtp_instance_queue_report(struct ast_rtp_instance *instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the value of sdes_received on the test engine</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param instance The RTP instance</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 1 if sdes_received, else 0</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_rtp_instance_get_sdes_received(struct ast_rtp_instance *instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Resets all the fields to default values for the test engine</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param instance The RTP instance</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_rtp_instance_reset_test_engine(struct ast_rtp_instance *instance);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span>  * \brief Convert given stat instance into json format</span><br><span>  * \param stats</span><br><span>diff --git a/main/rtp_engine.c b/main/rtp_engine.c</span><br><span>index 39ad1b3..3403d70 100644</span><br><span>--- a/main/rtp_engine.c</span><br><span>+++ b/main/rtp_engine.c</span><br><span>@@ -457,7 +457,7 @@</span><br><span> </span><br><span> int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   ao2_ref(instance, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+        ao2_cleanup(instance);</span><br><span> </span><br><span>   return 0;</span><br><span> }</span><br><span>@@ -2897,6 +2897,13 @@</span><br><span>      return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_rtp_engine_test *ast_rtp_instance_get_test(struct ast_rtp_instance *instance)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     return instance->engine->test;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int rtp_dtls_wrap_set_configuration(struct ast_rtp_instance *instance,</span><br><span>   const struct ast_rtp_dtls_cfg *dtls_cfg)</span><br><span> {</span><br><span>@@ -3759,6 +3766,123 @@</span><br><span>      ao2_unlock(rtp);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+size_t ast_rtp_instance_get_recv_buffer_max(struct ast_rtp_instance *instance)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   size_t res;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!test) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "There is no test engine set up!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ao2_lock(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+   res = test->recv_buffer_max(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_unlock(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+size_t ast_rtp_instance_get_recv_buffer_count(struct ast_rtp_instance *instance)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t res;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!test) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "There is no test engine set up!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ao2_lock(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+   res = test->recv_buffer_count(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+   ao2_unlock(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+size_t ast_rtp_instance_get_send_buffer_count(struct ast_rtp_instance *instance)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t res;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!test) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "There is no test engine set up!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ao2_lock(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+   res = test->send_buffer_count(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+   ao2_unlock(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_rtp_instance_set_schedid(struct ast_rtp_instance *instance, int id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!test) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "There is no test engine set up!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ao2_lock(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+   test->set_schedid(instance, id);</span><br><span style="color: hsl(120, 100%, 40%);">+   ao2_unlock(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_rtp_instance_drop_packets(struct ast_rtp_instance *instance, int num)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!test) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "There is no test engine set up!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test->packets_to_drop = num;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_rtp_instance_queue_report(struct ast_rtp_instance *instance)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!test) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "There is no test engine set up!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test->send_report = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_rtp_instance_get_sdes_received(struct ast_rtp_instance *instance)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!test) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "There is no test engine set up!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return test->sdes_received;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_rtp_instance_reset_test_engine(struct ast_rtp_instance *instance)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!test) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "There is no test engine set up!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test->packets_to_drop = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ test->send_report = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     test->sdes_received = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct ast_json *ast_rtp_convert_stats_json(const struct ast_rtp_instance_stats *stats)</span><br><span> {</span><br><span>     struct ast_json *j_res;</span><br><span>diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c</span><br><span>index 08138cb..5da095e 100644</span><br><span>--- a/res/res_rtp_asterisk.c</span><br><span>+++ b/res/res_rtp_asterisk.c</span><br><span>@@ -2371,6 +2371,60 @@</span><br><span> </span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+static size_t get_recv_buffer_count(struct ast_rtp_instance *instance)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rtp && rtp->recv_buffer) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return ast_data_buffer_count(rtp->recv_buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static size_t get_recv_buffer_max(struct ast_rtp_instance *instance)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rtp && rtp->recv_buffer) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return ast_data_buffer_max(rtp->recv_buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static size_t get_send_buffer_count(struct ast_rtp_instance *instance)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rtp && rtp->send_buffer) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return ast_data_buffer_count(rtp->send_buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void set_rtp_rtcp_schedid(struct ast_rtp_instance *instance, int id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rtp && rtp->rtcp) {</span><br><span style="color: hsl(120, 100%, 40%);">+            rtp->rtcp->schedid = id;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_rtp_engine_test ast_rtp_test = {</span><br><span style="color: hsl(120, 100%, 40%);">+    .packets_to_drop = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ .send_report = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+     .sdes_received = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+   .recv_buffer_count = get_recv_buffer_count,</span><br><span style="color: hsl(120, 100%, 40%);">+   .recv_buffer_max = get_recv_buffer_max,</span><br><span style="color: hsl(120, 100%, 40%);">+       .send_buffer_count = get_send_buffer_count,</span><br><span style="color: hsl(120, 100%, 40%);">+   .set_schedid = set_rtp_rtcp_schedid,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* RTP Engine Declaration */</span><br><span> static struct ast_rtp_engine asterisk_rtp_engine = {</span><br><span>   .name = "asterisk",</span><br><span>@@ -2410,6 +2464,9 @@</span><br><span>        .set_stream_num = ast_rtp_set_stream_num,</span><br><span>    .extension_enable = ast_rtp_extension_enable,</span><br><span>        .bundle = ast_rtp_bundle,</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+      .test = &ast_rtp_test,</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> };</span><br><span> </span><br><span> #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)</span><br><span>@@ -2923,11 +2980,21 @@</span><br><span> #ifdef HAVE_PJPROJECT</span><br><span>      struct ast_sockaddr *loop = rtcp ? &rtp->rtcp_loop : &rtp->rtp_loop;</span><br><span> #endif</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span>  if ((len = ast_recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa)) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-    return len;</span><br><span style="color: hsl(120, 100%, 40%);">+                return len;</span><br><span>  }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+  if (test && test->packets_to_drop > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                test->packets_to_drop--;</span><br><span style="color: hsl(120, 100%, 40%);">+           return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)</span><br><span>  /* If this is an SSL packet pass it to OpenSSL for processing. RFC section for first byte value:</span><br><span>      * https://tools.ietf.org/html/rfc5764#section-5.1.2 */</span><br><span>@@ -4595,6 +4662,9 @@</span><br><span>      struct ast_sockaddr remote_address = { {0,} };</span><br><span>       int rate = rtp_get_rate(frame->subclass.format) / 1000;</span><br><span>   unsigned int seqno;</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span>  if (ast_format_cmp(frame->subclass.format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) {</span><br><span>            frame->samples /= 2;</span><br><span>@@ -4604,6 +4674,14 @@</span><br><span>             return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+  if (test && test->send_report) {</span><br><span style="color: hsl(120, 100%, 40%);">+           test->send_report = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_rtcp_write(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (frame->frametype == AST_FRAME_VOICE) {</span><br><span>                pred = rtp->lastts + frame->samples;</span><br><span> </span><br><span>@@ -5641,7 +5719,7 @@</span><br><span>                * packet (pid+i)(modulo 2^16). Otherwise, it is set to 0. We cannot assume bits set</span><br><span>                  * to 0 after a bit set to 1 have actually been received.</span><br><span>             */</span><br><span style="color: hsl(0, 100%, 40%);">-             blp = current_word & 0xFF;</span><br><span style="color: hsl(120, 100%, 40%);">+                blp = current_word & 0xffff;</span><br><span>             blp_index = 1;</span><br><span>               while (blp) {</span><br><span>                        if (blp & 1) {</span><br><span>@@ -5721,6 +5799,9 @@</span><br><span>   unsigned int ssrc_seen;</span><br><span>      struct ast_rtp_rtcp_report_block *report_block;</span><br><span>      struct ast_frame *f = &ast_null_frame;</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_rtp_engine_test *test_engine;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> </span><br><span>         /* If this is encrypted then decrypt the payload */</span><br><span>  if ((*rtcpheader & 0xC0) && res_srtp && srtp && res_srtp->unprotect(</span><br><span>@@ -6161,6 +6242,11 @@</span><br><span>                                 ast_verbose("Received an SDES from %s\n",</span><br><span>                                  ast_sockaddr_stringify(addr));</span><br><span>                       }</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+                      if ((test_engine = ast_rtp_instance_get_test(instance))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            test_engine->sdes_received = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                    }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span>                    break;</span><br><span>               case RTCP_PT_BYE:</span><br><span>                    if (rtcp_debug_test_addr(addr)) {</span><br><span>@@ -7656,11 +7742,10 @@</span><br><span>                  if (res < 0) {</span><br><span>                            ast_debug(1, "Failed to send NACK request out\n");</span><br><span>                         } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_debug(2, "Sending a NACK request on RTP instance '%p' to get missing packets\n", instance);</span><br><span>                            /* Update RTCP SR/RR statistics */</span><br><span>                           ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, remote_address, ice, sr);</span><br><span>                         }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_debug(2, "Sending a NACK request on RTP instance '%p' to get missing packets\n", instance);</span><br><span>            }</span><br><span> </span><br><span>                return &ast_null_frame;</span><br><span>diff --git a/tests/test_data_buffer.c b/tests/test_data_buffer.c</span><br><span>index 93c2c06..2fd56e1 100644</span><br><span>--- a/tests/test_data_buffer.c</span><br><span>+++ b/tests/test_data_buffer.c</span><br><span>@@ -18,7 +18,7 @@</span><br><span> </span><br><span> /*!</span><br><span>  * \file</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Media Stream API Unit Tests</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Data Buffer API Unit Tests</span><br><span>  *</span><br><span>  * \author Ben Ford <bford@digium.com></span><br><span>  *</span><br><span>diff --git a/tests/test_res_rtp.c b/tests/test_res_rtp.c</span><br><span>new file mode 100644</span><br><span>index 0000000..ecedb4f</span><br><span>--- /dev/null</span><br><span>+++ b/tests/test_res_rtp.c</span><br><span>@@ -0,0 +1,516 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2019, Sangoma, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Ben Ford <bford@sangoma.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(120, 100%, 40%);">+ * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(120, 100%, 40%);">+ * channels for your use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(120, 100%, 40%);">+ * at the top of the source tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief RTP/RTCP Unit Tests</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \author Ben Ford <bford@digium.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*** MODULEINFO</span><br><span style="color: hsl(120, 100%, 40%);">+     <depend>TEST_FRAMEWORK</depend></span><br><span style="color: hsl(120, 100%, 40%);">+   <support_level>core</support_level></span><br><span style="color: hsl(120, 100%, 40%);">+ ***/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/module.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/test.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/rtp_engine.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/data_buffer.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/format_cache.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum test_type {</span><br><span style="color: hsl(120, 100%, 40%);">+  TEST_TYPE_NONE = 0,     /* No special setup required */</span><br><span style="color: hsl(120, 100%, 40%);">+       TEST_TYPE_NACK,         /* Enable NACK */</span><br><span style="color: hsl(120, 100%, 40%);">+     TEST_TYPE_REMB,         /* Enable REMB */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void ast_sched_context_destroy_wrapper(struct ast_sched_context *sched)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    if (sched) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_sched_context_destroy(sched);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int test_init_rtp_instances(struct ast_rtp_instance **instance1,</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_rtp_instance **instance2, struct ast_sched_context *test_sched,</span><br><span style="color: hsl(120, 100%, 40%);">+    enum test_type type)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_sockaddr addr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_sockaddr_parse(&addr, "127.0.0.1", 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    *instance1 = ast_rtp_instance_new("asterisk", test_sched, &addr, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ *instance2 = ast_rtp_instance_new("asterisk", test_sched, &addr, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!instance1 || !instance2) {</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_rtp_instance_set_prop(*instance1, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_MUX);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_rtp_instance_set_prop(*instance2, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_MUX);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (type == TEST_TYPE_NACK) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_rtp_instance_set_prop(*instance1, AST_RTP_PROPERTY_RETRANS_RECV, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_rtp_instance_set_prop(*instance1, AST_RTP_PROPERTY_RETRANS_SEND, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_rtp_instance_set_prop(*instance2, AST_RTP_PROPERTY_RETRANS_RECV, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_rtp_instance_set_prop(*instance2, AST_RTP_PROPERTY_RETRANS_SEND, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+      } else if (type == TEST_TYPE_REMB) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_rtp_instance_set_prop(*instance1, AST_RTP_PROPERTY_REMB, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_rtp_instance_set_prop(*instance2, AST_RTP_PROPERTY_REMB, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_rtp_instance_get_local_address(*instance1, &addr);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_rtp_instance_set_remote_address(*instance2, &addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_rtp_instance_get_local_address(*instance2, &addr);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_rtp_instance_set_remote_address(*instance1, &addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_rtp_instance_reset_test_engine(*instance1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_rtp_instance_activate(*instance1);</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_rtp_instance_activate(*instance2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void test_write_frames(struct ast_rtp_instance *instance, int seqno, int num)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       char data[320] = "";</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_frame frame_out = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .frametype = AST_FRAME_VOICE,</span><br><span style="color: hsl(120, 100%, 40%);">+         .subclass.format = ast_format_ulaw,</span><br><span style="color: hsl(120, 100%, 40%);">+           .data.ptr = data,</span><br><span style="color: hsl(120, 100%, 40%);">+             .datalen = 160,</span><br><span style="color: hsl(120, 100%, 40%);">+       };</span><br><span style="color: hsl(120, 100%, 40%);">+    int index;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_set_flag(&frame_out, AST_FRFLAG_HAS_SEQUENCE_NUMBER);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       for (index = 0; index < num; index++) {</span><br><span style="color: hsl(120, 100%, 40%);">+            frame_out.seqno = seqno + index;</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_rtp_instance_write(instance, &frame_out);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void test_read_frames(struct ast_rtp_instance *instance, int num)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_frame *frame_in;</span><br><span style="color: hsl(120, 100%, 40%);">+   int index;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (index = 0; index < num; index++) {</span><br><span style="color: hsl(120, 100%, 40%);">+            frame_in = ast_rtp_instance_read(instance, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (frame_in) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_frfree(frame_in);</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void test_write_and_read_frames(struct ast_rtp_instance *instance1,</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_rtp_instance *instance2, int seqno, int num)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    test_write_frames(instance1, seqno, num);</span><br><span style="color: hsl(120, 100%, 40%);">+     test_read_frames(instance2, num);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(nack_no_packet_loss)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_rtp_instance *, instance2, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_sched_context *, test_sched, NULL, ast_sched_context_destroy_wrapper);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "nack_no_packet_loss";</span><br><span style="color: hsl(120, 100%, 40%);">+              info->category = "/res/res_rtp/";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->summary = "nack no packet loss unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+         info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Tests sending packets with no packet loss and "</span><br><span style="color: hsl(120, 100%, 40%);">+                    "validates that the send buffer stores sent packets "</span><br><span style="color: hsl(120, 100%, 40%);">+                       "and the receive buffer is empty";</span><br><span style="color: hsl(120, 100%, 40%);">+          return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test_sched = ast_sched_context_create();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NACK)) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "Failed to initialize test!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test_write_and_read_frames(instance1, instance2, 1000, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, ast_rtp_instance_get_send_buffer_count(instance1) == 10,</span><br><span style="color: hsl(120, 100%, 40%);">+              "Send buffer did not have the expected count of 10");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_test_validate(test, ast_rtp_instance_get_recv_buffer_count(instance2) == 0,</span><br><span style="color: hsl(120, 100%, 40%);">+               "Receive buffer did not have the expected count of 0");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(nack_nominal)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_rtp_instance *, instance2, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_sched_context *, test_sched, NULL, ast_sched_context_destroy_wrapper);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "nack_nominal";</span><br><span style="color: hsl(120, 100%, 40%);">+             info->category = "/res/res_rtp/";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->summary = "nack nominal unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Tests sending packets with some packet loss and "</span><br><span style="color: hsl(120, 100%, 40%);">+                  "validates that a NACK request is sent on reaching "</span><br><span style="color: hsl(120, 100%, 40%);">+                        "the triggering amount of lost packets";</span><br><span style="color: hsl(120, 100%, 40%);">+            return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test_sched = ast_sched_context_create();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NACK)) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "Failed to initialize test!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Start normally */</span><br><span style="color: hsl(120, 100%, 40%);">+  test_write_and_read_frames(instance1, instance2, 1000, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Set the number of packets to drop when we send them next */</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_rtp_instance_drop_packets(instance2, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+ test_write_and_read_frames(instance1, instance2, 1010, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Send enough packets to reach the NACK trigger */</span><br><span style="color: hsl(120, 100%, 40%);">+   test_write_and_read_frames(instance1, instance2, 1020, ast_rtp_instance_get_recv_buffer_max(instance2) / 2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* This needs to be read as RTCP */</span><br><span style="color: hsl(120, 100%, 40%);">+   test_read_frames(instance1, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* We should have the missing packets to read now */</span><br><span style="color: hsl(120, 100%, 40%);">+  test_read_frames(instance2, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_test_validate(test, ast_rtp_instance_get_recv_buffer_count(instance2) == 0,</span><br><span style="color: hsl(120, 100%, 40%);">+               "Receive buffer did not have the expected count of 0");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(nack_overflow)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_rtp_instance *, instance2, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_sched_context *, test_sched, NULL, ast_sched_context_destroy_wrapper);</span><br><span style="color: hsl(120, 100%, 40%);">+    int max_packets;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "nack_overflow";</span><br><span style="color: hsl(120, 100%, 40%);">+            info->category = "/res/res_rtp/";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->summary = "nack overflow unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+               info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Tests that when the buffer hits its capacity, we "</span><br><span style="color: hsl(120, 100%, 40%);">+                 "queue all the packets we currently have stored";</span><br><span style="color: hsl(120, 100%, 40%);">+           return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test_sched = ast_sched_context_create();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NACK)) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "Failed to initialize test!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Start normally */</span><br><span style="color: hsl(120, 100%, 40%);">+  test_write_and_read_frames(instance1, instance2, 1000, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Send enough packets to fill the buffer */</span><br><span style="color: hsl(120, 100%, 40%);">+  max_packets = ast_rtp_instance_get_recv_buffer_max(instance2);</span><br><span style="color: hsl(120, 100%, 40%);">+        test_write_and_read_frames(instance1, instance2, 1020, max_packets);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_test_validate(test, ast_rtp_instance_get_recv_buffer_count(instance2) == max_packets,</span><br><span style="color: hsl(120, 100%, 40%);">+             "Receive buffer did not have the expected count of max buffer size");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Send the packet that will overflow the buffer */</span><br><span style="color: hsl(120, 100%, 40%);">+   test_write_and_read_frames(instance1, instance2, 1020 + max_packets, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_test_validate(test, ast_rtp_instance_get_recv_buffer_count(instance2) == 0,</span><br><span style="color: hsl(120, 100%, 40%);">+               "Receive buffer did not have the expected count of 0");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(lost_packet_stats_nominal)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_rtp_instance *, instance2, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_sched_context *, test_sched, NULL, ast_sched_context_destroy_wrapper);</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_rtp_instance_stats stats = { 0, };</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_rtp_instance_stat stat = AST_RTP_INSTANCE_STAT_RXPLOSS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "lost_packet_stats_nominal";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->category = "/res/res_rtp/";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->summary = "lost packet stats nominal unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+           info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Tests that when some packets are lost, we calculate that "</span><br><span style="color: hsl(120, 100%, 40%);">+                 "loss correctly when doing lost packet statistics";</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test_sched = ast_sched_context_create();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NONE)) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "Failed to initialize test!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Start normally */</span><br><span style="color: hsl(120, 100%, 40%);">+  test_write_and_read_frames(instance1, instance2, 1000, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Send some more packets, but with a gap */</span><br><span style="color: hsl(120, 100%, 40%);">+  test_write_and_read_frames(instance1, instance2, 1015, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Send a RR to calculate lost packet statistics. We should be missing 5 packets */</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_rtp_instance_queue_report(instance1);</span><br><span style="color: hsl(120, 100%, 40%);">+     test_write_frames(instance2, 1000, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Check RTCP stats to see if we got the expected packet loss count */</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_rtp_instance_get_stats(instance2, &stats, stat);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_test_validate(test, stats.rxploss == 5,</span><br><span style="color: hsl(120, 100%, 40%);">+           "Condition of 5 lost packets was not met");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(remb_nominal)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_rtp_instance *, instance2, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_sched_context *, test_sched, NULL, ast_sched_context_destroy_wrapper);</span><br><span style="color: hsl(120, 100%, 40%);">+    RAII_VAR(struct ast_frame *, frame_in, NULL, ast_frfree);</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Use the structure softmix_remb_collector uses to store information for REMB */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_rtp_rtcp_feedback feedback = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .fmt = AST_RTP_RTCP_FMT_REMB,</span><br><span style="color: hsl(120, 100%, 40%);">+         .remb.br_exp = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+             .remb.br_mantissa = 1000,</span><br><span style="color: hsl(120, 100%, 40%);">+     };</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_frame frame_out = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .frametype = AST_FRAME_RTCP,</span><br><span style="color: hsl(120, 100%, 40%);">+          .subclass.integer = AST_RTP_RTCP_PSFB,</span><br><span style="color: hsl(120, 100%, 40%);">+                .data.ptr = &feedback,</span><br><span style="color: hsl(120, 100%, 40%);">+            .datalen = sizeof(feedback),</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "remb_nominal";</span><br><span style="color: hsl(120, 100%, 40%);">+             info->category = "/res/res_rtp/";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->summary = "remb nominal unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Tests sending and receiving a REMB packet";</span><br><span style="color: hsl(120, 100%, 40%);">+                return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Disable for now - there's a bug! */</span><br><span style="color: hsl(120, 100%, 40%);">+            return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test_sched = ast_sched_context_create();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_REMB)) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "Failed to initialize test!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* The schedid must be 0 or greater, so let's do that now */</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_rtp_instance_set_schedid(instance1, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_rtp_instance_write(instance1, &frame_out);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * There may be some additional work that needs to be done here, depending on how</span><br><span style="color: hsl(120, 100%, 40%);">+      * Asterisk handles the reading in of compound packets. We might get an ast_null_frame</span><br><span style="color: hsl(120, 100%, 40%);">+         * here instead of the REMB frame. We'll need to check the frametype to distinguish</span><br><span style="color: hsl(120, 100%, 40%);">+        * between them (AST_FRAME_NULL for ast_null_frame, AST_FRAME_RTCP for REMB).</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+   frame_in = ast_rtp_instance_read(instance2, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_test_validate(test, frame_in != NULL, "Did not receive a REMB frame");</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_test_validate(test, frame_in->frametype == AST_FRAME_RTCP,</span><br><span style="color: hsl(120, 100%, 40%);">+             "REMB frame did not have the expected frametype");</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_test_validate(test, frame_in->subclass.integer == AST_RTP_RTCP_PSFB,</span><br><span style="color: hsl(120, 100%, 40%);">+           "REMB frame did not have the expected subclass integer");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(sr_rr_nominal)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_rtp_instance *, instance2, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_sched_context *, test_sched, NULL, ast_sched_context_destroy_wrapper);</span><br><span style="color: hsl(120, 100%, 40%);">+    RAII_VAR(struct ast_frame *, frame_in, NULL, ast_frfree);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "sr_rr_nominal";</span><br><span style="color: hsl(120, 100%, 40%);">+            info->category = "/res/res_rtp/";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->summary = "SR/RR nominal unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+               info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Tests sending SR/RR and receiving it; includes SDES";</span><br><span style="color: hsl(120, 100%, 40%);">+              return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test_sched = ast_sched_context_create();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NONE)) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "Failed to initialize test!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test_write_and_read_frames(instance1, instance2, 1000, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Set the send_report flag so we send a sender report instead of normal RTP. We</span><br><span style="color: hsl(120, 100%, 40%);">+       * also need to ensure that SDES processed.</span><br><span style="color: hsl(120, 100%, 40%);">+    */</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_rtp_instance_queue_report(instance1);</span><br><span style="color: hsl(120, 100%, 40%);">+     test_write_frames(instance1, 1010, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      frame_in = ast_rtp_instance_read(instance2, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_test_validate(test, frame_in->frametype == AST_FRAME_RTCP,</span><br><span style="color: hsl(120, 100%, 40%);">+             "Sender report frame did not have the expected frametype");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, frame_in->subclass.integer == AST_RTP_RTCP_SR,</span><br><span style="color: hsl(120, 100%, 40%);">+             "Sender report frame did not have the expected subclass integer");</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_test_validate(test, ast_rtp_instance_get_sdes_received(instance2) == 1,</span><br><span style="color: hsl(120, 100%, 40%);">+           "SDES was never processed for sender report");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_frfree(frame_in);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Set the send_report flag so we send a receiver report instead of normal RTP */</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_rtp_instance_queue_report(instance1);</span><br><span style="color: hsl(120, 100%, 40%);">+     test_write_frames(instance1, 1010, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      frame_in = ast_rtp_instance_read(instance2, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_test_validate(test, frame_in->frametype == AST_FRAME_RTCP,</span><br><span style="color: hsl(120, 100%, 40%);">+             "Receiver report frame did not have the expected frametype");</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_test_validate(test, frame_in->subclass.integer == AST_RTP_RTCP_RR,</span><br><span style="color: hsl(120, 100%, 40%);">+             "Receiver report frame did not have the expected subclass integer");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(fir_nominal)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_rtp_instance *, instance2, NULL, ast_rtp_instance_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct ast_sched_context *, test_sched, NULL, ast_sched_context_destroy_wrapper);</span><br><span style="color: hsl(120, 100%, 40%);">+    RAII_VAR(struct ast_frame *, frame_in, NULL, ast_frfree);</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_frame frame_out = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .frametype = AST_FRAME_CONTROL,</span><br><span style="color: hsl(120, 100%, 40%);">+               .subclass.integer = AST_CONTROL_VIDUPDATE,</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "fir_nominal";</span><br><span style="color: hsl(120, 100%, 40%);">+              info->category = "/res/res_rtp/";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->summary = "fir nominal unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+         info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Tests sending and receiving a FIR packet";</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Disable for now - there's a bug! */</span><br><span style="color: hsl(120, 100%, 40%);">+            return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   test_sched = ast_sched_context_create();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NONE)) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "Failed to initialize test!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Send some packets to learn SSRC */</span><br><span style="color: hsl(120, 100%, 40%);">+ test_write_and_read_frames(instance2, instance1, 1000, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* The schedid must be 0 or greater, so let's do that now */</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_rtp_instance_set_schedid(instance1, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * This will not directly write a frame out, but cause Asterisk to see it as a FIR</span><br><span style="color: hsl(120, 100%, 40%);">+     * request, which will then trigger rtp_write_rtcp_fir, which will send out the</span><br><span style="color: hsl(120, 100%, 40%);">+        * appropriate packet.</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_rtp_instance_write(instance1, &frame_out);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * We only receive one frame, the FIR request. It won't have a subclass integer of</span><br><span style="color: hsl(120, 100%, 40%);">+         * 206 (PSFB) because ast_rtcp_interpret sets it to 18 (AST_CONTROL_VIDUPDATE), so</span><br><span style="color: hsl(120, 100%, 40%);">+     * check for that.</span><br><span style="color: hsl(120, 100%, 40%);">+     *</span><br><span style="color: hsl(120, 100%, 40%);">+     * NOTE - similar to REMB, there may be more that needs to be done here when the</span><br><span style="color: hsl(120, 100%, 40%);">+       * packet is sent as a compound packet!</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+   frame_in = ast_rtp_instance_read(instance2, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_test_validate(test, frame_in != NULL, "Did not receive a FIR frame");</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_validate(test, frame_in->frametype == AST_FRAME_CONTROL,</span><br><span style="color: hsl(120, 100%, 40%);">+          "FIR frame did not have the expected frametype");</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_validate(test, frame_in->subclass.integer == AST_CONTROL_VIDUPDATE,</span><br><span style="color: hsl(120, 100%, 40%);">+               "FIR frame did not have the expected subclass integer");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int unload_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(nack_no_packet_loss);</span><br><span style="color: hsl(120, 100%, 40%);">+     AST_TEST_UNREGISTER(nack_nominal);</span><br><span style="color: hsl(120, 100%, 40%);">+    AST_TEST_UNREGISTER(nack_overflow);</span><br><span style="color: hsl(120, 100%, 40%);">+   AST_TEST_UNREGISTER(lost_packet_stats_nominal);</span><br><span style="color: hsl(120, 100%, 40%);">+       AST_TEST_UNREGISTER(remb_nominal);</span><br><span style="color: hsl(120, 100%, 40%);">+    AST_TEST_UNREGISTER(sr_rr_nominal);</span><br><span style="color: hsl(120, 100%, 40%);">+   AST_TEST_UNREGISTER(fir_nominal);</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int load_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       AST_TEST_REGISTER(nack_no_packet_loss);</span><br><span style="color: hsl(120, 100%, 40%);">+       AST_TEST_REGISTER(nack_nominal);</span><br><span style="color: hsl(120, 100%, 40%);">+      AST_TEST_REGISTER(nack_overflow);</span><br><span style="color: hsl(120, 100%, 40%);">+     AST_TEST_REGISTER(lost_packet_stats_nominal);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(remb_nominal);</span><br><span style="color: hsl(120, 100%, 40%);">+      AST_TEST_REGISTER(sr_rr_nominal);</span><br><span style="color: hsl(120, 100%, 40%);">+     AST_TEST_REGISTER(fir_nominal);</span><br><span style="color: hsl(120, 100%, 40%);">+       return AST_MODULE_LOAD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "RTP/RTCP test module");</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/12813">change 12813</a>. To unsubscribe, or for help writing mail filters, 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/c/asterisk/+/12813"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-Change-Id: I56107c7411003a247589bbb6086d25c54719901b </div>
<div style="display:none"> Gerrit-Change-Number: 12813 </div>
<div style="display:none"> Gerrit-PatchSet: 7 </div>
<div style="display:none"> Gerrit-Owner: Benjamin Keith Ford <bford@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua C. Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>