summaryrefslogtreecommitdiff
path: root/modules/opus/decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/opus/decode.c')
-rw-r--r--modules/opus/decode.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/modules/opus/decode.c b/modules/opus/decode.c
new file mode 100644
index 0000000..f2d67b1
--- /dev/null
+++ b/modules/opus/decode.c
@@ -0,0 +1,101 @@
+/**
+ * @file opus/decode.c Opus Decode
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+
+#include <re.h>
+#include <baresip.h>
+#include <opus/opus.h>
+#include "opus.h"
+
+
+struct audec_state {
+ OpusDecoder *dec;
+ unsigned ch;
+};
+
+
+static void destructor(void *arg)
+{
+ struct audec_state *ads = arg;
+
+ if (ads->dec)
+ opus_decoder_destroy(ads->dec);
+}
+
+
+int opus_decode_update(struct audec_state **adsp, const struct aucodec *ac,
+ const char *fmtp)
+{
+ struct audec_state *ads;
+ int opuserr, err = 0;
+ (void)fmtp;
+
+ if (!adsp || !ac || !ac->ch)
+ return EINVAL;
+
+ ads = *adsp;
+
+ if (ads)
+ return 0;
+
+ ads = mem_zalloc(sizeof(*ads), destructor);
+ if (!ads)
+ return ENOMEM;
+
+ ads->ch = ac->ch;
+
+ ads->dec = opus_decoder_create(ac->srate, ac->ch, &opuserr);
+ if (!ads->dec) {
+ warning("opus: decoder create: %s\n", opus_strerror(opuserr));
+ err = ENOMEM;
+ goto out;
+ }
+
+ out:
+ if (err)
+ mem_deref(ads);
+ else
+ *adsp = ads;
+
+ return err;
+}
+
+
+int opus_decode_frm(struct audec_state *ads, int16_t *sampv, size_t *sampc,
+ const uint8_t *buf, size_t len)
+{
+ int n;
+
+ if (!ads || !sampv || !sampc || !buf)
+ return EINVAL;
+
+ n = opus_decode(ads->dec, buf, (opus_int32)len,
+ sampv, (int)(*sampc/ads->ch), 0);
+ if (n < 0) {
+ warning("opus: decode error: %s\n", opus_strerror(n));
+ return EPROTO;
+ }
+
+ *sampc = n * ads->ch;
+
+ return 0;
+}
+
+
+int opus_decode_pkloss(struct audec_state *ads, int16_t *sampv, size_t *sampc)
+{
+ int n;
+
+ if (!ads || !sampv || !sampc)
+ return EINVAL;
+
+ n = opus_decode(ads->dec, NULL, 0, sampv, (int)(*sampc/ads->ch), 0);
+ if (n < 0)
+ return EPROTO;
+
+ *sampc = n * ads->ch;
+
+ return 0;
+}