1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
/**
* @file opus_multistream/decode.c Opus Multistream Decode
*
* Copyright (C) 2019 Alfred E. Heggestad
*/
#include <re.h>
#include <rem.h>
#include <baresip.h>
#include <opus/opus_multistream.h>
#include "opus_multistream.h"
struct audec_state {
OpusMSDecoder *dec;
unsigned ch;
};
static void destructor(void *arg)
{
struct audec_state *ads = arg;
if (ads->dec)
opus_multistream_decoder_destroy(ads->dec);
}
int opus_multistream_decode_update(struct audec_state **adsp,
const struct aucodec *ac, const char *fmtp)
{
struct audec_state *ads;
unsigned ch;
unsigned char mapping[256];
int opuserr, err = 0;
(void)fmtp;
if (!adsp || !ac || !ac->ch)
return EINVAL;
ads = *adsp;
if (ads)
return 0;
/* create one mapping per channel */
for (ch=0; ch<ac->ch; ch++) {
if (ch >= 256) {
warning("opus: Exceeding the acceptable"
" 255 channel-mappings\n");
return EINVAL;
}
else {
mapping[ch] = ch;
}
}
ads = mem_zalloc(sizeof(*ads), destructor);
if (!ads)
return ENOMEM;
ads->ch = ac->ch;
ads->dec = opus_multistream_decoder_create(ac->srate, ac->ch,
opus_ms_streams,
opus_ms_c_streams,
mapping, &opuserr);
if (!ads->dec) {
warning("opus_multistream: decoder create: %s\n",
opus_strerror(opuserr));
err = ENOMEM;
goto out;
}
out:
if (err)
mem_deref(ads);
else
*adsp = ads;
return err;
}
int opus_multistream_decode_frm(struct audec_state *ads,
int fmt, void *sampv, size_t *sampc,
bool marker, const uint8_t *buf, size_t len)
{
int n;
(void)marker;
if (!ads || !sampv || !sampc || !buf)
return EINVAL;
switch (fmt) {
case AUFMT_S16LE:
n = opus_multistream_decode(ads->dec, buf, (opus_int32)len,
sampv, (int)(*sampc/ads->ch), 0);
if (n < 0) {
warning("opus_multistream: decode error: %s\n",
opus_strerror(n));
return EPROTO;
}
break;
case AUFMT_FLOAT:
n = opus_multistream_decode_float(ads->dec,
buf, (opus_int32)len,
sampv, (int)(*sampc/ads->ch), 0);
if (n < 0) {
warning("opus_multistream: float decode error: %s\n",
opus_strerror(n));
return EPROTO;
}
break;
default:
return ENOTSUP;
}
*sampc = n * ads->ch;
return 0;
}
int opus_multistream_decode_pkloss(struct audec_state *ads,
int fmt, void *sampv, size_t *sampc,
const uint8_t *buf, size_t len)
{
int n;
(void)buf;
(void)len;
if (!ads || !sampv || !sampc)
return EINVAL;
switch (fmt) {
case AUFMT_S16LE:
n = opus_multistream_decode(ads->dec, NULL, 0,
sampv, (int)(*sampc/ads->ch), 0);
if (n < 0)
return EPROTO;
break;
case AUFMT_FLOAT:
n = opus_multistream_decode_float(ads->dec, NULL, 0,
sampv, (int)(*sampc/ads->ch), 0);
if (n < 0)
return EPROTO;
break;
default:
return ENOTSUP;
}
*sampc = n * ads->ch;
return 0;
}
|