ACK On Tue, Nov 12, 2013 at 03:52:36PM -0600, Jeremy White wrote: > Signed-off-by: Jeremy White <jwhite@xxxxxxxxxxxxxxx> > --- > common/Makefile.am | 2 + > common/snd_codec.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++--- > common/snd_codec.h | 20 ++++++-- > configure.ac | 4 ++ > spice.proto | 1 + > spice1.proto | 1 + > 6 files changed, 153 insertions(+), 11 deletions(-) > > diff --git a/common/Makefile.am b/common/Makefile.am > index c79f596..73703fc 100644 > --- a/common/Makefile.am > +++ b/common/Makefile.am > @@ -84,6 +84,7 @@ AM_CPPFLAGS = \ > $(GL_CFLAGS) \ > $(PIXMAN_CFLAGS) \ > $(CELT051_CFLAGS) \ > + $(OPUS_CFLAGS) \ > $(PROTOCOL_CFLAGS) \ > $(SMARTCARD_CFLAGS) \ > $(VISIBILITY_HIDDEN_CFLAGS) \ > @@ -92,6 +93,7 @@ AM_CPPFLAGS = \ > $(NULL) > > libspice_common_la_LIBADD = \ > + $(OPUS_LIBS) \ > $(CELT051_LIBS) > > MARSHALLERS_DEPS = \ > diff --git a/common/snd_codec.c b/common/snd_codec.c > index 2d13183..f737432 100644 > --- a/common/snd_codec.c > +++ b/common/snd_codec.c > @@ -48,6 +48,11 @@ typedef struct > CELTEncoder *celt_encoder; > CELTDecoder *celt_decoder; > #endif > + > +#if HAVE_OPUS > + OpusEncoder *opus_encoder; > + OpusDecoder *opus_decoder; > +#endif > } SndCodecInternal; > > > @@ -80,7 +85,7 @@ static int snd_codec_create_celt051(SndCodecInternal *codec, int encode, int dec > int celt_error; > > codec->celt_mode = celt051_mode_create(codec->frequency, > - SND_CODEC_CELT_PLAYBACK_CHAN, > + SND_CODEC_PLAYBACK_CHAN, > SND_CODEC_CELT_FRAME_SIZE, &celt_error); > if (! codec->celt_mode) > { > @@ -119,7 +124,7 @@ error: > static int snd_codec_encode_celt051(SndCodecInternal *codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size) > { > int n; > - if (in_size != SND_CODEC_CELT_FRAME_SIZE * SND_CODEC_CELT_PLAYBACK_CHAN * 2) > + if (in_size != SND_CODEC_CELT_FRAME_SIZE * SND_CODEC_PLAYBACK_CHAN * 2) > return SND_CODEC_INVALID_ENCODE_SIZE; > n = celt051_encode(codec->celt_encoder, (celt_int16_t *) in_ptr, NULL, out_ptr, *out_size); > if (n < 0) { > @@ -138,12 +143,93 @@ static int snd_codec_decode_celt051(SndCodecInternal *codec, uint8_t *in_ptr, in > spice_printerr("celt051_decode failed %d\n", n); > return SND_CODEC_DECODE_FAILED; > } > - *out_size = SND_CODEC_CELT_FRAME_SIZE * SND_CODEC_CELT_PLAYBACK_CHAN * 2 /* 16 fmt */; > + *out_size = SND_CODEC_CELT_FRAME_SIZE * SND_CODEC_PLAYBACK_CHAN * 2 /* 16 fmt */; > return SND_CODEC_OK; > } > #endif > > > +/* Opus support routines */ > +#if HAVE_OPUS > +static void snd_codec_destroy_opus(SndCodecInternal *codec) > +{ > + if (codec->opus_decoder) > + { > + opus_decoder_destroy(codec->opus_decoder); > + codec->opus_decoder = NULL; > + } > + > + if (codec->opus_encoder) > + { > + opus_encoder_destroy(codec->opus_encoder); > + codec->opus_encoder = NULL; > + } > + > +} > + > +static int snd_codec_create_opus(SndCodecInternal *codec, int encode, int decode) > +{ > + int opus_error; > + > + if (encode) > + { > + codec->opus_encoder = opus_encoder_create(codec->frequency, > + SND_CODEC_PLAYBACK_CHAN, > + OPUS_APPLICATION_AUDIO, &opus_error); > + if (! codec->opus_encoder) > + { > + spice_printerr("create opus encoder failed; error %d", opus_error); > + goto error; > + } > + } > + > + if (decode) > + { > + codec->opus_decoder = opus_decoder_create(codec->frequency, > + SND_CODEC_PLAYBACK_CHAN, &opus_error); > + if (! codec->opus_decoder) > + { > + spice_printerr("create opus decoder failed; error %d", opus_error); > + goto error; > + } > + } > + > + codec->mode = SPICE_AUDIO_DATA_MODE_OPUS; > + return SND_CODEC_OK; > + > +error: > + snd_codec_destroy_opus(codec); > + return SND_CODEC_UNAVAILABLE; > +} > + > +static int snd_codec_encode_opus(SndCodecInternal *codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size) > +{ > + int n; > + if (in_size != SND_CODEC_OPUS_FRAME_SIZE * SND_CODEC_PLAYBACK_CHAN * 2) > + return SND_CODEC_INVALID_ENCODE_SIZE; > + n = opus_encode(codec->opus_encoder, (opus_int16 *) in_ptr, SND_CODEC_OPUS_FRAME_SIZE, out_ptr, *out_size); > + if (n < 0) { > + spice_printerr("opus_encode failed %d\n", n); > + return SND_CODEC_ENCODE_FAILED; > + } > + *out_size = n; > + return SND_CODEC_OK; > +} > + > +static int snd_codec_decode_opus(SndCodecInternal *codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size) > +{ > + int n; > + n = opus_decode(codec->opus_decoder, in_ptr, in_size, (opus_int16 *) out_ptr, > + *out_size / SND_CODEC_PLAYBACK_CHAN / 2, 0); > + if (n < 0) { > + spice_printerr("opus_decode failed %d\n", n); > + return SND_CODEC_DECODE_FAILED; > + } > + *out_size = n * SND_CODEC_PLAYBACK_CHAN * 2 /* 16 fmt */; > + return SND_CODEC_OK; > +} > +#endif > + > > /*---------------------------------------------------------------------------- > ** PUBLIC INTERFACE > @@ -155,14 +241,23 @@ static int snd_codec_decode_celt051(SndCodecInternal *codec, uint8_t *in_ptr, in > use the given codec, FALSE otherwise. > mode must be a SPICE_AUDIO_DATA_MODE_XXX enum from spice/enum.h > */ > -int snd_codec_is_capable(int mode) > +int snd_codec_is_capable(int mode, int frequency) > { > #if HAVE_CELT051 > if (mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) > return TRUE; > -#else > - return FALSE; > #endif > + > +#if HAVE_OPUS > + if (mode == SPICE_AUDIO_DATA_MODE_OPUS && > + (frequency == SND_CODEC_ANY_FREQUENCY || > + frequency == 48000 || frequency == 24000 || > + frequency == 16000 || frequency == 12000 || > + frequency == 8000) ) > + return TRUE; > +#endif > + > + return FALSE; > } > > /* > @@ -191,6 +286,11 @@ int snd_codec_create(SndCodec *codec, int mode, int frequency, int encode, int d > rc = snd_codec_create_celt051(*c, encode, decode); > #endif > > +#if HAVE_OPUS > + if (mode == SPICE_AUDIO_DATA_MODE_OPUS) > + rc = snd_codec_create_opus(*c, encode, decode); > +#endif > + > return rc; > } > > @@ -208,6 +308,10 @@ void snd_codec_destroy(SndCodec *codec) > snd_codec_destroy_celt051(*c); > #endif > > +#if HAVE_OPUS > + snd_codec_destroy_opus(*c); > +#endif > + > free(*c); > *c = NULL; > } > @@ -225,6 +329,10 @@ int snd_codec_frame_size(SndCodec codec) > if (c && c->mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) > return SND_CODEC_CELT_FRAME_SIZE; > #endif > +#if HAVE_OPUS > + if (c && c->mode == SPICE_AUDIO_DATA_MODE_OPUS) > + return SND_CODEC_OPUS_FRAME_SIZE; > +#endif > return SND_CODEC_MAX_FRAME_SIZE; > } > > @@ -251,7 +359,18 @@ int snd_codec_encode(SndCodec codec, uint8_t *in_ptr, int in_size, uint8_t *out_ > SndCodecInternal *c = (SndCodecInternal *) codec; > #if HAVE_CELT051 > if (c && c->mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) > + { > + /* The output buffer size in celt determines the compression, > + and so is essentially mandatory to use a certain value (47) */ > + if (*out_size > SND_CODEC_CELT_COMPRESSED_FRAME_BYTES) > + *out_size = SND_CODEC_CELT_COMPRESSED_FRAME_BYTES; > return snd_codec_encode_celt051(c, in_ptr, in_size, out_ptr, out_size); > + } > +#endif > + > +#if HAVE_OPUS > + if (c && c->mode == SPICE_AUDIO_DATA_MODE_OPUS) > + return snd_codec_encode_opus(c, in_ptr, in_size, out_ptr, out_size); > #endif > > return SND_CODEC_ENCODER_UNAVAILABLE; > @@ -281,5 +400,10 @@ int snd_codec_decode(SndCodec codec, uint8_t *in_ptr, int in_size, uint8_t *out_ > return snd_codec_decode_celt051(c, in_ptr, in_size, out_ptr, out_size); > #endif > > +#if HAVE_OPUS > + if (c && c->mode == SPICE_AUDIO_DATA_MODE_OPUS) > + return snd_codec_decode_opus(c, in_ptr, in_size, out_ptr, out_size); > +#endif > + > return SND_CODEC_DECODER_UNAVAILABLE; > } > diff --git a/common/snd_codec.h b/common/snd_codec.h > index 069356f..e1edfe9 100644 > --- a/common/snd_codec.h > +++ b/common/snd_codec.h > @@ -24,6 +24,10 @@ > #include <celt051/celt.h> > #endif > > +#if HAVE_OPUS > +#include <opus.h> > +#endif > + > /* Spice uses a very fixed protocol when transmitting CELT audio; > audio must be transmitted in frames of 256, and we must compress > data down to a fairly specific size (47, computation below). > @@ -33,14 +37,20 @@ > #define SND_CODEC_CELT_FRAME_SIZE 256 > #define SND_CODEC_CELT_BIT_RATE (64 * 1024) > #define SND_CODEC_CELT_PLAYBACK_FREQ 44100 > -#define SND_CODEC_CELT_PLAYBACK_CHAN 2 > #define SND_CODEC_CELT_COMPRESSED_FRAME_BYTES (SND_CODEC_CELT_FRAME_SIZE * SND_CODEC_CELT_BIT_RATE / \ > SND_CODEC_CELT_PLAYBACK_FREQ / 8) > > +#define SND_CODEC_OPUS_FRAME_SIZE 480 > +#define SND_CODEC_OPUS_PLAYBACK_FREQ 48000 > +#define SND_CODEC_OPUS_COMPRESSED_FRAME_BYTES 480 > + > +#define SND_CODEC_PLAYBACK_CHAN 2 > + > +#define SND_CODEC_MAX_FRAME_SIZE (MAX(SND_CODEC_CELT_FRAME_SIZE, SND_CODEC_OPUS_FRAME_SIZE)) > +#define SND_CODEC_MAX_FRAME_BYTES (SND_CODEC_MAX_FRAME_SIZE * SND_CODEC_PLAYBACK_CHAN * 2 /* FMT_S16 */) > +#define SND_CODEC_MAX_COMPRESSED_BYTES MAX(SND_CODEC_CELT_COMPRESSED_FRAME_BYTES, SND_CODEC_OPUS_COMPRESSED_FRAME_BYTES) > > -#define SND_CODEC_MAX_FRAME_SIZE SND_CODEC_CELT_FRAME_SIZE > -#define SND_CODEC_MAX_FRAME_BYTES (SND_CODEC_MAX_FRAME_SIZE * SND_CODEC_CELT_PLAYBACK_CHAN * 2 /* FMT_S16 */) > -#define SND_CODEC_MAX_COMPRESSED_BYTES SND_CODEC_CELT_COMPRESSED_FRAME_BYTES > +#define SND_CODEC_ANY_FREQUENCY -1 > > #define SND_CODEC_OK 0 > #define SND_CODEC_UNAVAILABLE 1 > @@ -54,7 +64,7 @@ SPICE_BEGIN_DECLS > > typedef struct SndCodecInternal * SndCodec; > > -int snd_codec_is_capable(int mode); > +int snd_codec_is_capable(int mode, int frequency); > > int snd_codec_create(SndCodec *codec, int mode, int frequency, int encode, int decode); > void snd_codec_destroy(SndCodec *codec); > diff --git a/configure.ac b/configure.ac > index 3443334..273d935 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -67,6 +67,10 @@ fi > AM_CONDITIONAL([HAVE_CELT051], [test "x$have_celt051" = "xyes"]) > AM_COND_IF([HAVE_CELT051], AC_DEFINE([HAVE_CELT051], 1, [Define if we have celt051 codec])) > > +PKG_CHECK_MODULES([OPUS], [opus >= 0.9.14], have_opus=yes, have_opus=no) > +AM_CONDITIONAL([HAVE_OPUS], [test "x$have_opus" = "xyes"]) > +AM_COND_IF([HAVE_OPUS], AC_DEFINE([HAVE_OPUS], 1, [Define if we have Opus])) > + > AC_ARG_ENABLE([opengl], > AS_HELP_STRING([--enable-opengl=@<:@yes/no@:>@], > [Enable opengl support (not recommended) @<:@default=no@:>@]), > diff --git a/spice.proto b/spice.proto > index 04e7ea4..67b3803 100644 > --- a/spice.proto > +++ b/spice.proto > @@ -1067,6 +1067,7 @@ enum16 audio_data_mode { > INVALID, > RAW, > CELT_0_5_1, > + OPUS, > }; > > enum16 audio_fmt { > diff --git a/spice1.proto b/spice1.proto > index 2d22cdf..67eb0e6 100644 > --- a/spice1.proto > +++ b/spice1.proto > @@ -876,6 +876,7 @@ enum32 audio_data_mode { > INVALID, > RAW, > CELT_0_5_1, > + OPUS, > }; > > enum32 audio_fmt { > -- > 1.7.10.4 > > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel
Attachment:
pgpRthGECMM3Z.pgp
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel