diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2004-09-28 16:44:12 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2004-09-28 16:44:12 +0000 |
commit | 2748ae95482b17103909d2b9f0d65f3fb0948388 (patch) | |
tree | b09f604391722085286899789fb0c3c58d38f88d /ext/speex/gstspeexdec.c | |
parent | 0089ff9ed3851854071c74e82039b95e38940641 (diff) |
ext/speex/: Rewrote speex encoder, make sure it can be embedded in ogg.
Original commit message from CVS:
* ext/speex/gstspeex.c: (plugin_init):
* ext/speex/gstspeexdec.c: (gst_speex_dec_base_init),
(gst_speex_dec_class_init), (speex_dec_get_formats),
(speex_get_event_masks), (speex_get_query_types),
(gst_speex_dec_init), (speex_dec_convert), (speex_dec_src_query),
(speex_dec_src_event), (speex_dec_event), (speex_dec_chain),
(gst_speexdec_get_property), (gst_speexdec_set_property),
(speex_dec_change_state):
* ext/speex/gstspeexdec.h:
* ext/speex/gstspeexenc.c: (gst_speexenc_get_formats),
(gst_speexenc_get_type), (speex_caps_factory), (raw_caps_factory),
(gst_speexenc_base_init), (gst_speexenc_class_init),
(gst_speexenc_sinkconnect), (gst_speexenc_convert_src),
(gst_speexenc_convert_sink), (gst_speexenc_get_query_types),
(gst_speexenc_src_query), (gst_speexenc_init),
(gst_speexenc_get_tag_value), (comment_init), (comment_add),
(gst_speexenc_metadata_set1), (gst_speexenc_set_metadata),
(gst_speexenc_setup), (gst_speexenc_buffer_from_data),
(gst_speexenc_push_buffer), (gst_speexenc_set_header_on_caps),
(gst_speexenc_chain), (gst_speexenc_get_property),
(gst_speexenc_set_property), (gst_speexenc_change_state):
* ext/speex/gstspeexenc.h:
Rewrote speex encoder, make sure it can be embedded in ogg.
Implemented speex decoder.
Diffstat (limited to 'ext/speex/gstspeexdec.c')
-rw-r--r-- | ext/speex/gstspeexdec.c | 628 |
1 files changed, 515 insertions, 113 deletions
diff --git a/ext/speex/gstspeexdec.c b/ext/speex/gstspeexdec.c index 660f332b..da246aab 100644 --- a/ext/speex/gstspeexdec.c +++ b/ext/speex/gstspeexdec.c @@ -1,5 +1,5 @@ /* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> + * Copyright (C) 2004 Wim Taymans <wim@fluendo.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -17,177 +17,579 @@ * Boston, MA 02111-1307, USA. */ - #ifdef HAVE_CONFIG_H -#include "config.h" +# include "config.h" #endif -#include <string.h> #include "gstspeexdec.h" +#include <string.h> +#include <gst/tag/tag.h> -/* elementfactory information */ -GstElementDetails gst_speexdec_details = { - "speex audio decoder", +GST_DEBUG_CATEGORY (speexdec_debug); +#define GST_CAT_DEFAULT speexdec_debug + +static GstElementDetails speex_dec_details = { + "SpeexDec", "Codec/Decoder/Audio", - ".speex", - "Wim Taymans <wim.taymans@chello.be>", + "decode speex streams to audio", + "Wim Taymans <wim@fluendo.com>", }; -/* SpeexDec signals and args */ +/* Filter signals and args */ enum { /* FILL ME */ LAST_SIGNAL }; +#define DEFAULT_ENH TRUE + enum { - ARG_0 - /* FILL ME */ + ARG_0, + ARG_ENH }; -static void gst_speexdec_base_init (gpointer g_class); -static void gst_speexdec_class_init (GstSpeexDec * klass); -static void gst_speexdec_init (GstSpeexDec * speexdec); - -static void gst_speexdec_chain (GstPad * pad, GstData * _data); -static GstPadLinkReturn gst_speexdec_sinkconnect (GstPad * pad, - const GstCaps * caps); - -static GstElementClass *parent_class = NULL; - -/*static guint gst_speexdec_signals[LAST_SIGNAL] = { 0 }; */ - -GType -gst_speexdec_get_type (void) -{ - static GType speexdec_type = 0; - - if (!speexdec_type) { - static const GTypeInfo speexdec_info = { - sizeof (GstSpeexDecClass), - gst_speexdec_base_init, - NULL, - (GClassInitFunc) gst_speexdec_class_init, - NULL, - NULL, - sizeof (GstSpeexDec), - 0, - (GInstanceInitFunc) gst_speexdec_init, - }; - - speexdec_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstSpeexDec", &speexdec_info, - 0); - } - return speexdec_type; -} - -static GstStaticPadTemplate speexdec_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-speex, " - "rate = (int) [ 1000, 48000 ], " "channels = (int) 1") - ); - -static GstStaticPadTemplate speexdec_src_template = +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, " - "rate = (int) [ 1000, 48000 ], " "channels = (int) 1") + "signed = (boolean) true, " "width = (int) 16, " "depth = (int) 16") + ); + +static GstStaticPadTemplate speex_dec_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-speex") ); +GST_BOILERPLATE (GstSpeexDec, gst_speex_dec, GstElement, GST_TYPE_ELEMENT); + +static void speex_dec_chain (GstPad * pad, GstData * data); +static GstElementStateReturn speex_dec_change_state (GstElement * element); +static const GstFormat *speex_dec_get_formats (GstPad * pad); + +static gboolean speex_dec_src_event (GstPad * pad, GstEvent * event); +static gboolean speex_dec_src_query (GstPad * pad, + GstQueryType query, GstFormat * format, gint64 * value); +static gboolean speex_dec_convert (GstPad * pad, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value); + +static void gst_speexdec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_speexdec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); + static void -gst_speexdec_base_init (gpointer g_class) +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 (&speexdec_src_template)); + gst_static_pad_template_get (&speex_dec_src_factory)); gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&speexdec_sink_template)); - - gst_element_class_set_details (element_class, &gst_speexdec_details); + gst_static_pad_template_get (&speex_dec_sink_factory)); + gst_element_class_set_details (element_class, &speex_dec_details); } static void -gst_speexdec_class_init (GstSpeexDec * klass) +gst_speex_dec_class_init (GstSpeexDecClass * klass) { + GObjectClass *gobject_class; GstElementClass *gstelement_class; + gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ENH, + g_param_spec_boolean ("enh", "Enh", "Enable perceptual enhancement", + DEFAULT_ENH, G_PARAM_READWRITE)); + + gstelement_class->change_state = speex_dec_change_state; + + gobject_class->set_property = gst_speexdec_set_property; + gobject_class->get_property = gst_speexdec_get_property; + + GST_DEBUG_CATEGORY_INIT (speexdec_debug, "speexdec", 0, + "speex decoding element"); } -static void -gst_speexdec_init (GstSpeexDec * speexdec) +static const GstFormat * +speex_dec_get_formats (GstPad * pad) +{ + static GstFormat src_formats[] = { + GST_FORMAT_BYTES, + GST_FORMAT_DEFAULT, /* samples in the audio case */ + GST_FORMAT_TIME, + 0 + }; + static GstFormat sink_formats[] = { + GST_FORMAT_BYTES, + GST_FORMAT_TIME, + GST_FORMAT_DEFAULT, /* samples */ + 0 + }; + + return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats); +} + +static const GstEventMask * +speex_get_event_masks (GstPad * pad) { - GST_DEBUG ("gst_speexdec_init: initializing"); + static const GstEventMask speex_dec_src_event_masks[] = { + {GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH}, + {0,} + }; - /* create the sink and src pads */ - speexdec->sinkpad = + return speex_dec_src_event_masks; +} + +static const GstQueryType * +speex_get_query_types (GstPad * pad) +{ + static const GstQueryType speex_dec_src_query_types[] = { + GST_QUERY_TOTAL, + GST_QUERY_POSITION, + 0 + }; + + return speex_dec_src_query_types; +} + +static void +gst_speex_dec_init (GstSpeexDec * dec) +{ + dec->sinkpad = gst_pad_new_from_template (gst_static_pad_template_get - (&speexdec_sink_template), "sink"); - gst_element_add_pad (GST_ELEMENT (speexdec), speexdec->sinkpad); - gst_pad_set_chain_function (speexdec->sinkpad, gst_speexdec_chain); - gst_pad_set_link_function (speexdec->sinkpad, gst_speexdec_sinkconnect); + (&speex_dec_sink_factory), "sink"); + gst_pad_set_chain_function (dec->sinkpad, speex_dec_chain); + gst_pad_set_formats_function (dec->sinkpad, speex_dec_get_formats); + gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); - speexdec->srcpad = + dec->srcpad = gst_pad_new_from_template (gst_static_pad_template_get - (&speexdec_src_template), "src"); - gst_pad_use_explicit_caps (speexdec->srcpad); - gst_element_add_pad (GST_ELEMENT (speexdec), speexdec->srcpad); + (&speex_dec_src_factory), "src"); + gst_pad_use_explicit_caps (dec->srcpad); + gst_pad_set_event_mask_function (dec->srcpad, speex_get_event_masks); + gst_pad_set_event_function (dec->srcpad, speex_dec_src_event); + gst_pad_set_query_type_function (dec->srcpad, speex_get_query_types); + gst_pad_set_query_function (dec->srcpad, speex_dec_src_query); + gst_pad_set_formats_function (dec->srcpad, speex_dec_get_formats); + gst_pad_set_convert_function (dec->srcpad, speex_dec_convert); + gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); + + dec->enh = DEFAULT_ENH; + + GST_FLAG_SET (dec, GST_ELEMENT_EVENT_AWARE); +} +static gboolean +speex_dec_convert (GstPad * pad, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value) +{ + gboolean res = TRUE; + GstSpeexDec *dec; + guint64 scale = 1; + + dec = GST_SPEEXDEC (gst_pad_get_parent (pad)); + + if (dec->packetno < 1) + return FALSE; + + switch (src_format) { + case GST_FORMAT_TIME: + switch (*dest_format) { + case GST_FORMAT_BYTES: + scale = sizeof (float) * dec->header->nb_channels; + case GST_FORMAT_DEFAULT: + *dest_value = scale * (src_value * dec->header->rate / GST_SECOND); + break; + default: + res = FALSE; + } + break; + case GST_FORMAT_DEFAULT: + switch (*dest_format) { + case GST_FORMAT_BYTES: + *dest_value = src_value * sizeof (float) * dec->header->nb_channels; + break; + case GST_FORMAT_TIME: + *dest_value = src_value * GST_SECOND / dec->header->rate; + break; + default: + res = FALSE; + } + break; + case GST_FORMAT_BYTES: + switch (*dest_format) { + case GST_FORMAT_DEFAULT: + *dest_value = src_value / (sizeof (float) * dec->header->nb_channels); + break; + case GST_FORMAT_TIME: + *dest_value = src_value * GST_SECOND / + (dec->header->rate * sizeof (float) * dec->header->nb_channels); + break; + default: + res = FALSE; + } + break; + default: + res = FALSE; + } + + return res; } -static GstPadLinkReturn -gst_speexdec_sinkconnect (GstPad * pad, const GstCaps * caps) +static gboolean +speex_dec_src_query (GstPad * pad, GstQueryType query, GstFormat * format, + gint64 * value) +{ + gint64 samples_out = 0; + GstSpeexDec *dec = GST_SPEEXDEC (gst_pad_get_parent (pad)); + GstFormat my_format = GST_FORMAT_DEFAULT; + + if (query == GST_QUERY_POSITION) { + samples_out = dec->samples_out; + } else { + /* query peer in default format */ + if (!gst_pad_query (GST_PAD_PEER (dec->sinkpad), query, &my_format, + &samples_out)) + return FALSE; + } + + /* and convert to the final format */ + if (!gst_pad_convert (pad, GST_FORMAT_DEFAULT, samples_out, format, value)) + return FALSE; + + GST_LOG_OBJECT (dec, + "query %u: peer returned samples_out: %llu - we return %llu (format %u)\n", + query, samples_out, *value, *format); + return TRUE; +} + +static gboolean +speex_dec_src_event (GstPad * pad, GstEvent * event) +{ + gboolean res = TRUE; + GstSpeexDec *dec = GST_SPEEXDEC (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK:{ + guint64 value; + GstFormat my_format = GST_FORMAT_DEFAULT; + + /* convert to samples_out */ + res = speex_dec_convert (pad, GST_EVENT_SEEK_FORMAT (event), + GST_EVENT_SEEK_OFFSET (event), &my_format, &value); + if (res) { + GstEvent *real_seek = gst_event_new_seek ( + (GST_EVENT_SEEK_TYPE (event) & ~GST_SEEK_FORMAT_MASK) | + GST_FORMAT_DEFAULT, + value); + + res = gst_pad_send_event (GST_PAD_PEER (dec->sinkpad), real_seek); + } + gst_event_unref (event); + break; + } + default: + res = gst_pad_event_default (pad, event); + break; + } + + return res; +} + +static void +speex_dec_event (GstSpeexDec * dec, GstEvent * event) +{ + guint64 value, time, bytes; + + GST_LOG_OBJECT (dec, "handling event"); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_DISCONTINUOUS: + if (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT, + (gint64 *) & value)) { + dec->samples_out = value; + GST_DEBUG_OBJECT (dec, + "setting samples_out to %" G_GUINT64_FORMAT " after discont", + value); + } else { + GST_WARNING_OBJECT (dec, + "discont event didn't include offset, we might set it wrong now"); + } + if (dec->packetno < 2) { + if (dec->samples_out != 0) + GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), + ("can't handle discont before parsing first 2 packets")); + dec->packetno = 0; + gst_pad_push (dec->srcpad, GST_DATA (gst_event_new_discontinuous (FALSE, + GST_FORMAT_TIME, (guint64) 0, GST_FORMAT_DEFAULT, + (guint64) 0, GST_FORMAT_BYTES, (guint64) 0, 0))); + } else { + GstFormat time_format, default_format, bytes_format; + + time_format = GST_FORMAT_TIME; + default_format = GST_FORMAT_DEFAULT; + bytes_format = GST_FORMAT_BYTES; + + dec->packetno = 2; + /* if one of them works, all of them work */ + if (speex_dec_convert (dec->srcpad, GST_FORMAT_DEFAULT, + dec->samples_out, &time_format, &time) + && speex_dec_convert (dec->srcpad, GST_FORMAT_DEFAULT, + dec->samples_out, &bytes_format, &bytes)) { + gst_pad_push (dec->srcpad, + GST_DATA (gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, + time, GST_FORMAT_DEFAULT, dec->samples_out, + GST_FORMAT_BYTES, bytes, 0))); + } else { + GST_ERROR_OBJECT (dec, + "failed to parse data for DISCONT event, not sending any"); + } + } + gst_data_unref (GST_DATA (event)); + break; + default: + gst_pad_event_default (dec->sinkpad, event); + break; + } +} + +static void +speex_dec_chain (GstPad * pad, GstData * data) +{ + GstBuffer *buf; + GstSpeexDec *dec; + + dec = GST_SPEEXDEC (gst_pad_get_parent (pad)); + if (GST_IS_EVENT (data)) { + speex_dec_event (dec, GST_EVENT (data)); + return; + } + + buf = GST_BUFFER (data); + + if (dec->packetno == 0) { + GstCaps *caps; + + /* get the header */ + dec->header = + speex_packet_to_header (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_data_unref (data); + if (!dec->header) { + GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, + (NULL), ("couldn't read header")); + return; + } + if (dec->header->mode >= SPEEX_NB_MODES) { + GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, + (NULL), + ("Mode number %d does not (yet/any longer) exist in this version", + dec->header->mode)); + return; + } + + dec->mode = speex_mode_list[dec->header->mode]; + + /* initialize the decoder */ + dec->state = speex_decoder_init (dec->mode); + if (!dec->state) { + GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, + (NULL), ("couldn't initialize decoder")); + gst_data_unref (data); + return; + } + + speex_decoder_ctl (dec->state, SPEEX_SET_ENH, &dec->enh); + speex_decoder_ctl (dec->state, SPEEX_GET_FRAME_SIZE, &dec->frame_size); + + if (dec->header->nb_channels != 1) { + dec->callback.callback_id = SPEEX_INBAND_STEREO; + dec->callback.func = speex_std_stereo_request_handler; + dec->callback.data = &dec->stereo; + speex_decoder_ctl (dec->state, SPEEX_SET_HANDLER, &dec->callback); + } + + speex_decoder_ctl (dec->state, SPEEX_SET_SAMPLING_RATE, &dec->header->rate); + + speex_bits_init (&dec->bits); + + /* set caps */ + caps = gst_caps_new_simple ("audio/x-raw-int", + "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); + + if (!gst_pad_set_explicit_caps (dec->srcpad, caps)) { + gst_caps_free (caps); + return; + } + gst_caps_free (caps); + } else if (dec->packetno == 1) { + gchar *encoder = NULL; + + /* FIXME parse comments */ + GstTagList *list = gst_tag_list_from_vorbiscomment_buffer (buf, "", 1, + &encoder); + + gst_data_unref (data); + + if (!list) { + GST_WARNING_OBJECT (dec, "couldn't decode comments"); + list = gst_tag_list_new (); + } + if (encoder) { + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + GST_TAG_ENCODER, encoder, NULL); + g_free (encoder); + } + /* + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + GST_TAG_ENCODER_VERSION, dec->vi.version, NULL); + + if (dec->vi.bitrate_upper > 0) + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL); + if (vd->vi.bitrate_nominal > 0) + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL); + if (vd->vi.bitrate_lower > 0) + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL); + */ + gst_element_found_tags_for_pad (GST_ELEMENT (dec), dec->srcpad, 0, list); + } else { + gint i; + + /* send data to the bitstream */ + speex_bits_read_from (&dec->bits, GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf)); + gst_data_unref (data); + + /* now decode each frame */ + for (i = 0; i < dec->header->frames_per_packet; i++) { + gint ret; + GstBuffer *outbuf; + gint16 *out_data; + + ret = speex_decode (dec->state, &dec->bits, dec->output); + if (ret == -1) { + /* FIXME emit warning */ + break; + } else if (ret == -2) { + /* FIXME emit warning */ + break; + } + if (speex_bits_remaining (&dec->bits) < 0) { + fprintf (stderr, "Decoding overflow: corrupted stream?\n"); + break; + } + if (dec->header->nb_channels == 2) + speex_decode_stereo (dec->output, dec->frame_size, &dec->stereo); + + outbuf = gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET_NONE, + dec->frame_size * dec->header->nb_channels * 2); + out_data = (gint16 *) GST_BUFFER_DATA (outbuf); + + /*PCM saturation (just in case) */ + for (i = 0; i < dec->frame_size * dec->header->nb_channels; i++) { + if (dec->output[i] > 32000.0) + out_data[i] = 32000; + else if (dec->output[i] < -32000.0) + out_data[i] = -32000; + else + out_data[i] = (gint16) dec->output[i]; + } + + GST_BUFFER_OFFSET (outbuf) = dec->samples_out; + GST_BUFFER_OFFSET_END (outbuf) = dec->samples_out + dec->frame_size; + GST_BUFFER_TIMESTAMP (outbuf) = + dec->samples_out * GST_SECOND / dec->header->rate; + GST_BUFFER_DURATION (outbuf) = + dec->frame_size * GST_SECOND / dec->header->rate; + gst_pad_push (dec->srcpad, GST_DATA (outbuf)); + dec->samples_out += dec->frame_size; + } + } + dec->packetno++; +} + +static void +gst_speexdec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) { GstSpeexDec *speexdec; - gint rate; - GstStructure *structure; - - speexdec = GST_SPEEXDEC (gst_pad_get_parent (pad)); - - structure = gst_caps_get_structure (caps, 0); - gst_structure_get_int (structure, "rate", &rate); - - if (gst_pad_set_explicit_caps (speexdec->srcpad, - gst_caps_new_simple ("audio/x-raw-int", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "signed", G_TYPE_BOOLEAN, TRUE, - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, 1, NULL))) { - return GST_PAD_LINK_OK; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (GST_IS_SPEEXDEC (object)); + + speexdec = GST_SPEEXDEC (object); + + switch (prop_id) { + case ARG_ENH: + g_value_set_boolean (value, speexdec->enh); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } - return GST_PAD_LINK_REFUSED; } static void -gst_speexdec_chain (GstPad * pad, GstData * _data) +gst_speexdec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) { - GstBuffer *buf = GST_BUFFER (_data); GstSpeexDec *speexdec; - gchar *data; - guint size; - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); - /*g_return_if_fail(GST_IS_BUFFER(buf)); */ + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (GST_IS_SPEEXDEC (object)); + + speexdec = GST_SPEEXDEC (object); + + switch (prop_id) { + case ARG_ENH: + speexdec->enh = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} - speexdec = GST_SPEEXDEC (gst_pad_get_parent (pad)); - data = GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf); +static GstElementStateReturn +speex_dec_change_state (GstElement * element) +{ + GstSpeexDec *vd = GST_SPEEXDEC (element); + + switch (GST_STATE_TRANSITION (element)) { + case GST_STATE_NULL_TO_READY: + break; + case GST_STATE_READY_TO_PAUSED: + break; + case GST_STATE_PAUSED_TO_PLAYING: + break; + case GST_STATE_PLAYING_TO_PAUSED: + break; + case GST_STATE_PAUSED_TO_READY: + vd->packetno = 0; + vd->samples_out = 0; + break; + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } - gst_buffer_unref (buf); + return parent_class->change_state (element); } |