diff options
Diffstat (limited to 'pjmedia/src/pjmedia-audiodev')
-rw-r--r-- | pjmedia/src/pjmedia-audiodev/alsa_dev.c | 4 | ||||
-rw-r--r-- | pjmedia/src/pjmedia-audiodev/bb10_dev.c | 364 | ||||
-rw-r--r-- | pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp | 58 | ||||
-rw-r--r-- | pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp | 62 |
4 files changed, 342 insertions, 146 deletions
diff --git a/pjmedia/src/pjmedia-audiodev/alsa_dev.c b/pjmedia/src/pjmedia-audiodev/alsa_dev.c index 72b995e..31b3b06 100644 --- a/pjmedia/src/pjmedia-audiodev/alsa_dev.c +++ b/pjmedia/src/pjmedia-audiodev/alsa_dev.c @@ -1,4 +1,4 @@ -/* $Id: alsa_dev.c 4130 2012-05-17 08:35:51Z nanang $ */ +/* $Id: alsa_dev.c 4283 2012-10-12 06:19:32Z ming $ */ /* * Copyright (C) 2009-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2007-2009 Keystream AB and Konftel AB, All rights reserved. @@ -232,7 +232,7 @@ static pj_status_t add_dev (struct alsa_factory *af, const char *dev_name) pj_bzero(adi, sizeof(*adi)); /* Set device name */ - strcpy(adi->name, dev_name); + strncpy(adi->name, dev_name, sizeof(adi->name)); /* Check the number of playback channels */ adi->output_count = (pb_result>=0) ? 1 : 0; diff --git a/pjmedia/src/pjmedia-audiodev/bb10_dev.c b/pjmedia/src/pjmedia-audiodev/bb10_dev.c index 418256d..f920080 100644 --- a/pjmedia/src/pjmedia-audiodev/bb10_dev.c +++ b/pjmedia/src/pjmedia-audiodev/bb10_dev.c @@ -1,4 +1,4 @@ -/* $Id: bb10_dev.c 4151 2012-06-01 04:49:57Z ming $ */ +/* $Id: bb10_dev.c 4340 2013-02-05 05:15:01Z bennylp $ */ /* * Copyright (C) 2008-2012 Teluu Inc. (http://www.teluu.com) * @@ -33,6 +33,11 @@ #if defined(PJMEDIA_AUDIO_DEV_HAS_BB10) && PJMEDIA_AUDIO_DEV_HAS_BB10 != 0 +#ifndef PJ_BBSDK_VER + /* Format: 0xMMNNRR: MM: major, NN: minor, RR: revision */ +# define PJ_BBSDK_VER 0x100006 +#endif + #include <sys/time.h> #include <sys/types.h> #include <unistd.h> @@ -40,6 +45,9 @@ #include <pthread.h> #include <errno.h> #include <sys/asoundlib.h> +#if PJ_BBSDK_VER >= 0x100006 +#include <audio/audio_manager_routing.h> +#endif #define THIS_FILE "bb10_dev.c" @@ -114,8 +122,9 @@ struct bb10_stream int quit; /* Playback */ + unsigned int pb_ctrl_audio_manager_handle; snd_pcm_t *pb_pcm; - snd_mixer_t *pb_mixer; + unsigned int pb_audio_manager_handle; unsigned long pb_frames; /* samples_per_frame */ pjmedia_aud_play_cb pb_cb; unsigned pb_buf_size; @@ -124,7 +133,7 @@ struct bb10_stream /* Capture */ snd_pcm_t *ca_pcm; - snd_mixer_t *ca_mixer; + unsigned int ca_audio_manager_handle; unsigned long ca_frames; /* samples_per_frame */ pjmedia_aud_rec_cb ca_cb; unsigned ca_buf_size; @@ -160,8 +169,7 @@ static pj_status_t bb10_add_dev (struct bb10_factory *af) { pjmedia_aud_dev_info *adi; int pb_result, ca_result; - int card = -1; - int dev = 0; + unsigned int handle; snd_pcm_t *pcm_handle; if (af->dev_cnt >= PJ_ARRAY_SIZE(af->devs)) @@ -171,20 +179,29 @@ static pj_status_t bb10_add_dev (struct bb10_factory *af) TRACE_((THIS_FILE, "bb10_add_dev Enter")); - if ((pb_result = snd_pcm_open_preferred (&pcm_handle, &card, &dev, - SND_PCM_OPEN_PLAYBACK)) >= 0) + if ((pb_result = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT, + &pcm_handle, + &handle, + (char*)"voice", + SND_PCM_OPEN_PLAYBACK)) + >= 0) { - TRACE_((THIS_FILE, "Try to open the device for playback - success")); snd_pcm_close (pcm_handle); + audio_manager_free_handle(handle); } else { TRACE_((THIS_FILE, "Try to open the device for playback - failure")); } - if ((ca_result = snd_pcm_open_preferred (&pcm_handle, &card, &dev, - SND_PCM_OPEN_CAPTURE)) >=0) + if ((ca_result = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT, + &pcm_handle, + &handle, + (char*)"voice", + SND_PCM_OPEN_CAPTURE)) + >= 0) { - TRACE_((THIS_FILE, "Try to open the device for capture - success")); - snd_pcm_close (pcm_handle); + snd_pcm_close (pcm_handle); + audio_manager_free_handle(handle); + } else { TRACE_((THIS_FILE, "Try to open the device for capture - failure")); } @@ -239,7 +256,7 @@ pjmedia_aud_dev_factory* pjmedia_bb10_factory(pj_pool_factory *pf) static pj_status_t bb10_factory_init(pjmedia_aud_dev_factory *f) { pj_status_t status; - + status = bb10_factory_refresh(f); if (status != PJ_SUCCESS) return status; @@ -314,7 +331,7 @@ static pj_status_t bb10_factory_get_dev_info(pjmedia_aud_dev_factory *f, pj_memcpy(info, &af->devs[index], sizeof(*info)); info->caps = PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY | PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY; - + return PJ_SUCCESS; } @@ -358,7 +375,7 @@ static pj_status_t bb10_factory_default_param(pjmedia_aud_dev_factory *f, TRACE_((THIS_FILE, "bb10_factory_default_param clock = %d flags = %d" " spf = %d", param->clock_rate, param->flags, param->samples_per_frame)); - + return PJ_SUCCESS; } @@ -368,14 +385,16 @@ static void close_play_pcm(struct bb10_stream *stream) if (stream != NULL && stream->pb_pcm != NULL) { snd_pcm_close(stream->pb_pcm); stream->pb_pcm = NULL; - } -} -static void close_play_mixer(struct bb10_stream *stream) -{ - if (stream != NULL && stream->pb_mixer != NULL) { - snd_mixer_close(stream->pb_mixer); - stream->pb_mixer = NULL; + if (stream->pb_audio_manager_handle != 0) { + audio_manager_free_handle(stream->pb_audio_manager_handle); + stream->pb_audio_manager_handle = 0; + } + + if (stream->pb_ctrl_audio_manager_handle != 0) { + audio_manager_free_handle(stream->pb_ctrl_audio_manager_handle); + stream->pb_ctrl_audio_manager_handle = 0; + } } } @@ -391,14 +410,11 @@ static void close_capture_pcm(struct bb10_stream *stream) if (stream != NULL && stream->ca_pcm != NULL) { snd_pcm_close(stream->ca_pcm); stream->ca_pcm = NULL; - } -} -static void close_capture_mixer(struct bb10_stream *stream) -{ - if (stream != NULL && stream->ca_mixer != NULL) { - snd_mixer_close(stream->ca_mixer); - stream->ca_mixer = NULL; + if (stream->ca_audio_manager_handle != 0) { + audio_manager_free_handle(stream->ca_audio_manager_handle); + stream->ca_audio_manager_handle = 0; + } } } @@ -435,10 +451,9 @@ static int pb_thread_func (void *arg) if ((result = snd_pcm_plugin_prepare(stream->pb_pcm, SND_PCM_CHANNEL_PLAYBACK)) < 0) { - close_play_mixer(stream); close_play_pcm(stream); TRACE_((THIS_FILE, "pb_thread_func failed prepare = %d", result)); - return PJ_SUCCESS; + return PJ_SUCCESS; } while (!stream->quit) { @@ -451,6 +466,7 @@ static int pb_thread_func (void *arg) frame.timestamp.u64 = tstamp.u64; frame.bit_info = 0; + /* Read the audio from pjmedia */ result = stream->pb_cb (user_data, &frame); if (result != PJ_SUCCESS || stream->quit) break; @@ -460,18 +476,45 @@ static int pb_thread_func (void *arg) /* Write 640 to play unit */ result = snd_pcm_plugin_write(stream->pb_pcm,buf,size); - if (result != size) { - TRACE_((THIS_FILE, "pb_thread_func failed write = %d", result)); + if (result != size || result < 0) { + /* either the write to output device has failed or not the + * full amount of bytes have been written. This usually happens + * when audio routing is being changed by another thread + * Use a status variable for reading the error + */ + snd_pcm_channel_status_t status; + status.channel = SND_PCM_CHANNEL_PLAYBACK; + if (snd_pcm_plugin_status (stream->pb_pcm, &status) < 0) { + /* Call has failed nothing we can do except log and + * continue */ + PJ_LOG(4,(THIS_FILE, + "underrun: playback channel status error")); + } else { + /* The status of the error has been read + * RIM say these are expected so we can "re-prepare" the stream + */ + PJ_LOG(4,(THIS_FILE,"PLAY thread ERROR status = %d", + status.status)); + if (status.status == SND_PCM_STATUS_READY || + status.status == SND_PCM_STATUS_UNDERRUN || + status.status == SND_PCM_STATUS_ERROR ) + { + if (snd_pcm_plugin_prepare (stream->pb_pcm, + SND_PCM_CHANNEL_PLAYBACK) < 0) + { + PJ_LOG(4,(THIS_FILE, + "underrun: playback channel prepare error")); + } + } + } } - tstamp.u64 += nframes; } flush_play(stream); - close_play_mixer(stream); close_play_pcm(stream); TRACE_((THIS_FILE, "pb_thread_func: Stopped")); - + return PJ_SUCCESS; } @@ -513,29 +556,58 @@ static int ca_thread_func (void *arg) if ((result = snd_pcm_plugin_prepare (stream->ca_pcm, SND_PCM_CHANNEL_CAPTURE)) < 0) { - close_capture_mixer(stream); close_capture_pcm(stream); TRACE_((THIS_FILE, "ca_thread_func failed prepare = %d", result)); - return PJ_SUCCESS; + return PJ_SUCCESS; } while (!stream->quit) { pjmedia_frame frame; pj_bzero (buf, size); - + + /* read the input device */ result = snd_pcm_plugin_read(stream->ca_pcm, buf,size); - if (result == -EPIPE) { - PJ_LOG (4,(THIS_FILE, "ca_thread_func: overrun!")); - snd_pcm_plugin_prepare (stream->ca_pcm, SND_PCM_CHANNEL_CAPTURE); - continue; - } else if (result < 0) { - PJ_LOG (4,(THIS_FILE, "ca_thread_func: error reading data!")); + if(result <0 || result != size) { + /* We expect result to be size (640) + * It's not so we have to read the status error and "prepare" + * the channel. This usually happens when output audio routing + * has been changed by another thread. + * We won't "continue", instead just do what we can and leave + * the end of the loop to write what's in the buffer. Not entirely + * correct but saves a potential underrun in PJMEDIA + */ + PJ_LOG (4,(THIS_FILE, + "snd_pcm_plugin_read ERROR read = %d required = %d", + result,size)); + snd_pcm_channel_status_t status; + status.channel = SND_PCM_CHANNEL_CAPTURE; + if ((result = snd_pcm_plugin_status (stream->ca_pcm, &status)) < 0) + { + /* Should not fail but all we can do is continue */ + PJ_LOG(4,(THIS_FILE, "capture: snd_pcm_plugin_status ret = %d", + result)); + } else { + /* RIM say these are the errors that we should "prepare" + * after */ + if (status.status == SND_PCM_STATUS_READY || + status.status == SND_PCM_STATUS_OVERRUN || + status.status == SND_PCM_STATUS_ERROR) + { + if (snd_pcm_plugin_prepare (stream->ca_pcm, + SND_PCM_CHANNEL_CAPTURE) < 0) + { + PJ_LOG (4,(THIS_FILE, + "overrun: capture channel prepare error")); + } + } + } } if (stream->quit) break; + /* Write the capture audio data to PJMEDIA */ frame.type = PJMEDIA_FRAME_TYPE_AUDIO; frame.buf = (void *) buf; frame.size = size; @@ -550,19 +622,68 @@ static int ca_thread_func (void *arg) } flush_capture(stream); - close_capture_mixer(stream); close_capture_pcm(stream); TRACE_((THIS_FILE, "ca_thread_func: Stopped")); return PJ_SUCCESS; } +/* Audio routing, speaker/headset */ +static pj_status_t bb10_initialize_playback_ctrl(struct bb10_stream *stream, + bool speaker) +{ + /* Although the play and capture have audio manager handles, audio routing + * requires a separate handle + */ + int ret = PJ_SUCCESS; + + if (stream->pb_ctrl_audio_manager_handle == 0) { + /* lazy init an audio manager handle */ + ret = audio_manager_get_handle(AUDIO_TYPE_VIDEO_CHAT, 0, false, + &stream->pb_ctrl_audio_manager_handle); + if (ret != 0) { + TRACE_((THIS_FILE, "audio_manager_get_handle ret = %d",ret)); + return PJMEDIA_EAUD_SYSERR; + } + } + + /* Set for either speaker or earpiece */ + if (speaker) { + ret = audio_manager_set_handle_type( + stream->pb_ctrl_audio_manager_handle, + AUDIO_TYPE_VIDEO_CHAT, + AUDIO_DEVICE_SPEAKER, + AUDIO_DEVICE_DEFAULT); + } else { + ret = audio_manager_set_handle_type( + stream->pb_ctrl_audio_manager_handle, + AUDIO_TYPE_VIDEO_CHAT, + AUDIO_DEVICE_HANDSET, + AUDIO_DEVICE_DEFAULT); + } + + if (ret == 0) { + /* RIM recommend this call */ + ret = audio_manager_set_handle_routing_conditions( + stream->pb_ctrl_audio_manager_handle, + SETTINGS_RESET_ON_DEVICE_CONNECTION); + if (ret != 0) { + TRACE_((THIS_FILE, + "audio_manager_set_handle_routing_conditions ret = %d", + ret)); + return PJMEDIA_EAUD_SYSERR; + } + } else { + TRACE_((THIS_FILE, "audio_manager_set_handle_type ret = %d", ret)); + return PJMEDIA_EAUD_SYSERR; + } + + return PJ_SUCCESS; +} static pj_status_t bb10_open_playback (struct bb10_stream *stream, const pjmedia_aud_param *param) { - int card = -1; - int dev = 0; int ret = 0; snd_pcm_channel_info_t pi; snd_pcm_channel_setup_t setup; @@ -575,34 +696,54 @@ static pj_status_t bb10_open_playback (struct bb10_stream *stream, return PJMEDIA_EAUD_INVDEV; } - if ((ret = snd_pcm_open_preferred (&stream->pb_pcm, &card, &dev, - SND_PCM_OPEN_PLAYBACK)) < 0) + /* Use the bb10 audio manager API to open as opposed to QNX core audio + * Echo cancellation built in + */ + if ((ret = audio_manager_snd_pcm_open_name( + AUDIO_TYPE_VIDEO_CHAT, + &stream->pb_pcm, &stream->pb_audio_manager_handle, + (char*)"voice", + SND_PCM_OPEN_PLAYBACK)) < 0) { - TRACE_((THIS_FILE, "snd_pcm_open_preferred ret = %d", ret)); + TRACE_((THIS_FILE, "audio_manager_snd_pcm_open_name ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } + /* Required call from January 2013 gold OS release */ + if ((ret = snd_pcm_plugin_set_disable(stream->pb_pcm, + PLUGIN_DISABLE_MMAP)) < 0) + { + TRACE_((THIS_FILE, "snd_pcm_plugin_set_disable ret = %d", ret)); + return PJMEDIA_EAUD_SYSERR; + } + + /* Required call from January 2013 gold OS release */ + if ((ret = snd_pcm_plugin_set_enable(stream->pb_pcm, + PLUGIN_ROUTING)) < 0) + { + TRACE_((THIS_FILE, "snd_pcm_plugin_set_enable ret = %d", ret)); + return PJMEDIA_EAUD_SYSERR; + } + /* TODO PJ_ZERO */ memset (&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((ret = snd_pcm_plugin_info (stream->pb_pcm, &pi)) < 0) { - TRACE_((THIS_FILE, "snd_pcm_plugin_info ret = %d", ret)); - return PJMEDIA_EAUD_SYSERR; + TRACE_((THIS_FILE, "snd_pcm_plugin_info ret = %d", ret)); + return PJMEDIA_EAUD_SYSERR; } memset (&pp, 0, sizeof (pp)); - /* Request VoIP compatible capabilities - * On simulator frag_size is always negotiated to 170 - */ + /* Request VoIP compatible capabilities */ pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_PLAYBACK; pp.start_mode = SND_PCM_START_DATA; pp.stop_mode = SND_PCM_STOP_ROLLOVER; /* HARD CODE for the time being PJMEDIA expects 640 for 16khz */ pp.buf.block.frag_size = PREFERRED_FRAME_SIZE*2; - /* Increasing this internal buffer count delays write failure in the loop */ - pp.buf.block.frags_max = 4; + /* RIM recommends maximum of 3 */ + pp.buf.block.frags_max = 3; pp.buf.block.frags_min = 1; pp.format.interleave = 1; /* HARD CODE for the time being PJMEDIA expects 16khz */ @@ -622,7 +763,7 @@ static pj_status_t bb10_open_playback (struct bb10_stream *stream, memset (&group, 0, sizeof (group)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mixer_gid = &group.gid; - + if ((ret = snd_pcm_plugin_setup (stream->pb_pcm, &setup)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_setup ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; @@ -631,14 +772,6 @@ static pj_status_t bb10_open_playback (struct bb10_stream *stream, if (group.gid.name[0] == 0) { return PJMEDIA_EAUD_SYSERR; } - - if ((ret = snd_mixer_open (&stream->pb_mixer, card, - setup.mixer_device)) < 0) - { - TRACE_((THIS_FILE, "snd_mixer_open ret = %d", ret)); - return PJMEDIA_EAUD_SYSERR; - } - rate = param->clock_rate; /* Set the sound device buffer size and latency */ @@ -658,7 +791,7 @@ static pj_status_t bb10_open_playback (struct bb10_stream *stream, TRACE_((THIS_FILE, "bb10_open_playback: pb_frames = %d clock = %d", stream->pb_frames, param->clock_rate)); - + return PJ_SUCCESS; } @@ -668,8 +801,6 @@ static pj_status_t bb10_open_capture (struct bb10_stream *stream, int ret = 0; unsigned int rate; unsigned long tmp_buf_size; - int card = -1; - int dev = 0; int frame_size; snd_pcm_channel_info_t pi; snd_mixer_group_t group; @@ -679,11 +810,27 @@ static pj_status_t bb10_open_capture (struct bb10_stream *stream, if (param->rec_id < 0 || param->rec_id >= stream->af->dev_cnt) return PJMEDIA_EAUD_INVDEV; - /* BB10 Audio init here (not prepare) */ - if ((ret = snd_pcm_open_preferred (&stream->ca_pcm, &card, &dev, - SND_PCM_OPEN_CAPTURE)) < 0) + if ((ret=audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT, + &stream->ca_pcm, + &stream->ca_audio_manager_handle, + (char*)"voice", + SND_PCM_OPEN_CAPTURE)) < 0) + { + TRACE_((THIS_FILE, "audio_manager_snd_pcm_open_name ret = %d", ret)); + return PJMEDIA_EAUD_SYSERR; + } + /* Required call from January 2013 gold OS release */ + if ((ret = snd_pcm_plugin_set_disable (stream->ca_pcm, + PLUGIN_DISABLE_MMAP)) < 0) { - TRACE_((THIS_FILE, "snd_pcm_open_preferred ret = %d", ret)); + TRACE_(("snd_pcm_plugin_set_disable failed: %d",ret)); + return PJMEDIA_EAUD_SYSERR; + } + /* Required call from January 2013 gold OS release */ + if ((ret = snd_pcm_plugin_set_enable(stream->ca_pcm, + PLUGIN_ROUTING)) < 0) + { + TRACE_(("snd_pcm_plugin_set_enable failed: %d",ret)); return PJMEDIA_EAUD_SYSERR; } @@ -707,8 +854,8 @@ static pj_status_t bb10_open_capture (struct bb10_stream *stream, pp.stop_mode = SND_PCM_STOP_ROLLOVER; /* HARD CODE for the time being PJMEDIA expects 640 for 16khz */ pp.buf.block.frag_size = PREFERRED_FRAME_SIZE*2; - /* Not applicable for capture hence -1 */ - pp.buf.block.frags_max = -1; + /* From January 2013 gold OS release. RIM recommend these for capture */ + pp.buf.block.frags_max = 1; pp.buf.block.frags_min = 1; pp.format.interleave = 1; /* HARD CODE for the time being PJMEDIA expects 16khz */ @@ -740,18 +887,8 @@ static pj_status_t bb10_open_capture (struct bb10_stream *stream, } else { } - if ((ret = snd_mixer_open (&stream->ca_mixer, card, - setup.mixer_device)) < 0) - { - TRACE_((THIS_FILE,"snd_mixer_open ret = %d",ret)); - return PJMEDIA_EAUD_SYSERR; - } - - /* frag_size should be 160 */ frame_size = setup.buf.block.frag_size; - /* END BB10 init */ - /* Set clock rate */ rate = param->clock_rate; stream->ca_frames = (unsigned long) param->samples_per_frame / @@ -820,7 +957,6 @@ static pj_status_t bb10_factory_create_stream(pjmedia_aud_dev_factory *f, status = bb10_open_capture (stream, param); if (status != PJ_SUCCESS) { if (param->dir & PJMEDIA_DIR_PLAYBACK) { - close_play_mixer(stream); close_play_pcm(stream); } pj_pool_release (pool); @@ -828,12 +964,24 @@ static pj_status_t bb10_factory_create_stream(pjmedia_aud_dev_factory *f, } } + /* Part of the play functionality but the RIM/Truphone loopback sample + * initialializes after the play and capture + * "false" is default/earpiece for output + */ + status = bb10_initialize_playback_ctrl(stream,false); + if (status != PJ_SUCCESS) { + return PJMEDIA_EAUD_SYSERR; + } + *p_strm = &stream->base; return PJ_SUCCESS; } -/* API: get running parameter */ +/* + * API: get running parameter + * based on ALSA template + */ static pj_status_t bb10_stream_get_param(pjmedia_aud_stream *s, pjmedia_aud_param *pi) { @@ -847,7 +995,10 @@ static pj_status_t bb10_stream_get_param(pjmedia_aud_stream *s, } -/* API: get capability */ +/* + * API: get capability + * based on ALSA template +*/ static pj_status_t bb10_stream_get_cap(pjmedia_aud_stream *s, pjmedia_aud_dev_cap cap, void *pval) @@ -862,28 +1013,51 @@ static pj_status_t bb10_stream_get_cap(pjmedia_aud_stream *s, /* Recording latency */ *(unsigned*)pval = stream->param.input_latency_ms; return PJ_SUCCESS; + } else if (cap==PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY && (stream->param.dir & PJMEDIA_DIR_PLAYBACK)) { /* Playback latency */ *(unsigned*)pval = stream->param.output_latency_ms; return PJ_SUCCESS; + } else { return PJMEDIA_EAUD_INVCAP; } } -/* API: set capability */ +/* + * API: set capability + * Currently just supporting toggle between speaker and earpiece + */ static pj_status_t bb10_stream_set_cap(pjmedia_aud_stream *strm, pjmedia_aud_dev_cap cap, const void *value) { - PJ_UNUSED_ARG(strm); - PJ_UNUSED_ARG(cap); - PJ_UNUSED_ARG(value); + pj_status_t ret = PJ_SUCCESS; + struct bb10_stream *stream = (struct bb10_stream*)strm; + + if (cap != PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE || value == NULL) { + TRACE_((THIS_FILE,"bb10_stream_set_cap() = PJMEDIA_EAUD_INVCAP")); + return PJMEDIA_EAUD_INVCAP; + + } else { + pjmedia_aud_dev_route route = *((pjmedia_aud_dev_route*)value); + /* Use the initialization function which lazy-inits the + * handle for routing + */ + if (route == PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER) { + ret = bb10_initialize_playback_ctrl(stream,true); + } else { + ret = bb10_initialize_playback_ctrl(stream,false); + } + } - return PJMEDIA_EAUD_INVCAP; + if (ret != PJ_SUCCESS) { + TRACE_((THIS_FILE,"bb10_stream_set_cap() = %d",ret)); + } + return ret; } @@ -952,7 +1126,7 @@ static pj_status_t bb10_stream_stop (pjmedia_aud_stream *s) static pj_status_t bb10_stream_destroy (pjmedia_aud_stream *s) { struct bb10_stream *stream = (struct bb10_stream*)s; - + TRACE_((THIS_FILE,"bb10_stream_destroy()")); bb10_stream_stop (s); diff --git a/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp b/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp index d2c6564..9b60ae1 100644 --- a/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp +++ b/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp @@ -1,4 +1,4 @@ -/* $Id: symb_aps_dev.cpp 3841 2011-10-24 09:28:13Z ming $ */ +/* $Id: symb_aps_dev.cpp 4243 2012-08-31 11:42:17Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> @@ -973,7 +973,8 @@ static void RecCb(TAPSCommBuffer &buf, void *user_data) { unsigned samples_got; - samples_got = strm->param.ext_fmt.bitrate == 15200? 160 : 240; + samples_got = + strm->param.ext_fmt.det.aud.avg_bps == 15200? 160 : 240; /* Check if we got a normal frame. */ if (buf.iBuffer[0] == 1 && buf.iBuffer[1] == 0) { @@ -1171,9 +1172,9 @@ static void PlayCb(TAPSCommBuffer &buf, void *user_data) sf = pjmedia_frame_ext_get_subframe(frame, 0); samples_cnt = frame->samples_cnt / frame->subframe_cnt; - pj_assert((strm->param.ext_fmt.bitrate == 15200 && + pj_assert((strm->param.ext_fmt.det.aud.avg_bps == 15200 && samples_cnt == 160) || - (strm->param.ext_fmt.bitrate != 15200 && + (strm->param.ext_fmt.det.aud.avg_bps != 15200 && samples_cnt == 240)); if (sf->data && sf->bitlen) { @@ -1391,34 +1392,41 @@ static pj_status_t factory_init(pjmedia_aud_dev_factory *f) } if (supported) { + pjmedia_format ext_fmt; + switch(i) { case 0: /* AMRNB */ - af->dev_info.ext_fmt[fmt_cnt].id = PJMEDIA_FORMAT_AMR; - af->dev_info.ext_fmt[fmt_cnt].bitrate = 7400; - af->dev_info.ext_fmt[fmt_cnt].vad = PJ_TRUE; + pjmedia_format_init_audio(&ext_fmt, PJMEDIA_FORMAT_AMR, + 8000, 1, 16, 20, 7400, 12200); + af->dev_info.ext_fmt[fmt_cnt] = ext_fmt; + //af->dev_info.ext_fmt[fmt_cnt].vad = PJ_TRUE; ++fmt_cnt; break; case 1: /* G.711 */ - af->dev_info.ext_fmt[fmt_cnt].id = PJMEDIA_FORMAT_PCMU; - af->dev_info.ext_fmt[fmt_cnt].bitrate = 64000; - af->dev_info.ext_fmt[fmt_cnt].vad = PJ_FALSE; + pjmedia_format_init_audio(&ext_fmt, PJMEDIA_FORMAT_PCMU, + 8000, 1, 16, 20, 64000, 64000); + af->dev_info.ext_fmt[fmt_cnt] = ext_fmt; + //af->dev_info.ext_fmt[fmt_cnt].vad = PJ_FALSE; ++fmt_cnt; - af->dev_info.ext_fmt[fmt_cnt].id = PJMEDIA_FORMAT_PCMA; - af->dev_info.ext_fmt[fmt_cnt].bitrate = 64000; - af->dev_info.ext_fmt[fmt_cnt].vad = PJ_FALSE; + pjmedia_format_init_audio(&ext_fmt, PJMEDIA_FORMAT_PCMA, + 8000, 1, 16, 20, 64000, 64000); + af->dev_info.ext_fmt[fmt_cnt] = ext_fmt; + //af->dev_info.ext_fmt[fmt_cnt].vad = PJ_FALSE; ++fmt_cnt; g711_supported = PJ_TRUE; break; case 2: /* G.729 */ - af->dev_info.ext_fmt[fmt_cnt].id = PJMEDIA_FORMAT_G729; - af->dev_info.ext_fmt[fmt_cnt].bitrate = 8000; - af->dev_info.ext_fmt[fmt_cnt].vad = PJ_FALSE; + pjmedia_format_init_audio(&ext_fmt, PJMEDIA_FORMAT_G729, + 8000, 1, 16, 20, 8000, 8000); + af->dev_info.ext_fmt[fmt_cnt] = ext_fmt; + //af->dev_info.ext_fmt[fmt_cnt].vad = PJ_FALSE; ++fmt_cnt; break; case 3: /* iLBC */ - af->dev_info.ext_fmt[fmt_cnt].id = PJMEDIA_FORMAT_ILBC; - af->dev_info.ext_fmt[fmt_cnt].bitrate = 13333; - af->dev_info.ext_fmt[fmt_cnt].vad = PJ_TRUE; + pjmedia_format_init_audio(&ext_fmt, PJMEDIA_FORMAT_ILBC, + 8000, 1, 16, 30, 13333, 15200); + af->dev_info.ext_fmt[fmt_cnt] = ext_fmt; + //af->dev_info.ext_fmt[fmt_cnt].vad = PJ_TRUE; ++fmt_cnt; break; } @@ -1570,18 +1578,18 @@ static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, /* Set audio engine mode. */ if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_AMR) { - aps_setting.mode = (TAPSCodecMode)strm->param.ext_fmt.bitrate; + aps_setting.mode = (TAPSCodecMode)strm->param.ext_fmt.det.aud.avg_bps; } else if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_PCMU || strm->param.ext_fmt.id == PJMEDIA_FORMAT_L16 || (strm->param.ext_fmt.id == PJMEDIA_FORMAT_ILBC && - strm->param.ext_fmt.bitrate != 15200)) + strm->param.ext_fmt.det.aud.avg_bps != 15200)) { aps_setting.mode = EULawOr30ms; } else if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_PCMA || (strm->param.ext_fmt.id == PJMEDIA_FORMAT_ILBC && - strm->param.ext_fmt.bitrate == 15200)) + strm->param.ext_fmt.det.aud.avg_bps == 15200)) { aps_setting.mode = EALawOr20ms; } @@ -1596,11 +1604,13 @@ static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, { aps_setting.vad = EFalse; } else { - aps_setting.vad = strm->param.ext_fmt.vad; + aps_setting.vad = (strm->param.flags & PJMEDIA_AUD_DEV_CAP_VAD) && + strm->param.vad_enabled; } /* Set other audio engine attributes. */ - aps_setting.plc = strm->param.plc_enabled; + aps_setting.plc = (strm->param.flags & PJMEDIA_AUD_DEV_CAP_PLC) && + strm->param.plc_enabled; aps_setting.cng = aps_setting.vad; aps_setting.loudspk = strm->param.output_route==PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER; diff --git a/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp b/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp index 5b94903..70fe3b3 100644 --- a/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp +++ b/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp @@ -1,4 +1,4 @@ -/* $Id: symb_vas_dev.cpp 3841 2011-10-24 09:28:13Z ming $ */ +/* $Id: symb_vas_dev.cpp 4243 2012-08-31 11:42:17Z nanang $ */ /* * Copyright (C) 2009-2011 Teluu Inc. (http://www.teluu.com) * @@ -1015,7 +1015,8 @@ static void RecCb(CVoIPDataBuffer *buf, void *user_data) { unsigned samples_got; - samples_got = strm->param.ext_fmt.bitrate == 15200? 160 : 240; + samples_got = + strm->param.ext_fmt.det.aud.avg_bps == 15200? 160 : 240; /* Check if we got a normal or SID frame. */ if (buffer[0] != 0) { @@ -1214,9 +1215,9 @@ static void PlayCb(CVoIPDataBuffer *buf, void *user_data) sf = pjmedia_frame_ext_get_subframe(frame, 0); samples_cnt = frame->samples_cnt / frame->subframe_cnt; - pj_assert((strm->param.ext_fmt.bitrate == 15200 && + pj_assert((strm->param.ext_fmt.det.aud.avg_bps == 15200 && samples_cnt == 160) || - (strm->param.ext_fmt.bitrate != 15200 && + (strm->param.ext_fmt.det.aud.avg_bps != 15200 && samples_cnt == 240)); if (sf->data && sf->bitlen) { @@ -1230,7 +1231,8 @@ static void PlayCb(CVoIPDataBuffer *buf, void *user_data) buffer.Append(0); /* VAS iLBC frame is 20ms or 30ms */ - frame_len = strm->param.ext_fmt.bitrate == 15200? 38 : 50; + frame_len = + strm->param.ext_fmt.det.aud.avg_bps == 15200? 38 : 50; buffer.AppendFill(0, frame_len); } @@ -1244,7 +1246,8 @@ static void PlayCb(CVoIPDataBuffer *buf, void *user_data) buffer.Append(0); /* VAS iLBC frame is 20ms or 30ms */ - frame_len = strm->param.ext_fmt.bitrate == 15200? 38 : 50; + frame_len = + strm->param.ext_fmt.det.aud.avg_bps == 15200? 38 : 50; buffer.AppendFill(0, frame_len); } @@ -1408,40 +1411,47 @@ static pj_status_t factory_init(pjmedia_aud_dev_factory *f) vas_factory_ = NULL; for (TInt i = 0; i < dnlink_formats.Count(); i++) { + pjmedia_format ext_fmt; + /* Format must be supported by both downlink & uplink. */ if (uplink_formats.Find(dnlink_formats[i]) == KErrNotFound) continue; switch (dnlink_formats[i]) { case EAMR_NB: - af->dev_info.ext_fmt[ext_fmt_cnt].id = PJMEDIA_FORMAT_AMR; - af->dev_info.ext_fmt[ext_fmt_cnt].bitrate = 7400; - af->dev_info.ext_fmt[ext_fmt_cnt].vad = PJ_TRUE; + pjmedia_format_init_audio(&ext_fmt, PJMEDIA_FORMAT_AMR, + 8000, 1, 16, 20, 7400, 12200); + af->dev_info.ext_fmt[ext_fmt_cnt] = ext_fmt; + //af->dev_info.ext_fmt[ext_fmt_cnt].vad = PJ_TRUE; break; case EG729: - af->dev_info.ext_fmt[ext_fmt_cnt].id = PJMEDIA_FORMAT_G729; - af->dev_info.ext_fmt[ext_fmt_cnt].bitrate = 8000; - af->dev_info.ext_fmt[ext_fmt_cnt].vad = PJ_FALSE; + pjmedia_format_init_audio(&ext_fmt, PJMEDIA_FORMAT_G729, + 8000, 1, 16, 20, 8000, 8000); + af->dev_info.ext_fmt[ext_fmt_cnt] = ext_fmt; + //af->dev_info.ext_fmt[ext_fmt_cnt].vad = PJ_FALSE; break; case EILBC: - af->dev_info.ext_fmt[ext_fmt_cnt].id = PJMEDIA_FORMAT_ILBC; - af->dev_info.ext_fmt[ext_fmt_cnt].bitrate = 13333; - af->dev_info.ext_fmt[ext_fmt_cnt].vad = PJ_TRUE; + pjmedia_format_init_audio(&ext_fmt, PJMEDIA_FORMAT_ILBC, + 8000, 1, 16, 30, 13333, 15200); + af->dev_info.ext_fmt[ext_fmt_cnt] = ext_fmt; + //af->dev_info.ext_fmt[ext_fmt_cnt].vad = PJ_TRUE; break; case EG711: #if PJMEDIA_AUDIO_DEV_SYMB_VAS_VERSION==2 case EG711_10MS: #endif - af->dev_info.ext_fmt[ext_fmt_cnt].id = PJMEDIA_FORMAT_PCMU; - af->dev_info.ext_fmt[ext_fmt_cnt].bitrate = 64000; - af->dev_info.ext_fmt[ext_fmt_cnt].vad = PJ_FALSE; + pjmedia_format_init_audio(&ext_fmt, PJMEDIA_FORMAT_PCMU, + 8000, 1, 16, 20, 64000, 64000); + af->dev_info.ext_fmt[ext_fmt_cnt] = ext_fmt; + //af->dev_info.ext_fmt[ext_fmt_cnt].vad = PJ_FALSE; ++ext_fmt_cnt; - af->dev_info.ext_fmt[ext_fmt_cnt].id = PJMEDIA_FORMAT_PCMA; - af->dev_info.ext_fmt[ext_fmt_cnt].bitrate = 64000; - af->dev_info.ext_fmt[ext_fmt_cnt].vad = PJ_FALSE; + pjmedia_format_init_audio(&ext_fmt, PJMEDIA_FORMAT_PCMA, + 8000, 1, 16, 20, 64000, 64000); + af->dev_info.ext_fmt[ext_fmt_cnt] = ext_fmt; + //af->dev_info.ext_fmt[ext_fmt_cnt].vad = PJ_FALSE; break; default: @@ -1616,7 +1626,7 @@ static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, } else if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_AMR) { - vas_setting.mode = strm->param.ext_fmt.bitrate; + vas_setting.mode = strm->param.ext_fmt.det.aud.avg_bps; } else if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_PCMU) { @@ -1628,7 +1638,7 @@ static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, } else if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_ILBC) { - if (strm->param.ext_fmt.bitrate == 15200) + if (strm->param.ext_fmt.det.aud.avg_bps == 15200) vas_setting.mode = CVoIPFormatIntfc::EiLBC20mSecFrame; else vas_setting.mode = CVoIPFormatIntfc::EiLBC30mSecFrame; @@ -1647,11 +1657,13 @@ static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, { vas_setting.vad = EFalse; } else { - vas_setting.vad = strm->param.ext_fmt.vad; + vas_setting.vad = (strm->param.flags & PJMEDIA_AUD_DEV_CAP_VAD) && + strm->param.vad_enabled; } /* Set other audio engine attributes. */ - vas_setting.plc = strm->param.plc_enabled; + vas_setting.plc = (strm->param.flags & PJMEDIA_AUD_DEV_CAP_PLC) && + strm->param.plc_enabled; vas_setting.cng = vas_setting.vad; vas_setting.loudspk = strm->param.output_route==PJMEDIA_AUD_DEV_ROUTE_LOUDSPEAKER; |