diff --git a/gst/siren/Makefile.am b/gst/siren/Makefile.am index 2be9ede49a..c6d1d8cba7 100644 --- a/gst/siren/Makefile.am +++ b/gst/siren/Makefile.am @@ -10,7 +10,7 @@ libgstsiren_la_SOURCES = gstsiren.c \ libgstsiren_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \ $(GST_CFLAGS) -libgstsiren_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ \ +libgstsiren_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-@GST_MAJORMINOR@ \ $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM) libgstsiren_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstsiren_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/gst/siren/gstsirenenc.c b/gst/siren/gstsirenenc.c index dbf0f688d4..b6789a170d 100644 --- a/gst/siren/gstsirenenc.c +++ b/gst/siren/gstsirenenc.c @@ -69,17 +69,12 @@ enum ARG_0, }; - - -static void gst_siren_enc_finalize (GObject * object); - -static gboolean gst_siren_enc_sink_setcaps (GstPad * pad, GstCaps * caps); -static gboolean gst_siren_enc_sink_event (GstPad * pad, GstEvent * event); - -static GstFlowReturn gst_siren_enc_chain (GstPad * pad, GstBuffer * buf); -static GstStateChangeReturn -gst_siren_change_state (GstElement * element, GstStateChange transition); - +static gboolean gst_siren_enc_start (GstAudioEncoder * enc); +static gboolean gst_siren_enc_stop (GstAudioEncoder * enc); +static gboolean gst_siren_enc_set_format (GstAudioEncoder * enc, + GstAudioInfo * info); +static GstFlowReturn gst_siren_enc_handle_frame (GstAudioEncoder * enc, + GstBuffer * in_buf); static void _do_init (GType type) @@ -87,8 +82,8 @@ _do_init (GType type) GST_DEBUG_CATEGORY_INIT (sirenenc_debug, "sirenenc", 0, "sirenenc"); } -GST_BOILERPLATE_FULL (GstSirenEnc, gst_siren_enc, GstElement, - GST_TYPE_ELEMENT, _do_init); +GST_BOILERPLATE_FULL (GstSirenEnc, gst_siren_enc, GstAudioEncoder, + GST_TYPE_AUDIO_ENCODER, _do_init); static void gst_siren_enc_base_init (gpointer klass) @@ -107,17 +102,14 @@ gst_siren_enc_base_init (gpointer klass) static void gst_siren_enc_class_init (GstSirenEncClass * klass) { - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; + GstAudioEncoderClass *base_class = GST_AUDIO_ENCODER_CLASS (klass); GST_DEBUG ("Initializing Class"); - gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_siren_enc_finalize); - - gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_siren_change_state); + base_class->start = GST_DEBUG_FUNCPTR (gst_siren_enc_start); + base_class->stop = GST_DEBUG_FUNCPTR (gst_siren_enc_stop); + base_class->set_format = GST_DEBUG_FUNCPTR (gst_siren_enc_set_format); + base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_siren_enc_handle_frame); GST_DEBUG ("Class Init done"); } @@ -125,120 +117,81 @@ gst_siren_enc_class_init (GstSirenEncClass * klass) static void gst_siren_enc_init (GstSirenEnc * enc, GstSirenEncClass * klass) { - - GST_DEBUG_OBJECT (enc, "Initializing"); - enc->encoder = Siren7_NewEncoder (16000); - enc->adapter = gst_adapter_new (); - - enc->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); - enc->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); - - gst_pad_set_setcaps_function (enc->sinkpad, - GST_DEBUG_FUNCPTR (gst_siren_enc_sink_setcaps)); - gst_pad_set_event_function (enc->sinkpad, - GST_DEBUG_FUNCPTR (gst_siren_enc_sink_event)); - gst_pad_set_chain_function (enc->sinkpad, - GST_DEBUG_FUNCPTR (gst_siren_enc_chain)); - - gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad); - gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad); - - GST_DEBUG_OBJECT (enc, "Init done"); -} - -static void -gst_siren_enc_finalize (GObject * object) -{ - GstSirenEnc *enc = GST_SIREN_ENC (object); - - GST_DEBUG_OBJECT (object, "Disposing"); - - Siren7_CloseEncoder (enc->encoder); - g_object_unref (enc->adapter); - - G_OBJECT_CLASS (parent_class)->finalize (object); } static gboolean -gst_siren_enc_sink_setcaps (GstPad * pad, GstCaps * caps) +gst_siren_enc_start (GstAudioEncoder * enc) +{ + GstSirenEnc *senc = GST_SIREN_ENC (enc); + + GST_DEBUG_OBJECT (enc, "start"); + + senc->encoder = Siren7_NewEncoder (16000); + + return TRUE; +} + +static gboolean +gst_siren_enc_stop (GstAudioEncoder * enc) +{ + GstSirenEnc *senc = GST_SIREN_ENC (enc); + + GST_DEBUG_OBJECT (senc, "stop"); + + Siren7_CloseEncoder (senc->encoder); + + return TRUE; +} + +static gboolean +gst_siren_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) { GstSirenEnc *enc; gboolean res; GstCaps *outcaps; - enc = GST_SIREN_ENC (GST_PAD_PARENT (pad)); + enc = GST_SIREN_ENC (benc); outcaps = gst_static_pad_template_get_caps (&srctemplate); - res = gst_pad_set_caps (enc->srcpad, outcaps); + res = gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), outcaps); gst_caps_unref (outcaps); - return res; -} + /* report needs to base class */ + gst_audio_encoder_set_frame_samples_min (benc, 320); + gst_audio_encoder_set_frame_samples_max (benc, 320); + /* no remainder or flushing please */ + gst_audio_encoder_set_hard_min (benc, TRUE); + gst_audio_encoder_set_drainable (benc, FALSE); -static gboolean -gst_siren_enc_sink_event (GstPad * pad, GstEvent * event) -{ - GstSirenEnc *enc; - gboolean res; - - enc = GST_SIREN_ENC (GST_PAD_PARENT (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - gst_adapter_clear (enc->adapter); - res = gst_pad_push_event (enc->srcpad, event); - break; - case GST_EVENT_FLUSH_STOP: - gst_adapter_clear (enc->adapter); - res = gst_pad_push_event (enc->srcpad, event); - break; - default: - res = gst_pad_push_event (enc->srcpad, event); - break; - } return res; } static GstFlowReturn -gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) +gst_siren_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf) { GstSirenEnc *enc; GstFlowReturn ret = GST_FLOW_OK; GstBuffer *out_buf; guint8 *in_data, *out_data; - guint8 *to_free = NULL; guint i, size, num_frames; gint out_size, in_size; gint encode_ret; - gboolean discont; - GstClockTime timestamp; - guint64 distance; - GstCaps *outcaps; - enc = GST_SIREN_ENC (GST_PAD_PARENT (pad)); + g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); - discont = GST_BUFFER_IS_DISCONT (buf); - if (discont) { - GST_DEBUG_OBJECT (enc, "received DISCONT, flush adapter"); - gst_adapter_clear (enc->adapter); - enc->discont = TRUE; - } + enc = GST_SIREN_ENC (benc); - gst_adapter_push (enc->adapter, buf); + size = GST_BUFFER_SIZE (buf); - size = gst_adapter_available (enc->adapter); + GST_LOG_OBJECT (enc, "Received buffer of size %d", GST_BUFFER_SIZE (buf)); - GST_LOG_OBJECT (enc, "Received buffer of size %d with adapter of size : %d", - GST_BUFFER_SIZE (buf), size); + g_return_val_if_fail (size > 0, GST_FLOW_ERROR); + g_return_val_if_fail (size % 640 == 0, GST_FLOW_ERROR); /* we need to process 640 input bytes to produce 40 output bytes */ /* calculate the amount of frames we will handle */ num_frames = size / 640; - /* no frames, wait some more */ - if (num_frames == 0) - goto done; - /* this is the input/output size */ in_size = num_frames * 640; out_size = num_frames * 40; @@ -246,32 +199,14 @@ gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) GST_LOG_OBJECT (enc, "we have %u frames, %u in, %u out", num_frames, in_size, out_size); - /* set output caps when needed */ - if ((outcaps = GST_PAD_CAPS (enc->srcpad)) == NULL) { - outcaps = gst_static_pad_template_get_caps (&srctemplate); - gst_pad_set_caps (enc->srcpad, outcaps); - gst_caps_unref (outcaps); - } - /* get a buffer */ - ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, -1, - out_size, outcaps, &out_buf); + ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (benc), + -1, out_size, GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (benc)), &out_buf); if (ret != GST_FLOW_OK) goto alloc_failed; - /* get the timestamp for the output buffer */ - timestamp = gst_adapter_prev_timestamp (enc->adapter, &distance); - - /* add the amount of time taken by the distance */ - if (timestamp != -1) - timestamp += gst_util_uint64_scale_int (distance / 2, GST_SECOND, 16000); - - GST_LOG_OBJECT (enc, - "timestamp %" GST_TIME_FORMAT ", distance %" G_GUINT64_FORMAT, - GST_TIME_ARGS (timestamp), distance); - /* get the input data for all the frames */ - to_free = in_data = gst_adapter_take (enc->adapter, in_size); + in_data = GST_BUFFER_DATA (buf); out_data = GST_BUFFER_DATA (out_buf); for (i = 0; i < num_frames; i++) { @@ -289,20 +224,10 @@ gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) GST_LOG_OBJECT (enc, "Finished encoding"); - /* mark discont */ - if (enc->discont) { - GST_BUFFER_FLAG_SET (out_buf, GST_BUFFER_FLAG_DISCONT); - enc->discont = FALSE; - } - GST_BUFFER_TIMESTAMP (out_buf) = timestamp; - GST_BUFFER_DURATION (out_buf) = num_frames * FRAME_DURATION; - - ret = gst_pad_push (enc->srcpad, out_buf); + /* we encode all we get, pass it along */ + ret = gst_audio_encoder_finish_frame (benc, out_buf, -1); done: - if (to_free) - g_free (to_free); - return ret; /* ERRORS */ @@ -322,33 +247,6 @@ encode_error: } } -static GstStateChangeReturn -gst_siren_change_state (GstElement * element, GstStateChange transition) -{ - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - GstSirenEnc *enc = GST_SIREN_ENC (element); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - enc->discont = FALSE; - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_adapter_clear (enc->adapter); - break; - default: - break; - } - - return ret; -} - gboolean gst_siren_enc_plugin_init (GstPlugin * plugin) { diff --git a/gst/siren/gstsirenenc.h b/gst/siren/gstsirenenc.h index 1d63628dc4..3477db1a73 100644 --- a/gst/siren/gstsirenenc.h +++ b/gst/siren/gstsirenenc.h @@ -24,7 +24,7 @@ #define __GST_SIREN_ENC_H__ #include -#include +#include #include "siren7.h" @@ -48,21 +48,15 @@ typedef struct _GstSirenEncPrivate GstSirenEncPrivate; struct _GstSirenEnc { - GstElement parent; + GstAudioEncoder parent; /* protected by the stream lock */ SirenEncoder encoder; - GstAdapter *adapter; - - gboolean discont; - - GstPad *srcpad; - GstPad *sinkpad; }; struct _GstSirenEncClass { - GstElementClass parent_class; + GstAudioEncoderClass parent_class; }; GType gst_siren_enc_get_type (void);