[Spice-devel] [spice-common sound rework 1/3] Add a snd_codec interface to abstract the use of audio codecs such as celt.
Christophe Fergeau
cfergeau at redhat.com
Wed Oct 30 15:42:21 CET 2013
On Wed, Oct 16, 2013 at 11:46:12AM -0500, Jeremy White wrote:
> Signed-off-by: Jeremy White <jwhite at codeweavers.com>
> ---
> common/Makefile.am | 7 ++
> common/snd_codec.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> common/snd_codec.h | 69 +++++++++++++
> configure.ac | 16 +++
> 4 files changed, 377 insertions(+)
> create mode 100644 common/snd_codec.c
> create mode 100644 common/snd_codec.h
>
> diff --git a/common/Makefile.am b/common/Makefile.am
> index 45568c6..c79f596 100644
> --- a/common/Makefile.am
> +++ b/common/Makefile.am
> @@ -52,6 +52,8 @@ libspice_common_la_SOURCES = \
> ring.h \
> rop3.c \
> rop3.h \
> + snd_codec.c \
> + snd_codec.h \
> spice_common.h \
> ssl_verify.c \
> ssl_verify.h \
> @@ -81,6 +83,7 @@ endif
> AM_CPPFLAGS = \
> $(GL_CFLAGS) \
> $(PIXMAN_CFLAGS) \
> + $(CELT051_CFLAGS) \
> $(PROTOCOL_CFLAGS) \
> $(SMARTCARD_CFLAGS) \
> $(VISIBILITY_HIDDEN_CFLAGS) \
> @@ -88,6 +91,9 @@ AM_CPPFLAGS = \
> -std=gnu99 \
> $(NULL)
>
> +libspice_common_la_LIBADD = \
> + $(CELT051_LIBS)
> +
> MARSHALLERS_DEPS = \
> $(top_srcdir)/python_modules/__init__.py \
> $(top_srcdir)/python_modules/codegen.py \
> @@ -142,6 +148,7 @@ EXTRA_DIST = \
> quic_family_tmpl.c \
> quic_rgb_tmpl.c \
> quic_tmpl.c \
> + snd_codec.h \
> sw_canvas.c \
> sw_canvas.h \
> $(NULL)
> diff --git a/common/snd_codec.c b/common/snd_codec.c
> new file mode 100644
> index 0000000..d481356
> --- /dev/null
> +++ b/common/snd_codec.c
> @@ -0,0 +1,285 @@
> +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> +/*
> + Copyright (C) 2013 Jeremy White
> +
> + This library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + This library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with this library; if not, see <http://www.gnu.org/licenses/>.
> +*/
> +
> +/* snd_codec.c
> + General purpose sound codec routines for use by Spice.
> + These routines abstract the work of picking a codec and
> + encoding and decoding the buffers.
> + Note: these routines have some peculiarities that come from
> + wanting to provide full backwards compatibility with the original
> + Spice celt 0.51 implementation. It has some hard requirements
> + (fixed sample size, fixed compressed buffer size).
> +
> + See below for documentation of the public routines.
> +*/
> +
> +#include <stdio.h>
> +#include <string.h>
> +#include "config.h"
> +#include <spice/macros.h>
> +#include <spice/enums.h>
> +
> +
> +#include "snd_codec.h"
> +#include "mem.h"
> +#include "log.h"
> +
> +typedef struct
> +{
> + int mode;
> + int frequency;
> +#if HAVE_CELT051
> + CELTMode *celt_mode;
> + CELTEncoder *celt_encoder;
> + CELTDecoder *celt_decoder;
> +#endif
> +} SndCodecInternal;
> +
> +
> +
> +/* celt 0.51 specific support routines */
> +#if HAVE_CELT051
> +static void snd_codec_destroy_celt051(SndCodecInternal *codec)
> +{
> + if (codec->celt_decoder)
> + {
> + celt051_decoder_destroy(codec->celt_decoder);
> + codec->celt_decoder = NULL;
> + }
> +
> + if (codec->celt_encoder)
> + {
> + celt051_encoder_destroy(codec->celt_encoder);
> + codec->celt_encoder = NULL;
> + }
> +
> + if (codec->celt_mode)
> + {
> + celt051_mode_destroy(codec->celt_mode);
> + codec->celt_mode = NULL;
> + }
> +}
> +
> +static int snd_codec_create_celt051(SndCodecInternal *codec, int encode, int decode)
> +{
> + int celt_error;
> +
> + codec->celt_mode = celt051_mode_create(codec->frequency,
> + SND_CODEC_CELT_PLAYBACK_CHAN,
> + SND_CODEC_CELT_FRAME_SIZE, &celt_error);
> + if (! codec->celt_mode)
> + {
> + spice_printerr("create celt mode failed %d", celt_error);
> + return SND_CODEC_UNAVAILABLE;
> + }
> +
> + if (encode)
> + {
> + codec->celt_encoder = celt051_encoder_create(codec->celt_mode);
> + if (! codec->celt_encoder)
> + {
> + spice_printerr("create celt encoder failed");
> + goto error;
> + }
> + }
> +
> + if (decode)
> + {
> + codec->celt_decoder = celt051_decoder_create(codec->celt_mode);
> + if (! codec->celt_decoder)
> + {
> + spice_printerr("create celt decoder failed");
> + goto error;
> + }
> + }
> +
> + codec->mode = SPICE_AUDIO_DATA_MODE_CELT_0_5_1;
> + return SND_CODEC_OK;
> +
> +error:
> + snd_codec_destroy_celt051(codec);
> + return SND_CODEC_UNAVAILABLE;
> +}
> +
> +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)
> + 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) {
> + spice_printerr("celt051_encode failed %d\n", n);
> + return SND_CODEC_ENCODE_FAILED;
> + }
> + *out_size = n;
> + return SND_CODEC_OK;
> +}
> +
> +static int snd_codec_decode_celt051(SndCodecInternal *codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size)
> +{
> + int n;
> + n = celt051_decode(codec->celt_decoder, in_ptr, in_size, (celt_int16_t *) out_ptr);
> + if (n < 0) {
> + 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 */;
> + return SND_CODEC_OK;
> +}
> +#endif
> +
> +
> +
> +/*----------------------------------------------------------------------------
> +** PUBLIC INTERFACE
> +**--------------------------------------------------------------------------*/
> +
> +/*
> + snd_codec_is_capable
> + Returns TRUE if the current spice implementation can
> + 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)
> +{
> +#if HAVE_CELT051
> + if (mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1)
> + return TRUE;
> +#else
> + return FALSE;
> +#endif
> +}
> +
> +/*
> + snd_codec_create
> + Create a codec control. Required for most functions in this library.
> + Parameters:
> + 1. codec Pointer to preallocated codec control
> + 2. mode SPICE_AUDIO_DATA_MODE_XXX enum from spice/enum.h
> + 3. encode TRUE if encoding is desired
> + 4. decode TRUE if decoding is desired
> + Returns:
> + SND_CODEC_OK if all went well; a different code if not.
> +
> + snd_codec_destroy is the obvious partner of snd_codec_create.
> + */
> +int snd_codec_create(SndCodec *codec, int mode, int frequency, int encode, int decode)
> +{
> + int rc = SND_CODEC_UNAVAILABLE;
> + SndCodecInternal **c = (SndCodecInternal **) codec;
> +
> + *c = spice_malloc0(sizeof(**c));
*c = spice_new0(SndCodecInternal, 1); (or g_new0 + the free below replaced
by g_free) would be slightly nicer here
Apart from this, ACK
Christophe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20131030/4507a565/attachment-0001.pgp>
More information about the Spice-devel
mailing list