summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/README1
-rw-r--r--mk/modules.mk11
-rw-r--r--modules/mpa/decode.c136
-rw-r--r--modules/mpa/encode.c141
-rw-r--r--modules/mpa/module.mk14
-rw-r--r--modules/mpa/module.mk~14
-rw-r--r--modules/mpa/mpa.c189
-rw-r--r--modules/mpa/mpa.h32
-rw-r--r--modules/mpa/sdp.c54
-rw-r--r--src/audio.c47
10 files changed, 622 insertions, 17 deletions
diff --git a/docs/README b/docs/README
index d7d0a04..1a6f9be 100644
--- a/docs/README
+++ b/docs/README
@@ -69,6 +69,7 @@ Features:
- Opus
- Silk
- Speex
+ - MPA
* Audio-drivers:
- Advanced Linux Sound Architecture (ALSA) audio-driver
diff --git a/mk/modules.mk b/mk/modules.mk
index 8695814..1475247 100644
--- a/mk/modules.mk
+++ b/mk/modules.mk
@@ -30,6 +30,7 @@
# USE_ISAC iSAC audio codec
# USE_L16 L16 audio codec
# USE_LIBSRTP Secure RTP module using libsrtp
+# USE_MPA MPA audo codec
# USE_MPG123 Use mpg123
# USE_OPUS Opus audio codec
# USE_OSS OSS audio driver
@@ -147,6 +148,13 @@ ifeq ($(HAVE_SPEEXDSP),)
HAVE_SPEEXDSP := \
$(shell find $(SYSROOT)/lib -name libspeexdsp$(LIB_SUFFIX) 2>/dev/null)
endif
+ifneq ($(USE_MPG123),)
+ifneq ($(HAVE_SPEEXDSP),)
+USE_MPA := $(shell [ -f $(SYSROOT)/include/twolame.h ] || \
+ [ -f $(SYSROOT)/local/include/twolame.h ] || \
+ [ -f $(SYSROOT_ALT)/include/twolame.h ] && echo "yes")
+endif
+endif
USE_SPEEX := $(shell [ -f $(SYSROOT)/include/speex.h ] || \
[ -f $(SYSROOT)/include/speex/speex.h ] || \
[ -f $(SYSROOT)/local/include/speex.h ] || \
@@ -346,6 +354,9 @@ endif
ifneq ($(USE_OPUS),)
MODULES += opus
endif
+ifneq ($(USE_MPA),)
+MODULES += mpa
+endif
ifneq ($(USE_OSS),)
MODULES += oss
endif
diff --git a/modules/mpa/decode.c b/modules/mpa/decode.c
new file mode 100644
index 0000000..11ab8b4
--- /dev/null
+++ b/modules/mpa/decode.c
@@ -0,0 +1,136 @@
+/**
+ * @file mpa/decode.c mpa Decode
+ *
+ * Copyright (C) 2016 Symonics GmbH
+ */
+
+#include <re.h>
+#include <baresip.h>
+#include <mpg123.h>
+#include "mpa.h"
+
+
+struct audec_state {
+ mpg123_handle *dec;
+};
+
+
+static void destructor(void *arg)
+{
+ struct audec_state *ads = arg;
+
+ mpg123_close(ads->dec);
+ mpg123_delete(ads->dec);
+}
+
+
+int mpa_decode_update(struct audec_state **adsp, const struct aucodec *ac,
+ const char *fmtp)
+{
+ struct audec_state *ads;
+ int mpaerr, err=0;
+
+ if (!adsp || !ac || !ac->ch)
+ return EINVAL;
+
+ ads = *adsp;
+
+ if (ads)
+ return 0;
+
+ ads = mem_zalloc(sizeof(*ads), destructor);
+ if (!ads)
+ return ENOMEM;
+
+ mpg123_delete(ads->dec);
+ ads->dec = mpg123_new(NULL,&mpaerr);
+ if (!ads->dec) {
+ warning("mpa: decoder create: %s\n", mpg123_plain_strerror(mpaerr));
+ err = ENOMEM;
+ goto out;
+ }
+
+ mpaerr = mpg123_param(ads->dec, MPG123_VERBOSE, 4, 4.);
+ if(mpaerr != MPG123_OK) {
+ error("MPA libmpg123 param error %s", mpg123_plain_strerror(mpaerr));
+ return EINVAL;
+ }
+
+
+ mpaerr = mpg123_format(ads->dec, 48000 /*ac->srate*/, 2 /*ac->ch*/, MPG123_ENC_SIGNED_16);
+ if(mpaerr != MPG123_OK) {
+ error("MPA libmpg123 format error %s", mpg123_plain_strerror(mpaerr));
+ return EINVAL;
+ }
+
+ mpaerr = mpg123_open_feed(ads->dec);
+ if(mpaerr != MPG123_OK) {
+ error("MPA libmpg123 open feed error %s", mpg123_plain_strerror(mpaerr));
+ return EINVAL;
+ }
+
+
+ out:
+ if (err)
+ mem_deref(ads);
+ else
+ *adsp = ads;
+
+ return err;
+}
+
+
+int mpa_decode_frm(struct audec_state *ads, int16_t *sampv, size_t *sampc,
+ const uint8_t *buf, size_t len)
+{
+ int mpaerr, channels, encoding;
+ long samplerate;
+ size_t n;
+ uint32_t header;
+
+ if (!ads || !sampv || !sampc || !buf)
+ return EINVAL;
+
+ if(len<=4)
+ return EINVAL;
+ header = *(uint32_t*)buf;
+ if(header != 0) {
+ error("MPA header is not zero %08X\n", header);
+ return EPROTO;
+ }
+
+
+ mpaerr = mpg123_decode(ads->dec, buf+4, len-4, (unsigned char*)sampv, *sampc*2, &n);
+ if(mpaerr == MPG123_NEW_FORMAT) {
+ mpg123_getformat(ads->dec, &samplerate, &channels, &encoding);
+ info("MPA libmpg123 format change %d %d %04X\n",samplerate,channels,encoding);
+ }
+ else if(mpaerr == MPG123_NEED_MORE)
+ return 0;
+ else if(mpaerr != MPG123_OK) {
+ error("MPA libmpg123 feed error %d %s", mpaerr, mpg123_plain_strerror(mpaerr));
+ return EPROTO;
+ }
+
+// warning("mpa decode %d %d %d\n",*sampc,len,n);
+ *sampc = n / 2;
+
+ return 0;
+}
+
+int mpa_decode_pkloss(struct audec_state *ads, int16_t *sampv, size_t *sampc)
+{
+ if (!ads || !sampv || !sampc)
+ return EINVAL;
+
+ warning("mpa packet loss %d\n",*sampc);
+// n = opus_decode(ads->dec, NULL, 0, sampv, (int)(*sampc/ads->ch), 0);
+// if (n < 0)
+// return EPROTO;
+
+// *sampc = n * ads->ch;
+
+ return 0;
+}
+
+
diff --git a/modules/mpa/encode.c b/modules/mpa/encode.c
new file mode 100644
index 0000000..1195844
--- /dev/null
+++ b/modules/mpa/encode.c
@@ -0,0 +1,141 @@
+/**
+ * @file mpa/encode.c mpa Encode
+ *
+ * Copyright (C) 2016 Symonics GmbH
+ */
+
+#include <re.h>
+#include <baresip.h>
+#include <twolame.h>
+#include <string.h>
+#include <speex/speex_resampler.h>
+#include "mpa.h"
+
+
+struct auenc_state {
+ twolame_options *enc;
+ int channels;
+ SpeexResamplerState *resampler;
+};
+
+
+static void destructor(void *arg)
+{
+ struct auenc_state *aes = arg;
+
+ if (aes->enc)
+ twolame_close(&aes->enc);
+}
+
+int mpa_encode_update(struct auenc_state **aesp, const struct aucodec *ac,
+ struct auenc_param *param, const char *fmtp)
+{
+ struct auenc_state *aes;
+ struct mpa_param prm;
+ const struct aucodec *auc = aucodec_find("MPA", 90000, 1);
+ int mpares;
+
+ (void)param;
+
+ if (!aesp || !ac || !ac->ch)
+ return EINVAL;
+
+ aes = *aesp;
+
+ if (!aes) {
+ aes = mem_zalloc(sizeof(*aes), destructor);
+ aes->enc = twolame_init();
+ if (!aes->enc) {
+ warning("mpa: encoder create failed");
+ mem_deref(aes);
+ return ENOMEM;
+ }
+ aes->channels = auc->ch;
+ *aesp = aes;
+ }
+
+ prm.samplerate = 32000;
+ prm.bitrate = 128000;
+ prm.layer = 2;
+ prm.mode = STEREO;
+ mpa_decode_fmtp(&prm, fmtp);
+
+ mpares = 0;
+ mpares |= twolame_set_verbosity(aes->enc, 5);
+ mpares |= twolame_set_mode(aes->enc, prm.mode == SINGLE_CHANNEL ? TWOLAME_MONO :
+ prm.mode == DUAL_CHANNEL ? TWOLAME_DUAL_CHANNEL :
+ prm.mode == JOINT_STEREO ? TWOLAME_JOINT_STEREO :
+ prm.mode == STEREO ? TWOLAME_STEREO : TWOLAME_AUTO_MODE);
+ mpares |= twolame_set_version(aes->enc, prm.samplerate < 32000 ? TWOLAME_MPEG2 : TWOLAME_MPEG1);
+ mpares |= twolame_set_bitrate(aes->enc, prm.bitrate/1000);
+ mpares |= twolame_set_in_samplerate(aes->enc, prm.samplerate);
+ mpares |= twolame_set_out_samplerate(aes->enc, prm.samplerate);
+ mpares |= twolame_set_num_channels(aes->enc, 2);
+ if(mpares!=0) {
+ warning("mpa: encoder set failed\n");
+ return EINVAL;
+ }
+
+ twolame_print_config(aes->enc);
+
+ mpares = twolame_init_params(aes->enc);
+ if(mpares!=0) {
+ warning("mpa: encoder init params failed\n");
+ return EINVAL;
+ }
+
+ if(prm.samplerate != 48000) {
+ aes->resampler = speex_resampler_init(2, 48000, prm.samplerate, 3, &mpares);
+ if(mpares!=RESAMPLER_ERR_SUCCESS) {
+ warning("mpa: resampler init failed %d\n",mpares);
+ return EINVAL;
+ }
+
+ }
+ else
+ aes->resampler = NULL;
+ return 0;
+}
+
+
+int mpa_encode_frm(struct auenc_state *aes, uint8_t *buf, size_t *len,
+ const int16_t *sampv, size_t sampc)
+{
+ int n;
+ spx_uint32_t ds_len,in_len;
+ static int16_t ds[1920];
+
+ if (!aes || !buf || !len || !sampv)
+ return EINVAL;
+
+ if(aes->resampler) {
+ in_len = sampc/2;
+ n=speex_resampler_process_interleaved_int(aes->resampler, sampv, &in_len, ds, &ds_len);
+ if (n!=RESAMPLER_ERR_SUCCESS || in_len != sampc/2) {
+ warning("mpa: downsample error: %s\n", strerror(n));
+ return EPROTO;
+ }
+ n = twolame_encode_buffer_interleaved(aes->enc, ds, ds_len/2,
+ buf+4, (*len)-4);
+ warning("mpa encode %d %d %d %d %d\n",ds_len,sampc,aes->channels,*len,n);
+ }
+ else
+ n = twolame_encode_buffer_interleaved(aes->enc, sampv, (int)(sampc/2),
+ buf+4, (*len)-4);
+
+ if (n < 0) {
+ warning("mpa: encode error: %s\n", strerror((int)n));
+ return EPROTO;
+ }
+
+ if(n > 0) {
+ *(uint32_t*)buf = 0;
+ *len = n+4;
+ }
+ else
+ *len = 0;
+
+// warning("mpa encode %d %d %d %d\n",sampc,aes->channels,*len,n);
+ return 0;
+}
+
diff --git a/modules/mpa/module.mk b/modules/mpa/module.mk
new file mode 100644
index 0000000..b060f12
--- /dev/null
+++ b/modules/mpa/module.mk
@@ -0,0 +1,14 @@
+#
+# module.mk
+#
+# Copyright (C) 2016 Symonics GmbH
+#
+
+MOD := mpa
+$(MOD)_SRCS += mpa.c
+$(MOD)_SRCS += decode.c
+$(MOD)_SRCS += sdp.c
+$(MOD)_SRCS += encode.c
+$(MOD)_LFLAGS += -ltwolame -lmpg123 -lspeexdsp -lm
+
+include mk/mod.mk
diff --git a/modules/mpa/module.mk~ b/modules/mpa/module.mk~
new file mode 100644
index 0000000..9b4b98c
--- /dev/null
+++ b/modules/mpa/module.mk~
@@ -0,0 +1,14 @@
+#
+# module.mk
+#
+# Copyright (C) 2016 Symonics GmbH
+#
+
+MOD := mpa
+$(MOD)_SRCS += mpa.c
+$(MOD)_SRCS += decode.c
+$(MOD)_SRCS += sdp.c
+$(MOD)_SRCS += encode.c
+$(MOD)_LFLAGS += -ltwolame -lmpg123 -lm
+
+include mk/mod.mk
diff --git a/modules/mpa/mpa.c b/modules/mpa/mpa.c
new file mode 100644
index 0000000..cf0a273
--- /dev/null
+++ b/modules/mpa/mpa.c
@@ -0,0 +1,189 @@
+/**
+ * @file mpa.c mpa Audio Codec
+ *
+ * Copyright (C) 2016 Symonics GmbH
+ */
+
+#include <re.h>
+#include <baresip.h>
+#include <ctype.h>
+#include <string.h>
+#include "mpa.h"
+#include <mpg123.h>
+
+/**
+ * @defgroup mpa mpa
+ *
+ * The mpa audio codec
+ *
+ * Supported version:
+ * libmpg123 1.16.0 or later
+ * libtwolame 0.3.13 or later
+ *
+ * References:
+ *
+ * RFC 2250 RTP Payload Format for the mpa Speech and Audio Codec
+ *
+ */
+
+/*
+4.1.17. Registration of MIME media type audio/MPA
+
+ MIME media type name: audio
+
+ MIME subtype name: MPA (MPEG audio)
+
+ Required parameters: None
+
+ Optional parameters:
+ layer: which layer of MPEG audio encoding; permissible values
+ are 1, 2, 3.
+
+ samplerate: the rate at which audio is sampled. MPEG-1 audio
+ supports sampling rates of 32, 44.1, and 48 kHz; MPEG-2
+ supports sampling rates of 16, 22.05 and 24 kHz. This parameter
+ is separate from the RTP timestamp clock rate which is always
+ 90000 Hz for MPA.
+
+ mode: permissible values are "stereo", "joint_stereo",
+ "single_channel", "dual_channel". The "channels" parameter
+ does not apply to MPA. It is undefined to put a number of
+ channels in the SDP rtpmap attribute for MPA.
+
+ bitrate: the data rate for the audio bit stream.
+
+ ptime: RECOMMENDED duration of each packet in milliseconds.
+
+ maxptime: maximum duration of each packet in milliseconds.
+
+ Parameters which are omitted are left to the encoder to choose
+ based on the session bandwidth, configuration information, or
+ other constraints. The selected layer as well as the sampling
+ rate and mode are indicated in the payload so receivers can
+ process the data without these parameters being specified
+ externally.
+
+ Encoding considerations:
+ This type is only defined for transfer via RTP [RFC 3550].
+
+ Security considerations: See Section 5 of RFC 3555
+
+ Interoperability considerations: none
+
+ Published specification: RFC 3551
+
+ Applications which use this media type:
+ Audio and video streaming and conferencing tools.
+
+*/
+
+
+static struct aucodec mpa = {
+ .pt = NULL,
+ .name = "MPA",
+ .srate = 90000,
+ .ch = 1,
+ .fmtp = "",
+ .encupdh = mpa_encode_update,
+ .ench = mpa_encode_frm,
+ .decupdh = mpa_decode_update,
+ .dech = mpa_decode_frm,
+ .plch = mpa_decode_pkloss,
+};
+
+
+static int module_init(void)
+{
+ struct conf *conf = conf_cur();
+ uint32_t value;
+ static char fmtp[256];
+ static char mode[30];
+ int res;
+
+ /** generate fmtp string based on config file */
+
+ strcpy(mode,mpa.fmtp);
+
+ if (0 == conf_get_u32(conf, "mpa_bitrate", &value)) {
+ (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp),
+ ";bitrate=%d",
+ value);
+ }
+ if (0 == conf_get_u32(conf, "mpa_layer", &value)) {
+ if(value<1 || value>4) {
+ error("MPA layer 1, 2 or 3 are allowed.");
+ return -1;
+ }
+ (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp),
+ ";layer=%d",
+ value);
+ }
+ if (0 == conf_get_u32(conf, "mpa_samplerate", &value)) {
+ switch(value) {
+ case 32000:
+ case 44100:
+ case 48000:
+ case 16000:
+ case 22050:
+ case 24000:
+ break;
+ default:
+ error("MPA samplerates of 16, 22.05, 24, 32, 44.1, and 48 kHz are allowed.");
+ return -1;
+ }
+ (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp),
+ ";samplerate=%d",
+ value);
+ }
+ if (0 == conf_get_str(conf, "mpa_mode", mode, sizeof(mode))) {
+ char *p = mode;
+ while(*p) {
+ *p = tolower(*p);
+ p++;
+ }
+
+ if(strcmp(mode,"stereo") && strcmp(mode,"joint_stereo") && strcmp(mode,"single_channel") && strcmp(mode,"dual_channel")) {
+ error("MPA mode: Permissible values are stereo, joint_stereo, single_channel, dual_channel");
+ return -1;
+ }
+
+
+ (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp),
+ ";mode=%s",
+ mode);
+ }
+
+ if(fmtp[0]==';')
+ mpa.fmtp = fmtp+1;
+ else
+ mpa.fmtp = fmtp;
+
+ /* init decoder library */
+ res = mpg123_init();
+ if(res != MPG123_OK) {
+ error("MPA libmpg123 init error %s", mpg123_plain_strerror(res));
+ return -1;
+ }
+
+ aucodec_register(&mpa);
+
+ return 0;
+}
+
+
+static int module_close(void)
+{
+ aucodec_unregister(&mpa);
+
+ mpg123_exit();
+
+ return 0;
+}
+
+
+EXPORT_SYM const struct mod_export DECL_EXPORTS(mpa) = {
+ "MPA",
+ "audio codec",
+ module_init,
+ module_close,
+};
diff --git a/modules/mpa/mpa.h b/modules/mpa/mpa.h
new file mode 100644
index 0000000..f9c2934
--- /dev/null
+++ b/modules/mpa/mpa.h
@@ -0,0 +1,32 @@
+/**
+ * @file mpa.h Private mpa Interface
+ *
+ * Copyright (C) 2016 Symonics GmbH
+ */
+
+
+struct mpa_param {
+ unsigned samplerate;
+ unsigned bitrate;
+ unsigned layer;
+ enum { AUTO=0, STEREO, JOINT_STEREO, SINGLE_CHANNEL, DUAL_CHANNEL } mode;
+};
+
+
+/* Encode */
+int mpa_encode_update(struct auenc_state **aesp, const struct aucodec *ac,
+ struct auenc_param *prm, const char *fmtp);
+int mpa_encode_frm(struct auenc_state *aes, uint8_t *buf, size_t *len,
+ const int16_t *sampv, size_t sampc);
+
+
+/* Decode */
+int mpa_decode_update(struct audec_state **adsp, const struct aucodec *ac,
+ const char *fmtp);
+int mpa_decode_frm(struct audec_state *ads, int16_t *sampv, size_t *sampc,
+ const uint8_t *buf, size_t len);
+int mpa_decode_pkloss(struct audec_state *st, int16_t *sampv, size_t *sampc);
+
+
+/* SDP */
+void mpa_decode_fmtp(struct mpa_param *prm, const char *fmtp);
diff --git a/modules/mpa/sdp.c b/modules/mpa/sdp.c
new file mode 100644
index 0000000..0e4d811
--- /dev/null
+++ b/modules/mpa/sdp.c
@@ -0,0 +1,54 @@
+/**
+ * @file mpa/sdp.c mpa SDP Functions
+ *
+ * Copyright (C) 2016 Symonics GmbH
+ */
+
+#include <re.h>
+#include <baresip.h>
+#include <string.h>
+#include "mpa.h"
+
+
+static void assign_if(uint32_t *v, const struct pl *pl,
+ uint32_t min, uint32_t max)
+{
+ const uint32_t val = pl_u32(pl);
+
+ if (val < min || val > max)
+ return;
+
+ *v = val;
+}
+
+
+void mpa_decode_fmtp(struct mpa_param *prm, const char *fmtp)
+{
+ struct pl pl, val;
+
+ if (!prm || !fmtp)
+ return;
+
+ pl_set_str(&pl, fmtp);
+
+ if (fmt_param_get(&pl, "bitrate", &val))
+ assign_if(&prm->bitrate, &val, 32000, 512000);
+
+ if (fmt_param_get(&pl, "samplerate", &val))
+ assign_if(&prm->samplerate, &val, 16000, 48000);
+
+ if (fmt_param_get(&pl, "layer", &val))
+ assign_if(&prm->layer, &val, 1, 3);
+
+ if (fmt_param_get(&pl, "mode", &val)) {
+
+ if(!strncmp("stereo",pl.p,pl.l))
+ prm->mode = STEREO;
+ else if(!strncmp("joint_stereo",pl.p,pl.l))
+ prm->mode = JOINT_STEREO;
+ else if(!strncmp("single_channel",pl.p,pl.l))
+ prm->mode = SINGLE_CHANNEL;
+ else if(!strncmp("dual_channel",pl.p,pl.l))
+ prm->mode = DUAL_CHANNEL;
+ }
+}
diff --git a/src/audio.c b/src/audio.c
index c8996f2..b8dd9f9 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -53,7 +53,7 @@
*/
enum {
- AUDIO_SAMPSZ = 1920,
+ AUDIO_SAMPSZ = 2304,
};
@@ -92,6 +92,7 @@ struct autx {
size_t psize; /**< Packet size for sending */
bool marker; /**< Marker bit for outgoing RTP */
bool is_g722; /**< Set if encoder is G.722 codec */
+ bool is_mpa; /**< Set if encoder is MPA codec */
bool muted; /**< Audio source is muted */
int cur_key; /**< Currently transmitted event */
@@ -240,14 +241,25 @@ static inline uint32_t calc_nsamp(uint32_t srate, uint8_t channels,
/**
- * Get the DSP samplerate for an audio-codec (exception for G.722)
+ * Get the DSP samplerate for an audio-codec (exception for G.722 and MPA)
*/
static inline uint32_t get_srate(const struct aucodec *ac)
{
if (!ac)
return 0;
- return !str_casecmp(ac->name, "G722") ? 16000 : ac->srate;
+ return !str_casecmp(ac->name, "G722") ? 16000 : !str_casecmp(ac->name, "MPA") ? 48000 : ac->srate;
+}
+
+/**
+ * Get the DSP samplerate for an audio-codec (exception for G.722)
+ */
+static inline uint32_t get_ch(const struct aucodec *ac)
+{
+ if (!ac)
+ return 0;
+
+ return !str_casecmp(ac->name, "MPA") ? 2 : ac->ch;
}
@@ -257,7 +269,7 @@ static inline uint32_t get_framesize(const struct aucodec *ac,
if (!ac)
return 0;
- return calc_nsamp(get_srate(ac), ac->ch, ptime);
+ return calc_nsamp(get_srate(ac), get_ch(ac), ptime);
}
@@ -279,9 +291,9 @@ static int add_audio_codec(struct audio *a, struct sdp_media *m,
return 0;
}
- if (!in_range(&a->cfg.channels, ac->ch)) {
+ if (!in_range(&a->cfg.channels, get_ch(ac))) {
debug("audio: skip codec with %uch (audio range %uch-%uch)\n",
- ac->ch, a->cfg.channels.min, a->cfg.channels.max);
+ get_ch(ac), a->cfg.channels.min, a->cfg.channels.max);
return 0;
}
@@ -334,7 +346,7 @@ static void encode_rtp_send(struct audio *a, struct autx *tx,
/* The RTP clock rate used for generating the RTP timestamp is
* independent of the number of channels and the encoding
*/
- frame_size = (tx->is_g722 ? sampc/2 : sampc) / tx->ac->ch;
+ frame_size = (tx->is_g722 ? sampc/2 : tx->is_mpa ? sampc*90/48 : sampc) / get_ch(tx->ac);
tx->ts += (uint32_t)frame_size;
@@ -793,7 +805,7 @@ static void aufilt_param_set(struct aufilt_prm *prm,
}
prm->srate = get_srate(ac);
- prm->ch = ac->ch;
+ prm->ch = get_ch(ac);
prm->ptime = ptime;
}
@@ -922,7 +934,7 @@ static int start_player(struct aurx *rx, struct audio *a)
if (!ac)
return 0;
- channels_dsp = ac->ch;
+ channels_dsp = get_ch(ac);
if (a->cfg.srate_play && a->cfg.srate_play != srate_dsp) {
resamp = true;
@@ -938,14 +950,14 @@ static int start_player(struct aurx *rx, struct audio *a)
info("audio: enable auplay resampler:"
" %uHz/%uch --> %uHz/%uch\n",
- get_srate(ac), ac->ch, srate_dsp, channels_dsp);
+ get_srate(ac), get_ch(ac), srate_dsp, channels_dsp);
rx->sampv_rs = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
if (!rx->sampv_rs)
return ENOMEM;
err = auresamp_setup(&rx->resamp,
- get_srate(ac), ac->ch,
+ get_srate(ac), get_ch(ac),
srate_dsp, channels_dsp);
if (err) {
warning("audio: could not setup auplay resampler"
@@ -1000,7 +1012,7 @@ static int start_source(struct autx *tx, struct audio *a)
if (!ac)
return 0;
- channels_dsp = ac->ch;
+ channels_dsp = get_ch(ac);
if (a->cfg.srate_src && a->cfg.srate_src != srate_dsp) {
resamp = true;
@@ -1016,7 +1028,7 @@ static int start_source(struct autx *tx, struct audio *a)
info("audio: enable ausrc resampler:"
" %uHz/%uch <-- %uHz/%uch\n",
- get_srate(ac), ac->ch, srate_dsp, channels_dsp);
+ get_srate(ac), get_ch(ac), srate_dsp, channels_dsp);
tx->sampv_rs = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
if (!tx->sampv_rs)
@@ -1024,7 +1036,7 @@ static int start_source(struct autx *tx, struct audio *a)
err = auresamp_setup(&tx->resamp,
srate_dsp, channels_dsp,
- get_srate(ac), ac->ch);
+ get_srate(ac), get_ch(ac));
if (err) {
warning("audio: could not setup ausrc resampler"
" (%m)\n", err);
@@ -1169,7 +1181,7 @@ int audio_encoder_set(struct audio *a, const struct aucodec *ac,
if (ac != tx->ac) {
info("audio: Set audio encoder: %s %uHz %dch\n",
- ac->name, get_srate(ac), ac->ch);
+ ac->name, get_srate(ac), get_ch(ac));
/* Audio source must be stopped first */
if (reset) {
@@ -1177,6 +1189,7 @@ int audio_encoder_set(struct audio *a, const struct aucodec *ac,
}
tx->is_g722 = (0 == str_casecmp(ac->name, "G722"));
+ tx->is_mpa = (0 == str_casecmp(ac->name, "MPA"));
tx->enc = mem_deref(tx->enc);
tx->ac = ac;
}
@@ -1221,7 +1234,7 @@ int audio_decoder_set(struct audio *a, const struct aucodec *ac,
if (ac != rx->ac) {
info("audio: Set audio decoder: %s %uHz %dch\n",
- ac->name, get_srate(ac), ac->ch);
+ ac->name, get_srate(ac), get_ch(ac));
rx->pt = pt_rx;
rx->ac = ac;
@@ -1370,7 +1383,7 @@ static int aucodec_print(struct re_printf *pf, const struct aucodec *ac)
if (!ac)
return 0;
- return re_hprintf(pf, "%s %uHz/%dch", ac->name, get_srate(ac), ac->ch);
+ return re_hprintf(pf, "%s %uHz/%dch", ac->name, get_srate(ac), get_ch(ac));
}