Skip to content
Snippets Groups Projects
test_jitterbuf.c 34.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	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 = 0;
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "jitterbuffer_overflow_control";
    		info->category = "/main/jitterbuf/";
    		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;
    	}
    
    	test_jb_overflow_frame_insertion(jb, JB_TYPE_CONTROL);
    
    	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;
    }
    
    
    Richard Mudgett's avatar
    Richard Mudgett committed
    /*!
     * \internal
     * \brief Insert frames into the jitter buffer for the resynch tests
     */
    
    static void test_jb_resynch_frame_insertion(struct jitterbuf *jb, enum jb_frame_type frame_type)
    {
    	int i = 0;
    
    	for (i = 0; i < 20; i++) {
    		jb_put(jb, NULL, frame_type, 20, i * 20, i * 20 + 5);
    	}
    
    	for (i = 20; i < 40; i++) {
    		jb_put(jb, NULL, frame_type, 20, i * 20 + 500, i * 20 + 5);
    	}
    }
    
    AST_TEST_DEFINE(jitterbuffer_resynch_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 interpolated_frames = 0;
    	int i;
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "jitterbuffer_resynch_control";
    		info->category = "/main/jitterbuf/";
    		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");
    		goto cleanup;
    	}
    
    	test_jb_populate_config(&jbconf);
    	jbconf.resync_threshold = 200;
    	if (jb_setconf(jb, &jbconf) != JB_OK) {
    		ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
    		goto cleanup;
    	}
    
    	test_jb_resynch_frame_insertion(jb, JB_TYPE_CONTROL);
    
    	for (i = 0; i <= 40; i++) {
    		if (jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN) == JB_INTERP) {
    			++interpolated_frames;
    		}
    	}
    
    	if (jb_getinfo(jb, &jbinfo) != JB_OK) {
    		ast_test_status_update(test, "Failed to get jitterbuffer information\n");
    		goto cleanup;
    	}
    	/* With control frames, a resync happens automatically */
    	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
    	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_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;
    
    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_resynch_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 interpolated_frames = 0;
    	int i;
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "jitterbuffer_resynch_voice";
    		info->category = "/main/jitterbuf/";
    		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");
    		goto cleanup;
    	}
    
    	test_jb_populate_config(&jbconf);
    	jbconf.resync_threshold = 200;
    	if (jb_setconf(jb, &jbconf) != JB_OK) {
    		ast_test_status_update(test, "Failed to set jitterbuffer configuration\n");
    		goto cleanup;
    	}
    
    	test_jb_resynch_frame_insertion(jb, JB_TYPE_VOICE);
    
    	for (i = 0; i <= 40; i++) {
    		if (jb_get(jb, &frame, i * 20 + 5, DEFAULT_CODEC_INTERP_LEN) == JB_INTERP) {
    			++interpolated_frames;
    		}
    	}
    
    	if (jb_getinfo(jb, &jbinfo) != JB_OK) {
    		ast_test_status_update(test, "Failed to get jitterbuffer information\n");
    		goto cleanup;
    	}
    	/* The first three packets before the resync should be dropped */
    	JB_INFO_PRINT_FRAME_DEBUG(jbinfo);
    	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_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;
    
    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;
    }
    
    static int unload_module(void)
    {
    	AST_TEST_UNREGISTER(jitterbuffer_nominal_voice_frames);
    	AST_TEST_UNREGISTER(jitterbuffer_nominal_control_frames);
    	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_lost_control);
    	AST_TEST_UNREGISTER(jitterbuffer_late_voice);
    	AST_TEST_UNREGISTER(jitterbuffer_late_control);
    	AST_TEST_UNREGISTER(jitterbuffer_overflow_voice);
    	AST_TEST_UNREGISTER(jitterbuffer_overflow_control);
    	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);
    
    	/* 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, "Jitter Buffer Tests");