diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-01-25 13:22:43 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-01-25 13:22:43 +0100 |
commit | a2a430024136fd947637ff56a4fea6a2689ca59d (patch) | |
tree | 8cab3177242814f02b1e49a51d81b5f2f1660621 /gst/adpcmdec/adpcmdec.c | |
parent | 071c6e8f15f2afff7ca4ce5934c3bae1d76aea95 (diff) | |
parent | 8fb0beaf00aeae2ef6081d08f0d74d6e655a53da (diff) | |
download | gstreamer-plugins-bad-a2a430024136fd947637ff56a4fea6a2689ca59d.tar.gz |
Merge branch 'master' into 0.11
Conflicts:
configure.ac
ext/kate/gstkateenc.c
gst/colorspace/colorspace.c
gst/mpegvideoparse/mpegvideoparse.c
Diffstat (limited to 'gst/adpcmdec/adpcmdec.c')
-rw-r--r-- | gst/adpcmdec/adpcmdec.c | 261 |
1 files changed, 88 insertions, 173 deletions
diff --git a/gst/adpcmdec/adpcmdec.c b/gst/adpcmdec/adpcmdec.c index 0fcfeb03f..c6eb749d3 100644 --- a/gst/adpcmdec/adpcmdec.c +++ b/gst/adpcmdec/adpcmdec.c @@ -28,7 +28,7 @@ #endif #include <gst/gst.h> -#include <gst/base/gstadapter.h> +#include <gst/audio/gstaudiodecoder.h> #define GST_TYPE_ADPCM_DEC \ (adpcmdec_get_type ()) @@ -69,80 +69,29 @@ enum adpcm_layout typedef struct _ADPCMDecClass { - GstElementClass parent_class; + GstAudioDecoderClass parent_class; } ADPCMDecClass; typedef struct _ADPCMDec { - GstElement parent; - - GstPad *sinkpad; - GstPad *srcpad; - - GstCaps *output_caps; + GstAudioDecoder parent; enum adpcm_layout layout; int rate; int channels; int blocksize; - - gboolean is_setup; - - GstClockTime timestamp; - GstClockTime base_timestamp; - - guint64 out_samples; - - GstAdapter *adapter; - } ADPCMDec; GType adpcmdec_get_type (void); -GST_BOILERPLATE (ADPCMDec, adpcmdec, GstElement, GST_TYPE_ELEMENT); -static gboolean -adpcmdec_setup (ADPCMDec * dec) -{ - dec->output_caps = gst_caps_new_simple ("audio/x-raw-int", - "rate", G_TYPE_INT, dec->rate, - "channels", G_TYPE_INT, dec->channels, - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "signed", G_TYPE_BOOLEAN, TRUE, NULL); - - if (dec->output_caps) { - gst_pad_set_caps (dec->srcpad, dec->output_caps); - } - - dec->is_setup = TRUE; - dec->timestamp = GST_CLOCK_TIME_NONE; - dec->base_timestamp = GST_CLOCK_TIME_NONE; - dec->adapter = gst_adapter_new (); - dec->out_samples = 0; - - return TRUE; -} - -static void -adpcmdec_teardown (ADPCMDec * dec) -{ - if (dec->output_caps) { - gst_caps_unref (dec->output_caps); - dec->output_caps = NULL; - } - if (dec->adapter) { - g_object_unref (dec->adapter); - dec->adapter = NULL; - } - dec->is_setup = FALSE; -} +GST_BOILERPLATE (ADPCMDec, adpcmdec, GstAudioDecoder, GST_TYPE_AUDIO_DECODER); static gboolean -adpcmdec_sink_setcaps (GstPad * pad, GstCaps * caps) +adpcmdec_set_format (GstAudioDecoder * bdec, GstCaps * in_caps) { - ADPCMDec *dec = (ADPCMDec *) gst_pad_get_parent (pad); - GstStructure *structure = gst_caps_get_structure (caps, 0); + ADPCMDec *dec = (ADPCMDec *) (bdec); + GstStructure *structure = gst_caps_get_structure (in_caps, 0); const gchar *layout; + GstCaps *caps; layout = gst_structure_get_string (structure, "layout"); if (!layout) @@ -163,9 +112,16 @@ adpcmdec_sink_setcaps (GstPad * pad, GstCaps * caps) if (!gst_structure_get_int (structure, "channels", &dec->channels)) return FALSE; - if (dec->is_setup) - adpcmdec_teardown (dec); - gst_object_unref (dec); + caps = gst_caps_new_simple ("audio/x-raw-int", + "rate", G_TYPE_INT, dec->rate, + "channels", G_TYPE_INT, dec->channels, + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, + "endianness", G_TYPE_INT, G_BYTE_ORDER, + "signed", G_TYPE_BOOLEAN, TRUE, NULL); + + gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (bdec), caps); + gst_caps_unref (caps); return TRUE; } @@ -377,10 +333,10 @@ adpcmdec_decode_ima_block (ADPCMDec * dec, int n_samples, const guint8 * data, return TRUE; } -static GstFlowReturn +static GstBuffer * adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize) { - gboolean res; + gboolean res = FALSE; GstBuffer *outbuf = NULL; int outsize; int samples; @@ -390,7 +346,7 @@ adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize) give two initial sample values per channel. Then the remainder gives two samples per byte */ if (blocksize < 7 * dec->channels) - return GST_FLOW_ERROR; + goto exit; samples = (blocksize - 7 * dec->channels) * 2 + 2 * dec->channels; outsize = 2 * samples; outbuf = gst_buffer_new_and_alloc (outsize); @@ -401,7 +357,7 @@ adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize) /* Each block has a 4 byte header per channel, include an initial sample. Then the remainder gives two samples per byte */ if (blocksize < 4 * dec->channels) - return GST_FLOW_ERROR; + goto exit; samples = (blocksize - 4 * dec->channels) * 2 + dec->channels; outsize = 2 * samples; outbuf = gst_buffer_new_and_alloc (outsize); @@ -410,155 +366,114 @@ adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize) (gint16 *) (GST_BUFFER_DATA (outbuf))); } else { GST_WARNING_OBJECT (dec, "Unknown layout"); - return GST_FLOW_ERROR; } if (!res) { - gst_buffer_unref (outbuf); + if (outbuf) + gst_buffer_unref (outbuf); + outbuf = NULL; GST_WARNING_OBJECT (dec, "Decode of block failed"); - return GST_FLOW_ERROR; } - gst_buffer_set_caps (outbuf, dec->output_caps); - GST_BUFFER_TIMESTAMP (outbuf) = dec->timestamp; - dec->out_samples += samples / dec->channels; - dec->timestamp = dec->base_timestamp + - gst_util_uint64_scale_int (dec->out_samples, GST_SECOND, dec->rate); - GST_BUFFER_DURATION (outbuf) = dec->timestamp - GST_BUFFER_TIMESTAMP (outbuf); - - return gst_pad_push (dec->srcpad, outbuf); +exit: + return outbuf; } static GstFlowReturn -adpcmdec_chain (GstPad * pad, GstBuffer * buf) +adpcmdec_parse (GstAudioDecoder * bdec, GstAdapter * adapter, + gint * offset, gint * length) { - ADPCMDec *dec = (ADPCMDec *) gst_pad_get_parent (pad); - GstFlowReturn ret = GST_FLOW_OK; - guint8 *data; - GstBuffer *databuf = NULL; + ADPCMDec *dec = (ADPCMDec *) (bdec); + guint size; - if (!dec->is_setup) - adpcmdec_setup (dec); + size = gst_adapter_available (adapter); + g_return_val_if_fail (size > 0, GST_FLOW_ERROR); - if (dec->base_timestamp == GST_CLOCK_TIME_NONE) { - dec->base_timestamp = GST_BUFFER_TIMESTAMP (buf); - if (dec->base_timestamp == GST_CLOCK_TIME_NONE) - dec->base_timestamp = 0; - dec->timestamp = dec->base_timestamp; + if (dec->blocksize < 0) { + /* No explicit blocksize; we just process one input buffer at a time */ + *offset = 0; + *length = size; + } else { + if (size >= dec->blocksize) { + *offset = 0; + *length = dec->blocksize; + } else { + return GST_FLOW_UNEXPECTED; + } } - if (dec->blocksize > 0) { - gst_adapter_push (dec->adapter, buf); + return GST_FLOW_OK; +} - while (gst_adapter_available (dec->adapter) >= dec->blocksize) { - databuf = gst_adapter_take_buffer (dec->adapter, dec->blocksize); - data = GST_BUFFER_DATA (databuf); +static GstFlowReturn +adpcmdec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buffer) +{ + ADPCMDec *dec = (ADPCMDec *) (bdec); + GstFlowReturn ret = GST_FLOW_OK; + guint8 *data; + GstBuffer *outbuf = NULL; - ret = adpcmdec_decode_block (dec, data, dec->blocksize); + /* no fancy draining */ + if (G_UNLIKELY (!buffer)) + return GST_FLOW_OK; - /* Done with input data, free it */ - gst_buffer_unref (databuf); + if (!dec->blocksize) + return GST_FLOW_NOT_NEGOTIATED; - if (ret != GST_FLOW_OK) - goto done; - } - } else { - /* No explicit blocksize; we just process one input buffer at a time */ - ret = adpcmdec_decode_block (dec, GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf)); - gst_buffer_unref (buf); + data = GST_BUFFER_DATA (buffer); + outbuf = adpcmdec_decode_block (dec, data, dec->blocksize); + + if (outbuf == NULL) { + GST_AUDIO_DECODER_ERROR (bdec, 1, STREAM, DECODE, (NULL), + ("frame decode failed"), ret); } -done: - gst_object_unref (dec); + if (ret == GST_FLOW_OK) + ret = gst_audio_decoder_finish_frame (bdec, outbuf, 1); return ret; } static gboolean -adpcmdec_sink_event (GstPad * pad, GstEvent * event) +adpcmdec_start (GstAudioDecoder * bdec) { - ADPCMDec *dec = (ADPCMDec *) gst_pad_get_parent (pad); - gboolean res; - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_STOP: - dec->out_samples = 0; - dec->timestamp = GST_CLOCK_TIME_NONE; - dec->base_timestamp = GST_CLOCK_TIME_NONE; - gst_adapter_clear (dec->adapter); - /* Fall through */ - default: - res = gst_pad_push_event (dec->srcpad, event); - break; - } - gst_object_unref (dec); - return res; -} + ADPCMDec *dec = (ADPCMDec *) bdec; -static GstStateChangeReturn -adpcmdec_change_state (GstElement * element, GstStateChange transition) -{ - GstStateChangeReturn ret; - ADPCMDec *dec = (ADPCMDec *) element; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - default: - break; - } + GST_DEBUG_OBJECT (dec, "start"); - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - adpcmdec_teardown (dec); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - return ret; + dec->blocksize = 0; + dec->rate = 0; + dec->channels = 0; + + return TRUE; } -static void -adpcmdec_dispose (GObject * obj) +static gboolean +adpcmdec_stop (GstAudioDecoder * dec) { - G_OBJECT_CLASS (parent_class)->dispose (obj); + GST_DEBUG_OBJECT (dec, "stop"); + + return TRUE; } static void adpcmdec_init (ADPCMDec * dec, ADPCMDecClass * klass) { - dec->sinkpad = - gst_pad_new_from_static_template (&adpcmdec_sink_template, "sink"); - gst_pad_set_setcaps_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (adpcmdec_sink_setcaps)); - gst_pad_set_chain_function (dec->sinkpad, GST_DEBUG_FUNCPTR (adpcmdec_chain)); - gst_pad_set_event_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (adpcmdec_sink_event)); - gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); - dec->srcpad = - gst_pad_new_from_static_template (&adpcmdec_src_template, "src"); - gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); } static void adpcmdec_class_init (ADPCMDecClass * klass) { - GObjectClass *gobjectclass = (GObjectClass *) klass; - GstElementClass *gstelement_class = (GstElementClass *) klass; - gobjectclass->dispose = adpcmdec_dispose; - gstelement_class->change_state = adpcmdec_change_state; -} static void + GstAudioDecoderClass *base_class = (GstAudioDecoderClass *) klass; + + base_class->start = GST_DEBUG_FUNCPTR (adpcmdec_start); + base_class->stop = GST_DEBUG_FUNCPTR (adpcmdec_stop); + base_class->set_format = GST_DEBUG_FUNCPTR (adpcmdec_set_format); + base_class->parse = GST_DEBUG_FUNCPTR (adpcmdec_parse); + base_class->handle_frame = GST_DEBUG_FUNCPTR (adpcmdec_handle_frame); +} +static void adpcmdec_base_init (gpointer klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); |