#include "precompile.h" #include "audiocodec.h" #include "audiocontext.h" #include "other/wsola.h" #include "codec/codecmgr.h" #include "codec/g711codec.h" #ifdef _WIN32 #include "codec/g729acodec.h" #endif // _WIN32 #include static apr_status_t read_frame(void *self, audioframe_t *frame) { audiocodec_t *codec = CONTAINING_RECORD(self, audiocodec_t, base); codec_t *private_codec = codec->private_codec; apr_status_t status; if (codec->base.downstream == NULL) { if (codec->flag & AUDIO_CODEC_OPT_DECODE_READ) { frame->size = codec->ptime * 2 * codec->clock / 1000; memset(frame->buffer, 0, frame->size); return APR_SUCCESS; } else { return APR_EGENERAL; } } codec->tmp_frame.size = SUGGEST_FRAME_SIZE; status = codec->base.downstream->vtbl->read_frame(codec->base.downstream, &codec->tmp_frame); if (status != APR_SUCCESS) { if (codec->flag & AUDIO_CODEC_OPT_DECODE_READ) { if (codec->flag&AUDIO_CODEC_OPT_PLC && codec->last_plc) { wsola_generate(codec->plc_state, (short*)frame->buffer); frame->size = codec->ptime * 2 * codec->clock / 1000; codec->last_plc--; } else { frame->size = codec->ptime * 2 * codec->clock / 1000; memset(frame->buffer, 0, frame->size); } return APR_SUCCESS; } } else { if (codec->flag & AUDIO_CODEC_OPT_ENCODE_READ) { status = private_codec->factory->encode(private_codec, codec->tmp_frame.buffer, codec->tmp_frame.size, frame->buffer, &frame->size); if (status != APR_SUCCESS || frame->size == 0) { frame->size = codec->ptime * 2 * codec->clock / 1000; memset(frame->buffer, 0, frame->size); status = APR_SUCCESS; } } else { status = private_codec->factory->decode(private_codec, codec->tmp_frame.buffer, codec->tmp_frame.size, frame->buffer, &frame->size); if (status != APR_SUCCESS || frame->size == 0) { frame->size = codec->ptime * 2 * codec->clock / 1000; memset(frame->buffer, 0, frame->size); status = APR_SUCCESS; } if (status == APR_SUCCESS && codec->flag&AUDIO_CODEC_OPT_PLC) { wsola_save(codec->plc_state, (short*)frame->buffer, 0); codec->last_plc = 1; } } } return status; } static apr_status_t write_frame(void *self, const audioframe_t *frame) { audiocodec_t *codec = CONTAINING_RECORD(self, audiocodec_t, base); codec_t *private_codec = codec->private_codec; apr_status_t status; if (codec->base.downstream == NULL) return APR_EGENERAL; codec->tmp_frame.size = SUGGEST_FRAME_SIZE; codec->tmp_frame.dtmf = frame->dtmf; if (codec->flag & AUDIO_CODEC_OPT_ENCODE_READ) { status = private_codec->factory->decode(private_codec, frame->buffer, frame->size, codec->tmp_frame.buffer, &codec->tmp_frame.size); } else { status = private_codec->factory->encode(private_codec, frame->buffer, frame->size, codec->tmp_frame.buffer, &codec->tmp_frame.size); } if (status == APR_SUCCESS) { status = codec->base.downstream->vtbl->write_frame(codec->base.downstream, &codec->tmp_frame); } return status; } static audiostream_vtbl_t g_stream_vtbl = { &read_frame, &write_frame, }; apr_status_t audiocodec_create(apr_pool_t *pool, audioengine_t *engine, const char *name, int clock, int ptime, int flag, audiocodec_t**p_codec) { audiocodec_t *codec; codec_factory_t *factory; factory = codec_factory_find(name); if (!factory) return APR_NOTFOUND; codec = apr_palloc(pool, sizeof(audiocodec_t)); codec->private_codec = factory->create(pool, clock, ptime); if (!codec->private_codec) { return APR_EGENERAL; } codec->ptime = ptime; codec->clock = clock; audiostream_init(engine, &g_stream_vtbl, &codec->base); codec->base.direction = STREAM_DIR_BOTH; codec->tmp_frame.size = SUGGEST_FRAME_SIZE; codec->tmp_frame.buffer = apr_palloc(pool, SUGGEST_FRAME_SIZE); codec->tmp_frame.dtmf = 0; codec->flag = flag; codec->last_plc = 0; wsola_create(clock, ptime * clock / 1000, 1, WSOLA_NO_FADING, (wsola_t**)&codec->plc_state); *p_codec = codec; return APR_SUCCESS; } apr_status_t audiocodec_set_param(audiocodec_t *codec, const char *key, const char *value) { codec_t *private_codec = codec->private_codec; return private_codec->factory->set_param(private_codec, key, value); } apr_status_t audiocodec_get_param(audiocodec_t *codec, const char *key, char *value) { codec_t *private_codec = codec->private_codec; return private_codec->factory->get_param(private_codec, key, value); } apr_status_t audiocodec_init(audiocodec_t *codec) { codec_t *private_codec = codec->private_codec; return private_codec->factory->init(private_codec); } apr_status_t audiocodec_term(audiocodec_t *codec) { codec_t *private_codec = codec->private_codec; return private_codec->factory->term(private_codec); } void audiocodec_destroy(audiocodec_t *codec) { codec_t *private_codec = codec->private_codec; private_codec->factory->destroy(private_codec); wsola_destroy(codec->plc_state); codec->plc_state = NULL; } apr_status_t audiocodec_pcma_decode(const void *inbuf,int insize,void *outbuf,int *outsize) { return pcma_codec_decode(inbuf, insize, outbuf, outsize); } apr_status_t audiocodec_pcmu_decode(const void *inbuf,int insize,void *outbuf,int *outsize) { return pcmu_codec_decode(inbuf, insize, outbuf, outsize); } apr_status_t audiocodec_g729a_decode(const void *inbuf,int insize,void *outbuf,int *outsize) { #ifdef _WIN32 return audio_g729a_codec_decode(inbuf, insize, outbuf, outsize); #else return 0; #endif // _WIN32 }