summaryrefslogtreecommitdiff
path: root/modules/silk/silk.c
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2014-02-09 11:50:07 +0100
committerAlfred E. Heggestad <aeh@db.org>2014-02-09 11:50:07 +0100
commit98bf08bdcf2edd9d397f32650a8bfe62186fbecf (patch)
treeebc6ec71f44bff8c42e4eefced61948623df02fc /modules/silk/silk.c
parente6ad5cf4401b860ba402d4b7b3c7c254bc87a019 (diff)
baresip 0.4.10
Diffstat (limited to 'modules/silk/silk.c')
-rw-r--r--modules/silk/silk.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/modules/silk/silk.c b/modules/silk/silk.c
new file mode 100644
index 0000000..95f708c
--- /dev/null
+++ b/modules/silk/silk.c
@@ -0,0 +1,259 @@
+/**
+ * @file silk.c Skype SILK audio codec
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <re.h>
+#include <baresip.h>
+#include <silk/SKP_Silk_SDK_API.h>
+
+
+/*
+ * References: https://developer.skype.com/silk
+ */
+
+
+enum {
+ MAX_BYTES_PER_FRAME = 250,
+ MAX_FRAME_SIZE = 2*480,
+};
+
+
+struct auenc_state {
+ void *enc;
+ SKP_SILK_SDK_EncControlStruct encControl;
+};
+
+struct audec_state {
+ void *dec;
+ SKP_SILK_SDK_DecControlStruct decControl;
+};
+
+
+static void encode_destructor(void *arg)
+{
+ struct auenc_state *st = arg;
+
+ mem_deref(st->enc);
+}
+
+
+static void decode_destructor(void *arg)
+{
+ struct audec_state *st = arg;
+
+ mem_deref(st->dec);
+}
+
+
+static int encode_update(struct auenc_state **aesp,
+ const struct aucodec *ac,
+ struct auenc_param *prm, const char *fmtp)
+{
+ struct auenc_state *st;
+ int ret, err = 0;
+ int32_t enc_size;
+ (void)fmtp;
+
+ if (!aesp || !ac || !prm)
+ return EINVAL;
+ if (*aesp)
+ return 0;
+
+ ret = SKP_Silk_SDK_Get_Encoder_Size(&enc_size);
+ if (ret || enc_size <= 0)
+ return EINVAL;
+
+ st = mem_alloc(sizeof(*st), encode_destructor);
+ if (!st)
+ return ENOMEM;
+
+ st->enc = mem_alloc(enc_size, NULL);
+ if (!st->enc) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ ret = SKP_Silk_SDK_InitEncoder(st->enc, &st->encControl);
+ if (ret) {
+ err = EPROTO;
+ goto out;
+ }
+
+ st->encControl.API_sampleRate = ac->srate;
+ st->encControl.maxInternalSampleRate = ac->srate;
+ st->encControl.packetSize = prm->ptime * ac->srate / 1000;
+ st->encControl.bitRate = 64000;
+ st->encControl.complexity = 2;
+ st->encControl.useInBandFEC = 0;
+ st->encControl.useDTX = 0;
+
+ info("silk: encoder: %dHz, psize=%d, bitrate=%d, complex=%d,"
+ " fec=%d, dtx=%d\n",
+ st->encControl.API_sampleRate,
+ st->encControl.packetSize,
+ st->encControl.bitRate,
+ st->encControl.complexity,
+ st->encControl.useInBandFEC,
+ st->encControl.useDTX);
+
+ out:
+ if (err)
+ mem_deref(st);
+ else
+ *aesp = st;
+
+ return err;
+}
+
+
+static int decode_update(struct audec_state **adsp,
+ const struct aucodec *ac, const char *fmtp)
+{
+ struct audec_state *st;
+ int ret, err = 0;
+ int32_t dec_size;
+ (void)fmtp;
+
+ if (*adsp)
+ return 0;
+
+ ret = SKP_Silk_SDK_Get_Decoder_Size(&dec_size);
+ if (ret || dec_size <= 0)
+ return EINVAL;
+
+ st = mem_alloc(sizeof(*st), decode_destructor);
+ if (!st)
+ return ENOMEM;
+
+ st->dec = mem_alloc(dec_size, NULL);
+ if (!st->dec) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ ret = SKP_Silk_SDK_InitDecoder(st->dec);
+ if (ret) {
+ err = EPROTO;
+ goto out;
+ }
+
+ st->decControl.API_sampleRate = ac->srate;
+
+ out:
+ if (err)
+ mem_deref(st);
+ else
+ *adsp = st;
+
+ return err;
+}
+
+
+static int encode(struct auenc_state *st, uint8_t *buf, size_t *len,
+ const int16_t *sampv, size_t sampc)
+{
+ int ret;
+ int16_t nBytesOut;
+
+ if (*len < MAX_BYTES_PER_FRAME)
+ return ENOMEM;
+
+ nBytesOut = *len;
+ ret = SKP_Silk_SDK_Encode(st->enc,
+ &st->encControl,
+ sampv,
+ (int)sampc,
+ buf,
+ &nBytesOut);
+ if (ret) {
+ warning("silk: SKP_Silk_SDK_Encode: ret=%d\n", ret);
+ }
+
+ *len = nBytesOut;
+
+ return 0;
+}
+
+
+static int decode(struct audec_state *st, int16_t *sampv,
+ size_t *sampc, const uint8_t *buf, size_t len)
+{
+ int16_t nsamp = *sampc;
+ int ret;
+
+ ret = SKP_Silk_SDK_Decode(st->dec,
+ &st->decControl,
+ 0,
+ buf,
+ (int)len,
+ sampv,
+ &nsamp);
+ if (ret) {
+ warning("silk: SKP_Silk_SDK_Decode: ret=%d\n", ret);
+ }
+
+ *sampc = nsamp;
+
+ return 0;
+}
+
+
+static int plc(struct audec_state *st, int16_t *sampv, size_t *sampc)
+{
+ int16_t nsamp = *sampc;
+ int ret;
+
+ ret = SKP_Silk_SDK_Decode(st->dec,
+ &st->decControl,
+ 1,
+ NULL,
+ 0,
+ sampv,
+ &nsamp);
+ if (ret)
+ return EPROTO;
+
+ *sampc = nsamp;
+
+ return 0;
+}
+
+
+static struct aucodec silk[] = {
+ {
+ LE_INIT, 0, "SILK", 24000, 1, NULL,
+ encode_update, encode, decode_update, decode, plc, 0, 0
+ },
+
+};
+
+
+static int module_init(void)
+{
+ debug("silk: SILK %s\n", SKP_Silk_SDK_get_version());
+
+ aucodec_register(&silk[0]);
+
+ return 0;
+}
+
+
+static int module_close(void)
+{
+ int i = ARRAY_SIZE(silk);
+
+ while (i--)
+ aucodec_unregister(&silk[i]);
+
+ return 0;
+}
+
+
+/** Module exports */
+EXPORT_SYM const struct mod_export DECL_EXPORTS(silk) = {
+ "silk",
+ "codec",
+ module_init,
+ module_close
+};