[asterisk-commits] mjordan: branch mjordan/trunk_jitter_tests r358809 - /team/mjordan/trunk_jitt...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Mar 12 21:44:09 CDT 2012


Author: mjordan
Date: Mon Mar 12 21:44:07 2012
New Revision: 358809

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=358809
Log:
Add remaining tests for jitterbuffer

Add the remaining tests, which were mostly permutations of the
existing tests added earlier.

Modified:
    team/mjordan/trunk_jitter_tests/tests/test_jitterbuffer.c

Modified: team/mjordan/trunk_jitter_tests/tests/test_jitterbuffer.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk_jitter_tests/tests/test_jitterbuffer.c?view=diff&rev=358809&r1=358808&r2=358809
==============================================================================
--- team/mjordan/trunk_jitter_tests/tests/test_jitterbuffer.c (original)
+++ team/mjordan/trunk_jitter_tests/tests/test_jitterbuffer.c Mon Mar 12 21:44:07 2012
@@ -1,9 +1,9 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) <Year>, <Your Name Here>
+ * Copyright (C) 2012, Matt Jordan
  *
- * <Your Name Here> <<Your Email Here>>
+ * Matt Jordan <mjordan at digium.com>
  *
  * See http://www.asterisk.org for more information about
  * the Asterisk project. Please do not directly contact
@@ -18,11 +18,10 @@
 
 /*!
  * \file
- * \brief Skeleton Test
+ * \brief Unit tests for channel jitter buffers
  *
- * \author\verbatim <Your Name Here> <<Your Email Here>> \endverbatim
+ * \author\verbatim Matt Jordan <mjordan at digium.com> \endverbatim
  *
- * This is a skeleton for development of an Asterisk test module
  * \ingroup tests
  */
 
@@ -47,11 +46,10 @@
 #define DEFAULT_CODEC_INTERP_LEN 20
 
 /*! \internal
- * Test two numeric (long int) values.  It is expected that the attribute value is
- * some numeric attribute in a jb_info object.  Failure automatically attempts
+ * Test two numeric (long int) values.  Failure automatically attempts
  * to jump to a cleanup tag
  */
-#define JB_INFO_NUMERIC_TEST(attribute, expected) do { \
+#define JB_NUMERIC_TEST(attribute, expected) do { \
 	if (attribute != expected) { \
 		ast_test_status_update(test, #attribute ": expected [%ld]; actual [%ld]\n", (long int)expected, attribute); \
 		goto cleanup; \
@@ -62,7 +60,7 @@
  * Print out as debug the frame related contents of a jb_info object
  */
 #define JB_INFO_PRINT_FRAME_DEBUG(jbinfo) do { \
-	ast_verb(1, "JitterBuffer Frame Info:\n" \
+	ast_debug(1, "JitterBuffer Frame Info:\n" \
 		"\tFrames In: %ld\n\tFrames Out: %ld\n" \
 		"\tDropped Frames: %ld\n\tLate Frames: %ld\n" \
 		"\tLost Frames: %ld\n\tOut of Order Frames: %ld\n" \
@@ -75,7 +73,7 @@
  * This macro installs the error, warning, and debug functions for a test.  It is
  * expected that at the end of a test, the functions are removed.
  * Note that the debug statement is in here merely to aid in tracing in a lot where
- * the jitterbuffer debug begins.
+ * the jitter buffer debug begins.
  */
 #define JB_TEST_BEGIN(test_name) do { \
 	jb_setoutput(test_jb_error_output, test_jb_warn_output, test_jb_debug_output); \
@@ -165,7 +163,8 @@
 		info->category = "/main/jitterbuffer/";
 		info->summary = "Nominal operation of jitterbuffer with audio data";
 		info->description =
-			"Tests the nominal case of putting audio data into a jitter buffer";
+			"Tests the nominal case of putting audio data into a jitter buffer, "
+			"retrieving the frames, and querying for the next frame";
 		return AST_TEST_NOT_RUN;
 	case TEST_EXECUTE:
 		break;
@@ -200,16 +199,9 @@
 				jitter_buffer_return_codes[ret], i);
 			goto cleanup;
 		}
-		if (frame.ms != 20) {
-			ast_test_status_update(test,
-				"Unexpected ms value [%ld] on frame %d - expected %d\n", frame.ms, i, 20);
-			goto cleanup;
-		}
-		if (frame.ts != i * 20 - jb->info.resync_offset) {
-			ast_test_status_update(test,
-				"Unexpected ts value [%ld] on frame %d - expected %ld\n", frame.ts, i, i * 20 - jb->info.resync_offset);
-			goto cleanup;
-		}
+		JB_NUMERIC_TEST(frame.ms, 20);
+		JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
+		JB_NUMERIC_TEST(jb_next(jb), (i + 1) * 20 + 5);
 	}
 
 	result = AST_TEST_PASS;
@@ -218,12 +210,13 @@
 		ast_test_status_update(test, "Failed to get jitterbuffer information\n");
 		goto cleanup;
 	}
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_dropped, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_in, 40);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_out, 40);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_late, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_lost, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_ooo, 0);
+	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
 
 cleanup:
 	if (jb) {
@@ -253,7 +246,8 @@
 		info->category = "/main/jitterbuffer/";
 		info->summary = "Nominal operation of jitterbuffer with control frames";
 		info->description =
-			"Tests the nominal case of putting control frames into a jitter buffer";
+			"Tests the nominal case of putting control frames into a jitter buffer, "
+			"retrieving the frames, and querying for the next frame";
 		return AST_TEST_NOT_RUN;
 	case TEST_EXECUTE:
 		break;
@@ -288,28 +282,22 @@
 				jitter_buffer_return_codes[ret], i);
 			goto cleanup;
 		}
-		if (frame.ms != 20) {
-			ast_test_status_update(test,
-				"Unexpected ms value [%ld] on frame %d - expected %d\n", frame.ms, i, 20);
-			goto cleanup;
-		}
-		if (frame.ts != i * 20 - jb->info.resync_offset) {
-			ast_test_status_update(test,
-				"Unexpected ts value [%ld] on frame %d - expected %ld\n", frame.ts, i, i * 20 - jb->info.resync_offset);
-			goto cleanup;
-		}
+		JB_NUMERIC_TEST(frame.ms, 20);
+		JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
+		JB_NUMERIC_TEST(jb_next(jb), (i + 1) * 20 + 5);
 	}
 
 	if (jb_getinfo(jb, &jbinfo) != JB_OK) {
 		ast_test_status_update(test, "Failed to get jitterbuffer information\n");
 		goto cleanup;
 	}
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_dropped, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_in, 40);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_out, 40);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_late, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_lost, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_ooo, 0);
+	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
 
 	result = AST_TEST_PASS;
 
@@ -393,32 +381,119 @@
 				jitter_buffer_return_codes[ret], i);
 			goto cleanup;
 		}
-		if (frame.ms != 20) {
-			ast_test_status_update(test,
-				"Unexpected ms value [%ld] on frame %d - expected %d\n", frame.ms, i, 20);
-			goto cleanup;
-		}
-		if (frame.ts != i * 20 - jb->info.resync_offset) {
-			ast_test_status_update(test,
-				"Unexpected ts value [%ld] on frame %d - expected %ld\n", frame.ts, i, i * 20 - jb->info.resync_offset);
-			goto cleanup;
-		}
+		JB_NUMERIC_TEST(frame.ms, 20);
+		JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
 	}
 
 	if (jb_getinfo(jb, &jbinfo) != JB_OK) {
 		ast_test_status_update(test, "Failed to get jitterbuffer information\n");
 		goto cleanup;
 	}
+	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 10);
+
+	result = AST_TEST_PASS;
+
+cleanup:
+	if (jb) {
+		/* No need to do anything - this will put all frames on the 'free' list,
+		 * so jb_destroy will dispose of them */
+		while (jb_getall(jb, &frame) == JB_OK) { }
+		jb_destroy(jb);
+	}
+
+	JB_TEST_END;
+
+	return result;
+}
+
+AST_TEST_DEFINE(jitterbuffer_out_of_order_control)
+{
+	enum ast_test_result_state result = AST_TEST_FAIL;
+	struct jitterbuf *jb = NULL;
+	struct jb_frame frame;
+	struct jb_info jbinfo;
+	struct jb_conf jbconf;
+	int i;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "jitterbuffer_out_of_order_voice";
+		info->category = "/main/jitterbuffer/";
+		info->summary = "Tests sending out of order audio frames to a jitter buffer";
+		info->description =
+			"Every 5th frame sent to a jitter buffer is reversed with the previous "
+			"frame.  The expected result is to have a jitter buffer with the frames "
+			"in order, while a total of 10 frames should be recorded as having been "
+			"received out of order.";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	JB_TEST_BEGIN("jitterbuffer_out_of_order_control");
+
+	if (!(jb = jb_new())) {
+		ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
+		goto cleanup;
+	}
+
+	test_jb_populate_config(&jbconf);
+	if (jb_setconf(jb, &jbconf) != JB_OK) {
+		ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
+		goto cleanup;
+	}
+
+	for (i = 0; i < 40; i++) {
+		if (i % 4 == 0) {
+			/* Add 5th frame */
+			if (jb_put(jb, NULL, JB_TYPE_CONTROL, 20, (i + 1) * 20, (i + 1) * 20 + 5) == JB_DROP) {
+				ast_test_status_update(test, "Jitter buffer dropped packet %d\n", (i+1));
+				goto cleanup;
+			}
+			/* Add 4th frame */
+			if (jb_put(jb, NULL, JB_TYPE_CONTROL, 20, i * 20, i * 20 + 5) == JB_DROP) {
+				ast_test_status_update(test, "Jitter buffer dropped packet %d\n", i);
+				goto cleanup;
+			}
+			i++;
+		} else {
+			if (jb_put(jb, NULL, JB_TYPE_CONTROL, 20, i * 20, i * 20 + 5) == JB_DROP) {
+				ast_test_status_update(test, "Jitter buffer dropped packet %d\n", i);
+				goto cleanup;
+			}
+		}
+	}
+
+	for (i = 0; i < 40; i++) {
+		enum jb_return_code ret;
+		/* We should have a frame for each point in time */
+		if ((ret = jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN)) != JB_OK) {
+			ast_test_status_update(test,
+				"Unexpected jitter buffer return code [%s] when retrieving frame %d\n",
+				jitter_buffer_return_codes[ret], i);
+			goto cleanup;
+		}
+		JB_NUMERIC_TEST(frame.ms, 20);
+		JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
+	}
+
 	if (jb_getinfo(jb, &jbinfo) != JB_OK) {
 		ast_test_status_update(test, "Failed to get jitterbuffer information\n");
 		goto cleanup;
 	}
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_dropped, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_in, 40);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_out, 40);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_late, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_lost, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_ooo, 10);
+	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 10);
 
 	result = AST_TEST_PASS;
 
@@ -492,16 +567,8 @@
 				goto cleanup;
 			}
 		} else {
-			if (frame.ms != 20) {
-				ast_test_status_update(test,
-					"Unexpected ms value [%ld] on frame %d - expected %d\n", frame.ms, i, 20);
-				goto cleanup;
-			}
-			if (frame.ts != i * 20 - jb->info.resync_offset) {
-				ast_test_status_update(test,
-					"Unexpected ts value [%ld] on frame %d - expected %ld\n", frame.ts, i, i * 20 - jb->info.resync_offset);
-				goto cleanup;
-			}
+			JB_NUMERIC_TEST(frame.ms, 20);
+			JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
 		}
 	}
 
@@ -513,12 +580,12 @@
 	/* Note: The first frame (at i = 0) never got added, so nothing existed at that point.
 	 * Its neither dropped nor lost.
 	 */
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_ooo, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_late, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_lost, 7);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_in, 32);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_out, 32);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_dropped, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_lost, 7);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 32);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 32);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
 
 	result = AST_TEST_PASS;
 
@@ -535,6 +602,98 @@
 	return result;
 }
 
+AST_TEST_DEFINE(jitterbuffer_lost_control)
+{
+	enum ast_test_result_state result = AST_TEST_FAIL;
+	struct jitterbuf *jb = NULL;
+	struct jb_frame frame;
+	struct jb_conf jbconf;
+	struct jb_info jbinfo;
+	int i;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "jitterbuffer_lost_control";
+		info->category = "/main/jitterbuffer/";
+		info->summary = "Tests missing frames in the jitterbuffer";
+		info->description =
+			"Every 5th frame that would be sent to a jitter buffer is instead"
+			"dropped.  When reading data from the jitter buffer, the jitter buffer"
+			"simply reports that no frame exists for that time slot";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	JB_TEST_BEGIN("jitterbuffer_lost_control");
+
+	if (!(jb = jb_new())) {
+		ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
+		goto cleanup;
+	}
+
+	test_jb_populate_config(&jbconf);
+	if (jb_setconf(jb, &jbconf) != JB_OK) {
+		ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
+		goto cleanup;
+	}
+
+	for (i = 0; i < 40; i++) {
+		if (i % 5 == 0) {
+			i++;
+		}
+		if (jb_put(jb, NULL, JB_TYPE_CONTROL, 20, i * 20, i * 20 + 5) == JB_DROP) {
+			ast_test_status_update(test, "Jitter buffer dropped packet %d\n", i);
+			goto cleanup;
+		}
+	}
+
+	for (i = 0; i < 40; i++) {
+		enum jb_return_code ret;
+		if ((ret = jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN)) != JB_OK) {
+			/* If we didn't get an OK, make sure that it was an expected lost frame */
+			if (!(ret == JB_NOFRAME && i % 5 == 0)) {
+				ast_test_status_update(test,
+					"Unexpected jitter buffer return code [%s] when retrieving frame %d\n",
+					jitter_buffer_return_codes[ret], i);
+				goto cleanup;
+			}
+		} else {
+			JB_NUMERIC_TEST(frame.ms, 20);
+			JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
+		}
+	}
+
+	if (jb_getinfo(jb, &jbinfo) != JB_OK) {
+		ast_test_status_update(test, "Failed to get jitterbuffer information\n");
+		goto cleanup;
+	}
+	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
+	/* Note: The first frame (at i = 0) never got added, so nothing existed at that point.
+	 * Its neither dropped nor lost.
+	 */
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 32);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 32);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
+
+	result = AST_TEST_PASS;
+
+cleanup:
+	if (jb) {
+		/* No need to do anything - this will put all frames on the 'free' list,
+		 * so jb_destroy will dispose of them */
+		while (jb_getall(jb, &frame) == JB_OK) { }
+		jb_destroy(jb);
+	}
+
+	JB_TEST_END;
+
+	return result;
+}
+
 AST_TEST_DEFINE(jitterbuffer_late_voice)
 {
 	enum ast_test_result_state result = AST_TEST_FAIL;
@@ -548,17 +707,16 @@
 	case TEST_INIT:
 		info->name = "jitterbuffer_late_voice";
 		info->category = "/main/jitterbuffer/";
-		info->summary = "Tests sending frames to a jitterbuffer that are late";
+		info->summary = "Tests sending frames to a jitter buffer that arrive late";
 		info->description =
-			"Every 5th frame sent to a jitter buffer is put into the jitterbuffer just"
-			"prior to the arrival of the 6th frame.  The expected result is to have a";
-		/* TODO: */
+			"Every 5th frame sent to a jitter buffer arrives late, but still in "
+			"order with respect to the previous and next packet";
 		return AST_TEST_NOT_RUN;
 	case TEST_EXECUTE:
 		break;
 	}
 
-	JB_TEST_BEGIN("jitterbuffer_late_audio");
+	JB_TEST_BEGIN("jitterbuffer_late_voice");
 
 	if (!(jb = jb_new())) {
 		ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
@@ -595,16 +753,8 @@
 				jitter_buffer_return_codes[ret], i);
 			goto cleanup;
 		}
-		if (frame.ms != 20) {
-			ast_test_status_update(test,
-				"Unexpected ms value [%ld] on frame %d - expected %d\n", frame.ms, i, 20);
-			goto cleanup;
-		}
-		if (frame.ts != i * 20 - jb->info.resync_offset) {
-			ast_test_status_update(test,
-				"Unexpected ts value [%ld] on frame %d - expected %ld\n", frame.ts, i, i * 20 - jb->info.resync_offset);
-			goto cleanup;
-		}
+		JB_NUMERIC_TEST(frame.ms, 20);
+		JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
 	}
 
 	if (jb_getinfo(jb, &jbinfo) != JB_OK) {
@@ -612,12 +762,12 @@
 		goto cleanup;
 	}
 	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_ooo, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_late, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_lost, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_in, 40);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_out, 40);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_dropped, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
 
 	result = AST_TEST_PASS;
 
@@ -634,7 +784,7 @@
 	return result;
 }
 
-AST_TEST_DEFINE(jitterbuffer_overflow)
+AST_TEST_DEFINE(jitterbuffer_late_control)
 {
 	enum ast_test_result_state result = AST_TEST_FAIL;
 	struct jitterbuf *jb = NULL;
@@ -645,16 +795,19 @@
 
 	switch (cmd) {
 	case TEST_INIT:
-		info->name = "jitterbuffer_overflow";
+		info->name = "jitterbuffer_late_control";
 		info->category = "/main/jitterbuffer/";
-		info->summary = "Tests sending frames to a jitterbuffer that are late";
-		info->description = "Blahblah";
-		/* TODO: */
+		info->summary = "Tests sending frames to a jitter buffer that arrive late";
+		info->description =
+			"Every 5th frame sent to a jitter buffer arrives late, but still in "
+			"order with respect to the previous and next packet";
 		return AST_TEST_NOT_RUN;
 	case TEST_EXECUTE:
 		break;
 	}
 
+	JB_TEST_BEGIN("jitterbuffer_late_voice");
+
 	if (!(jb = jb_new())) {
 		ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
 		goto cleanup;
@@ -666,24 +819,45 @@
 		goto cleanup;
 	}
 
-	for (i = 0; i < 100; i++) {
-		jb_put(jb, NULL, JB_TYPE_VOICE, 20, i * 20, i * 20 + 5);
-	}
-
-	i = 0;
-	while (jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN) == JB_OK) {
-		++i;
-	}
-
+	for (i = 0; i < 40; i++) {
+		if (i % 5 == 0) {
+			/* Add 5th frame */
+			if (jb_put(jb, NULL, JB_TYPE_CONTROL, 20, i * 20, i * 20 + 20) == JB_DROP) {
+				ast_test_status_update(test, "Jitter buffer dropped packet %d\n", (i+1));
+				goto cleanup;
+			}
+		} else {
+			if (jb_put(jb, NULL, JB_TYPE_CONTROL, 20, i * 20, i * 20 + 5) == JB_DROP) {
+				ast_test_status_update(test, "Jitter buffer dropped packet %d\n", i);
+				goto cleanup;
+			}
+		}
+	}
+
+	for (i = 0; i < 40; i++) {
+		enum jb_return_code ret;
+		/* We should have a frame for each point in time */
+		if ((ret = jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN)) != JB_OK) {
+			ast_test_status_update(test,
+				"Unexpected jitter buffer return code [%s] when retrieving frame %d\n",
+				jitter_buffer_return_codes[ret], i);
+			goto cleanup;
+		}
+		JB_NUMERIC_TEST(frame.ms, 20);
+		JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
+	}
 
 	if (jb_getinfo(jb, &jbinfo) != JB_OK) {
 		ast_test_status_update(test, "Failed to get jitterbuffer information\n");
 		goto cleanup;
 	}
-
 	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_dropped, 49);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_out, 51);
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
 
 	result = AST_TEST_PASS;
 
@@ -694,6 +868,156 @@
 		while (jb_getall(jb, &frame) == JB_OK) { }
 		jb_destroy(jb);
 	}
+
+	JB_TEST_END;
+
+	return result;
+}
+
+AST_TEST_DEFINE(jitterbuffer_overflow_voice)
+{
+	enum ast_test_result_state result = AST_TEST_FAIL;
+	struct jitterbuf *jb = NULL;
+	struct jb_frame frame;
+	struct jb_info jbinfo;
+	struct jb_conf jbconf;
+	int i;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "jitterbuffer_overflow_voice";
+		info->category = "/main/jitterbuffer/";
+		info->summary = "Tests overfilling a jitter buffer with voice frames";
+		info->description = "Tests overfilling a jitter buffer with voice frames";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	JB_TEST_BEGIN("jitterbuffer_overflow_voice");
+
+	if (!(jb = jb_new())) {
+		ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
+		goto cleanup;
+	}
+
+	test_jb_populate_config(&jbconf);
+	if (jb_setconf(jb, &jbconf) != JB_OK) {
+		ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
+		goto cleanup;
+	}
+
+	for (i = 0; i < 100; i++) {
+		jb_put(jb, NULL, JB_TYPE_VOICE, 20, i * 20, i * 20 + 5);
+	}
+
+	i = 0;
+	while (jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN) == JB_OK) {
+		JB_NUMERIC_TEST(frame.ms, 20);
+		JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
+		++i;
+	}
+
+
+	if (jb_getinfo(jb, &jbinfo) != JB_OK) {
+		ast_test_status_update(test, "Failed to get jitterbuffer information\n");
+		goto cleanup;
+	}
+
+	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 49);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 51);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 51);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	/* Note that the last frame will be interpolated */
+	JB_NUMERIC_TEST(jbinfo.frames_lost, 1);
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
+
+	result = AST_TEST_PASS;
+
+cleanup:
+	if (jb) {
+		/* No need to do anything - this will put all frames on the 'free' list,
+		 * so jb_destroy will dispose of them */
+		while (jb_getall(jb, &frame) == JB_OK) { }
+		jb_destroy(jb);
+	}
+
+	JB_TEST_END;
+
+	return result;
+}
+
+AST_TEST_DEFINE(jitterbuffer_overflow_control)
+{
+	enum ast_test_result_state result = AST_TEST_FAIL;
+	struct jitterbuf *jb = NULL;
+	struct jb_frame frame;
+	struct jb_info jbinfo;
+	struct jb_conf jbconf;
+	int i;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "jitterbuffer_overflow_control";
+		info->category = "/main/jitterbuffer/";
+		info->summary = "Tests overfilling a jitter buffer with control frames";
+		info->description = "Tests overfilling a jitter buffer with control frames";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	JB_TEST_BEGIN("jitterbuffer_overflow_control");
+
+	if (!(jb = jb_new())) {
+		ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
+		goto cleanup;
+	}
+
+	test_jb_populate_config(&jbconf);
+	if (jb_setconf(jb, &jbconf) != JB_OK) {
+		ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
+		goto cleanup;
+	}
+
+	for (i = 0; i < 100; i++) {
+		jb_put(jb, NULL, JB_TYPE_CONTROL, 20, i * 20, i * 20 + 5);
+	}
+
+	i = 0;
+	while (jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN) == JB_OK) {
+		JB_NUMERIC_TEST(frame.ms, 20);
+		JB_NUMERIC_TEST(frame.ts, i * 20 - jb->info.resync_offset);
+		++i;
+	}
+
+
+	if (jb_getinfo(jb, &jbinfo) != JB_OK) {
+		ast_test_status_update(test, "Failed to get jitterbuffer information\n");
+		goto cleanup;
+	}
+
+	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 49);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 51);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 51);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_lost, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
+
+	result = AST_TEST_PASS;
+
+cleanup:
+	if (jb) {
+		/* No need to do anything - this will put all frames on the 'free' list,
+		 * so jb_destroy will dispose of them */
+		while (jb_getall(jb, &frame) == JB_OK) { }
+		jb_destroy(jb);
+	}
+
+	JB_TEST_END;
+
 	return result;
 }
 
@@ -711,13 +1035,17 @@
 	case TEST_INIT:
 		info->name = "jitterbuffer_resynch_control";
 		info->category = "/main/jitterbuffer/";
-		info->summary = "Tests sending frames to a jitterbuffer that are late";
-		info->description = "Blahblah";
-		/* TODO: */
+		info->summary = "Tests sending control frames that force a resynch";
+		info->description = "Control frames are sent to a jitter buffer.  After some "
+			"number of frames, the source timestamps jump, forcing a resync of "
+			"the jitter buffer.  Since the frames are control, the resync happens "
+			"immediately.";
 		return AST_TEST_NOT_RUN;
 	case TEST_EXECUTE:
 		break;
 	}
+
+	JB_TEST_BEGIN("jitterbuffer_resynch_control");
 
 	if (!(jb = jb_new())) {
 		ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
@@ -751,11 +1079,13 @@
 	}
 	/* With control frames, a resync happens automatically */
 	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_dropped, 0);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_out, 40);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_in, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 40);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 40);
 	/* Verify that each of the interpolated frames is counted */
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_lost, interpolated_frames);
+	JB_NUMERIC_TEST(jbinfo.frames_lost, interpolated_frames);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
 
 	result = AST_TEST_PASS;
 
@@ -766,10 +1096,13 @@
 		while (jb_getall(jb, &frame) == JB_OK) { }
 		jb_destroy(jb);
 	}
+
+	JB_TEST_END;
+
 	return result;
 }
 
-AST_TEST_DEFINE(jitterbuffer_resynch_audio)
+AST_TEST_DEFINE(jitterbuffer_resynch_voice)
 {
 	enum ast_test_result_state result = AST_TEST_FAIL;
 	struct jitterbuf *jb = NULL;
@@ -781,15 +1114,19 @@
 
 	switch (cmd) {
 	case TEST_INIT:
-		info->name = "jitterbuffer_resynch_audio";
+		info->name = "jitterbuffer_resynch_voice";
 		info->category = "/main/jitterbuffer/";
-		info->summary = "Tests sending frames to a jitterbuffer that are late";
-		info->description = "Blahblah";
-		/* TODO: */
+		info->summary = "Tests sending voice frames that force a resynch";
+		info->description = "Voice frames are sent to a jitter buffer.  After some "
+			"number of frames, the source timestamps jump, forcing a resync of "
+			"the jitter buffer.  Since the frames are voice, the resync happens "
+			"after observing three packets that break the resync threshold.";
 		return AST_TEST_NOT_RUN;
 	case TEST_EXECUTE:
 		break;
 	}
+
+	JB_TEST_BEGIN("jitterbuffer_resynch_voice");
 
 	if (!(jb = jb_new())) {
 		ast_test_status_update(test, "Failed to allocate memory for jitterbuffer\n");
@@ -823,11 +1160,13 @@
 	}
 	/* The first three packets before the resync should be dropped */
 	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_dropped, 3);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_out, 37);
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_in, 37);
+	JB_NUMERIC_TEST(jbinfo.frames_dropped, 3);
+	JB_NUMERIC_TEST(jbinfo.frames_out, 37);
+	JB_NUMERIC_TEST(jbinfo.frames_in, 37);
 	/* Verify that each of the interpolated frames is counted */
-	JB_INFO_NUMERIC_TEST(jbinfo.frames_lost, interpolated_frames);
+	JB_NUMERIC_TEST(jbinfo.frames_lost, interpolated_frames);
+	JB_NUMERIC_TEST(jbinfo.frames_late, 0);
+	JB_NUMERIC_TEST(jbinfo.frames_ooo, 0);
 
 
 	result = AST_TEST_PASS;
@@ -839,6 +1178,9 @@
 		while (jb_getall(jb, &frame) == JB_OK) { }
 		jb_destroy(jb);
 	}
+
+	JB_TEST_END;
+
 	return result;
 }
 
@@ -846,26 +1188,43 @@
 {
 	AST_TEST_UNREGISTER(jitterbuffer_nominal_voice_frames);
 	AST_TEST_UNREGISTER(jitterbuffer_nominal_control_frames);
-	AST_TEST_UNREGISTER(jitterbuffer_out_of_order_audio);
-	AST_TEST_UNREGISTER(jitterbuffer_lost_audio);
-	AST_TEST_UNREGISTER(jitterbuffer_late_audio);
-	AST_TEST_UNREGISTER(jitterbuffer_overflow);
-	AST_TEST_UNREGISTER(jitterbuffer_resynch_audio);
+	AST_TEST_UNREGISTER(jitterbuffer_out_of_order_voice);
+	AST_TEST_UNREGISTER(jitterbuffer_out_of_order_control);
+	AST_TEST_UNREGISTER(jitterbuffer_lost_voice);
+	AST_TEST_UNREGISTER(jitterbuffer_late_voice);
+	AST_TEST_UNREGISTER(jitterbuffer_overflow_voice);
+	AST_TEST_UNREGISTER(jitterbuffer_resynch_voice);
 	AST_TEST_UNREGISTER(jitterbuffer_resynch_control);
 	return 0;
 }
 
 static int load_module(void)
 {
+	/* Nominal - put / get frames */
 	AST_TEST_REGISTER(jitterbuffer_nominal_voice_frames);
 	AST_TEST_REGISTER(jitterbuffer_nominal_control_frames);
-	AST_TEST_REGISTER(jitterbuffer_out_of_order_audio);
-	AST_TEST_REGISTER(jitterbuffer_lost_audio);
-	AST_TEST_REGISTER(jitterbuffer_late_audio);
-	AST_TEST_REGISTER(jitterbuffer_overflow);
-	AST_TEST_REGISTER(jitterbuffer_resynch_audio);
+
+	/* Out of order frame arrival */
+	AST_TEST_REGISTER(jitterbuffer_out_of_order_voice);
+	AST_TEST_REGISTER(jitterbuffer_out_of_order_control);
+
+	/* Lost frame arrival */
+	AST_TEST_REGISTER(jitterbuffer_lost_voice);
+	AST_TEST_REGISTER(jitterbuffer_lost_control);
+
+	/* Late frame arrival */
+	AST_TEST_REGISTER(jitterbuffer_late_voice);
+	AST_TEST_REGISTER(jitterbuffer_late_control);
+
+	/* Buffer overflow */
+	AST_TEST_REGISTER(jitterbuffer_overflow_voice);
+	AST_TEST_REGISTER(jitterbuffer_overflow_control);
+
+	/* Buffer resynch */
+	AST_TEST_REGISTER(jitterbuffer_resynch_voice);
 	AST_TEST_REGISTER(jitterbuffer_resynch_control);
+
 	return AST_MODULE_LOAD_SUCCESS;
 }
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Jitterbuffer Test");
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Jitter Buffer Tests");




More information about the asterisk-commits mailing list