diff options
Diffstat (limited to 'ext/speex')
-rw-r--r-- | ext/speex/gstspeexdec.c | 111 | ||||
-rw-r--r-- | ext/speex/gstspeexenc.c | 107 |
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); |