Updated audio test
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/projects/aps-direct@2464 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjmedia/src/pjmedia-audiodev/audiodev.c b/pjmedia/src/pjmedia-audiodev/audiodev.c
index ab72ec0..e2f209d 100644
--- a/pjmedia/src/pjmedia-audiodev/audiodev.c
+++ b/pjmedia/src/pjmedia-audiodev/audiodev.c
@@ -44,6 +44,7 @@
/* The audio subsystem */
static struct aud_subsys
{
+ unsigned init_count;
pj_pool_factory *pf;
unsigned factory_cnt;
@@ -64,6 +65,13 @@
unsigned i;
pj_status_t status = PJ_ENOMEM;
+ /* Allow init() to be called multiple times as long as there is matching
+ * number of shutdown().
+ */
+ if (aud_subsys.init_count++ != 0) {
+ return PJ_SUCCESS;
+ }
+
aud_subsys.pf = pf;
aud_subsys.factory_cnt = 0;
@@ -101,6 +109,14 @@
{
unsigned i;
+ /* Allow shutdown() to be called multiple times as long as there is matching
+ * number of init().
+ */
+ if (aud_subsys.init_count == 0) {
+ return PJ_SUCCESS;
+ }
+ --aud_subsys.init_count;
+
for (i=0; i<aud_subsys.factory_cnt; ++i) {
pjmedia_aud_dev_factory *f = aud_subsys.factories[i].f;
diff --git a/pjmedia/src/pjmedia-audiodev/pa_dev.c b/pjmedia/src/pjmedia-audiodev/pa_dev.c
index 06d273c..0a0e7a2 100644
--- a/pjmedia/src/pjmedia-audiodev/pa_dev.c
+++ b/pjmedia/src/pjmedia-audiodev/pa_dev.c
@@ -685,6 +685,8 @@
const PaStreamInfo *paSI;
PaError err;
+ PJ_ASSERT_RETURN(rec_cb && p_snd_strm, PJ_EINVAL);
+
rec_id = param->rec_id;
if (rec_id < 0) {
rec_id = pa_get_default_input_dev(param->channel_count);
@@ -788,6 +790,8 @@
unsigned paFrames, paRate, paLatency;
PaError err;
+ PJ_ASSERT_RETURN(play_cb && p_snd_strm, PJ_EINVAL);
+
play_id = param->play_id;
if (play_id < 0) {
play_id = pa_get_default_output_dev(param->channel_count);
@@ -898,6 +902,8 @@
unsigned paFrames, paRate, paInputLatency, paOutputLatency;
PaError err;
+ PJ_ASSERT_RETURN(play_cb && rec_cb && p_snd_strm, PJ_EINVAL);
+
rec_id = param->rec_id;
if (rec_id < 0) {
rec_id = pa_get_default_input_dev(param->channel_count);
diff --git a/pjsip-apps/src/samples/auddemo.c b/pjsip-apps/src/samples/auddemo.c
index dbb2b8f..e4cbba5 100644
--- a/pjsip-apps/src/samples/auddemo.c
+++ b/pjsip-apps/src/samples/auddemo.c
@@ -25,6 +25,7 @@
#define THIS_FILE "auddemo.c"
#define MAX_DEVICES 64
+#define WAV_FILE "auddemo.wav"
static unsigned dev_count;
@@ -166,7 +167,7 @@
for (i=0; i<info.ext_fmt_cnt; ++i) {
char bitrate[32];
- switch (info.ext_fmt[i].fmt_id) {
+ switch (info.ext_fmt[i].id) {
case PJMEDIA_FORMAT_L16:
strcat(formats, "L16/");
break;
@@ -275,6 +276,140 @@
}
+static pj_status_t wav_rec_cb(void *user_data, pjmedia_frame *frame)
+{
+ return pjmedia_port_put_frame((pjmedia_port*)user_data, frame);
+}
+
+static void record(unsigned rec_index, const char *filename)
+{
+ pj_pool_t *pool = NULL;
+ pjmedia_port *wav = NULL;
+ pjmedia_aud_dev_param param;
+ pjmedia_aud_stream *strm = NULL;
+ char line[10];
+ pj_status_t status;
+
+ if (filename == NULL)
+ filename = WAV_FILE;
+
+ pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "wav",
+ 1000, 1000, NULL);
+
+ status = pjmedia_wav_writer_port_create(pool, filename, 16000,
+ 1, 320, 16, 0, 0, &wav);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error creating WAV file", status);
+ goto on_return;
+ }
+
+ status = pjmedia_aud_dev_default_param(dev_id[rec_index], ¶m);
+ if (status != PJ_SUCCESS) {
+ app_perror("pjmedia_aud_dev_default_param()", status);
+ goto on_return;
+ }
+
+ param.dir = PJMEDIA_DIR_CAPTURE;
+ param.clock_rate = wav->info.clock_rate;
+ param.samples_per_frame = wav->info.samples_per_frame;
+ param.channel_count = wav->info.channel_count;
+ param.bits_per_sample = wav->info.bits_per_sample;
+
+ status = pjmedia_aud_stream_create(¶m, &wav_rec_cb, NULL, wav,
+ &strm);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error opening the sound device", status);
+ goto on_return;
+ }
+
+ status = pjmedia_aud_stream_start(strm);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error starting the sound device", status);
+ goto on_return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Recording started, press ENTER to stop"));
+ fgets(line, sizeof(line), stdin);
+
+on_return:
+ if (strm) {
+ pjmedia_aud_stream_stop(strm);
+ pjmedia_aud_stream_destroy(strm);
+ }
+ if (wav)
+ pjmedia_port_destroy(wav);
+ if (pool)
+ pj_pool_release(pool);
+}
+
+
+static pj_status_t wav_play_cb(void *user_data, pjmedia_frame *frame)
+{
+ return pjmedia_port_get_frame((pjmedia_port*)user_data, frame);
+}
+
+
+static void play_file(unsigned play_index, const char *filename)
+{
+ pj_pool_t *pool = NULL;
+ pjmedia_port *wav = NULL;
+ pjmedia_aud_dev_param param;
+ pjmedia_aud_stream *strm = NULL;
+ char line[10];
+ pj_status_t status;
+
+ if (filename == NULL)
+ filename = WAV_FILE;
+
+ pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "wav",
+ 1000, 1000, NULL);
+
+ status = pjmedia_wav_player_port_create(pool, filename, 20, 0, 0, &wav);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error opening WAV file", status);
+ goto on_return;
+ }
+
+ status = pjmedia_aud_dev_default_param(dev_id[play_index], ¶m);
+ if (status != PJ_SUCCESS) {
+ app_perror("pjmedia_aud_dev_default_param()", status);
+ goto on_return;
+ }
+
+ param.dir = PJMEDIA_DIR_PLAYBACK;
+ param.clock_rate = wav->info.clock_rate;
+ param.samples_per_frame = wav->info.samples_per_frame;
+ param.channel_count = wav->info.channel_count;
+ param.bits_per_sample = wav->info.bits_per_sample;
+
+ status = pjmedia_aud_stream_create(¶m, NULL, &wav_play_cb, wav,
+ &strm);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error opening the sound device", status);
+ goto on_return;
+ }
+
+ status = pjmedia_aud_stream_start(strm);
+ if (status != PJ_SUCCESS) {
+ app_perror("Error starting the sound device", status);
+ goto on_return;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "Playback started, press ENTER to stop"));
+ fgets(line, sizeof(line), stdin);
+
+on_return:
+ if (strm) {
+ pjmedia_aud_stream_stop(strm);
+ pjmedia_aud_stream_destroy(strm);
+ }
+ if (wav)
+ pjmedia_port_destroy(wav);
+ if (pool)
+ pj_pool_release(pool);
+}
+
+
static void print_menu(void)
{
puts("");
@@ -288,6 +423,8 @@
puts(" CR: clock rate");
puts(" PTIM: ptime in ms");
puts(" CH: # of channels");
+ puts(" r RID [FILE] Record capture device RID to WAV file");
+ puts(" p PID [FILE] Playback WAV file to device ID PID");
puts(" v Toggle log verbosity");
puts(" q Quit");
puts("");
@@ -391,6 +528,40 @@
}
break;
+ case 'r':
+ /* record */
+ {
+ int index;
+ char filename[80];
+ int count;
+
+ count = sscanf(line+2, "%d %s", &index, filename);
+ if (count==1)
+ record(index, NULL);
+ else if (count==2)
+ record(index, filename);
+ else
+ puts("error: invalid command syntax");
+ }
+ break;
+
+ case 'p':
+ /* playback */
+ {
+ int index;
+ char filename[80];
+ int count;
+
+ count = sscanf(line+2, "%d %s", &index, filename);
+ if (count==1)
+ play_file(index, NULL);
+ else if (count==2)
+ play_file(index, filename);
+ else
+ puts("error: invalid command syntax");
+ }
+ break;
+
case 'v':
if (pj_log_get_level() <= 3) {
pj_log_set_level(5);