diff options
Diffstat (limited to 'modules/opus/decode.c')
-rw-r--r-- | modules/opus/decode.c | 101 |
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; +} |