summaryrefslogtreecommitdiff
path: root/modules/mpa/decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mpa/decode.c')
-rw-r--r--modules/mpa/decode.c136
1 files changed, 136 insertions, 0 deletions
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;
+}
+
+