|
@@ -1,816 +0,0 @@
|
|
|
-#include "stdafx.h"
|
|
|
-#include "SpBase.h"
|
|
|
-#include "audio_session.h"
|
|
|
-
|
|
|
-#include <memutil.h>
|
|
|
-#include <rtp.h>
|
|
|
-#include <rtpsession.h>
|
|
|
-
|
|
|
-#include <audioframework.h>
|
|
|
-#include <portaudio.h>
|
|
|
-
|
|
|
-#include <libaudioqueue.h>
|
|
|
-
|
|
|
-#include "rec_common.h"
|
|
|
-
|
|
|
-#define AUDIO_CLOCK 8000
|
|
|
-#define AUDIO_SHM_FRAME_TIME 20 // 20ms
|
|
|
-
|
|
|
-typedef struct audio_recorder_t audio_recorder_t;
|
|
|
-typedef struct audio_phonemedia_t audio_phonemedia_t;
|
|
|
-
|
|
|
-struct audio_session_t
|
|
|
-{
|
|
|
- audio_session_conf_t conf;
|
|
|
- Clibaudioqueue *m_audio_shm_q;
|
|
|
- void *object;
|
|
|
- int (*stop)(void *object);
|
|
|
- void (*destroy)(void *object);
|
|
|
-};
|
|
|
-
|
|
|
-static int translate_id(int in_direction, int idx);
|
|
|
-
|
|
|
-//....
|
|
|
-
|
|
|
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
-//// audio recorder, get captured buffer, and write to audio share memory queue
|
|
|
-
|
|
|
-struct audio_recorder_t
|
|
|
-{
|
|
|
- apr_pool_t *pool;
|
|
|
- audiomicspk_t *micspkstream;
|
|
|
- audioresize_t *resizestream;
|
|
|
- audiocustom_t *customstream;
|
|
|
- audio_session_t *owner;
|
|
|
-};
|
|
|
-
|
|
|
-static apr_status_t recorder_on_write_frame(void *cust, const audioframe_t *frm, void *user_data)
|
|
|
-{
|
|
|
- audio_recorder_t *recorder = (audio_recorder_t *)user_data;
|
|
|
- audio_session_t *session = recorder->owner;
|
|
|
- audio_frame *tmp_frm = NULL;
|
|
|
- try {
|
|
|
- tmp_frm = new audio_frame();
|
|
|
- tmp_frm->data = new char[frm->size];
|
|
|
- memcpy(tmp_frm->data, frm->buffer, frm->size);
|
|
|
- tmp_frm->format = 1;
|
|
|
- tmp_frm->framesize = frm->size;
|
|
|
- tmp_frm->nchannels = 1;
|
|
|
- tmp_frm->samplespersec = AUDIO_CLOCK;
|
|
|
- tmp_frm->bitspersample = 16;
|
|
|
- } catch (std::bad_alloc &) {
|
|
|
- Dbg("memory allocation failed!");
|
|
|
- return APR_ENOMEM;
|
|
|
- }
|
|
|
- if (session->m_audio_shm_q->InsertAudio(tmp_frm)) { // already delete in InsertAudio
|
|
|
- return APR_SUCCESS;
|
|
|
- } else {
|
|
|
- Dbg("shm audio queue insertaudio failed!");
|
|
|
- delete tmp_frm->data;
|
|
|
- delete tmp_frm;
|
|
|
- }
|
|
|
- return APR_EGENERAL;
|
|
|
-}
|
|
|
-
|
|
|
-static int recorder_create(audio_session_t *session, audio_recorder_t **p_recorder)
|
|
|
-{
|
|
|
- audio_recorder_t *recorder = ZALLOC_T(audio_recorder_t);
|
|
|
- if (recorder) {
|
|
|
- recorder->owner = session;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- return -1;
|
|
|
-}
|
|
|
-
|
|
|
-static int recorder_start(audio_recorder_t *recorder)
|
|
|
-{
|
|
|
- audio_session_t *session = recorder->owner;
|
|
|
- apr_status_t status;
|
|
|
- int dev_in;
|
|
|
-
|
|
|
- dev_in = translate_id(TRUE, session->conf.in_dev[DEV_HANDFREE]);
|
|
|
- if (dev_in < 0) {
|
|
|
- Dbg("cannot find audio dev_in device, id = %d", session->conf.in_dev[DEV_HANDFREE]);
|
|
|
- return Error_Param;
|
|
|
- }
|
|
|
-
|
|
|
- status = apr_pool_create(&recorder->pool, NULL);
|
|
|
- if (status != APR_SUCCESS) {
|
|
|
- Dbg("create pool failed!");
|
|
|
- goto on_error;
|
|
|
- }
|
|
|
-
|
|
|
- status = audiomicspk_create(recorder->pool, NULL,
|
|
|
- AMS_OPT_AS_ENGINE | AMS_OPT_RECORD, AUDIO_CLOCK,
|
|
|
- dev_in, 0, &recorder->micspkstream);
|
|
|
- if (status != APR_SUCCESS) {
|
|
|
- Dbg("create micspk failed!");
|
|
|
- goto on_error;
|
|
|
- }
|
|
|
-
|
|
|
- status = audioresize_create(recorder->pool, NULL,
|
|
|
- 0, 0, FRAME_TIME*2*AUDIO_CLOCK/1000, AUDIO_SHM_FRAME_TIME*2*AUDIO_CLOCK/1000,
|
|
|
- &recorder->resizestream);
|
|
|
- if (status != 0) {
|
|
|
- Dbg("create audio resize failed!");
|
|
|
- goto on_error;
|
|
|
- }
|
|
|
-
|
|
|
- status = audiocustom_create(recorder->pool, NULL, NULL,
|
|
|
- &recorder_on_write_frame, recorder, &recorder->customstream);
|
|
|
- if (status != 0) {
|
|
|
- Dbg("create audiocustom stream failed!");
|
|
|
- goto on_error;
|
|
|
- }
|
|
|
-
|
|
|
- status = audiomicspk_connect_pipeline(recorder->micspkstream, STREAM_DIR_WRITE,
|
|
|
- &recorder->resizestream->base, &recorder->customstream->base, NULL);
|
|
|
- if (status != 0) {
|
|
|
- Dbg("audiomicspk connect pipeline failed!");
|
|
|
- goto on_error;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-
|
|
|
-on_error:
|
|
|
- if (recorder->micspkstream) {
|
|
|
- audiomicspk_disconnect_pipeline(recorder->micspkstream, NULL);
|
|
|
- audiomicspk_destroy(recorder->micspkstream);
|
|
|
- recorder->micspkstream = NULL;
|
|
|
- }
|
|
|
- if (recorder->resizestream) {
|
|
|
- audioresize_destroy(recorder->resizestream);
|
|
|
- recorder->resizestream = NULL;
|
|
|
- }
|
|
|
- if (recorder->customstream) {
|
|
|
- audiocustom_destroy(recorder->customstream);
|
|
|
- recorder->customstream = NULL;
|
|
|
- }
|
|
|
- if (recorder->pool) {
|
|
|
- apr_pool_destroy(recorder->pool);
|
|
|
- recorder->pool = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- return Error_Resource;
|
|
|
-}
|
|
|
-
|
|
|
-static int recorder_stop(void *object)
|
|
|
-{
|
|
|
- audio_recorder_t *recorder = (audio_recorder_t*)object;
|
|
|
- if (recorder->micspkstream) {
|
|
|
- audiomicspk_disconnect_pipeline(recorder->micspkstream, NULL);
|
|
|
- audiomicspk_destroy(recorder->micspkstream);
|
|
|
- recorder->micspkstream = NULL;
|
|
|
- }
|
|
|
- if (recorder->resizestream) {
|
|
|
- audioresize_destroy(recorder->resizestream);
|
|
|
- recorder->resizestream = NULL;
|
|
|
- }
|
|
|
- if (recorder->customstream) {
|
|
|
- audiocustom_destroy(recorder->customstream);
|
|
|
- recorder->customstream = NULL;
|
|
|
- }
|
|
|
- if (recorder->pool) {
|
|
|
- apr_pool_destroy(recorder->pool);
|
|
|
- recorder->pool = NULL;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static void recorder_destroy(void *object)
|
|
|
-{
|
|
|
- audio_recorder_t *recorder = (audio_recorder_t*)object;
|
|
|
- free(recorder);
|
|
|
-}
|
|
|
-
|
|
|
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
-//// audio phone media
|
|
|
-
|
|
|
-struct audio_phonemedia_t
|
|
|
-{
|
|
|
- audio_session_phonemedia_conf_t conf;
|
|
|
- audio_session_t *owner;
|
|
|
-
|
|
|
- apr_pool_t *pool;
|
|
|
- audioengine_t *engine;
|
|
|
- audiocontext_t *context;
|
|
|
-
|
|
|
- audiobridge_t *bridge;
|
|
|
- apr_pool_t *micspk_pool;
|
|
|
- audiomicspk_t *micspkstream;
|
|
|
- audiodsp_t *dspstream;
|
|
|
- audioaec_t *aecstream;
|
|
|
- audioresize_t *resizestream;
|
|
|
- audiortp_t *rtpstream;
|
|
|
- audiocodec_t *codecstream;
|
|
|
- rtp_session_t *rtpsess;
|
|
|
-
|
|
|
- struct
|
|
|
- {
|
|
|
- audioresize_t *resizestream;
|
|
|
- audiortp_t *rtpstream;
|
|
|
- audiocodec_t *codecstream;
|
|
|
- rtp_session_t *rtpsess;
|
|
|
- int state;
|
|
|
- audio_session_remote_recording_conf_t conf;
|
|
|
- }record;
|
|
|
-};
|
|
|
-
|
|
|
-static int phonemedia_stop(void *object);
|
|
|
-
|
|
|
-static int phonemedia_create(audio_session_t *session, const audio_session_phonemedia_conf_t *conf, audio_phonemedia_t **p_media)
|
|
|
-{
|
|
|
- audio_phonemedia_t *media = ZALLOC_T(audio_phonemedia_t);
|
|
|
- if (media) {
|
|
|
- memcpy(&media->conf, conf, sizeof(audio_session_phonemedia_conf_t));
|
|
|
- media->owner = session;
|
|
|
- *p_media = media;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int phonemedia_on_remote_recording(audio_phonemedia_t *media)
|
|
|
-{
|
|
|
- int rc = 0;
|
|
|
- audio_session_t *session = media->owner;
|
|
|
- assert(media->record.state);
|
|
|
-
|
|
|
- audiocontext_remove_driver(media->context, &media->bridge->base);
|
|
|
- {
|
|
|
- audio_session_remote_recording_conf_t *conf = &media->record.conf;
|
|
|
- int clock = REC_COMMON_AUDIO_CLOCK;
|
|
|
- int ptime = REC_COMMON_AUDIO_FRAME_PTIME;
|
|
|
- apr_status_t status;
|
|
|
- rc = rtp_session_create2(conf->local_rtp_ip, conf->local_rtp_port, 2, &media->record.rtpsess);
|
|
|
- if (rc != 0)
|
|
|
- goto on_error;
|
|
|
- rtp_session_reset2(media->record.rtpsess, RTP_SESSION_FLAG_SENDONLY|RTP_SESSION_FLAG_NO_RTCP, conf->remote_rtp_ip, conf->remote_rtp_port, conf->remote_rtp_port+1);
|
|
|
- status = audioresize_create(media->pool, media->engine, FRAME_TIME*2*clock/1000, ptime*2*clock/1000, FRAME_TIME*2*clock/1000, ptime*2*clock/1000, &media->record.resizestream);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
- status = audiocodec_create(media->pool, media->engine, "G729", clock, FRAME_TIME, AUDIO_CODEC_OPT_ENCODE_WRITE, &media->record.codecstream);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
- status = audiortp_create(media->pool, media->engine, media->record.rtpsess, &media->record.rtpstream);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
- {
|
|
|
- int param;
|
|
|
- param = clock;
|
|
|
- audiortp_set_param(media->record.rtpstream, AUDIO_RTP_FLAG_SEND_CLOCK, ¶m);
|
|
|
- audiortp_set_param(media->record.rtpstream, AUDIO_RTP_FLAG_RECV_CLOCK, ¶m);
|
|
|
- param = REC_COMMON_AUDIO_PT;
|
|
|
- audiortp_set_param(media->record.rtpstream, AUDIO_RTP_FLAG_SEND_PT, ¶m);
|
|
|
- audiortp_set_param(media->record.rtpstream, AUDIO_RTP_FLAG_RECV_PT, ¶m);
|
|
|
- param = ptime;
|
|
|
- audiortp_set_param(media->record.rtpstream, AUDIO_RTP_FLAG_SEND_PTIME, ¶m);
|
|
|
- audiortp_set_param(media->record.rtpstream, AUDIO_RTP_FLAG_RECV_PTIME, ¶m);
|
|
|
- audiortp_init(media->record.rtpstream);
|
|
|
- }
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_WRITE, &media->record.resizestream->base, &media->record.codecstream->base, &media->record.rtpstream->base, NULL);
|
|
|
- audiobridge_set_recorder(media->bridge, &media->record.resizestream->base);
|
|
|
-on_error:
|
|
|
- if (status != APR_SUCCESS) {
|
|
|
- Dbg("create remote recording objects failed!");
|
|
|
- rc = Error_Resource;
|
|
|
- }
|
|
|
- }
|
|
|
- audiocontext_add_driver(media->context, &media->bridge->base);
|
|
|
-
|
|
|
- return rc;
|
|
|
-}
|
|
|
-
|
|
|
-static int phonemedia_start(audio_phonemedia_t *media)
|
|
|
-{
|
|
|
- audio_session_t *session = media->owner;
|
|
|
- apr_status_t status;
|
|
|
- int rc;
|
|
|
- int opt_micspk;
|
|
|
- int in_dev;
|
|
|
- int out_dev;
|
|
|
- const char *codec;
|
|
|
-
|
|
|
- in_dev = translate_id(TRUE, session->conf.in_dev[media->conf.dev_type]);
|
|
|
- if (in_dev < 0) {
|
|
|
- Dbg("in_dev invalid! id:%d", in_dev);
|
|
|
- return Error_Param;
|
|
|
- }
|
|
|
- out_dev = translate_id(FALSE, session->conf.out_dev[media->conf.dev_type]);
|
|
|
- if (out_dev < 0) {
|
|
|
- Dbg("out_dev invalid! id:%d", out_dev);
|
|
|
- return Error_Param;
|
|
|
- }
|
|
|
-
|
|
|
- opt_micspk = AMS_OPT_AS_STREAM;
|
|
|
- if (media->conf.dir & DIR_TX) {
|
|
|
- opt_micspk |= AMS_OPT_PLAY;
|
|
|
- }
|
|
|
- if (media->conf.dir &DIR_RX) {
|
|
|
- opt_micspk |= AMS_OPT_RECORD;
|
|
|
- }
|
|
|
-
|
|
|
- switch (media->conf.local_pt) {
|
|
|
- case 0:
|
|
|
- codec = "PCMU";
|
|
|
- if (media->conf.local_ptime == 0)
|
|
|
- media->conf.local_ptime = 20;
|
|
|
- if (media->conf.remote_ptime == 0)
|
|
|
- media->conf.remote_ptime = 20;
|
|
|
- break;
|
|
|
-#if 0
|
|
|
- case 4:
|
|
|
- codec = "G723";
|
|
|
- if (media->conf.local_ptime == 0)
|
|
|
- media->conf.local_ptime = 30;
|
|
|
- if (media->conf.remote_ptime == 0)
|
|
|
- media->conf.remote_ptime = 30;
|
|
|
- break;
|
|
|
-#endif
|
|
|
- case 8:
|
|
|
- codec = "PCMA";
|
|
|
- if (media->conf.local_ptime == 0)
|
|
|
- media->conf.local_ptime = 20;
|
|
|
- if (media->conf.remote_ptime == 0)
|
|
|
- media->conf.remote_ptime = 20;
|
|
|
- break;
|
|
|
- case 18:
|
|
|
- codec = "G729";
|
|
|
- if (media->conf.local_ptime == 0)
|
|
|
- media->conf.local_ptime = 20;
|
|
|
- if (media->conf.remote_ptime == 0)
|
|
|
- media->conf.remote_ptime = 20;
|
|
|
- break;
|
|
|
- default:
|
|
|
- codec = NULL;
|
|
|
- break;
|
|
|
- }
|
|
|
- if (codec == NULL)
|
|
|
- goto on_error;
|
|
|
- assert(media->conf.local_ptime == media->conf.remote_ptime);
|
|
|
-
|
|
|
- status = apr_pool_create(&media->pool, NULL);
|
|
|
- if (status != APR_SUCCESS) {
|
|
|
- Dbg("create pool failed!");
|
|
|
- return Error_Resource;
|
|
|
- }
|
|
|
-
|
|
|
- status = audioengine_create(media->pool, &media->engine);
|
|
|
- if (status != APR_SUCCESS) {
|
|
|
- Dbg("create audio engine failed!");
|
|
|
- goto on_error;
|
|
|
- }
|
|
|
-
|
|
|
- status = audioengine_start(media->engine);
|
|
|
- if (status != APR_SUCCESS) {
|
|
|
- goto on_error;
|
|
|
- }
|
|
|
-
|
|
|
- rc = rtp_session_create2(media->conf.local_rtp_ip, media->conf.local_rtp_port,
|
|
|
- 2, &media->rtpsess);
|
|
|
- if (rc != 0) {
|
|
|
- goto on_error;
|
|
|
- }
|
|
|
- rc = rtp_session_reset2(media->rtpsess, media->conf.dir, media->conf.remote_rtp_ip,
|
|
|
- media->conf.remote_rtp_port, media->conf.remote_rtp_port+1);
|
|
|
- if (rc != 0) {
|
|
|
- goto on_error;
|
|
|
- }
|
|
|
-
|
|
|
- status = audiobridge_create(media->pool, media->engine, &media->bridge);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
- status = apr_pool_create(&media->micspk_pool, media->pool);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
- status = audiomicspk_create(media->micspk_pool, media->engine, opt_micspk,
|
|
|
- AUDIO_CLOCK, in_dev, out_dev, &media->micspkstream);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
- status = audiodsp_create(media->pool, media->engine, AUDIO_DSP_AGC|AUDIO_DSP_DENOISE,
|
|
|
- AUDIO_DSP_AGC, AUDIO_CLOCK, &media->dspstream);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
- status = audioaec_create(media->pool, media->engine, AUDIO_CLOCK, FRAME_TIME,
|
|
|
- AUDIO_AEC_OPT_READ_AS_CAPTURE, &media->aecstream);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
- status = audioresize_create(media->pool, media->engine, FRAME_TIME*2*AUDIO_CLOCK/1000,
|
|
|
- media->conf.remote_ptime*2*AUDIO_CLOCK/1000, FRAME_TIME*2*AUDIO_CLOCK/1000,
|
|
|
- media->conf.local_ptime*2*AUDIO_CLOCK/1000, &media->resizestream);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
- status = audiocodec_create(media->pool, media->engine, codec, AUDIO_CLOCK, FRAME_TIME,
|
|
|
- AUDIO_CODEC_OPT_ENCODE_WRITE, &media->codecstream);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
- status = audiortp_create(media->pool, media->engine, media->rtpsess, &media->rtpstream);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
-
|
|
|
- {
|
|
|
- int param;
|
|
|
- param = AUDIO_CLOCK;
|
|
|
- audiortp_set_param(media->rtpstream, AUDIO_RTP_FLAG_SEND_CLOCK, ¶m);
|
|
|
- audiortp_set_param(media->rtpstream, AUDIO_RTP_FLAG_RECV_CLOCK, ¶m);
|
|
|
- param = media->conf.local_pt;
|
|
|
- audiortp_set_param(media->rtpstream, AUDIO_RTP_FLAG_SEND_PT, ¶m);
|
|
|
- param = media->conf.remote_pt;
|
|
|
- audiortp_set_param(media->rtpstream, AUDIO_RTP_FLAG_RECV_PT, ¶m);
|
|
|
- param = media->conf.local_dtmf_pt;
|
|
|
- audiortp_set_param(media->rtpstream, AUDIO_RTP_FLAG_SEND_DTMF, ¶m);
|
|
|
- param = media->conf.remote_dtmf_pt;
|
|
|
- audiortp_set_param(media->rtpstream, AUDIO_RTP_FLAG_RECV_DTMF, ¶m);
|
|
|
- param = media->conf.local_ptime;
|
|
|
- audiortp_set_param(media->rtpstream, AUDIO_RTP_FLAG_SEND_PTIME, ¶m);
|
|
|
- param = media->conf.remote_ptime;
|
|
|
- audiortp_set_param(media->rtpstream, AUDIO_RTP_FLAG_RECV_PTIME, ¶m);
|
|
|
-
|
|
|
- audiortp_init(media->rtpstream);
|
|
|
- }
|
|
|
-
|
|
|
- if (media->conf.dir == DIR_TX) {
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_READ, &media->aecstream->base, &media->dspstream->base, &media->micspkstream->base, NULL);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_LEFT, &media->aecstream->base);
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_WRITE, &media->resizestream->base, &media->codecstream->base, &media->rtpstream->base, NULL);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_RIGHT, &media->resizestream->base);
|
|
|
- } else if (media->conf.dir == DIR_RX) {
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_WRITE, &media->micspkstream->base, NULL);
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_READ, &media->resizestream->base, &media->codecstream->base, &media->rtpstream->base, NULL);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_LEFT, &media->micspkstream->base);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_RIGHT, &media->resizestream->base);
|
|
|
- } else {
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_BOTH, &media->resizestream->base, &media->codecstream->base, &media->rtpstream->base, NULL);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_RIGHT, &media->resizestream->base);
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_BOTH, &media->aecstream->base, &media->dspstream->base, &media->micspkstream->base, NULL);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_LEFT, &media->aecstream->base);
|
|
|
- }
|
|
|
-
|
|
|
- status = audiocontext_create(media->pool, media->engine, &media->context);
|
|
|
- if (status != APR_SUCCESS)
|
|
|
- goto on_error;
|
|
|
-
|
|
|
- audiocontext_add_driver(media->context, &media->bridge->base);
|
|
|
- audioengine_start_context(media->engine, media->context);
|
|
|
-
|
|
|
- if (media->record.state) {
|
|
|
- rc = phonemedia_on_remote_recording(media);
|
|
|
- if (rc != 0) {
|
|
|
- goto on_error;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-
|
|
|
-on_error:
|
|
|
- phonemedia_stop(media);
|
|
|
- return Error_Resource;
|
|
|
-}
|
|
|
-
|
|
|
-static int phonemedia_stop(void *object)
|
|
|
-{
|
|
|
- audio_phonemedia_t *media = (audio_phonemedia_t*)object;
|
|
|
- if (media->context) {
|
|
|
- audioengine_stop_context(media->engine, media->context);
|
|
|
- audiocontext_remove_driver(media->context, &media->bridge->base);
|
|
|
- audiocontext_destroy(media->context);
|
|
|
- media->context = NULL;
|
|
|
- }
|
|
|
- if (media->engine) {
|
|
|
- audioengine_stop(media->engine);
|
|
|
- audioengine_destroy(media->engine);
|
|
|
- media->engine = NULL;
|
|
|
- }
|
|
|
- if (media->bridge) {
|
|
|
- audiobridge_destroy(media->bridge);
|
|
|
- media->bridge = NULL;
|
|
|
- }
|
|
|
- if (media->resizestream) {
|
|
|
- audioresize_destroy(media->resizestream);
|
|
|
- media->resizestream = NULL;
|
|
|
- }
|
|
|
- if (media->codecstream) {
|
|
|
- audiocodec_destroy(media->codecstream);
|
|
|
- media->codecstream = NULL;
|
|
|
- }
|
|
|
- if (media->rtpstream) {
|
|
|
- audiortp_destroy(media->rtpstream);
|
|
|
- media->rtpstream = NULL;
|
|
|
- }
|
|
|
- if (media->rtpsess) {
|
|
|
- rtp_session_destroy(media->rtpsess);
|
|
|
- media->rtpsess = NULL;
|
|
|
- }
|
|
|
- if (media->aecstream) {
|
|
|
- audioaec_destroy(media->aecstream);
|
|
|
- media->aecstream = NULL;
|
|
|
- }
|
|
|
- if (media->dspstream) {
|
|
|
- audiodsp_destroy(media->dspstream);
|
|
|
- media->dspstream = NULL;
|
|
|
- }
|
|
|
- if (media->micspkstream) {
|
|
|
- audiomicspk_destroy(media->micspkstream);
|
|
|
- media->micspkstream = NULL;
|
|
|
- apr_pool_destroy(media->micspk_pool);
|
|
|
- media->micspk_pool = NULL;
|
|
|
- }
|
|
|
- if (media->record.state) {
|
|
|
- if (media->record.codecstream) {
|
|
|
- audiocodec_destroy(media->record.codecstream);
|
|
|
- media->record.codecstream = NULL;
|
|
|
- }
|
|
|
- if (media->record.resizestream) {
|
|
|
- audioresize_destroy(media->record.resizestream);
|
|
|
- media->record.resizestream = NULL;
|
|
|
- }
|
|
|
- if (media->record.rtpstream) {
|
|
|
- audiortp_destroy(media->record.rtpstream);
|
|
|
- media->record.rtpstream = NULL;
|
|
|
- rtp_session_destroy(media->record.rtpsess);
|
|
|
- media->record.rtpsess = NULL;
|
|
|
- }
|
|
|
- media->record.state = 0;
|
|
|
- }
|
|
|
- if (media->pool) {
|
|
|
- apr_pool_destroy(media->pool);
|
|
|
- media->pool = NULL;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static void phonemedia_destroy(void *object)
|
|
|
-{
|
|
|
- audio_phonemedia_t *media = (audio_phonemedia_t *)object;
|
|
|
- free(media);
|
|
|
-}
|
|
|
-
|
|
|
-static int phonemedia_chang_dev(void *object, e_dev_type t)
|
|
|
-{
|
|
|
- audio_phonemedia_t *media = (audio_phonemedia_t *)object;
|
|
|
- audio_session_t *session = media->owner;
|
|
|
- int opt_micspk;
|
|
|
- int in_dev;
|
|
|
- int out_dev;
|
|
|
-
|
|
|
- in_dev = translate_id(TRUE, session->conf.in_dev[media->conf.dev_type]);
|
|
|
- if (in_dev < 0) {
|
|
|
- Dbg("in_dev invalid! id:%d", in_dev);
|
|
|
- return Error_Param;
|
|
|
- }
|
|
|
- out_dev = translate_id(FALSE, session->conf.out_dev[media->conf.dev_type]);
|
|
|
- if (out_dev < 0) {
|
|
|
- Dbg("out_dev invalid! id:%d", out_dev);
|
|
|
- return Error_Param;
|
|
|
- }
|
|
|
-
|
|
|
- opt_micspk = AMS_OPT_AS_STREAM;
|
|
|
- if (media->conf.dir & DIR_TX) {
|
|
|
- opt_micspk |= AMS_OPT_PLAY;
|
|
|
- }
|
|
|
- if (media->conf.dir &DIR_RX) {
|
|
|
- opt_micspk |= AMS_OPT_RECORD;
|
|
|
- }
|
|
|
-
|
|
|
- if (media->pool) {
|
|
|
- //apr_status_t status;
|
|
|
- audiocontext_remove_driver(media->context, &media->bridge->base);
|
|
|
- audiomicspk_destroy(media->micspkstream);
|
|
|
- media->micspkstream = NULL;
|
|
|
- apr_pool_destroy(media->micspk_pool);
|
|
|
- apr_pool_create(&media->micspk_pool, media->pool);
|
|
|
- audiomicspk_create(media->micspk_pool, media->engine, opt_micspk, AUDIO_CLOCK,
|
|
|
- in_dev, out_dev, &media->micspkstream);
|
|
|
- if (media->conf.dir == DIR_TX) {
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_READ, &media->aecstream->base, &media->dspstream->base, &media->micspkstream->base, NULL);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_LEFT, &media->aecstream->base);
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_WRITE, &media->resizestream->base, &media->codecstream->base, &media->rtpstream->base, NULL);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_RIGHT, &media->resizestream->base);
|
|
|
- } else if (media->conf.dir == DIR_RX) {
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_WRITE, &media->micspkstream->base, NULL);
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_READ, &media->resizestream->base, &media->codecstream->base, &media->rtpstream->base, NULL);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_LEFT, &media->micspkstream->base);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_RIGHT, &media->resizestream->base);
|
|
|
- } else {
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_BOTH, &media->resizestream->base, &media->codecstream->base, &media->rtpstream->base, NULL);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_RIGHT, &media->resizestream->base);
|
|
|
- audiostream_connect_pipeline(STREAM_DIR_BOTH, &media->aecstream->base, &media->dspstream->base, &media->micspkstream->base, NULL);
|
|
|
- audiobridge_set_leg(media->bridge, AUDIO_BRIDGE_LEG_LEFT, &media->aecstream->base);
|
|
|
- }
|
|
|
- audiocontext_add_driver(media->context, &media->bridge->base);
|
|
|
- return 0;
|
|
|
- } else {
|
|
|
- return Error_NotInit;
|
|
|
- }
|
|
|
-
|
|
|
- return Error_Unexpect;
|
|
|
-}
|
|
|
-
|
|
|
-static int phonemedia_start_remote_recording(void *object, const audio_session_remote_recording_conf_t *conf)
|
|
|
-{
|
|
|
- audio_phonemedia_t *media = (audio_phonemedia_t *)object;
|
|
|
- media->record.state = TRUE;
|
|
|
- memcpy(&media->record.conf, conf, sizeof(audio_session_remote_recording_conf_t));
|
|
|
- if (media->pool) {
|
|
|
- int rc = phonemedia_on_remote_recording(media);
|
|
|
- if (rc != 0) {
|
|
|
- Dbg("start remote recording failed!");
|
|
|
- }
|
|
|
- return rc;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
-//// audio session
|
|
|
-
|
|
|
-int audio_session_create(const audio_session_conf_t *conf, audio_session_t **p_session)
|
|
|
-{
|
|
|
- audio_session_t *session = ZALLOC_T(audio_session_t);
|
|
|
- if (session) {
|
|
|
- memcpy(&session->conf, conf, sizeof(audio_session_conf_t));
|
|
|
- session->m_audio_shm_q = new Clibaudioqueue(conf->shm_audioq_name);
|
|
|
- *p_session = session;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- return Error_Resource;
|
|
|
-}
|
|
|
-int audio_session_start_recording(audio_session_t *session)
|
|
|
-{
|
|
|
- if (!session->object) {
|
|
|
- audio_recorder_t *recorder;
|
|
|
- int rc = recorder_create(session, &recorder);
|
|
|
- if (rc == 0) {
|
|
|
- session->object = recorder;
|
|
|
- session->stop = &recorder_stop;
|
|
|
- session->destroy = &recorder_destroy;
|
|
|
- rc = recorder_start(recorder);
|
|
|
- if (rc != 0) {
|
|
|
- Dbg("recorder start failed!");
|
|
|
- recorder_destroy(recorder);
|
|
|
- session->object = NULL;
|
|
|
- }
|
|
|
- }
|
|
|
- return rc;
|
|
|
- } else {
|
|
|
- return Error_Duplication;
|
|
|
- }
|
|
|
-}
|
|
|
-int audio_session_start_phonemedia(audio_session_t *session, const audio_session_phonemedia_conf_t *conf)
|
|
|
-{
|
|
|
- if (!session->object) {
|
|
|
- audio_phonemedia_t *media;
|
|
|
- int rc = phonemedia_create(session, conf, &media);
|
|
|
- if (rc == 0) {
|
|
|
- session->object = media;
|
|
|
- session->stop = &phonemedia_stop;
|
|
|
- session->destroy = &phonemedia_destroy;
|
|
|
- rc = phonemedia_start(media);
|
|
|
- if (rc != 0) {
|
|
|
- Dbg("recorder start failed!");
|
|
|
- phonemedia_destroy(media);
|
|
|
- session->object = NULL;
|
|
|
- }
|
|
|
- }
|
|
|
- return rc;
|
|
|
- } else {
|
|
|
- return Error_Duplication;
|
|
|
- }
|
|
|
-}
|
|
|
-int audio_session_stop(audio_session_t *session)
|
|
|
-{
|
|
|
- if (session->object) {
|
|
|
- int rc = session->stop(session->object);
|
|
|
- if (rc == 0) {
|
|
|
- session->destroy(session->object);
|
|
|
- session->object = NULL;
|
|
|
- } else {
|
|
|
- Dbg("session stop failed!");
|
|
|
- }
|
|
|
- return rc;
|
|
|
- } else {
|
|
|
- return Error_NotInit;
|
|
|
- }
|
|
|
-}
|
|
|
-void audio_session_destroy(audio_session_t *session)
|
|
|
-{
|
|
|
- delete session->m_audio_shm_q;
|
|
|
- free(session);
|
|
|
-}
|
|
|
-int audio_session_change_dev(audio_session_t *session, e_dev_type t)
|
|
|
-{
|
|
|
- return phonemedia_chang_dev(session->object, t);
|
|
|
-}
|
|
|
-int audio_session_start_remote_recording(audio_session_t *session, const audio_session_remote_recording_conf_t *conf)
|
|
|
-{
|
|
|
- return phonemedia_start_remote_recording(session->object, conf);
|
|
|
-}
|
|
|
-
|
|
|
-static void __stdcall __audio_log_func(int level, const char *s)
|
|
|
-{
|
|
|
- Dbg(s);
|
|
|
-}
|
|
|
-int audio_lib_init()
|
|
|
-{
|
|
|
- audio_log_set_func(&__audio_log_func);
|
|
|
-
|
|
|
- int rc = audioframework_init();
|
|
|
- if (rc != 0) {
|
|
|
- return Error_Resource;
|
|
|
- } else {
|
|
|
- int icnt, ocnt;
|
|
|
- audio_log_set_func(NULL);
|
|
|
- rc = audio_get_dev_count(&icnt, &ocnt);
|
|
|
- if (rc == 0) {
|
|
|
- int i;
|
|
|
- Dbg("audio input devices(%d):", icnt);
|
|
|
- for (i = 0; i < icnt; ++i) {
|
|
|
- CSimpleStringA str = audio_get_dev_name(true, i);
|
|
|
- Dbg("%d = %s", i, (LPCSTR)str);
|
|
|
- }
|
|
|
- Dbg("audio output devices(%d):", ocnt);
|
|
|
- for (i = 0; i < ocnt; ++i) {
|
|
|
- CSimpleStringA str = audio_get_dev_name(false, i);
|
|
|
- Dbg("%d = %s", i, (LPCSTR)str);
|
|
|
- }
|
|
|
- }
|
|
|
- audio_log_set_func(&__audio_log_func);
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-void audio_lib_deinit()
|
|
|
-{
|
|
|
- audioframework_term();
|
|
|
-}
|
|
|
-int audio_get_dev_count(int *in_cnt, int *out_cnt)
|
|
|
-{
|
|
|
- int icnt = 0, ocnt = 0;
|
|
|
- int cnt = Pa_GetDeviceCount();
|
|
|
- for (int i = 0; i < cnt; ++i) {
|
|
|
- const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
|
|
|
- if (info->maxInputChannels)
|
|
|
- icnt ++;
|
|
|
- if (info->maxOutputChannels)
|
|
|
- ocnt ++;
|
|
|
- }
|
|
|
- if (in_cnt)
|
|
|
- *in_cnt = icnt;
|
|
|
- if (out_cnt)
|
|
|
- *out_cnt = ocnt;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-CSimpleStringA audio_get_dev_name(bool in_direction, int idx)
|
|
|
-{
|
|
|
- audio_log_set_func(NULL);
|
|
|
- int cnt = Pa_GetDeviceCount();
|
|
|
- int ii, i;
|
|
|
- for (i = 0, ii = 0; i < cnt; ++i) {
|
|
|
- const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
|
|
|
- if (in_direction) {
|
|
|
- if (info->maxInputChannels) {
|
|
|
- if (idx == ii) {
|
|
|
- audio_log_set_func(__audio_log_func);
|
|
|
- return CSimpleStringA(info->name);
|
|
|
- }
|
|
|
- ii++;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (info->maxOutputChannels) {
|
|
|
- if (idx == ii) {
|
|
|
- audio_log_set_func(__audio_log_func);
|
|
|
- return CSimpleStringA(info->name);
|
|
|
- }
|
|
|
- ii++;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- audio_log_set_func(__audio_log_func);
|
|
|
- return CSimpleStringA();
|
|
|
-}
|
|
|
-static int translate_id(int in_direction, int idx)
|
|
|
-{
|
|
|
- int i, n, ii;
|
|
|
- audio_log_set_func(NULL);
|
|
|
- n = Pa_GetDeviceCount();
|
|
|
- for (i = 0, ii = 0; i < n; ++i) {
|
|
|
- const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
|
|
|
- if (in_direction) {
|
|
|
- if (info->maxInputChannels) {
|
|
|
- if (ii == idx) {
|
|
|
- audio_log_set_func(__audio_log_func);
|
|
|
- return i;
|
|
|
- }
|
|
|
- ii++;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (info->maxOutputChannels) {
|
|
|
- if (ii == idx) {
|
|
|
- audio_log_set_func(__audio_log_func);
|
|
|
- return i;
|
|
|
- }
|
|
|
- ii++;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- audio_log_set_func(__audio_log_func);
|
|
|
- return -1;
|
|
|
-}
|