summaryrefslogtreecommitdiff
path: root/ext/speex
diff options
context:
space:
mode:
Diffstat (limited to 'ext/speex')
-rw-r--r--ext/speex/gstspeexdec.c111
-rw-r--r--ext/speex/gstspeexenc.c107
2 files changed, 115 insertions, 103 deletions
diff --git a/ext/speex/gstspeexdec.c b/ext/speex/gstspeexdec.c
index 6db93197c..de4121436 100644
--- a/ext/speex/gstspeexdec.c
+++ b/ext/speex/gstspeexdec.c
@@ -46,6 +46,7 @@
#include <stdlib.h>
#include <string.h>
#include <gst/tag/tag.h>
+#include <gst/audio/audio.h>
GST_DEBUG_CATEGORY_STATIC (speexdec_debug);
#define GST_CAT_DEFAULT speexdec_debug
@@ -58,15 +59,15 @@ enum
ARG_ENH
};
+#define FORMAT_STR GST_AUDIO_NE(S16)
+
static GstStaticPadTemplate speex_dec_src_factory =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw-int, "
- "rate = (int) [ 6000, 48000 ], "
- "channels = (int) [ 1, 2 ], "
- "endianness = (int) BYTE_ORDER, "
- "signed = (boolean) true, " "width = (int) 16, " "depth = (int) 16")
+ GST_STATIC_CAPS ("audio/x-raw, "
+ "format = (string) " FORMAT_STR ", "
+ "rate = (int) [ 6000, 48000 ], " "channels = (int) [ 1, 2 ]")
);
static GstStaticPadTemplate speex_dec_sink_factory =
@@ -76,9 +77,8 @@ GST_STATIC_PAD_TEMPLATE ("sink",
GST_STATIC_CAPS ("audio/x-speex")
);
-GST_BOILERPLATE (GstSpeexDec, gst_speex_dec, GstAudioDecoder,
- GST_TYPE_AUDIO_DECODER);
-
+#define gst_speex_dec_parent_class parent_class
+G_DEFINE_TYPE (GstSpeexDec, gst_speex_dec, GST_TYPE_AUDIO_DECODER);
static gboolean gst_speex_dec_start (GstAudioDecoder * dec);
static gboolean gst_speex_dec_stop (GstAudioDecoder * dec);
@@ -93,26 +93,14 @@ static void gst_speex_dec_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void
-gst_speex_dec_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&speex_dec_src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&speex_dec_sink_factory));
- gst_element_class_set_details_simple (element_class, "Speex audio decoder",
- "Codec/Decoder/Audio",
- "decode speex streams to audio", "Wim Taymans <wim@fluendo.com>");
-}
-
-static void
gst_speex_dec_class_init (GstSpeexDecClass * klass)
{
GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
GstAudioDecoderClass *base_class;
gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
base_class = (GstAudioDecoderClass *) klass;
gobject_class->set_property = gst_speex_dec_set_property;
@@ -127,6 +115,14 @@ gst_speex_dec_class_init (GstSpeexDecClass * klass)
g_param_spec_boolean ("enh", "Enh", "Enable perceptual enhancement",
DEFAULT_ENH, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&speex_dec_src_factory));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&speex_dec_sink_factory));
+ gst_element_class_set_details_simple (gstelement_class, "Speex audio decoder",
+ "Codec/Decoder/Audio",
+ "decode speex streams to audio", "Wim Taymans <wim@fluendo.com>");
+
GST_DEBUG_CATEGORY_INIT (speexdec_debug, "speexdec", 0,
"speex decoding element");
}
@@ -157,7 +153,7 @@ gst_speex_dec_reset (GstSpeexDec * dec)
}
static void
-gst_speex_dec_init (GstSpeexDec * dec, GstSpeexDecClass * g_class)
+gst_speex_dec_init (GstSpeexDec * dec)
{
dec->enh = DEFAULT_ENH;
@@ -193,10 +189,13 @@ static GstFlowReturn
gst_speex_dec_parse_header (GstSpeexDec * dec, GstBuffer * buf)
{
GstCaps *caps;
+ char *data;
+ gsize size;
/* get the header */
- dec->header = speex_packet_to_header ((char *) GST_BUFFER_DATA (buf),
- GST_BUFFER_SIZE (buf));
+ data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+ dec->header = speex_packet_to_header (data, size);
+ gst_buffer_unmap (buf, data, size);
if (!dec->header)
goto no_header;
@@ -230,12 +229,10 @@ gst_speex_dec_parse_header (GstSpeexDec * dec, GstBuffer * buf)
speex_bits_init (&dec->bits);
/* set caps */
- caps = gst_caps_new_simple ("audio/x-raw-int",
+ caps = gst_caps_new_simple ("audio/x-raw",
+ "format", G_TYPE_STRING, FORMAT_STR,
"rate", G_TYPE_INT, dec->header->rate,
- "channels", G_TYPE_INT, dec->header->nb_channels,
- "signed", G_TYPE_BOOLEAN, TRUE,
- "endianness", G_TYPE_INT, G_BYTE_ORDER,
- "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, NULL);
+ "channels", G_TYPE_INT, dec->header->nb_channels, NULL);
if (!gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), caps))
goto nego_failed;
@@ -362,19 +359,18 @@ gst_speex_dec_parse_data (GstSpeexDec * dec, GstBuffer * buf)
{
GstFlowReturn res = GST_FLOW_OK;
gint i, fpp;
- guint size;
- guint8 *data;
SpeexBits *bits;
+ gsize size;
+ char *data;
if (!dec->frame_duration)
goto not_negotiated;
- if (G_LIKELY (GST_BUFFER_SIZE (buf))) {
- data = GST_BUFFER_DATA (buf);
- size = GST_BUFFER_SIZE (buf);
-
+ if (G_LIKELY (gst_buffer_get_size (buf))) {
/* send data to the bitstream */
- speex_bits_read_from (&dec->bits, (char *) data, size);
+ data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+ speex_bits_read_from (&dec->bits, data, size);
+ gst_buffer_unmap (buf, data, size);
fpp = dec->header->frames_per_packet;
bits = &dec->bits;
@@ -397,7 +393,7 @@ gst_speex_dec_parse_data (GstSpeexDec * dec, GstBuffer * buf)
GST_LOG_OBJECT (dec, "decoding frame %d/%d, %d bits remaining", i, fpp,
bits ? speex_bits_remaining (bits) : -1);
-
+#if 0
res =
gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec),
GST_BUFFER_OFFSET_NONE, dec->frame_size * dec->header->nb_channels * 2,
@@ -407,10 +403,17 @@ gst_speex_dec_parse_data (GstSpeexDec * dec, GstBuffer * buf)
GST_DEBUG_OBJECT (dec, "buf alloc flow: %s", gst_flow_get_name (res));
return res;
}
+#endif
+ /* FIXME, we can use a bufferpool because we have fixed size buffers. We
+ * could also use an allocator */
+ outbuf =
+ gst_buffer_new_allocate (NULL,
+ dec->frame_size * dec->header->nb_channels * 2, 0);
- out_data = (gint16 *) GST_BUFFER_DATA (outbuf);
-
+ out_data = gst_buffer_map (outbuf, &size, NULL, GST_MAP_WRITE);
ret = speex_decode_int (dec->state, bits, out_data);
+ gst_buffer_unmap (outbuf, out_data, size);
+
if (ret == -1) {
/* uh? end of stream */
if (fpp == 0 && speex_bits_remaining (bits) < 8) {
@@ -455,6 +458,26 @@ not_negotiated:
}
}
+static gboolean
+memcmp_buffers (GstBuffer * buf1, GstBuffer * buf2)
+{
+ gsize size1, size2;
+ gpointer data1;
+ gboolean res;
+
+ size1 = gst_buffer_get_size (buf1);
+ size2 = gst_buffer_get_size (buf2);
+
+ if (size1 != size2)
+ return FALSE;
+
+ data1 = gst_buffer_map (buf1, NULL, NULL, GST_MAP_READ);
+ res = gst_buffer_memcmp (buf2, 0, data1, size1) == 0;
+ gst_buffer_unmap (buf1, data1, size1);
+
+ return res;
+}
+
static GstFlowReturn
gst_speex_dec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buf)
{
@@ -470,15 +493,11 @@ gst_speex_dec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buf)
/* If we have the streamheader and vorbiscomment from the caps already
* ignore them here */
if (dec->streamheader && dec->vorbiscomment) {
- if (GST_BUFFER_SIZE (dec->streamheader) == GST_BUFFER_SIZE (buf)
- && memcmp (GST_BUFFER_DATA (dec->streamheader), GST_BUFFER_DATA (buf),
- GST_BUFFER_SIZE (buf)) == 0) {
+ if (memcmp_buffers (dec->streamheader, buf)) {
GST_DEBUG_OBJECT (dec, "found streamheader");
gst_audio_decoder_finish_frame (bdec, NULL, 1);
res = GST_FLOW_OK;
- } else if (GST_BUFFER_SIZE (dec->vorbiscomment) == GST_BUFFER_SIZE (buf)
- && memcmp (GST_BUFFER_DATA (dec->vorbiscomment), GST_BUFFER_DATA (buf),
- GST_BUFFER_SIZE (buf)) == 0) {
+ } else if (memcmp_buffers (dec->vorbiscomment, buf)) {
GST_DEBUG_OBJECT (dec, "found vorbiscomments");
gst_audio_decoder_finish_frame (bdec, NULL, 1);
res = GST_FLOW_OK;
diff --git a/ext/speex/gstspeexenc.c b/ext/speex/gstspeexenc.c
index 1c6f71c14..e4eda25cf 100644
--- a/ext/speex/gstspeexenc.c
+++ b/ext/speex/gstspeexenc.c
@@ -52,14 +52,14 @@
GST_DEBUG_CATEGORY_STATIC (speexenc_debug);
#define GST_CAT_DEFAULT speexenc_debug
+#define FORMAT_STR GST_AUDIO_NE(S16)
+
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw-int, "
- "rate = (int) [ 6000, 48000 ], "
- "channels = (int) [ 1, 2 ], "
- "endianness = (int) BYTE_ORDER, "
- "signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16")
+ GST_STATIC_CAPS ("audio/x-raw, "
+ "format = (string) " FORMAT_STR ", "
+ "rate = (int) [ 6000, 48000 ], " "channels = (int) [ 1, 2 ]")
);
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
@@ -133,43 +133,23 @@ static GstFlowReturn gst_speex_enc_handle_frame (GstAudioEncoder * enc,
static gboolean gst_speex_enc_sink_event (GstAudioEncoder * enc,
GstEvent * event);
-static void
-gst_speex_enc_setup_interfaces (GType speexenc_type)
-{
- static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
-
- g_type_add_interface_static (speexenc_type, GST_TYPE_TAG_SETTER,
- &tag_setter_info);
-
- GST_DEBUG_CATEGORY_INIT (speexenc_debug, "speexenc", 0, "Speex encoder");
-}
-
-GST_BOILERPLATE_FULL (GstSpeexEnc, gst_speex_enc, GstAudioEncoder,
- GST_TYPE_AUDIO_ENCODER, gst_speex_enc_setup_interfaces);
-
-static void
-gst_speex_enc_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_factory));
- gst_element_class_set_details_simple (element_class, "Speex audio encoder",
- "Codec/Encoder/Audio",
- "Encodes audio in Speex format", "Wim Taymans <wim@fluendo.com>");
-}
+#define gst_speex_enc_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstSpeexEnc, gst_speex_enc, GST_TYPE_AUDIO_ENCODER,
+ G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL);
+ G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL));
static void
gst_speex_enc_class_init (GstSpeexEncClass * klass)
{
GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
GstAudioEncoderClass *base_class;
gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
base_class = (GstAudioEncoderClass *) klass;
+ gobject_class->finalize = gst_speex_enc_finalize;
gobject_class->set_property = gst_speex_enc_set_property;
gobject_class->get_property = gst_speex_enc_get_property;
@@ -224,7 +204,15 @@ gst_speex_enc_class_init (GstSpeexEncClass * klass)
"The last status message", NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
- gobject_class->finalize = gst_speex_enc_finalize;
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&src_factory));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&sink_factory));
+ gst_element_class_set_details_simple (gstelement_class, "Speex audio encoder",
+ "Codec/Encoder/Audio",
+ "Encodes audio in Speex format", "Wim Taymans <wim@fluendo.com>");
+
+ GST_DEBUG_CATEGORY_INIT (speexenc_debug, "speexenc", 0, "Speex encoder");
}
static void
@@ -240,7 +228,7 @@ gst_speex_enc_finalize (GObject * object)
}
static void
-gst_speex_enc_init (GstSpeexEnc * enc, GstSpeexEncClass * klass)
+gst_speex_enc_init (GstSpeexEnc * enc)
{
GstAudioEncoder *benc = GST_AUDIO_ENCODER (enc);
@@ -496,10 +484,8 @@ gst_speex_enc_setup (GstSpeexEnc * enc)
static GstFlowReturn
gst_speex_enc_push_buffer (GstSpeexEnc * enc, GstBuffer * buffer)
{
- guint size;
-
- size = GST_BUFFER_SIZE (buffer);
- GST_DEBUG_OBJECT (enc, "pushing output buffer of size %u", size);
+ GST_DEBUG_OBJECT (enc, "pushing output buffer of size %u",
+ gst_buffer_get_size (buffer));
return gst_pad_push (GST_AUDIO_ENCODER_SRC_PAD (enc), buffer);
}
@@ -537,21 +523,27 @@ static GstFlowReturn
gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf)
{
gint frame_size = enc->frame_size;
- gint bytes = frame_size * 2 * enc->channels, samples, size;
+ gint bytes = frame_size * 2 * enc->channels, samples;
gint outsize, written, dtx_ret = 0;
- guint8 *data;
+ guint8 *data, *bdata, *outdata;
+ gsize bsize, size;
GstBuffer *outbuf;
GstFlowReturn ret = GST_FLOW_OK;
if (G_LIKELY (buf)) {
- data = GST_BUFFER_DATA (buf);
- size = GST_BUFFER_SIZE (buf);
+ bdata = gst_buffer_map (buf, &bsize, NULL, GST_MAP_READ);
- if (G_UNLIKELY (size % bytes)) {
+ if (G_UNLIKELY (bsize % bytes)) {
GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
- size = ((size / bytes) + 1) * bytes;
+
+ size = ((bsize / bytes) + 1) * bytes;
data = g_malloc0 (size);
- memcpy (data, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ memcpy (data, bdata, bsize);
+ gst_buffer_unmap (buf, bdata, bsize);
+ bdata = NULL;
+ } else {
+ data = bdata;
+ size = bsize;
}
} else {
GST_DEBUG_OBJECT (enc, "nothing to drain");
@@ -578,22 +570,29 @@ gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf)
speex_bits_insert_terminator (&enc->bits);
outsize = speex_bits_nbytes (&enc->bits);
+ if (bdata)
+ gst_buffer_unmap (buf, bdata, bsize);
+
+#if 0
ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc),
GST_BUFFER_OFFSET_NONE, outsize,
GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf);
if ((GST_FLOW_OK != ret))
goto done;
+#endif
+ outbuf = gst_buffer_new_allocate (NULL, outsize, 0);
+ outdata = gst_buffer_map (outbuf, NULL, NULL, GST_MAP_WRITE);
- written = speex_bits_write (&enc->bits,
- (gchar *) GST_BUFFER_DATA (outbuf), outsize);
+ written = speex_bits_write (&enc->bits, (gchar *) outdata, outsize);
if (G_UNLIKELY (written < outsize)) {
GST_ERROR_OBJECT (enc, "short write: %d < %d bytes", written, outsize);
- GST_BUFFER_SIZE (outbuf) = written;
} else if (G_UNLIKELY (written > outsize)) {
GST_ERROR_OBJECT (enc, "overrun: %d > %d bytes", written, outsize);
+ written = outsize;
}
+ gst_buffer_unmap (outbuf, outdata, written);
if (!dtx_ret)
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
@@ -640,7 +639,7 @@ _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
va_start (va, buf);
/* put buffers in a fixed list */
while (buf) {
- g_assert (gst_buffer_is_metadata_writable (buf));
+ g_assert (gst_buffer_is_writable (buf));
/* mark buffer */
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
@@ -684,9 +683,7 @@ gst_speex_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
/* create header buffer */
data = (guint8 *) speex_header_to_packet (&enc->header, &data_len);
- buf1 = gst_buffer_new ();
- GST_BUFFER_DATA (buf1) = GST_BUFFER_MALLOCDATA (buf1) = data;
- GST_BUFFER_SIZE (buf1) = data_len;
+ buf1 = gst_buffer_new_wrapped (data, data_len);
GST_BUFFER_OFFSET_END (buf1) = 0;
GST_BUFFER_OFFSET (buf1) = 0;
@@ -701,10 +698,6 @@ gst_speex_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
/* negotiate with these caps */
GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
- gst_buffer_set_caps (buf1, caps);
- gst_buffer_set_caps (buf2, caps);
- gst_caps_unref (caps);
-
/* push out buffers */
ret = gst_speex_enc_push_buffer (enc, buf1);
@@ -722,7 +715,7 @@ gst_speex_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
}
GST_DEBUG_OBJECT (enc, "received buffer %p of %u bytes", buf,
- buf ? GST_BUFFER_SIZE (buf) : 0);
+ buf ? gst_buffer_get_size (buf) : 0);
ret = gst_speex_enc_encode (enc, buf);