diff options
20 files changed, 496 insertions, 8 deletions
diff --git a/pjsip-apps/src/test-pjsua/inc_cfg.py b/pjsip-apps/src/test-pjsua/inc_cfg.py index 531fd1cb..d8519c3f 100644 --- a/pjsip-apps/src/test-pjsua/inc_cfg.py +++ b/pjsip-apps/src/test-pjsua/inc_cfg.py @@ -1,4 +1,4 @@ -# $Id:$ +# $Id$ import random DEFAULT_ECHO = True @@ -71,13 +71,19 @@ class TestParam: process = [] # the function for test body test_func = None + post_func = None + user_data = None def __init__( self, title, # Test title inst_params, # InstanceParam's as list - func=None): + func=None, + post_func=None, + user_data=None): self.title = title self.inst_params = inst_params self.test_func = func + self.post_func = post_func + self.user_data = user_data diff --git a/pjsip-apps/src/test-pjsua/inc_const.py b/pjsip-apps/src/test-pjsua/inc_const.py index 37c7e96a..dd8d1b1a 100644 --- a/pjsip-apps/src/test-pjsua/inc_const.py +++ b/pjsip-apps/src/test-pjsua/inc_const.py @@ -1,4 +1,4 @@ -# $Id:$ +# $Id$ # Useful constants @@ -34,6 +34,18 @@ MEDIA_ACTIVE = "Media for call [0-9]+ is active" RX_DTMF = "Incoming DTMF on call [0-9]+: " ########################## +# MEDIA +# + +# Connecting/disconnecting ports +MEDIA_CONN_PORT_SUCCESS = "Port \d+ \(.+\) transmitting to port" +MEDIA_DISCONN_PORT_SUCCESS = "Port \d+ \(.+\) stop transmitting to port" + +# Filename to play / record +MEDIA_PLAY_FILE = "--play-file (\S+)" +MEDIA_REC_FILE = "--rec-file (\S+)" + +########################## # MISC # diff --git a/pjsip-apps/src/test-pjsua/mod_call.py b/pjsip-apps/src/test-pjsua/mod_call.py index ff41593f..03023418 100644 --- a/pjsip-apps/src/test-pjsua/mod_call.py +++ b/pjsip-apps/src/test-pjsua/mod_call.py @@ -1,4 +1,4 @@ -# $Id:$ +# $Id$ import time import imp import sys @@ -9,7 +9,7 @@ cfg_file = imp.load_source("cfg_file", sys.argv[2]) # Test body function -def test_func(t): +def test_func(t, user_data): callee = t.process[0] caller = t.process[1] diff --git a/pjsip-apps/src/test-pjsua/mod_media_playrec.py b/pjsip-apps/src/test-pjsua/mod_media_playrec.py new file mode 100644 index 00000000..8d8a60fe --- /dev/null +++ b/pjsip-apps/src/test-pjsua/mod_media_playrec.py @@ -0,0 +1,86 @@ +# $Id$ + +# PLAYFILE -> RECFILE: +# input file is played and is recorded to output, then compare them. +# null-audio +# port 1: wav file input xxxxxx.clock_rate.wav, e.g: test1.8.wav +# port 2: wav file ouput xxxxxx.clock_rate.wav, e.g: res1.8.wav +# wav input more than 3 seconds + +import time +import imp +import sys +import re +import subprocess +import inc_const as const + +# Load configuration +cfg_file = imp.load_source("cfg_file", sys.argv[2]) + +# WAV similarity calculator +COMPARE_WAV_EXE = "tools/cmp_wav.exe" + +# UserData +class mod_media_playrec_user_data: + input_filename = "" + output_filename = "" + +# Test body function +def test_func(t, ud): + endpt = t.process[0] + + # Get input file name + endpt.sync_stdout() + endpt.send("dc") + line = endpt.expect(const.MEDIA_PLAY_FILE) + ud.input_filename = re.compile(const.MEDIA_PLAY_FILE).match(line).group(1) + endpt.trace("Input file = " + ud.input_filename) + + # Get output file name + endpt.sync_stdout() + endpt.send("dc") + line = endpt.expect(const.MEDIA_REC_FILE) + ud.output_filename = re.compile(const.MEDIA_REC_FILE).match(line).group(1) + endpt.trace("Output file = " + ud.output_filename) + + # Find appropriate clock rate for the input file + clock_rate = re.compile(".+(\.\d+\.wav)$").match(ud.output_filename).group(1) + if (clock_rate==None): + endpt.trace("Cannot compare input & output, incorrect output filename format") + return + ud.input_filename = re.sub("\.\d+\.wav$", clock_rate, ud.input_filename) + endpt.trace("WAV file to be compared with output = " + ud.input_filename) + + # Connect input-output file + endpt.sync_stdout() + + endpt.send("cc 1 2") + endpt.expect(const.MEDIA_CONN_PORT_SUCCESS) + + # Wait + time.sleep(3) + + endpt.sync_stdout() + + # Disconnect input-output file + endpt.send("cd 1 2") + endpt.expect(const.MEDIA_DISCONN_PORT_SUCCESS) + + +# Post body function +def post_func(t, ud): + endpt = t.process[0] + + # Check WAV similarity + fullcmd = COMPARE_WAV_EXE + " " + ud.input_filename + " " + ud.output_filename + " " + "3000" + endpt.trace("Popen " + fullcmd) + cmp_proc = subprocess.Popen(fullcmd, stdout=subprocess.PIPE, universal_newlines=True) + line = cmp_proc.stdout.readline() + endpt.trace("WAV similarity = " + line) + + +# Here where it all comes together +test = cfg_file.test_param +test.test_func = test_func +test.post_func = post_func +test.user_data = mod_media_playrec_user_data() diff --git a/pjsip-apps/src/test-pjsua/mod_pres.py b/pjsip-apps/src/test-pjsua/mod_pres.py index e3b996a8..6b6fb2b3 100644 --- a/pjsip-apps/src/test-pjsua/mod_pres.py +++ b/pjsip-apps/src/test-pjsua/mod_pres.py @@ -1,4 +1,4 @@ -# $Id:$ +# $Id$ import time import imp import sys @@ -9,7 +9,7 @@ cfg_file = imp.load_source("cfg_file", sys.argv[2]) # Test body function -def test_func(t): +def test_func(t, user_data): u1 = t.process[0] uri1 = cfg_file.test_param.inst_params[0].uri acc1 = "-1" diff --git a/pjsip-apps/src/test-pjsua/run.py b/pjsip-apps/src/test-pjsua/run.py index 0b374def..34792dad 100644 --- a/pjsip-apps/src/test-pjsua/run.py +++ b/pjsip-apps/src/test-pjsua/run.py @@ -178,7 +178,7 @@ for inst_param in script.test.inst_params: # Run the test function if script.test.test_func != None: try: - script.test.test_func(script.test) + script.test.test_func(script.test, script.test.user_data) except TestError, e: handle_error(e.desc, script.test) @@ -196,6 +196,13 @@ for p in script.test.process: p.expect(const.DESTROYED, False) p.wait() +# Run the post test function +if script.test.post_func != None: + try: + script.test.post_func(script.test, script.test.user_data) + except TestError, e: + handle_error(e.desc, script.test) + # Done print "Test " + script.test.title + " completed successfully" sys.exit(0) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_16.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_16.py new file mode 100644 index 00000000..484fe6d6 --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_16.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 16 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 16000 --play-file wavs/input.11.wav --rec-file wavs/tmp_output.16.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_22.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_22.py new file mode 100644 index 00000000..71f71dcd --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_22.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 22 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 22050 --play-file wavs/input.11.wav --rec-file wavs/tmp_output.22.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_32.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_32.py new file mode 100644 index 00000000..8f9ca47d --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_32.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 32 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 32000 --play-file wavs/input.11.wav --rec-file wavs/tmp_output.32.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_44.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_44.py new file mode 100644 index 00000000..42bba809 --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_44.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 44 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 44100 --play-file wavs/input.11.wav --rec-file wavs/tmp_output.44.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_48.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_48.py new file mode 100644 index 00000000..f4b996b0 --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_48.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 48 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 48000 --play-file wavs/input.11.wav --rec-file wavs/tmp_output.48.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_8.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_8.py new file mode 100644 index 00000000..e502fc4f --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_11_8.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 8 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 8000 --play-file wavs/input.11.wav --rec-file wavs/tmp_output.8.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_11.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_11.py new file mode 100644 index 00000000..8abd534e --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_11.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 11 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 11025 --play-file wavs/input.8.wav --rec-file wavs/tmp_output.11.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_16.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_16.py new file mode 100644 index 00000000..4b19b23f --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_16.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 16 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 16000 --play-file wavs/input.8.wav --rec-file wavs/tmp_output.16.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_22.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_22.py new file mode 100644 index 00000000..092b6396 --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_22.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 22 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 22050 --play-file wavs/input.8.wav --rec-file wavs/tmp_output.22.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_32.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_32.py new file mode 100644 index 00000000..a3c91330 --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_32.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 32 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 32000 --play-file wavs/input.8.wav --rec-file wavs/tmp_output.32.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_44.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_44.py new file mode 100644 index 00000000..90f99df1 --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_44.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 44 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 44100 --play-file wavs/input.8.wav --rec-file wavs/tmp_output.44.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_48.py b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_48.py new file mode 100644 index 00000000..bdb82a37 --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-media-playrec/100_resample_lf_8_48.py @@ -0,0 +1,11 @@ +# $Id$ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 48 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 48000 --play-file wavs/input.8.wav --rec-file wavs/tmp_output.48.wav") + ] + ) diff --git a/pjsip-apps/src/test-pjsua/tools/cmp_wav.c b/pjsip-apps/src/test-pjsua/tools/cmp_wav.c new file mode 100644 index 00000000..398a7210 --- /dev/null +++ b/pjsip-apps/src/test-pjsua/tools/cmp_wav.c @@ -0,0 +1,245 @@ +/* $Id$ */ + +#include <pjmedia.h> +#include <pjlib-util.h> +#include <pjlib.h> +#include <stdio.h> +#include <stdlib.h> + +#define app_perror(a,b,c) printf("%s: %s (%d)", a, b, c) + + +/* For logging purpose. */ +#define THIS_FILE "cmp_wav.c" +#define BYTES_PER_FRAME 512 + +static const char *desc = +" FILE \n" +" \n" +" cmp_wav.c \n" +" \n" +" PURPOSE \n" +" \n" +" Compare two WAV files. \n" +" \n" +" USAGE \n" +" \n" +" cmp_wav ORIGINAL_WAV DEGRADED_WAV [TIME] [DETAIL] \n" +" \n" +" ORIGINAL_WAV The original WAV file as reference. \n" +" DEGRADED_WAV The degraded WAV file. \n" +" TIME Compare only some part of the files \n" +" (in ms, since the beginning). \n" +" Specify 0 (default) to compare the whole time. \n" +" DETAIL Show detail result, 1 or 0 (default=0, means no)\n" +" \n" +" Both files must have same clock rate and must contain \n" +" uncompressed (i.e. 16bit) PCM. \n"; + + +/* Sum of multiplication of corresponding samples in buf1 & buf2 */ +double sum_mult_sig(pj_int16_t *buf1, pj_int16_t *buf2, unsigned nsamples) +{ + double mag = 0; + + while (nsamples--) + mag += (double)*buf1++ * (double)*buf2++; + + return mag; +} + + +/* + * main() + */ +int main(int argc, char *argv[]) +{ + pj_caching_pool cp; + pjmedia_endpt *med_endpt; + pj_pool_t *pool; + pjmedia_port *file_ori_port; + pjmedia_port *file_deg_port; + pj_status_t status; + unsigned first_nsamples = 0; + unsigned samples_compared = 0; + + char buf1[BYTES_PER_FRAME]; + char buf2[BYTES_PER_FRAME]; + + double ref_mag = 0; + double deg_mag = 0; + double mix_mag = 0; + + int detail = 0; + int res_deg, res_mix, res_overall; + + if (argc < 3) { + puts("Error: original & degraded filename required"); + puts(desc); + return 1; + } + + /* Set log level. */ + pj_log_set_level(3); + + /* Must init PJLIB first: */ + status = pj_init(); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); + + /* Must create a pool factory before we can allocate any memory. */ + pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0); + + /* + * Initialize media endpoint. + * This will implicitly initialize PJMEDIA too. + */ + status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); + + /* Create memory pool for our file player */ + pool = pj_pool_create( &cp.factory, /* pool factory */ + "wav", /* pool name. */ + 4000, /* init size */ + 4000, /* increment size */ + NULL /* callback on error */ + ); + + /* Create file media port from the original WAV file */ + status = pjmedia_wav_player_port_create( pool, /* memory pool */ + argv[1], /* file to play */ + 40, /* ptime. */ + PJMEDIA_FILE_NO_LOOP, /* flags */ + 0, /* default buffer */ + &file_ori_port/* returned port */ + ); + if (status != PJ_SUCCESS) { + app_perror(THIS_FILE, "Unable to use WAV file", status); + return 1; + } + + /* Create file media port from the degraded WAV file */ + status = pjmedia_wav_player_port_create( pool, /* memory pool */ + argv[2], /* file to play */ + 40, /* ptime. */ + PJMEDIA_FILE_NO_LOOP, /* flags */ + 0, /* default buffer */ + &file_deg_port/* returned port */ + ); + if (status != PJ_SUCCESS) { + app_perror(THIS_FILE, "Unable to use WAV file", status); + return 1; + } + + if (file_ori_port->info.clock_rate != file_deg_port->info.clock_rate) { + app_perror(THIS_FILE, "Clock rates must be same.", PJ_EINVAL); + return 1; + } + + if (argc > 3) + first_nsamples = atoi(argv[3]) * file_ori_port->info.clock_rate / 1000; + + if (argc > 4) + detail = atoi(argv[4]); + + while (1) { + pjmedia_frame f1, f2; + + f1.buf = buf1; + f1.size = BYTES_PER_FRAME; + f2.buf = buf2; + f2.size = BYTES_PER_FRAME; + + status = pjmedia_port_get_frame(file_ori_port, &f1); + if (status == PJ_EEOF) { + break; + } else if (status != PJ_SUCCESS) { + app_perror(THIS_FILE, "Error occured while reading file", status); + break; + } + status = pjmedia_port_get_frame(file_deg_port, &f2); + if (status == PJ_EEOF) { + break; + } else if (status != PJ_SUCCESS) { + app_perror(THIS_FILE, "Error occured while reading file", status); + break; + } + + /* Calculate magnitudes */ + ref_mag += sum_mult_sig(f1.buf, f1.buf, BYTES_PER_FRAME >> 1); + deg_mag += sum_mult_sig(f2.buf, f2.buf, BYTES_PER_FRAME >> 1); + mix_mag += sum_mult_sig(f1.buf, f2.buf, BYTES_PER_FRAME >> 1); + + samples_compared += BYTES_PER_FRAME >> 1; + if (first_nsamples && samples_compared >= first_nsamples) + break; + } + + /* Degraded magnitude compared to reference magnitude + */ + res_deg = (int) (deg_mag / ref_mag * 100.0); + if (res_deg < 0) + res_deg = -1; + else if (res_deg >= 81) + res_deg = 9; + else + res_deg = pj_isqrt(res_deg); + + /* Mixed magnitude (don't know what this is actually :D) compared to + * reference magnitude + */ + res_mix = (int) (mix_mag / ref_mag * 100.0); + if (res_mix < 0) + res_mix = -1; + else if (res_mix >= 81) + res_mix = 9; + else + res_mix = pj_isqrt(res_mix); + + /* Overall score. + * If mixed score is -1, then overall score should be -1 as well. + * Apply no weighting (1:1) for now. + */ + if (res_mix == -1) + res_overall = -1; + else + res_overall = (res_mix*1 + res_deg*1) / 2; + + if (detail) { + printf("Reference = %.0f\n", ref_mag); + printf("Degraded = %.0f\n", deg_mag); + printf("Mixed = %.0f\n", mix_mag); + + printf("\n"); + + printf("Score 1 = %d\n", res_deg); + printf("Score 2 = %d\n", res_mix); + + printf("\n"); + } + + printf("Overall = %d\n", res_overall); + + /* Destroy file port */ + status = pjmedia_port_destroy( file_ori_port ); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); + + status = pjmedia_port_destroy( file_deg_port ); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); + + /* Release application pool */ + pj_pool_release( pool ); + + /* Destroy media endpoint. */ + pjmedia_endpt_destroy( med_endpt ); + + /* Destroy pool factory */ + pj_caching_pool_destroy( &cp ); + + /* Shutdown PJLIB */ + pj_shutdown(); + + + /* Done. */ + return 0; +} + diff --git a/pjsip-apps/src/test-pjsua/tools/cmp_wav.exe b/pjsip-apps/src/test-pjsua/tools/cmp_wav.exe Binary files differnew file mode 100644 index 00000000..6220771b --- /dev/null +++ b/pjsip-apps/src/test-pjsua/tools/cmp_wav.exe |