Opus support: Support multistream

This commit is contained in:
Ilari Liusvaara 2013-02-20 05:06:57 +02:00
parent 7beef32a8a
commit db28464d61
2 changed files with 441 additions and 39 deletions

View file

@ -17,6 +17,8 @@ struct invalid_state : public std::runtime_error { invalid_state(); };
class encoder;
class decoder;
class multistream_encoder;
class multistream_decoder;
template<typename T> struct generic_eget
{
@ -25,6 +27,12 @@ template<typename T> struct generic_eget
T errordefault() const;
};
template<typename T> struct generic_meget : public generic_eget<T>
{
using generic_eget<T>::operator();
T operator()(multistream_encoder& e) const;
};
template<typename T> struct generic_get
{
typedef T drettype;
@ -34,6 +42,13 @@ template<typename T> struct generic_get
T errordefault() const;
};
template<typename T> struct generic_mget : public generic_get<T>
{
using generic_get<T>::operator();
T operator()(multistream_decoder& e) const;
T operator()(multistream_encoder& e) const;
};
template<typename T> struct generic_dget
{
typedef T drettype;
@ -41,6 +56,12 @@ template<typename T> struct generic_dget
T errordefault() const;
};
template<typename T> struct generic_mdget : public generic_dget<T>
{
using generic_dget<T>::operator();
T operator()(multistream_decoder& e) const;
};
struct samplerate
{
samplerate(int32_t _fs) { fs = _fs; }
@ -52,6 +73,9 @@ struct samplerate
operator int32_t() { return fs; }
typedef samplerate erettype;
samplerate operator()(encoder& e) const;
samplerate operator()(multistream_encoder& e) const;
samplerate operator()(decoder& e) const;
samplerate operator()(multistream_decoder& e) const;
samplerate errordefault() const { return samplerate(0); }
private:
int32_t fs;
@ -61,9 +85,10 @@ struct complexity
{
complexity(int32_t _c) { c = _c; }
operator int32_t() { return c; }
static generic_eget<complexity> get;
static generic_meget<complexity> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
int32_t c;
@ -75,9 +100,10 @@ struct bitrate
static bitrate _auto;
static bitrate max;
operator int32_t() { return b; }
static generic_eget<bitrate> get;
static generic_meget<bitrate> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
int32_t b;
@ -89,9 +115,10 @@ struct vbr
static vbr cbr;
static vbr _vbr;
operator bool() { return v; }
static generic_eget<vbr> get;
static generic_meget<vbr> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
bool v;
@ -103,9 +130,10 @@ struct vbr_constraint
static vbr_constraint unconstrained;
static vbr_constraint constrained;
operator bool() { return c; }
static generic_eget<vbr_constraint> get;
static generic_meget<vbr_constraint> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
bool c;
@ -118,9 +146,10 @@ struct force_channels
static force_channels mono;
static force_channels stereo;
operator int32_t() { return f; }
static generic_eget<force_channels> get;
static generic_meget<force_channels> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
int32_t f;
@ -153,9 +182,10 @@ struct bandwidth
static bandwidth superwide;
static bandwidth full;
operator int32_t() { return bw; }
static generic_get<bandwidth> get;
static generic_mget<bandwidth> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
int32_t bw;
@ -168,9 +198,10 @@ struct signal
static signal music;
static signal voice;
operator int32_t() { return s; }
static generic_eget<signal> get;
static generic_meget<signal> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
int32_t s;
@ -183,9 +214,10 @@ struct application
static application voice;
static application lowdelay;
operator int32_t() { return app; }
static generic_eget<application> get;
static generic_meget<application> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
int32_t app;
@ -198,6 +230,7 @@ struct _lookahead
operator uint32_t() { return l; }
typedef _lookahead erettype;
_lookahead operator()(encoder& e) const;
_lookahead operator()(multistream_encoder& e) const;
_lookahead errordefault() const { return _lookahead(0);}
private:
uint32_t l;
@ -210,9 +243,10 @@ struct fec
static fec disabled;
static fec enabled;
operator bool() { return f; }
static generic_eget<fec> get;
static generic_meget<fec> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
bool f;
@ -222,9 +256,10 @@ struct lossperc
{
lossperc(uint32_t _loss) { loss = _loss; };
operator uint32_t() { return loss; }
static generic_eget<lossperc> get;
static generic_meget<lossperc> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
uint32_t loss;
@ -236,9 +271,10 @@ struct dtx
static dtx disabled;
static dtx enabled;
operator bool() { return d; }
static generic_eget<dtx> get;
static generic_meget<dtx> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
bool d;
@ -251,9 +287,10 @@ struct lsbdepth
static lsbdepth d16;
static lsbdepth d24;
operator uint32_t() { return depth; }
static generic_eget<lsbdepth> get;
static generic_meget<lsbdepth> get;
typedef void erettype;
void operator()(encoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
private:
uint32_t depth;
@ -264,9 +301,10 @@ struct _pktduration
_pktduration() { d = 0; }
_pktduration(uint32_t _d) { d = _d; }
operator uint32_t() { return d; }
typedef _pktduration erettype;
_pktduration operator()(encoder& e) const;
_pktduration errordefault() const { return _pktduration(0); }
typedef _pktduration drettype;
_pktduration operator()(decoder& e) const;
_pktduration operator()(multistream_decoder& e) const;
_pktduration errordefault() const; /*{ return _pktduration(0); }*/
private:
uint32_t d;
};
@ -278,6 +316,8 @@ struct _reset
typedef void erettype;
void operator()(decoder& e) const;
void operator()(encoder& e) const;
void operator()(multistream_decoder& e) const;
void operator()(multistream_encoder& e) const;
void errordefault() const {}
};
extern _reset reset;
@ -291,6 +331,8 @@ struct _finalrange
typedef _finalrange erettype;
_finalrange operator()(decoder& e) const;
_finalrange operator()(encoder& e) const;
_finalrange operator()(multistream_decoder& e) const;
_finalrange operator()(multistream_encoder& e) const;
_finalrange errordefault() const { return _finalrange(0); }
private:
uint32_t f;
@ -316,9 +358,10 @@ struct gain
{
gain(int32_t _g) { g = _g; };
operator int32_t() { return g; }
static generic_dget<gain> get;
static generic_mdget<gain> get;
typedef void drettype;
void operator()(decoder& d) const;
void operator()(multistream_decoder& d) const;
gain errordefault() const { return gain(0); }
private:
int32_t g;
@ -331,6 +374,8 @@ struct set_control_int
typedef void erettype;
void operator()(encoder& e) const;
void operator()(decoder& e) const;
void operator()(multistream_encoder& e) const;
void operator()(multistream_decoder& e) const;
void errordefault() const {}
private:
int32_t ctl;
@ -344,6 +389,8 @@ struct get_control_int
typedef int32_t erettype;
int32_t operator()(encoder& e) const;
int32_t operator()(decoder& e) const;
int32_t operator()(multistream_encoder& e) const;
int32_t operator()(multistream_decoder& e) const;
int32_t errordefault() const { return -1; }
private:
int32_t ctl;
@ -358,6 +405,7 @@ public:
encoder(const encoder& e);
encoder(const encoder& e, char* memory);
static size_t size(bool stereo);
size_t size() const { return size(stereo); }
encoder& operator=(const encoder& e);
template<typename T> typename T::erettype ctl(const T& c) { return c(*this); }
template<typename T> typename T::erettype ctl_quiet(const T& c)
@ -383,6 +431,7 @@ public:
decoder(const decoder& e);
decoder(const decoder& e, char* memory);
static size_t size(bool stereo);
size_t size() const { return size(stereo); }
decoder& operator=(const decoder& e);
template<typename T> typename T::drettype ctl(const T& c) { return c(*this); }
template<typename T> typename T::drettype ctl_quiet(const T& c)
@ -421,6 +470,78 @@ private:
bool user;
};
class multistream_encoder
{
public:
multistream_encoder(samplerate rate, unsigned channels, unsigned streams,
unsigned coupled_streams, const unsigned char* mapping, application app, char* memory = NULL);
static size_t size(unsigned streams, unsigned coupled_streams);
size_t size() const { return size(streams, coupled); }
multistream_encoder(const multistream_encoder& e);
multistream_encoder(const multistream_encoder& e, char* memory);
multistream_encoder& operator=(const multistream_encoder& e);
~multistream_encoder();
encoder& operator[](size_t idx);
size_t encode(const int16_t* in, uint32_t inframes, unsigned char* out, uint32_t maxout);
size_t encode(const float* in, uint32_t inframes, unsigned char* out, uint32_t maxout);
template<typename T> typename T::erettype ctl(const T& c) { return c(*this); }
template<typename T> typename T::erettype ctl_quiet(const T& c)
{
try { return c(*this); } catch(...) { return c.errordefault(); }
}
uint8_t get_channels() { return channels; }
uint8_t get_streams() { return streams; }
void* getmem() { return memory + offset; }
private:
void init_copy(const multistream_encoder& e, char* memory);
char* substream(size_t idx);
void set_params(uint8_t _channels, uint8_t _streams, uint8_t _coupled);
char* memory;
bool user;
uint8_t channels;
uint8_t streams;
uint8_t coupled;
size_t offset;
size_t opussize;
};
class multistream_decoder
{
public:
multistream_decoder(samplerate rate, unsigned channels, unsigned streams,
unsigned coupled_streams, const unsigned char* mapping, char* memory = NULL);
static size_t size(unsigned streams, unsigned coupled_streams);
size_t size() const { return size(streams, coupled); }
multistream_decoder(const multistream_decoder& e);
multistream_decoder(const multistream_decoder& e, char* memory);
multistream_decoder& operator=(const multistream_decoder& e);
~multistream_decoder();
decoder& operator[](size_t idx);
template<typename T> typename T::drettype ctl(const T& c) { return c(*this); }
template<typename T> typename T::drettype ctl_quiet(const T& c)
{
try { return c(*this); } catch(...) { return c.errordefault(); }
}
size_t decode(const unsigned char* in, uint32_t insize, int16_t* out, uint32_t maxframes,
bool decode_fec = false);
size_t decode(const unsigned char* in, uint32_t insize, float* out, uint32_t maxframes,
bool decode_fec = false);
uint8_t get_channels() { return channels; }
uint8_t get_streams() { return streams; }
void* getmem() { return memory + offset; }
private:
void init_copy(const multistream_decoder& e, char* memory);
char* substream(size_t idx);
void set_params(uint8_t _channels, uint8_t _streams, uint8_t _coupled);
char* memory;
bool user;
uint8_t channels;
uint8_t streams;
uint8_t coupled;
size_t offset;
size_t opussize;
};
struct parsed_frame
{
const unsigned char* ptr;

View file

@ -3,6 +3,7 @@
#include "opus.hpp"
#include <opus.h>
#include <opus_defines.h>
#include <opus_multistream.h>
#include <sstream>
#include <cstring>
@ -87,6 +88,13 @@ unimplemented::unimplemented()
invalid_state::invalid_state()
: std::runtime_error("Invalid state") {}
char* alignptr(char* ptr, size_t align)
{
while((intptr_t)ptr % align)
ptr++;
return ptr;
}
int32_t throwex(int32_t ret)
{
if(ret >= 0)
@ -146,7 +154,8 @@ template<> gain get_ctlnum<gain>::errordefault() { return gain(0); }
OpusEncoder* E(encoder& e) { return reinterpret_cast<OpusEncoder*>(e.getmem()); }
OpusDecoder* D(decoder& d) { return reinterpret_cast<OpusDecoder*>(d.getmem()); }
OpusRepacketizer* R(repacketizer& r) { return reinterpret_cast<OpusRepacketizer*>(r.getmem()); }
OpusMSEncoder* ME(multistream_encoder& e) { return reinterpret_cast<OpusMSEncoder*>(e.getmem()); }
OpusMSDecoder* MD(multistream_decoder& d) { return reinterpret_cast<OpusMSDecoder*>(d.getmem()); }
template<typename T> T generic_ctl(encoder& e, int32_t ctl)
{
@ -172,14 +181,34 @@ template<typename T> T generic_ctl(decoder& d, int32_t ctl, T val)
throwex(opus_decoder_ctl(D(d), ctl, val));
}
template<typename T> T do_generic_get(encoder& e)
template<typename T> T generic_ctl(multistream_encoder& e, int32_t ctl, T val)
{
return T(generic_ctl<int32_t>(e, get_ctlnum<T>::num));
throwex(opus_multistream_encoder_ctl(ME(e), ctl, val));
}
template<typename T> T do_generic_get(decoder& d)
template<typename T> T generic_ctl(multistream_encoder& e, int32_t ctl)
{
return T(generic_ctl<int32_t>(d, get_ctlnum<T>::num));
T val;
throwex(opus_multistream_encoder_ctl(ME(e), ctl, &val));
return val;
}
template<typename T> T generic_ctl(multistream_decoder& d, int32_t ctl, T val)
{
throwex(opus_multistream_decoder_ctl(MD(d), ctl, val));
}
template<typename T> T generic_ctl(multistream_decoder& d, int32_t ctl)
{
T val;
throwex(opus_multistream_decoder_ctl(MD(d), ctl, &val));
return val;
}
template<typename T, typename U> T do_generic_get(U& e)
{
return T(generic_ctl<int32_t>(e, get_ctlnum<T>::num));
}
template<typename T> T generic_eget<T>::operator()(encoder& e) const
@ -187,11 +216,21 @@ template<typename T> T generic_eget<T>::operator()(encoder& e) const
return do_generic_get<T>(e);
}
template<typename T> T generic_meget<T>::operator()(multistream_encoder& e) const
{
return do_generic_get<T>(e);
}
template<typename T> T generic_dget<T>::operator()(decoder& d) const
{
return do_generic_get<T>(d);
}
template<typename T> T generic_mdget<T>::operator()(multistream_decoder& d) const
{
return do_generic_get<T>(d);
}
template<typename T> T generic_get<T>::operator()(decoder& d) const
{
return do_generic_get<T>(d);
@ -202,6 +241,16 @@ template<typename T> T generic_get<T>::operator()(encoder& e) const
return do_generic_get<T>(e);
}
template<typename T> T generic_mget<T>::operator()(multistream_encoder& e) const
{
return do_generic_get<T>(e);
}
template<typename T> T generic_mget<T>::operator()(multistream_decoder& d) const
{
return do_generic_get<T>(d);
}
template<typename T> T generic_eget<T>::errordefault() const
{
return get_ctlnum<T>::errordefault();
@ -217,7 +266,6 @@ template<typename T> T generic_get<T>::errordefault() const
return get_ctlnum<T>::errordefault();
}
samplerate samplerate::operator()(encoder& e) const
{
return samplerate(generic_ctl<int32_t>(e, OPUS_GET_SAMPLE_RATE_REQUEST));
@ -228,35 +276,40 @@ void complexity::operator()(encoder& e) const
generic_ctl(e, OPUS_SET_COMPLEXITY_REQUEST, c);
}
generic_eget<complexity> complexity::get;
generic_meget<complexity> complexity::get;
void bitrate::operator()(encoder& e) const
{
generic_ctl(e, OPUS_SET_BITRATE_REQUEST, b);
}
generic_eget<bitrate> bitrate::get;
void bitrate::operator()(multistream_encoder& e) const
{
generic_ctl(e, OPUS_SET_BITRATE_REQUEST, b);
}
generic_meget<bitrate> bitrate::get;
void vbr::operator()(encoder& e) const
{
generic_ctl<int32_t>(e, OPUS_SET_VBR_REQUEST, (int32_t)(v ? 1 : 0));
}
generic_eget<vbr> vbr::get;
generic_meget<vbr> vbr::get;
void vbr_constraint::operator()(encoder& e) const
{
generic_ctl<int32_t>(e, OPUS_SET_VBR_CONSTRAINT_REQUEST, (int32_t)(c ? 1 : 0));
}
generic_eget<vbr_constraint> vbr_constraint::get;
generic_meget<vbr_constraint> vbr_constraint::get;
void force_channels::operator()(encoder& e) const
{
generic_ctl(e, OPUS_SET_FORCE_CHANNELS_REQUEST, f);
}
generic_eget<force_channels> force_channels::get;
generic_meget<force_channels> force_channels::get;
void max_bandwidth::operator()(encoder& e) const
{
@ -270,21 +323,21 @@ void bandwidth::operator()(encoder& e) const
generic_ctl(e, OPUS_SET_BANDWIDTH_REQUEST, bw);
}
generic_get<bandwidth> bandwidth::get;
generic_mget<bandwidth> bandwidth::get;
void signal::operator()(encoder& e) const
{
generic_ctl(e, OPUS_SET_SIGNAL_REQUEST, s);
}
generic_eget<signal> signal::get;
generic_meget<signal> signal::get;
void application::operator()(encoder& e) const
{
generic_ctl(e, OPUS_SET_APPLICATION_REQUEST, app);
}
generic_eget<application> application::get;
generic_meget<application> application::get;
_lookahead _lookahead::operator()(encoder& e) const
{
@ -296,32 +349,32 @@ void fec::operator()(encoder& e) const
generic_ctl<int32_t>(e, OPUS_SET_INBAND_FEC_REQUEST, (int32_t)(f ? 1 : 0));
}
generic_eget<fec> fec::get;
generic_meget<fec> fec::get;
void lossperc::operator()(encoder& e) const
{
generic_ctl(e, OPUS_SET_PACKET_LOSS_PERC_REQUEST, (int32_t)loss);
}
generic_eget<lossperc> lossperc::get;
generic_meget<lossperc> lossperc::get;
void dtx::operator()(encoder& e) const
{
generic_ctl<int32_t>(e, OPUS_SET_DTX_REQUEST, (int32_t)(d ? 1 : 0));
}
generic_eget<dtx> dtx::get;
generic_meget<dtx> dtx::get;
void lsbdepth::operator()(encoder& e) const
{
generic_ctl(e, OPUS_SET_LSB_DEPTH_REQUEST, (int32_t)depth);
}
generic_eget<lsbdepth> lsbdepth::get;
generic_meget<lsbdepth> lsbdepth::get;
_pktduration _pktduration::operator()(encoder& e) const
_pktduration _pktduration::operator()(decoder& d) const
{
return _pktduration(generic_ctl<int32_t>(e, OPUS_GET_LAST_PACKET_DURATION_REQUEST));
return _pktduration(generic_ctl<int32_t>(d, OPUS_GET_LAST_PACKET_DURATION_REQUEST));
}
void _reset::operator()(decoder& d) const
@ -359,7 +412,7 @@ void gain::operator()(decoder& d) const
generic_ctl(d, OPUS_SET_GAIN_REQUEST, g);
}
generic_dget<gain> gain::get;
generic_mdget<gain> gain::get;
void set_control_int::operator()(encoder& e) const
{
@ -371,6 +424,16 @@ void set_control_int::operator()(decoder& d) const
generic_ctl(d, ctl, val);
}
void set_control_int::operator()(multistream_encoder& e) const
{
generic_ctl(e, ctl, val);
}
void set_control_int::operator()(multistream_decoder& d) const
{
generic_ctl(d, ctl, val);
}
int32_t get_control_int::operator()(encoder& e) const
{
return generic_ctl<int32_t>(e, ctl);
@ -381,10 +444,23 @@ int32_t get_control_int::operator()(decoder& d) const
return generic_ctl<int32_t>(d, ctl);
}
int32_t get_control_int::operator()(multistream_encoder& e) const
{
return generic_ctl<int32_t>(e, ctl);
}
int32_t get_control_int::operator()(multistream_decoder& d) const
{
return generic_ctl<int32_t>(d, ctl);
}
void force_instantiate()
{
encoder e(samplerate::r48k, true, application::audio);
decoder d(samplerate::r48k, true);
multistream_encoder me(samplerate::r48k, 1, 1, 0, NULL, application::audio);
multistream_decoder md(samplerate::r48k, 1, 1, 0, NULL);
complexity::get(e);
bitrate::get(e);
vbr::get(e);
@ -400,6 +476,19 @@ void force_instantiate()
dtx::get(e);
lsbdepth::get(e);
gain::get(d);
bitrate::get(me);
lsbdepth::get(me);
vbr::get(me);
vbr_constraint::get(me);
application::get(me);
bandwidth::get(me);
bandwidth::get(md);
complexity::get(me);
lossperc::get(me);
dtx::get(me);
signal::get(me);
fec::get(me);
force_channels::get(me);
complexity::get.errordefault();
bitrate::get.errordefault();
@ -416,6 +505,8 @@ void force_instantiate()
lsbdepth::get.errordefault();
gain::get.errordefault();
d.ctl(opus::pktduration);
//d.ctl_quiet(opus::pktduration);
e.ctl_quiet(opus::reset);
e.ctl_quiet(opus::finalrange);
e.ctl_quiet(opus::signal::get);
@ -446,7 +537,8 @@ encoder::encoder(samplerate rate, bool _stereo, application app, char* _memory)
try {
throwex(opus_encoder_init(E(*this), rate, _stereo ? 2 : 1, app));
} catch(...) {
delete[] reinterpret_cast<char*>(memory);
if(!user)
delete[] reinterpret_cast<char*>(memory);
throw;
}
}
@ -506,7 +598,8 @@ decoder::decoder(samplerate rate, bool _stereo, char* _memory)
try {
throwex(opus_decoder_init(D(*this), rate, _stereo ? 2 : 1));
} catch(...) {
delete[] reinterpret_cast<char*>(memory);
if(!user)
delete[] reinterpret_cast<char*>(memory);
throw;
}
}
@ -627,6 +720,194 @@ unsigned repacketizer::get_nb_frames()
return opus_repacketizer_get_nb_frames(R(*this));
}
encoder& multistream_encoder::operator[](size_t idx)
{
if(idx > (size_t)streams)
throw opus::bad_argument();
return *reinterpret_cast<encoder*>(substream(idx));
}
size_t multistream_encoder::size(unsigned streams, unsigned coupled_streams)
{
return alignof(encoder) + streams * sizeof(encoder) + opus_multistream_encoder_get_size(streams,
coupled_streams);
}
multistream_encoder::~multistream_encoder()
{
if(!user)
delete memory;
}
multistream_encoder::multistream_encoder(samplerate rate, unsigned _channels, unsigned _streams,
unsigned coupled_streams, const unsigned char* mapping, application app, char* _memory)
{
user = (_memory != NULL);
memory = _memory ? alignptr(_memory, alignof(encoder)) : new char[size(streams, coupled_streams)];
set_params(_channels, _streams, coupled_streams);
try {
throwex(opus_multistream_encoder_init(ME(*this), rate, channels, _streams, coupled_streams, mapping,
app));
} catch(...) {
if(!user)
delete[] memory;
throw;
}
}
multistream_encoder::multistream_encoder(const multistream_encoder& e)
{
init_copy(e, new char[e.size()]);
user = false;
}
multistream_encoder::multistream_encoder(const multistream_encoder& e, char* memory)
{
init_copy(e, memory);
user = true;
}
multistream_encoder& multistream_encoder::operator=(const multistream_encoder& e)
{
if(this == &e)
return *this;
if(streams != e.streams || coupled != e.coupled)
throw std::runtime_error("Stream mismatch in assignment");
memcpy(ME(*this), e.memory + e.offset, opussize);
channels = e.channels;
return *this;
}
void multistream_encoder::init_copy(const multistream_encoder& e, char* _memory)
{
user = (_memory != NULL);
set_params(e.channels, e.streams, e.coupled);
memory = _memory ? alignptr(_memory, alignof(encoder)) : new char[e.size()];
memcpy(ME(*this), e.memory + e.offset, opussize);
for(int32_t i = 0; i < streams; i++) {
OpusEncoder* e;
opus_multistream_encoder_ctl(ME(*this), OPUS_MULTISTREAM_GET_ENCODER_STATE(i, &e));
new(substream(i)) encoder(e, i < coupled);
}
}
size_t multistream_encoder::encode(const int16_t* in, uint32_t inframes, unsigned char* out, uint32_t maxout)
{
return throwex(opus_multistream_encode(ME(*this), in, inframes, out, maxout));
}
size_t multistream_encoder::encode(const float* in, uint32_t inframes, unsigned char* out, uint32_t maxout)
{
return throwex(opus_multistream_encode_float(ME(*this), in, inframes, out, maxout));
}
char* multistream_encoder::substream(size_t idx)
{
return memory + idx * sizeof(encoder);
}
void multistream_encoder::set_params(uint8_t _channels, uint8_t _streams, uint8_t _coupled)
{
channels = _channels;
streams = _streams;
coupled = _coupled;
offset = _streams * sizeof(encoder);
opussize = opus_multistream_encoder_get_size(_streams, _coupled);
}
decoder& multistream_decoder::operator[](size_t idx)
{
if(idx > (size_t)streams)
throw opus::bad_argument();
return *reinterpret_cast<decoder*>(substream(idx));
}
size_t multistream_decoder::size(unsigned streams, unsigned coupled_streams)
{
return streams * sizeof(decoder) + opus_multistream_decoder_get_size(streams,
coupled_streams);
}
multistream_decoder::multistream_decoder(samplerate rate, unsigned _channels, unsigned _streams,
unsigned coupled_streams, const unsigned char* mapping, char* _memory)
{
user = (memory != NULL);
memory = _memory ? alignptr(_memory, alignof(decoder)) : new char[size(streams, coupled_streams)];
set_params(_channels, _streams, coupled_streams);
try {
throwex(opus_multistream_decoder_init(MD(*this), rate, channels, streams, coupled_streams, mapping));
} catch(...) {
if(!user)
delete[] memory;
throw;
}
}
multistream_decoder::multistream_decoder(const multistream_decoder& e)
{
init_copy(e, NULL);
}
multistream_decoder::multistream_decoder(const multistream_decoder& e, char* memory)
{
init_copy(e, memory);
}
multistream_decoder::~multistream_decoder()
{
if(!user)
delete memory;
}
multistream_decoder& multistream_decoder::operator=(const multistream_decoder& d)
{
if(this == &d)
return *this;
if(streams != d.streams || coupled != d.coupled)
throw std::runtime_error("Stream mismatch in assignment");
memcpy(MD(*this), d.memory + d.offset, opussize);
channels = d.channels;
return *this;
}
void multistream_decoder::init_copy(const multistream_decoder& e, char* _memory)
{
user = (_memory != NULL);
set_params(e.channels, e.streams, e.coupled);
memory = _memory ? alignptr(_memory, alignof(decoder)) : new char[e.size()];
memcpy(MD(*this), e.memory + e.offset, opussize);
for(int32_t i = 0; i < (size_t)streams; i++) {
OpusDecoder* e;
opus_multistream_decoder_ctl(MD(*this), OPUS_MULTISTREAM_GET_DECODER_STATE(i, &e));
new(substream(i)) decoder(e, i < coupled);
}
}
size_t multistream_decoder::decode(const unsigned char* in, uint32_t insize, int16_t* out, uint32_t maxframes,
bool decode_fec)
{
return throwex(opus_multistream_decode(MD(*this), in, insize, out, maxframes, decode_fec));
}
size_t multistream_decoder::decode(const unsigned char* in, uint32_t insize, float* out, uint32_t maxframes,
bool decode_fec)
{
return throwex(opus_multistream_decode_float(MD(*this), in, insize, out, maxframes, decode_fec));
}
void multistream_decoder::set_params(uint8_t _channels, uint8_t _streams, uint8_t _coupled)
{
channels = _channels;
streams = _streams;
coupled = _coupled;
offset = _streams * sizeof(encoder);
opussize = opus_multistream_decoder_get_size(_streams, _coupled);
}
char* multistream_decoder::substream(size_t idx)
{
return memory + idx * sizeof(encoder);
}
uint32_t packet_get_nb_frames(const unsigned char* packet, size_t len)
{
return throwex(opus_packet_get_nb_frames(packet, len));