2005-05-05 Wim Taymans <wim@fluendo.com>
+ * gst/base/Makefile.am:
+ * gst/base/gstbasesink.h:
+ * gst/base/gstbasesrc.c: (gst_basesrc_init),
+ (gst_basesrc_set_dataflow_funcs), (gst_basesrc_query):
+ * gst/base/gstcollectpads.c: (gst_collectpads_get_type),
+ (gst_collectpads_class_init), (gst_collectpads_init),
+ (gst_collectpads_finalize), (gst_collectpads_new),
+ (gst_collectpads_set_function), (gst_collectpads_add_pad),
+ (find_pad), (gst_collectpads_remove_pad),
+ (gst_collectpads_is_active), (gst_collectpads_collect),
+ (gst_collectpads_collect_range), (gst_collectpads_start),
+ (gst_collectpads_stop), (gst_collectpads_peek),
+ (gst_collectpads_pop), (gst_collectpads_available),
+ (gst_collectpads_read), (gst_collectpads_flush),
+ (gst_collectpads_chain):
+ * gst/base/gstcollectpads.h:
+ * gst/elements/Makefile.am:
+ * gst/elements/gstelements.c:
+ * gst/elements/gstfakesink.c: (gst_fakesink_class_init),
+ (gst_fakesink_get_times), (gst_fakesink_event),
+ (gst_fakesink_preroll), (gst_fakesink_render):
+ * gst/elements/gstfilesink.c: (gst_filesink_class_init),
+ (gst_filesink_init), (gst_filesink_set_location),
+ (gst_filesink_open_file), (gst_filesink_close_file),
+ (gst_filesink_pad_query), (gst_filesink_event),
+ (gst_filesink_render), (gst_filesink_change_state):
+ * gst/elements/gstfilesink.h:
+ Added object to help in making collect pad based elements.
+ Ported filesink.
+ Make event function in sink baseclass return gboolean.
+
+2005-05-05 Wim Taymans <wim@fluendo.com>
+
* gst/gstbin.c: (gst_bin_send_event), (compare_name),
(gst_bin_get_by_name):
* gst/gstbuffer.h:
gstbasesink.c \
gstbasesrc.c \
gstbasetransform.c \
+ gstcollectpads.c \
gsttypefindhelper.c
libgstbase_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
gstbasesink.h \
gstbasesrc.h \
gstbasetransform.h \
+ gstcollectpads.h \
gsttypefindhelper.h
void (*get_times) (GstBaseSink *sink, GstBuffer *buffer,
GstClockTime *start, GstClockTime *end);
- void (*event) (GstBaseSink *sink, GstEvent *event);
+ gboolean (*event) (GstBaseSink *sink, GstEvent *event);
GstFlowReturn (*preroll) (GstBaseSink *sink, GstBuffer *buffer);
GstFlowReturn (*render) (GstBaseSink *sink, GstBuffer *buffer);
};
basesrc->srcpad = pad;
gst_element_add_pad (GST_ELEMENT (basesrc), pad);
+ basesrc->random_access = TRUE;
basesrc->segment_start = -1;
basesrc->segment_end = -1;
basesrc->blocksize = DEFAULT_BLOCKSIZE;
static void
gst_basesrc_set_dataflow_funcs (GstBaseSrc * this)
{
+ GST_DEBUG ("updating dataflow functions");
+
if (this->has_loop)
gst_pad_set_loop_function (this->srcpad, gst_basesrc_loop);
else
{
gboolean ret;
- /* FIXME-wim: is this cast right? */
ret = gst_basesrc_get_size (src, (guint64 *) value);
GST_DEBUG ("getting length %d %lld", ret, *value);
return ret;
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstcollectpads.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gstcollectpads.h"
+
+static GstFlowReturn gst_collectpads_chain (GstPad * pad, GstBuffer * buffer);
+
+static void gst_collectpads_class_init (GstCollectPadsClass * klass);
+static void gst_collectpads_init (GstCollectPads * pads);
+static void gst_collectpads_finalize (GObject * object);
+
+static GstObjectClass *parent_class = NULL;
+
+GType
+gst_collectpads_get_type (void)
+{
+ static GType collect_type = 0;
+
+ if (!collect_type) {
+ static const GTypeInfo collect_info = {
+ sizeof (GstCollectPadsClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gst_collectpads_class_init,
+ NULL,
+ NULL,
+ sizeof (GstCollectPads),
+ 0,
+ (GInstanceInitFunc) gst_collectpads_init,
+ NULL
+ };
+
+ collect_type = g_type_register_static (GST_TYPE_OBJECT, "GstCollectPads",
+ &collect_info, 0);
+ }
+ return collect_type;
+}
+
+static void
+gst_collectpads_class_init (GstCollectPadsClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstObjectClass *gstobject_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstobject_class = (GstObjectClass *) klass;
+
+ gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_collectpads_finalize);
+
+ parent_class = g_type_class_ref (GST_TYPE_OBJECT);
+}
+
+static void
+gst_collectpads_init (GstCollectPads * pads)
+{
+ pads->cond = g_cond_new ();
+ pads->data = NULL;
+ pads->cookie = 0;
+ pads->numpads = 0;
+ pads->queuedpads = 0;
+ pads->started = FALSE;
+}
+
+static void
+gst_collectpads_finalize (GObject * object)
+{
+ GstCollectPads *pads = GST_COLLECTPADS (object);
+
+ g_cond_free (pads->cond);
+ /* FIXME, free data */
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/**
+ * gst_collectpads_new:
+ *
+ * Create a new instance of #GstCollectsPads.
+ *
+ * Returns: a new #GstCollectPads, or NULL in case of an error.
+ *
+ * MT safe.
+ */
+GstCollectPads *
+gst_collectpads_new (void)
+{
+ GstCollectPads *newcoll;
+
+ newcoll = g_object_new (GST_TYPE_COLLECTPADS, NULL);
+
+ return newcoll;
+}
+
+/**
+ * gst_collectpads_set_function:
+ * @pads: the collectspads to use
+ * @func: the function to set
+ * @user_data: user data passed to the function
+ *
+ * Set the callback function and user data that will be called when
+ * all the pads added to the collection have buffers queued.
+ *
+ * MT safe.
+ */
+void
+gst_collectpads_set_function (GstCollectPads * pads,
+ GstCollectPadsFunction func, gpointer user_data)
+{
+ g_return_if_fail (pads != NULL);
+
+ GST_LOCK (pads);
+ pads->func = func;
+ pads->user_data = user_data;
+ GST_UNLOCK (pads);
+}
+
+/**
+ * gst_collectpads_add_pad:
+ * @pads: the collectspads to use
+ * @pad: the pad to add
+ * @size: the size of the returned GstCollectData structure
+ *
+ * Add a pad to the collection of collect pads. The pad has to be
+ * a sinkpad.
+ *
+ * You specify a size for the returned #GstCollectData structure
+ * so that you can use it to store additional information.
+ *
+ * Returns: a new #GstCollectData to identify the new pad. Or NULL
+ * if wrong parameters are supplied.
+ *
+ * MT safe.
+ */
+GstCollectData *
+gst_collectpads_add_pad (GstCollectPads * pads, GstPad * pad, guint size)
+{
+ GstCollectData *data;
+
+ g_return_val_if_fail (pads != NULL, NULL);
+ g_return_val_if_fail (pad != NULL, NULL);
+ g_return_val_if_fail (GST_PAD_IS_SINK (pad), NULL);
+ g_return_val_if_fail (size >= sizeof (GstCollectData), NULL);
+
+ data = g_malloc0 (size);
+ data->collect = pads;
+ data->pad = pad;
+ data->buffer = NULL;
+
+ GST_LOCK (pads);
+ pads->data = g_slist_append (pads->data, data);
+ gst_pad_set_chain_function (pad, gst_collectpads_chain);
+ gst_pad_set_element_private (pad, data);
+ pads->numpads++;
+ pads->cookie++;
+ GST_UNLOCK (pads);
+
+ return data;
+}
+
+static gint
+find_pad (GstCollectData * data, GstPad * pad)
+{
+ if (data->pad == pad)
+ return 0;
+ return 1;
+}
+
+/**
+ * gst_collectpads_remove_pad:
+ * @pads: the collectspads to use
+ * @pad: the pad to remove
+ *
+ * Remove a pad from the collection of collect pads.
+ *
+ * Returns: TRUE if the pad could be removed.
+ *
+ * MT safe.
+ */
+gboolean
+gst_collectpads_remove_pad (GstCollectPads * pads, GstPad * pad)
+{
+ GSList *list;
+
+ g_return_val_if_fail (pads != NULL, FALSE);
+ g_return_val_if_fail (pad != NULL, FALSE);
+
+ GST_LOCK (pads);
+ list = g_slist_find_custom (pads->data, pad, (GCompareFunc) find_pad);
+ if (list) {
+ g_free (list->data);
+ pads->data = g_slist_delete_link (pads->data, list);
+ }
+ pads->numpads--;
+ pads->cookie++;
+ GST_UNLOCK (pads);
+
+ return list != NULL;
+}
+
+/**
+ * gst_collectpads_is_active:
+ * @pads: the collectspads to use
+ * @pad: the pad to check
+ *
+ * Check if a pad is active.
+ *
+ * Returns: TRUE if the pad is active.
+ *
+ * MT safe.
+ */
+gboolean
+gst_collectpads_is_active (GstCollectPads * pads, GstPad * pad)
+{
+ g_return_val_if_fail (pads != NULL, FALSE);
+ g_return_val_if_fail (pad != NULL, FALSE);
+
+ return FALSE;
+}
+
+/**
+ * gst_collectpads_collect:
+ * @pads: the collectspads to use
+ *
+ * Collect data on all pads. This function is usually called
+ * from a GstTask function in an element.
+ *
+ * Returns: GstFlowReturn of the operation.
+ *
+ * MT safe.
+ */
+GstFlowReturn
+gst_collectpads_collect (GstCollectPads * pads)
+{
+ g_return_val_if_fail (pads != NULL, GST_FLOW_ERROR);
+
+ return GST_FLOW_ERROR;
+}
+
+/**
+ * gst_collectpads_collect_range:
+ * @pads: the collectspads to use
+ * @offset: the offset to collect
+ * @length: the length to collect
+ *
+ * Collect data with @offset and @length on all pads. This function
+ * is typically called in the getrange function of an element.
+ *
+ * Returns: GstFlowReturn of the operation.
+ *
+ * MT safe.
+ */
+GstFlowReturn
+gst_collectpads_collect_range (GstCollectPads * pads, guint64 offset,
+ guint length)
+{
+ g_return_val_if_fail (pads != NULL, GST_FLOW_ERROR);
+
+ return GST_FLOW_ERROR;
+}
+
+/**
+ * gst_collectpads_start:
+ * @pads: the collectspads to use
+ *
+ * Starts the processing of data in the collectpads.
+ *
+ * MT safe.
+ */
+void
+gst_collectpads_start (GstCollectPads * pads)
+{
+ g_return_if_fail (pads != NULL);
+
+ GST_LOCK (pads);
+ pads->started = TRUE;
+ GST_UNLOCK (pads);
+}
+
+/**
+ * gst_collectpads_stop:
+ * @pads: the collectspads to use
+ *
+ * Stops the processing of data in the collectpads. this function
+ * will also unblock any blocking operations.
+ *
+ * MT safe.
+ */
+void
+gst_collectpads_stop (GstCollectPads * pads)
+{
+ g_return_if_fail (pads != NULL);
+
+ GST_LOCK (pads);
+ pads->started = FALSE;
+ GST_COLLECTPADS_SIGNAL (pads);
+ GST_UNLOCK (pads);
+}
+
+/**
+ * gst_collectpads_peek:
+ * @pads: the collectspads to peek
+ * @data: the data to use
+ *
+ * Peek at the buffer currently queued in @data. This function
+ * should be called with the @pads LOCK held, such as in the callback
+ * handler.
+ *
+ * Returns: The buffer in @data or NULL if no buffer is queued. You
+ * should unref the buffer after usage.
+ *
+ * MT safe.
+ */
+GstBuffer *
+gst_collectpads_peek (GstCollectPads * pads, GstCollectData * data)
+{
+ GstBuffer *result;
+
+ result = data->buffer;
+ gst_buffer_ref (result);
+
+ return result;
+}
+
+/**
+ * gst_collectpads_pop:
+ * @pads: the collectspads to pop
+ * @data: the data to use
+ *
+ * Pop the buffer currently queued in @data. This function
+ * should be called with the @pads LOCK held, such as in the callback
+ * handler.
+ *
+ * Returns: The buffer in @data or NULL if no buffer was queued. The
+ * You should unref the buffer after usage.
+ *
+ * MT safe.
+ */
+GstBuffer *
+gst_collectpads_pop (GstCollectPads * pads, GstCollectData * data)
+{
+ GstBuffer *result;
+
+ result = data->buffer;
+ gst_buffer_replace (&data->buffer, NULL);
+ data->pos = 0;
+ pads->queuedpads--;
+
+ GST_COLLECTPADS_SIGNAL (pads);
+
+ return result;
+}
+
+/**
+ * gst_collectpads_available:
+ * @pads: the collectspads to query
+ *
+ * Query how much bytes can be read from each queued buffer. This means
+ * that the result of this call is the maximum number of bytes that can
+ * be read from each of the pads.
+ *
+ * This function should be called with @pads LOCK held, such as
+ * in the callback.
+ *
+ * Returns: The maximum number of bytes queued on all pad. This function
+ * returns 0 if a pad has no queued buffer.
+ *
+ * MT safe.
+ */
+guint
+gst_collectpads_available (GstCollectPads * pads)
+{
+ GSList *collected;
+ guint result = G_MAXUINT;
+
+ for (collected = pads->data; collected; collected = g_slist_next (collected)) {
+ GstCollectData *pdata;
+ gint size;
+
+ pdata = (GstCollectData *) collected->data;
+
+ if (pdata->buffer == NULL)
+ goto not_filled;
+
+ size = GST_BUFFER_SIZE (pdata->buffer) - pdata->pos;
+
+ if (size < result)
+ result = size;
+ }
+ return result;
+
+not_filled:
+ {
+ return 0;
+ }
+}
+
+/**
+ * gst_collectpads_read:
+ * @pads: the collectspads to query
+ * @data: the data to use
+ * @bytes: a pointer to a byte array
+ * @size: the number of bytes to read
+ *
+ * Get a pointer in @bytes where @size bytes can be read from the
+ * given pad data.
+ *
+ * This function should be called with @pads LOCK held, such as
+ * in the callback.
+ *
+ * Returns: The number of bytes available for consumption in the
+ * memory pointed to by @bytes. This can be less than @size and
+ * is 0 if the pad is end-of-stream.
+ *
+ * MT safe.
+ */
+guint
+gst_collectpads_read (GstCollectPads * pads, GstCollectData * data,
+ guint8 ** bytes, guint size)
+{
+ guint readsize;
+
+ readsize = MIN (size, GST_BUFFER_SIZE (data->buffer) - data->pos);
+
+ *bytes = GST_BUFFER_DATA (data->buffer) + data->pos;
+
+ return readsize;
+}
+
+/**
+ * gst_collectpads_flush:
+ * @pads: the collectspads to query
+ * @data: the data to use
+ * @size: the number of bytes to flush
+ *
+ * Flush @size bytes from the pad @data.
+ *
+ * This function should be called with @pads LOCK held, such as
+ * in the callback.
+ *
+ * Returns: The number of bytes flushed This can be less than @size and
+ * is 0 if the pad was end-of-stream.
+ *
+ * MT safe.
+ */
+guint
+gst_collectpads_flush (GstCollectPads * pads, GstCollectData * data, guint size)
+{
+ guint flushsize;
+
+ flushsize = MIN (size, GST_BUFFER_SIZE (data->buffer) - data->pos);
+
+ data->pos += size;
+
+ if (data->pos >= GST_BUFFER_SIZE (data->buffer)) {
+ GstBuffer *buf;
+
+ buf = gst_collectpads_pop (pads, data);
+ gst_buffer_unref (buf);
+ }
+
+ return flushsize;
+}
+
+static GstFlowReturn
+gst_collectpads_chain (GstPad * pad, GstBuffer * buffer)
+{
+ GstCollectData *data;
+ GstCollectPads *pads;
+ guint64 size;
+ GstFlowReturn ret;
+
+ GST_DEBUG ("chain");
+
+ /* some magic to get the managing collectpads */
+ data = (GstCollectData *) gst_pad_get_element_private (pad);
+ if (data == NULL)
+ goto not_ours;
+
+ pads = data->collect;
+ size = GST_BUFFER_SIZE (buffer);
+
+ GST_LOCK (pads);
+
+ /* if not started, bail out */
+ if (!pads->started)
+ goto not_started;
+
+ /* queue buffer on this pad, block if filled */
+ while (data->buffer != NULL) {
+ GST_COLLECTPADS_WAIT (pads);
+ /* after a signal, we could be stopped */
+ if (!pads->started)
+ goto not_started;
+ }
+ pads->queuedpads++;
+ gst_buffer_replace (&data->buffer, buffer);
+
+ /* if all pads have data and we have a function, call it */
+ if ((pads->queuedpads == pads->numpads) && pads->func) {
+ ret = pads->func (pads, pads->user_data);
+ } else {
+ ret = GST_FLOW_OK;
+ }
+ GST_UNLOCK (pads);
+
+ return ret;
+
+ /* ERRORS */
+not_ours:
+ {
+ GST_DEBUG ("collectpads not ours");
+ return GST_FLOW_ERROR;
+ }
+not_started:
+ {
+ GST_UNLOCK (pads);
+ GST_DEBUG ("collectpads not started");
+ return GST_FLOW_WRONG_STATE;
+ }
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstcollectpads.h:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_COLLECTPADS_H__
+#define __GST_COLLECTPADS_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_COLLECTPADS (gst_collectpads_get_type())
+#define GST_COLLECTPADS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COLLECTPADS,GstCollectPads))
+#define GST_COLLECTPADS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_COLLECTPADS,GstCollectPadsClass))
+#define GST_COLLECTPADS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_COLLECTPADS, GstCollectPadsClass))
+#define GST_IS_COLLECTPADS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COLLECTPADS))
+#define GST_IS_COLLECTPADS_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COLLECTPADS))
+
+/* manages a set of pads that operate in collect mode. This means
+ * that control is given to the manager of this object when all
+ * pads have data.
+ *
+ * - pads are added to the collection with add/remove_pad. The pad
+ * has to be a sinkpad. The chain function of the pad is
+ * overridden. The element_private of the pad is used to store
+ * private information.
+ * - For each pad, data is queued in the chain function or by
+ * performing a pull_range.
+ * - When data is queued on all pads, a callback function is
+ * called.
+ * - Data can be dequeued from the pad with the _pop() method.
+ * One can _peek() at the data with the peek function.
+ * - Data can also be dequeued with the available/read/flush
+ * calls.
+ */
+
+typedef struct _GstCollectPads GstCollectPads;
+typedef struct _GstCollectPadsClass GstCollectPadsClass;
+
+typedef struct _GstCollectData
+{
+ GstCollectPads *collect;
+ GstPad *pad;
+ GstBuffer *buffer;
+ guint pos;
+ gboolean eos;
+} GstCollectData;
+
+/* function will be called when all pads have data */
+typedef GstFlowReturn (*GstCollectPadsFunction) (GstCollectPads *pads, gpointer user_data);
+
+#define GST_COLLECTPADS_GET_COND(pads) (((GstCollectPads *)pads)->cond)
+#define GST_COLLECTPADS_WAIT(pads) (g_cond_wait (GST_COLLECTPADS_GET_COND (pads), GST_GET_LOCK (pads)))
+#define GST_COLLECTPADS_SIGNAL(pads) (g_cond_signal (GST_COLLECTPADS_GET_COND (pads)))
+#define GST_COLLECTPADS_BROADCAST(pads)(g_cond_broadcast (GST_COLLECTPADS_GET_COND (pads)))
+
+struct _GstCollectPads {
+ GstObject object;
+
+ /*< public >*/ /* with LOCK */
+ GSList *data; /* GstCollectData in this collection */
+ guint32 cookie;
+
+ GCond *cond; /* to signal removal of data */
+
+ /*< private >*/
+ GstCollectPadsFunction func; /* function and user_data for callback */
+ gpointer user_data;
+
+ guint numpads; /* number of pads */
+ guint queuedpads; /* number of pads with a buffer */
+
+ gboolean started;
+};
+
+struct _GstCollectPadsClass {
+ GstObjectClass parent_class;
+
+};
+
+GType gst_collectpads_get_type(void);
+
+/* creating the object */
+GstCollectPads* gst_collectpads_new (void);
+
+/* set the callback */
+void gst_collectpads_set_function (GstCollectPads *pads, GstCollectPadsFunction func,
+ gpointer user_data);
+
+/* pad management */
+GstCollectData* gst_collectpads_add_pad (GstCollectPads *pads, GstPad *pad, guint size);
+gboolean gst_collectpads_remove_pad (GstCollectPads *pads, GstPad *pad);
+gboolean gst_collectpads_is_active (GstCollectPads *pads, GstPad *pad);
+
+/* start/stop collection */
+GstFlowReturn gst_collectpads_collect (GstCollectPads *pads);
+GstFlowReturn gst_collectpads_collect_range (GstCollectPads *pads, guint64 offset, guint length);
+
+void gst_collectpads_start (GstCollectPads *pads);
+void gst_collectpads_stop (GstCollectPads *pads);
+
+/* get collected buffers */
+GstBuffer* gst_collectpads_peek (GstCollectPads *pads, GstCollectData *data);
+GstBuffer* gst_collectpads_pop (GstCollectPads *pads, GstCollectData *data);
+
+/* get collected bytes */
+guint gst_collectpads_available (GstCollectPads *pads);
+guint gst_collectpads_read (GstCollectPads *pads, GstCollectData *data,
+ guint8 **bytes, guint size);
+guint gst_collectpads_flush (GstCollectPads *pads, GstCollectData *data,
+ guint size);
+
+G_END_DECLS
+
+#endif /* __GST_COLLECTPADS_H__ */
gstcapsfilter.c \
gstfakesrc.c \
gstfakesink.c \
+ gstfilesink.c \
gstfilesrc.c \
gstidentity.c \
gstelements.c \
EXTRA_DIST = \
gstaggregator.c \
gstcapsfilter.c \
- gstfilesink.c \
gstfdsink.c \
gstfdsrc.c \
gstmd5sink.c \
{"identity", GST_RANK_NONE, gst_identity_get_type},
// {"fdsink", GST_RANK_NONE, gst_fdsink_get_type},
// {"fdsrc", GST_RANK_NONE, gst_fdsrc_get_type},
-// {"filesink", GST_RANK_NONE, gst_filesink_get_type},
+ {"filesink", GST_RANK_NONE, gst_filesink_get_type},
// {"md5sink", GST_RANK_NONE, gst_md5sink_get_type},
#ifndef HAVE_WIN32
// {"multifilesrc", GST_RANK_NONE, gst_multifilesrc_get_type},
GstBuffer * buffer);
static GstFlowReturn gst_fakesink_render (GstBaseSink * bsink,
GstBuffer * buffer);
-static void gst_fakesink_event (GstBaseSink * bsink, GstEvent * event);
+static gboolean gst_fakesink_event (GstBaseSink * bsink, GstEvent * event);
static void gst_fakesink_get_times (GstBaseSink * bsink, GstBuffer * buffer,
GstClockTime * start, GstClockTime * end);
}
}
-static void
+static gboolean
gst_fakesink_event (GstBaseSink * bsink, GstEvent * event)
{
GstFakeSink *sink = GST_FAKESINK (bsink);
g_object_notify (G_OBJECT (sink), "last_message");
}
+
+ return TRUE;
}
static GstFlowReturn
static gboolean gst_filesink_open_file (GstFileSink * sink);
static void gst_filesink_close_file (GstFileSink * sink);
-static gboolean gst_filesink_handle_event (GstPad * pad, GstEvent * event);
+static gboolean gst_filesink_event (GstBaseSink * sink, GstEvent * event);
+static GstFlowReturn gst_filesink_render (GstBaseSink * sink,
+ GstBuffer * buffer);
+
static gboolean gst_filesink_pad_query (GstPad * pad, GstQueryType type,
GstFormat * format, gint64 * value);
-static void gst_filesink_chain (GstPad * pad, GstData * _data);
static void gst_filesink_uri_handler_init (gpointer g_iface,
gpointer iface_data);
static GstElementStateReturn gst_filesink_change_state (GstElement * element);
-static guint gst_filesink_signals[LAST_SIGNAL] = { 0 };
+//static guint gst_filesink_signals[LAST_SIGNAL] = { 0 };
static void
_do_init (GType filesink_type)
"filesink element");
}
-GST_BOILERPLATE_FULL (GstFileSink, gst_filesink, GstElement, GST_TYPE_ELEMENT,
+GST_BOILERPLATE_FULL (GstFileSink, gst_filesink, GstBaseSink, GST_TYPE_BASESINK,
_do_init);
-
static void
gst_filesink_base_init (gpointer g_class)
{
gst_filesink_class_init (GstFileSinkClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstBaseSinkClass *gstbasesink_class = GST_BASESINK_CLASS (klass);
gobject_class->set_property = gst_filesink_set_property;
gobject_class->get_property = gst_filesink_get_property;
g_param_spec_string ("location", "File Location",
"Location of the file to write", NULL, G_PARAM_READWRITE));
- gst_filesink_signals[SIGNAL_HANDOFF] =
- g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GstFileSinkClass, handoff), NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
gobject_class->dispose = gst_filesink_dispose;
+
+ gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_filesink_render);
+ gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_filesink_event);
}
static void
gst_filesink_init (GstFileSink * filesink)
{
GstPad *pad;
- pad =
- gst_pad_new_from_template (gst_static_pad_template_get (&sinktemplate),
- "sink");
- gst_element_add_pad (GST_ELEMENT (filesink), pad);
- gst_pad_set_chain_function (pad, gst_filesink_chain);
-
- GST_FLAG_SET (GST_ELEMENT (filesink), GST_ELEMENT_EVENT_AWARE);
+ pad = GST_BASESINK_PAD (filesink);
gst_pad_set_query_function (pad, gst_filesink_pad_query);
gst_pad_set_query_type_function (pad, gst_filesink_get_query_types);
gst_filesink_set_location (GstFileSink * sink, const gchar * location)
{
/* the element must be stopped or paused in order to do this */
- if (GST_STATE (sink) > GST_STATE_PAUSED)
- return FALSE;
- if (GST_STATE (sink) == GST_STATE_PAUSED &&
- GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN))
+ if (GST_STATE (sink) >= GST_STATE_PAUSED)
return FALSE;
g_free (sink->filename);
sink->uri = NULL;
}
- if (GST_STATE (sink) == GST_STATE_PAUSED)
- gst_filesink_open_file (sink);
-
return TRUE;
}
static void
static gboolean
gst_filesink_open_file (GstFileSink * sink)
{
- g_return_val_if_fail (!GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN), FALSE);
-
/* open the file */
if (sink->filename == NULL || sink->filename[0] == '\0') {
GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND,
return FALSE;
}
- GST_FLAG_SET (sink, GST_FILESINK_OPEN);
-
sink->data_written = 0;
return TRUE;
static void
gst_filesink_close_file (GstFileSink * sink)
{
- g_return_if_fail (GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN));
-
if (fclose (sink->file) != 0) {
GST_ELEMENT_ERROR (sink, RESOURCE, CLOSE,
(_("Error closing file \"%s\"."), sink->filename), GST_ERROR_SYSTEM);
- } else {
- GST_FLAG_UNSET (sink, GST_FILESINK_OPEN);
}
}
case GST_QUERY_TOTAL:
switch (*format) {
case GST_FORMAT_BYTES:
- if (GST_FLAG_IS_SET (GST_ELEMENT (sink), GST_FILESINK_OPEN)) {
- *value = sink->data_written; /* FIXME - doesn't the kernel provide
- such a function? */
- break;
- }
+ *value = sink->data_written; /* FIXME - doesn't the kernel provide
+ such a function? */
+ break;
default:
return FALSE;
}
case GST_QUERY_POSITION:
switch (*format) {
case GST_FORMAT_BYTES:
- if (GST_FLAG_IS_SET (GST_ELEMENT (sink), GST_FILESINK_OPEN)) {
- *value = ftell (sink->file);
- break;
- }
+ *value = ftell (sink->file);
+ break;
default:
return FALSE;
}
/* handle events (search) */
static gboolean
-gst_filesink_handle_event (GstPad * pad, GstEvent * event)
+gst_filesink_event (GstBaseSink * sink, GstEvent * event)
{
GstEventType type;
GstFileSink *filesink;
- filesink = GST_FILESINK (gst_pad_get_parent (pad));
-
- if (!(GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN))) {
- gst_event_unref (event);
- return FALSE;
- }
+ filesink = GST_FILESINK (sink);
type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
switch (type) {
case GST_EVENT_SEEK:
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
- gst_event_unref (event);
return FALSE;
}
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
if (fflush (filesink->file)) {
- gst_event_unref (event);
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
(_("Error while writing to file \"%s\"."), filesink->filename),
GST_ERROR_SYSTEM);
g_warning ("unknown seek method!");
break;
}
- gst_event_unref (event);
break;
case GST_EVENT_DISCONTINUOUS:
{
- gint64 offset;
-
- if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &offset))
- fseek (filesink->file, offset, SEEK_SET);
+ gint64 soffset, eoffset;
- gst_event_unref (event);
+ if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &soffset,
+ &eoffset))
+ fseek (filesink->file, soffset, SEEK_SET);
break;
}
case GST_EVENT_FLUSH:
if (fflush (filesink->file)) {
- gst_event_unref (event);
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
(_("Error while writing to file \"%s\"."), filesink->filename),
GST_ERROR_SYSTEM);
}
break;
- case GST_EVENT_EOS:
- gst_event_unref (event);
- gst_filesink_close_file (filesink);
- gst_element_set_eos (GST_ELEMENT (filesink));
- break;
default:
- gst_pad_event_default (pad, event);
break;
}
*
* take the buffer from the pad and write to file if it's open
*/
-static void
-gst_filesink_chain (GstPad * pad, GstData * _data)
+static GstFlowReturn
+gst_filesink_render (GstBaseSink * sink, GstBuffer * buffer)
{
- GstBuffer *buf = GST_BUFFER (_data);
GstFileSink *filesink;
+ guint bytes_written = 0, back_pending = 0;
+ guint size;
- g_return_if_fail (pad != NULL);
- g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (buf != NULL);
+ size = GST_BUFFER_SIZE (buffer);
- filesink = GST_FILESINK (gst_pad_get_parent (pad));
+ filesink = GST_FILESINK (sink);
- if (GST_IS_EVENT (buf)) {
- gst_filesink_handle_event (pad, GST_EVENT (buf));
- return;
- }
+ if (ftell (filesink->file) < filesink->data_written)
+ back_pending = filesink->data_written - ftell (filesink->file);
- if (GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN)) {
- guint bytes_written = 0, back_pending = 0;
+ while (bytes_written < size) {
+ size_t wrote = fwrite (GST_BUFFER_DATA (buffer) + bytes_written, 1,
+ size - bytes_written, filesink->file);
- if (ftell (filesink->file) < filesink->data_written)
- back_pending = filesink->data_written - ftell (filesink->file);
- while (bytes_written < GST_BUFFER_SIZE (buf)) {
- size_t wrote = fwrite (GST_BUFFER_DATA (buf) + bytes_written, 1,
- GST_BUFFER_SIZE (buf) - bytes_written,
- filesink->file);
-
- if (wrote <= 0) {
- GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
- (_("Error while writing to file \"%s\"."), filesink->filename),
- ("Only %d of %d bytes written: %s",
- bytes_written, GST_BUFFER_SIZE (buf), strerror (errno)));
- break;
- }
- bytes_written += wrote;
+ if (wrote <= 0) {
+ GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
+ (_("Error while writing to file \"%s\"."), filesink->filename),
+ ("Only %d of %d bytes written: %s",
+ bytes_written, size, strerror (errno)));
+ break;
}
-
- filesink->data_written += bytes_written - back_pending;
+ bytes_written += wrote;
}
- gst_buffer_unref (buf);
+ filesink->data_written += bytes_written - back_pending;
- g_signal_emit (G_OBJECT (filesink),
- gst_filesink_signals[SIGNAL_HANDOFF], 0, filesink);
+ return GST_FLOW_OK;
}
static GstElementStateReturn
gst_filesink_change_state (GstElement * element)
{
- g_return_val_if_fail (GST_IS_FILESINK (element), GST_STATE_FAILURE);
+ GstElementStateReturn ret;
+ gint transition;
- switch (GST_STATE_TRANSITION (element)) {
- case GST_STATE_PAUSED_TO_READY:
- if (GST_FLAG_IS_SET (element, GST_FILESINK_OPEN))
- gst_filesink_close_file (GST_FILESINK (element));
- break;
+ transition = GST_STATE_TRANSITION (element);
+ switch (transition) {
+ case GST_STATE_NULL_TO_READY:
+ break;
case GST_STATE_READY_TO_PAUSED:
- if (!GST_FLAG_IS_SET (element, GST_FILESINK_OPEN)) {
- if (!gst_filesink_open_file (GST_FILESINK (element)))
- return GST_STATE_FAILURE;
- }
+ if (!gst_filesink_open_file (GST_FILESINK (element)))
+ goto open_error;
+ break;
+ case GST_STATE_PAUSED_TO_PLAYING:
+ break;
+ default:
break;
}
- if (GST_ELEMENT_CLASS (parent_class)->change_state)
- return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
- return GST_STATE_SUCCESS;
+ switch (transition) {
+ case GST_STATE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_PAUSED_TO_READY:
+ gst_filesink_close_file (GST_FILESINK (element));
+ break;
+ case GST_STATE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+
+open_error:
+ {
+ return GST_STATE_FAILURE;
+ }
}
/*** GSTURIHANDLER INTERFACE *************************************************/
#define __GST_FILESINK_H__
#include <gst/gst.h>
+#include <gst/base/gstbasesink.h>
G_BEGIN_DECLS
-
#define GST_TYPE_FILESINK \
(gst_filesink_get_type())
#define GST_FILESINK(obj) \
typedef struct _GstFileSink GstFileSink;
typedef struct _GstFileSinkClass GstFileSinkClass;
-typedef enum {
- GST_FILESINK_OPEN = GST_ELEMENT_FLAG_LAST,
-
- GST_FILESINK_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2
-} GstFileSinkFlags;
-
struct _GstFileSink {
- GstElement element;
+ GstBaseSink parent;
gchar *filename;
gchar *uri;
};
struct _GstFileSinkClass {
- GstElementClass parent_class;
-
- /* signals */
- void (*handoff) (GstElement *element, GstPad *pad);
+ GstBaseSinkClass parent_class;
};
GType gst_filesink_get_type(void);
gstbasesink.c \
gstbasesrc.c \
gstbasetransform.c \
+ gstcollectpads.c \
gsttypefindhelper.c
libgstbase_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
gstbasesink.h \
gstbasesrc.h \
gstbasetransform.h \
+ gstcollectpads.h \
gsttypefindhelper.h
void (*get_times) (GstBaseSink *sink, GstBuffer *buffer,
GstClockTime *start, GstClockTime *end);
- void (*event) (GstBaseSink *sink, GstEvent *event);
+ gboolean (*event) (GstBaseSink *sink, GstEvent *event);
GstFlowReturn (*preroll) (GstBaseSink *sink, GstBuffer *buffer);
GstFlowReturn (*render) (GstBaseSink *sink, GstBuffer *buffer);
};
basesrc->srcpad = pad;
gst_element_add_pad (GST_ELEMENT (basesrc), pad);
+ basesrc->random_access = TRUE;
basesrc->segment_start = -1;
basesrc->segment_end = -1;
basesrc->blocksize = DEFAULT_BLOCKSIZE;
static void
gst_basesrc_set_dataflow_funcs (GstBaseSrc * this)
{
+ GST_DEBUG ("updating dataflow functions");
+
if (this->has_loop)
gst_pad_set_loop_function (this->srcpad, gst_basesrc_loop);
else
{
gboolean ret;
- /* FIXME-wim: is this cast right? */
ret = gst_basesrc_get_size (src, (guint64 *) value);
GST_DEBUG ("getting length %d %lld", ret, *value);
return ret;
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstcollectpads.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gstcollectpads.h"
+
+static GstFlowReturn gst_collectpads_chain (GstPad * pad, GstBuffer * buffer);
+
+static void gst_collectpads_class_init (GstCollectPadsClass * klass);
+static void gst_collectpads_init (GstCollectPads * pads);
+static void gst_collectpads_finalize (GObject * object);
+
+static GstObjectClass *parent_class = NULL;
+
+GType
+gst_collectpads_get_type (void)
+{
+ static GType collect_type = 0;
+
+ if (!collect_type) {
+ static const GTypeInfo collect_info = {
+ sizeof (GstCollectPadsClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gst_collectpads_class_init,
+ NULL,
+ NULL,
+ sizeof (GstCollectPads),
+ 0,
+ (GInstanceInitFunc) gst_collectpads_init,
+ NULL
+ };
+
+ collect_type = g_type_register_static (GST_TYPE_OBJECT, "GstCollectPads",
+ &collect_info, 0);
+ }
+ return collect_type;
+}
+
+static void
+gst_collectpads_class_init (GstCollectPadsClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstObjectClass *gstobject_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstobject_class = (GstObjectClass *) klass;
+
+ gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_collectpads_finalize);
+
+ parent_class = g_type_class_ref (GST_TYPE_OBJECT);
+}
+
+static void
+gst_collectpads_init (GstCollectPads * pads)
+{
+ pads->cond = g_cond_new ();
+ pads->data = NULL;
+ pads->cookie = 0;
+ pads->numpads = 0;
+ pads->queuedpads = 0;
+ pads->started = FALSE;
+}
+
+static void
+gst_collectpads_finalize (GObject * object)
+{
+ GstCollectPads *pads = GST_COLLECTPADS (object);
+
+ g_cond_free (pads->cond);
+ /* FIXME, free data */
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/**
+ * gst_collectpads_new:
+ *
+ * Create a new instance of #GstCollectsPads.
+ *
+ * Returns: a new #GstCollectPads, or NULL in case of an error.
+ *
+ * MT safe.
+ */
+GstCollectPads *
+gst_collectpads_new (void)
+{
+ GstCollectPads *newcoll;
+
+ newcoll = g_object_new (GST_TYPE_COLLECTPADS, NULL);
+
+ return newcoll;
+}
+
+/**
+ * gst_collectpads_set_function:
+ * @pads: the collectspads to use
+ * @func: the function to set
+ * @user_data: user data passed to the function
+ *
+ * Set the callback function and user data that will be called when
+ * all the pads added to the collection have buffers queued.
+ *
+ * MT safe.
+ */
+void
+gst_collectpads_set_function (GstCollectPads * pads,
+ GstCollectPadsFunction func, gpointer user_data)
+{
+ g_return_if_fail (pads != NULL);
+
+ GST_LOCK (pads);
+ pads->func = func;
+ pads->user_data = user_data;
+ GST_UNLOCK (pads);
+}
+
+/**
+ * gst_collectpads_add_pad:
+ * @pads: the collectspads to use
+ * @pad: the pad to add
+ * @size: the size of the returned GstCollectData structure
+ *
+ * Add a pad to the collection of collect pads. The pad has to be
+ * a sinkpad.
+ *
+ * You specify a size for the returned #GstCollectData structure
+ * so that you can use it to store additional information.
+ *
+ * Returns: a new #GstCollectData to identify the new pad. Or NULL
+ * if wrong parameters are supplied.
+ *
+ * MT safe.
+ */
+GstCollectData *
+gst_collectpads_add_pad (GstCollectPads * pads, GstPad * pad, guint size)
+{
+ GstCollectData *data;
+
+ g_return_val_if_fail (pads != NULL, NULL);
+ g_return_val_if_fail (pad != NULL, NULL);
+ g_return_val_if_fail (GST_PAD_IS_SINK (pad), NULL);
+ g_return_val_if_fail (size >= sizeof (GstCollectData), NULL);
+
+ data = g_malloc0 (size);
+ data->collect = pads;
+ data->pad = pad;
+ data->buffer = NULL;
+
+ GST_LOCK (pads);
+ pads->data = g_slist_append (pads->data, data);
+ gst_pad_set_chain_function (pad, gst_collectpads_chain);
+ gst_pad_set_element_private (pad, data);
+ pads->numpads++;
+ pads->cookie++;
+ GST_UNLOCK (pads);
+
+ return data;
+}
+
+static gint
+find_pad (GstCollectData * data, GstPad * pad)
+{
+ if (data->pad == pad)
+ return 0;
+ return 1;
+}
+
+/**
+ * gst_collectpads_remove_pad:
+ * @pads: the collectspads to use
+ * @pad: the pad to remove
+ *
+ * Remove a pad from the collection of collect pads.
+ *
+ * Returns: TRUE if the pad could be removed.
+ *
+ * MT safe.
+ */
+gboolean
+gst_collectpads_remove_pad (GstCollectPads * pads, GstPad * pad)
+{
+ GSList *list;
+
+ g_return_val_if_fail (pads != NULL, FALSE);
+ g_return_val_if_fail (pad != NULL, FALSE);
+
+ GST_LOCK (pads);
+ list = g_slist_find_custom (pads->data, pad, (GCompareFunc) find_pad);
+ if (list) {
+ g_free (list->data);
+ pads->data = g_slist_delete_link (pads->data, list);
+ }
+ pads->numpads--;
+ pads->cookie++;
+ GST_UNLOCK (pads);
+
+ return list != NULL;
+}
+
+/**
+ * gst_collectpads_is_active:
+ * @pads: the collectspads to use
+ * @pad: the pad to check
+ *
+ * Check if a pad is active.
+ *
+ * Returns: TRUE if the pad is active.
+ *
+ * MT safe.
+ */
+gboolean
+gst_collectpads_is_active (GstCollectPads * pads, GstPad * pad)
+{
+ g_return_val_if_fail (pads != NULL, FALSE);
+ g_return_val_if_fail (pad != NULL, FALSE);
+
+ return FALSE;
+}
+
+/**
+ * gst_collectpads_collect:
+ * @pads: the collectspads to use
+ *
+ * Collect data on all pads. This function is usually called
+ * from a GstTask function in an element.
+ *
+ * Returns: GstFlowReturn of the operation.
+ *
+ * MT safe.
+ */
+GstFlowReturn
+gst_collectpads_collect (GstCollectPads * pads)
+{
+ g_return_val_if_fail (pads != NULL, GST_FLOW_ERROR);
+
+ return GST_FLOW_ERROR;
+}
+
+/**
+ * gst_collectpads_collect_range:
+ * @pads: the collectspads to use
+ * @offset: the offset to collect
+ * @length: the length to collect
+ *
+ * Collect data with @offset and @length on all pads. This function
+ * is typically called in the getrange function of an element.
+ *
+ * Returns: GstFlowReturn of the operation.
+ *
+ * MT safe.
+ */
+GstFlowReturn
+gst_collectpads_collect_range (GstCollectPads * pads, guint64 offset,
+ guint length)
+{
+ g_return_val_if_fail (pads != NULL, GST_FLOW_ERROR);
+
+ return GST_FLOW_ERROR;
+}
+
+/**
+ * gst_collectpads_start:
+ * @pads: the collectspads to use
+ *
+ * Starts the processing of data in the collectpads.
+ *
+ * MT safe.
+ */
+void
+gst_collectpads_start (GstCollectPads * pads)
+{
+ g_return_if_fail (pads != NULL);
+
+ GST_LOCK (pads);
+ pads->started = TRUE;
+ GST_UNLOCK (pads);
+}
+
+/**
+ * gst_collectpads_stop:
+ * @pads: the collectspads to use
+ *
+ * Stops the processing of data in the collectpads. this function
+ * will also unblock any blocking operations.
+ *
+ * MT safe.
+ */
+void
+gst_collectpads_stop (GstCollectPads * pads)
+{
+ g_return_if_fail (pads != NULL);
+
+ GST_LOCK (pads);
+ pads->started = FALSE;
+ GST_COLLECTPADS_SIGNAL (pads);
+ GST_UNLOCK (pads);
+}
+
+/**
+ * gst_collectpads_peek:
+ * @pads: the collectspads to peek
+ * @data: the data to use
+ *
+ * Peek at the buffer currently queued in @data. This function
+ * should be called with the @pads LOCK held, such as in the callback
+ * handler.
+ *
+ * Returns: The buffer in @data or NULL if no buffer is queued. You
+ * should unref the buffer after usage.
+ *
+ * MT safe.
+ */
+GstBuffer *
+gst_collectpads_peek (GstCollectPads * pads, GstCollectData * data)
+{
+ GstBuffer *result;
+
+ result = data->buffer;
+ gst_buffer_ref (result);
+
+ return result;
+}
+
+/**
+ * gst_collectpads_pop:
+ * @pads: the collectspads to pop
+ * @data: the data to use
+ *
+ * Pop the buffer currently queued in @data. This function
+ * should be called with the @pads LOCK held, such as in the callback
+ * handler.
+ *
+ * Returns: The buffer in @data or NULL if no buffer was queued. The
+ * You should unref the buffer after usage.
+ *
+ * MT safe.
+ */
+GstBuffer *
+gst_collectpads_pop (GstCollectPads * pads, GstCollectData * data)
+{
+ GstBuffer *result;
+
+ result = data->buffer;
+ gst_buffer_replace (&data->buffer, NULL);
+ data->pos = 0;
+ pads->queuedpads--;
+
+ GST_COLLECTPADS_SIGNAL (pads);
+
+ return result;
+}
+
+/**
+ * gst_collectpads_available:
+ * @pads: the collectspads to query
+ *
+ * Query how much bytes can be read from each queued buffer. This means
+ * that the result of this call is the maximum number of bytes that can
+ * be read from each of the pads.
+ *
+ * This function should be called with @pads LOCK held, such as
+ * in the callback.
+ *
+ * Returns: The maximum number of bytes queued on all pad. This function
+ * returns 0 if a pad has no queued buffer.
+ *
+ * MT safe.
+ */
+guint
+gst_collectpads_available (GstCollectPads * pads)
+{
+ GSList *collected;
+ guint result = G_MAXUINT;
+
+ for (collected = pads->data; collected; collected = g_slist_next (collected)) {
+ GstCollectData *pdata;
+ gint size;
+
+ pdata = (GstCollectData *) collected->data;
+
+ if (pdata->buffer == NULL)
+ goto not_filled;
+
+ size = GST_BUFFER_SIZE (pdata->buffer) - pdata->pos;
+
+ if (size < result)
+ result = size;
+ }
+ return result;
+
+not_filled:
+ {
+ return 0;
+ }
+}
+
+/**
+ * gst_collectpads_read:
+ * @pads: the collectspads to query
+ * @data: the data to use
+ * @bytes: a pointer to a byte array
+ * @size: the number of bytes to read
+ *
+ * Get a pointer in @bytes where @size bytes can be read from the
+ * given pad data.
+ *
+ * This function should be called with @pads LOCK held, such as
+ * in the callback.
+ *
+ * Returns: The number of bytes available for consumption in the
+ * memory pointed to by @bytes. This can be less than @size and
+ * is 0 if the pad is end-of-stream.
+ *
+ * MT safe.
+ */
+guint
+gst_collectpads_read (GstCollectPads * pads, GstCollectData * data,
+ guint8 ** bytes, guint size)
+{
+ guint readsize;
+
+ readsize = MIN (size, GST_BUFFER_SIZE (data->buffer) - data->pos);
+
+ *bytes = GST_BUFFER_DATA (data->buffer) + data->pos;
+
+ return readsize;
+}
+
+/**
+ * gst_collectpads_flush:
+ * @pads: the collectspads to query
+ * @data: the data to use
+ * @size: the number of bytes to flush
+ *
+ * Flush @size bytes from the pad @data.
+ *
+ * This function should be called with @pads LOCK held, such as
+ * in the callback.
+ *
+ * Returns: The number of bytes flushed This can be less than @size and
+ * is 0 if the pad was end-of-stream.
+ *
+ * MT safe.
+ */
+guint
+gst_collectpads_flush (GstCollectPads * pads, GstCollectData * data, guint size)
+{
+ guint flushsize;
+
+ flushsize = MIN (size, GST_BUFFER_SIZE (data->buffer) - data->pos);
+
+ data->pos += size;
+
+ if (data->pos >= GST_BUFFER_SIZE (data->buffer)) {
+ GstBuffer *buf;
+
+ buf = gst_collectpads_pop (pads, data);
+ gst_buffer_unref (buf);
+ }
+
+ return flushsize;
+}
+
+static GstFlowReturn
+gst_collectpads_chain (GstPad * pad, GstBuffer * buffer)
+{
+ GstCollectData *data;
+ GstCollectPads *pads;
+ guint64 size;
+ GstFlowReturn ret;
+
+ GST_DEBUG ("chain");
+
+ /* some magic to get the managing collectpads */
+ data = (GstCollectData *) gst_pad_get_element_private (pad);
+ if (data == NULL)
+ goto not_ours;
+
+ pads = data->collect;
+ size = GST_BUFFER_SIZE (buffer);
+
+ GST_LOCK (pads);
+
+ /* if not started, bail out */
+ if (!pads->started)
+ goto not_started;
+
+ /* queue buffer on this pad, block if filled */
+ while (data->buffer != NULL) {
+ GST_COLLECTPADS_WAIT (pads);
+ /* after a signal, we could be stopped */
+ if (!pads->started)
+ goto not_started;
+ }
+ pads->queuedpads++;
+ gst_buffer_replace (&data->buffer, buffer);
+
+ /* if all pads have data and we have a function, call it */
+ if ((pads->queuedpads == pads->numpads) && pads->func) {
+ ret = pads->func (pads, pads->user_data);
+ } else {
+ ret = GST_FLOW_OK;
+ }
+ GST_UNLOCK (pads);
+
+ return ret;
+
+ /* ERRORS */
+not_ours:
+ {
+ GST_DEBUG ("collectpads not ours");
+ return GST_FLOW_ERROR;
+ }
+not_started:
+ {
+ GST_UNLOCK (pads);
+ GST_DEBUG ("collectpads not started");
+ return GST_FLOW_WRONG_STATE;
+ }
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstcollectpads.h:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_COLLECTPADS_H__
+#define __GST_COLLECTPADS_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_COLLECTPADS (gst_collectpads_get_type())
+#define GST_COLLECTPADS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COLLECTPADS,GstCollectPads))
+#define GST_COLLECTPADS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_COLLECTPADS,GstCollectPadsClass))
+#define GST_COLLECTPADS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_COLLECTPADS, GstCollectPadsClass))
+#define GST_IS_COLLECTPADS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COLLECTPADS))
+#define GST_IS_COLLECTPADS_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COLLECTPADS))
+
+/* manages a set of pads that operate in collect mode. This means
+ * that control is given to the manager of this object when all
+ * pads have data.
+ *
+ * - pads are added to the collection with add/remove_pad. The pad
+ * has to be a sinkpad. The chain function of the pad is
+ * overridden. The element_private of the pad is used to store
+ * private information.
+ * - For each pad, data is queued in the chain function or by
+ * performing a pull_range.
+ * - When data is queued on all pads, a callback function is
+ * called.
+ * - Data can be dequeued from the pad with the _pop() method.
+ * One can _peek() at the data with the peek function.
+ * - Data can also be dequeued with the available/read/flush
+ * calls.
+ */
+
+typedef struct _GstCollectPads GstCollectPads;
+typedef struct _GstCollectPadsClass GstCollectPadsClass;
+
+typedef struct _GstCollectData
+{
+ GstCollectPads *collect;
+ GstPad *pad;
+ GstBuffer *buffer;
+ guint pos;
+ gboolean eos;
+} GstCollectData;
+
+/* function will be called when all pads have data */
+typedef GstFlowReturn (*GstCollectPadsFunction) (GstCollectPads *pads, gpointer user_data);
+
+#define GST_COLLECTPADS_GET_COND(pads) (((GstCollectPads *)pads)->cond)
+#define GST_COLLECTPADS_WAIT(pads) (g_cond_wait (GST_COLLECTPADS_GET_COND (pads), GST_GET_LOCK (pads)))
+#define GST_COLLECTPADS_SIGNAL(pads) (g_cond_signal (GST_COLLECTPADS_GET_COND (pads)))
+#define GST_COLLECTPADS_BROADCAST(pads)(g_cond_broadcast (GST_COLLECTPADS_GET_COND (pads)))
+
+struct _GstCollectPads {
+ GstObject object;
+
+ /*< public >*/ /* with LOCK */
+ GSList *data; /* GstCollectData in this collection */
+ guint32 cookie;
+
+ GCond *cond; /* to signal removal of data */
+
+ /*< private >*/
+ GstCollectPadsFunction func; /* function and user_data for callback */
+ gpointer user_data;
+
+ guint numpads; /* number of pads */
+ guint queuedpads; /* number of pads with a buffer */
+
+ gboolean started;
+};
+
+struct _GstCollectPadsClass {
+ GstObjectClass parent_class;
+
+};
+
+GType gst_collectpads_get_type(void);
+
+/* creating the object */
+GstCollectPads* gst_collectpads_new (void);
+
+/* set the callback */
+void gst_collectpads_set_function (GstCollectPads *pads, GstCollectPadsFunction func,
+ gpointer user_data);
+
+/* pad management */
+GstCollectData* gst_collectpads_add_pad (GstCollectPads *pads, GstPad *pad, guint size);
+gboolean gst_collectpads_remove_pad (GstCollectPads *pads, GstPad *pad);
+gboolean gst_collectpads_is_active (GstCollectPads *pads, GstPad *pad);
+
+/* start/stop collection */
+GstFlowReturn gst_collectpads_collect (GstCollectPads *pads);
+GstFlowReturn gst_collectpads_collect_range (GstCollectPads *pads, guint64 offset, guint length);
+
+void gst_collectpads_start (GstCollectPads *pads);
+void gst_collectpads_stop (GstCollectPads *pads);
+
+/* get collected buffers */
+GstBuffer* gst_collectpads_peek (GstCollectPads *pads, GstCollectData *data);
+GstBuffer* gst_collectpads_pop (GstCollectPads *pads, GstCollectData *data);
+
+/* get collected bytes */
+guint gst_collectpads_available (GstCollectPads *pads);
+guint gst_collectpads_read (GstCollectPads *pads, GstCollectData *data,
+ guint8 **bytes, guint size);
+guint gst_collectpads_flush (GstCollectPads *pads, GstCollectData *data,
+ guint size);
+
+G_END_DECLS
+
+#endif /* __GST_COLLECTPADS_H__ */
gstcapsfilter.c \
gstfakesrc.c \
gstfakesink.c \
+ gstfilesink.c \
gstfilesrc.c \
gstidentity.c \
gstelements.c \
EXTRA_DIST = \
gstaggregator.c \
gstcapsfilter.c \
- gstfilesink.c \
gstfdsink.c \
gstfdsrc.c \
gstmd5sink.c \
{"identity", GST_RANK_NONE, gst_identity_get_type},
// {"fdsink", GST_RANK_NONE, gst_fdsink_get_type},
// {"fdsrc", GST_RANK_NONE, gst_fdsrc_get_type},
-// {"filesink", GST_RANK_NONE, gst_filesink_get_type},
+ {"filesink", GST_RANK_NONE, gst_filesink_get_type},
// {"md5sink", GST_RANK_NONE, gst_md5sink_get_type},
#ifndef HAVE_WIN32
// {"multifilesrc", GST_RANK_NONE, gst_multifilesrc_get_type},
GstBuffer * buffer);
static GstFlowReturn gst_fakesink_render (GstBaseSink * bsink,
GstBuffer * buffer);
-static void gst_fakesink_event (GstBaseSink * bsink, GstEvent * event);
+static gboolean gst_fakesink_event (GstBaseSink * bsink, GstEvent * event);
static void gst_fakesink_get_times (GstBaseSink * bsink, GstBuffer * buffer,
GstClockTime * start, GstClockTime * end);
}
}
-static void
+static gboolean
gst_fakesink_event (GstBaseSink * bsink, GstEvent * event)
{
GstFakeSink *sink = GST_FAKESINK (bsink);
g_object_notify (G_OBJECT (sink), "last_message");
}
+
+ return TRUE;
}
static GstFlowReturn
static gboolean gst_filesink_open_file (GstFileSink * sink);
static void gst_filesink_close_file (GstFileSink * sink);
-static gboolean gst_filesink_handle_event (GstPad * pad, GstEvent * event);
+static gboolean gst_filesink_event (GstBaseSink * sink, GstEvent * event);
+static GstFlowReturn gst_filesink_render (GstBaseSink * sink,
+ GstBuffer * buffer);
+
static gboolean gst_filesink_pad_query (GstPad * pad, GstQueryType type,
GstFormat * format, gint64 * value);
-static void gst_filesink_chain (GstPad * pad, GstData * _data);
static void gst_filesink_uri_handler_init (gpointer g_iface,
gpointer iface_data);
static GstElementStateReturn gst_filesink_change_state (GstElement * element);
-static guint gst_filesink_signals[LAST_SIGNAL] = { 0 };
+//static guint gst_filesink_signals[LAST_SIGNAL] = { 0 };
static void
_do_init (GType filesink_type)
"filesink element");
}
-GST_BOILERPLATE_FULL (GstFileSink, gst_filesink, GstElement, GST_TYPE_ELEMENT,
+GST_BOILERPLATE_FULL (GstFileSink, gst_filesink, GstBaseSink, GST_TYPE_BASESINK,
_do_init);
-
static void
gst_filesink_base_init (gpointer g_class)
{
gst_filesink_class_init (GstFileSinkClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstBaseSinkClass *gstbasesink_class = GST_BASESINK_CLASS (klass);
gobject_class->set_property = gst_filesink_set_property;
gobject_class->get_property = gst_filesink_get_property;
g_param_spec_string ("location", "File Location",
"Location of the file to write", NULL, G_PARAM_READWRITE));
- gst_filesink_signals[SIGNAL_HANDOFF] =
- g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GstFileSinkClass, handoff), NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
gobject_class->dispose = gst_filesink_dispose;
+
+ gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_filesink_render);
+ gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_filesink_event);
}
static void
gst_filesink_init (GstFileSink * filesink)
{
GstPad *pad;
- pad =
- gst_pad_new_from_template (gst_static_pad_template_get (&sinktemplate),
- "sink");
- gst_element_add_pad (GST_ELEMENT (filesink), pad);
- gst_pad_set_chain_function (pad, gst_filesink_chain);
-
- GST_FLAG_SET (GST_ELEMENT (filesink), GST_ELEMENT_EVENT_AWARE);
+ pad = GST_BASESINK_PAD (filesink);
gst_pad_set_query_function (pad, gst_filesink_pad_query);
gst_pad_set_query_type_function (pad, gst_filesink_get_query_types);
gst_filesink_set_location (GstFileSink * sink, const gchar * location)
{
/* the element must be stopped or paused in order to do this */
- if (GST_STATE (sink) > GST_STATE_PAUSED)
- return FALSE;
- if (GST_STATE (sink) == GST_STATE_PAUSED &&
- GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN))
+ if (GST_STATE (sink) >= GST_STATE_PAUSED)
return FALSE;
g_free (sink->filename);
sink->uri = NULL;
}
- if (GST_STATE (sink) == GST_STATE_PAUSED)
- gst_filesink_open_file (sink);
-
return TRUE;
}
static void
static gboolean
gst_filesink_open_file (GstFileSink * sink)
{
- g_return_val_if_fail (!GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN), FALSE);
-
/* open the file */
if (sink->filename == NULL || sink->filename[0] == '\0') {
GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND,
return FALSE;
}
- GST_FLAG_SET (sink, GST_FILESINK_OPEN);
-
sink->data_written = 0;
return TRUE;
static void
gst_filesink_close_file (GstFileSink * sink)
{
- g_return_if_fail (GST_FLAG_IS_SET (sink, GST_FILESINK_OPEN));
-
if (fclose (sink->file) != 0) {
GST_ELEMENT_ERROR (sink, RESOURCE, CLOSE,
(_("Error closing file \"%s\"."), sink->filename), GST_ERROR_SYSTEM);
- } else {
- GST_FLAG_UNSET (sink, GST_FILESINK_OPEN);
}
}
case GST_QUERY_TOTAL:
switch (*format) {
case GST_FORMAT_BYTES:
- if (GST_FLAG_IS_SET (GST_ELEMENT (sink), GST_FILESINK_OPEN)) {
- *value = sink->data_written; /* FIXME - doesn't the kernel provide
- such a function? */
- break;
- }
+ *value = sink->data_written; /* FIXME - doesn't the kernel provide
+ such a function? */
+ break;
default:
return FALSE;
}
case GST_QUERY_POSITION:
switch (*format) {
case GST_FORMAT_BYTES:
- if (GST_FLAG_IS_SET (GST_ELEMENT (sink), GST_FILESINK_OPEN)) {
- *value = ftell (sink->file);
- break;
- }
+ *value = ftell (sink->file);
+ break;
default:
return FALSE;
}
/* handle events (search) */
static gboolean
-gst_filesink_handle_event (GstPad * pad, GstEvent * event)
+gst_filesink_event (GstBaseSink * sink, GstEvent * event)
{
GstEventType type;
GstFileSink *filesink;
- filesink = GST_FILESINK (gst_pad_get_parent (pad));
-
- if (!(GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN))) {
- gst_event_unref (event);
- return FALSE;
- }
+ filesink = GST_FILESINK (sink);
type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
switch (type) {
case GST_EVENT_SEEK:
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_BYTES) {
- gst_event_unref (event);
return FALSE;
}
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
if (fflush (filesink->file)) {
- gst_event_unref (event);
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
(_("Error while writing to file \"%s\"."), filesink->filename),
GST_ERROR_SYSTEM);
g_warning ("unknown seek method!");
break;
}
- gst_event_unref (event);
break;
case GST_EVENT_DISCONTINUOUS:
{
- gint64 offset;
-
- if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &offset))
- fseek (filesink->file, offset, SEEK_SET);
+ gint64 soffset, eoffset;
- gst_event_unref (event);
+ if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &soffset,
+ &eoffset))
+ fseek (filesink->file, soffset, SEEK_SET);
break;
}
case GST_EVENT_FLUSH:
if (fflush (filesink->file)) {
- gst_event_unref (event);
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
(_("Error while writing to file \"%s\"."), filesink->filename),
GST_ERROR_SYSTEM);
}
break;
- case GST_EVENT_EOS:
- gst_event_unref (event);
- gst_filesink_close_file (filesink);
- gst_element_set_eos (GST_ELEMENT (filesink));
- break;
default:
- gst_pad_event_default (pad, event);
break;
}
*
* take the buffer from the pad and write to file if it's open
*/
-static void
-gst_filesink_chain (GstPad * pad, GstData * _data)
+static GstFlowReturn
+gst_filesink_render (GstBaseSink * sink, GstBuffer * buffer)
{
- GstBuffer *buf = GST_BUFFER (_data);
GstFileSink *filesink;
+ guint bytes_written = 0, back_pending = 0;
+ guint size;
- g_return_if_fail (pad != NULL);
- g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (buf != NULL);
+ size = GST_BUFFER_SIZE (buffer);
- filesink = GST_FILESINK (gst_pad_get_parent (pad));
+ filesink = GST_FILESINK (sink);
- if (GST_IS_EVENT (buf)) {
- gst_filesink_handle_event (pad, GST_EVENT (buf));
- return;
- }
+ if (ftell (filesink->file) < filesink->data_written)
+ back_pending = filesink->data_written - ftell (filesink->file);
- if (GST_FLAG_IS_SET (filesink, GST_FILESINK_OPEN)) {
- guint bytes_written = 0, back_pending = 0;
+ while (bytes_written < size) {
+ size_t wrote = fwrite (GST_BUFFER_DATA (buffer) + bytes_written, 1,
+ size - bytes_written, filesink->file);
- if (ftell (filesink->file) < filesink->data_written)
- back_pending = filesink->data_written - ftell (filesink->file);
- while (bytes_written < GST_BUFFER_SIZE (buf)) {
- size_t wrote = fwrite (GST_BUFFER_DATA (buf) + bytes_written, 1,
- GST_BUFFER_SIZE (buf) - bytes_written,
- filesink->file);
-
- if (wrote <= 0) {
- GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
- (_("Error while writing to file \"%s\"."), filesink->filename),
- ("Only %d of %d bytes written: %s",
- bytes_written, GST_BUFFER_SIZE (buf), strerror (errno)));
- break;
- }
- bytes_written += wrote;
+ if (wrote <= 0) {
+ GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
+ (_("Error while writing to file \"%s\"."), filesink->filename),
+ ("Only %d of %d bytes written: %s",
+ bytes_written, size, strerror (errno)));
+ break;
}
-
- filesink->data_written += bytes_written - back_pending;
+ bytes_written += wrote;
}
- gst_buffer_unref (buf);
+ filesink->data_written += bytes_written - back_pending;
- g_signal_emit (G_OBJECT (filesink),
- gst_filesink_signals[SIGNAL_HANDOFF], 0, filesink);
+ return GST_FLOW_OK;
}
static GstElementStateReturn
gst_filesink_change_state (GstElement * element)
{
- g_return_val_if_fail (GST_IS_FILESINK (element), GST_STATE_FAILURE);
+ GstElementStateReturn ret;
+ gint transition;
- switch (GST_STATE_TRANSITION (element)) {
- case GST_STATE_PAUSED_TO_READY:
- if (GST_FLAG_IS_SET (element, GST_FILESINK_OPEN))
- gst_filesink_close_file (GST_FILESINK (element));
- break;
+ transition = GST_STATE_TRANSITION (element);
+ switch (transition) {
+ case GST_STATE_NULL_TO_READY:
+ break;
case GST_STATE_READY_TO_PAUSED:
- if (!GST_FLAG_IS_SET (element, GST_FILESINK_OPEN)) {
- if (!gst_filesink_open_file (GST_FILESINK (element)))
- return GST_STATE_FAILURE;
- }
+ if (!gst_filesink_open_file (GST_FILESINK (element)))
+ goto open_error;
+ break;
+ case GST_STATE_PAUSED_TO_PLAYING:
+ break;
+ default:
break;
}
- if (GST_ELEMENT_CLASS (parent_class)->change_state)
- return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
- return GST_STATE_SUCCESS;
+ switch (transition) {
+ case GST_STATE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_PAUSED_TO_READY:
+ gst_filesink_close_file (GST_FILESINK (element));
+ break;
+ case GST_STATE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+
+open_error:
+ {
+ return GST_STATE_FAILURE;
+ }
}
/*** GSTURIHANDLER INTERFACE *************************************************/
#define __GST_FILESINK_H__
#include <gst/gst.h>
+#include <gst/base/gstbasesink.h>
G_BEGIN_DECLS
-
#define GST_TYPE_FILESINK \
(gst_filesink_get_type())
#define GST_FILESINK(obj) \
typedef struct _GstFileSink GstFileSink;
typedef struct _GstFileSinkClass GstFileSinkClass;
-typedef enum {
- GST_FILESINK_OPEN = GST_ELEMENT_FLAG_LAST,
-
- GST_FILESINK_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2
-} GstFileSinkFlags;
-
struct _GstFileSink {
- GstElement element;
+ GstBaseSink parent;
gchar *filename;
gchar *uri;
};
struct _GstFileSinkClass {
- GstElementClass parent_class;
-
- /* signals */
- void (*handoff) (GstElement *element, GstPad *pad);
+ GstBaseSinkClass parent_class;
};
GType gst_filesink_get_type(void);