From: Wim Taymans Date: Tue, 5 Apr 2005 08:44:20 +0000 (+0000) Subject: gst/: Made base source class, make fakesrc extend it. X-Git-Tag: RELEASE-0_9_2~575 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8cf38d3d3a3cc186a032e23d41752eed7e68ca87;p=platform%2Fupstream%2Fgstreamer.git gst/: Made base source class, make fakesrc extend it. Original commit message from CVS: * gst/base/Makefile.am: * gst/base/README: * gst/base/gstbasesink.c: (gst_basesink_base_init), (gst_basesink_pad_getcaps), (gst_basesink_pad_setcaps), (gst_basesink_pad_buffer_alloc), (gst_basesink_init), (gst_basesink_do_sync), (gst_basesink_chain_unlocked): * gst/base/gstbasesrc.c: (gst_basesrc_get_type), (gst_basesrc_base_init), (gst_basesrc_class_init), (gst_basesrc_init), (gst_basesrc_get_formats), (gst_basesrc_get_query_types), (gst_basesrc_query), (gst_basesrc_get_event_mask), (gst_basesrc_event_handler), (gst_basesrc_set_property), (gst_basesrc_get_property), (gst_basesrc_get_range_unlocked), (gst_basesrc_get_range), (gst_basesrc_loop), (gst_basesrc_activate), (gst_basesrc_change_state): * gst/base/gstbasesrc.h: * gst/elements/gstfakesrc.c: (gst_fakesrc_base_init), (gst_fakesrc_class_init), (gst_fakesrc_init), (gst_fakesrc_event_handler), (gst_fakesrc_set_property), (gst_fakesrc_get_property), (gst_fakesrc_create): * gst/elements/gstfakesrc.h: * gst/elements/gstfilesrc.c: (gst_filesrc_getrange), (gst_filesrc_open_file), (gst_filesrc_loop), (gst_filesrc_activate), (filesrc_find_peek), (gst_filesrc_type_find): Made base source class, make fakesrc extend it. Add comments to basesink class. Some filesrc cleanup. --- diff --git a/ChangeLog b/ChangeLog index 559bcad..b24208e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2005-04-04 Wim Taymans + + * gst/base/Makefile.am: + * gst/base/README: + * gst/base/gstbasesink.c: (gst_basesink_base_init), + (gst_basesink_pad_getcaps), (gst_basesink_pad_setcaps), + (gst_basesink_pad_buffer_alloc), (gst_basesink_init), + (gst_basesink_do_sync), (gst_basesink_chain_unlocked): + * gst/base/gstbasesrc.c: (gst_basesrc_get_type), + (gst_basesrc_base_init), (gst_basesrc_class_init), + (gst_basesrc_init), (gst_basesrc_get_formats), + (gst_basesrc_get_query_types), (gst_basesrc_query), + (gst_basesrc_get_event_mask), (gst_basesrc_event_handler), + (gst_basesrc_set_property), (gst_basesrc_get_property), + (gst_basesrc_get_range_unlocked), (gst_basesrc_get_range), + (gst_basesrc_loop), (gst_basesrc_activate), + (gst_basesrc_change_state): + * gst/base/gstbasesrc.h: + * gst/elements/gstfakesrc.c: (gst_fakesrc_base_init), + (gst_fakesrc_class_init), (gst_fakesrc_init), + (gst_fakesrc_event_handler), (gst_fakesrc_set_property), + (gst_fakesrc_get_property), (gst_fakesrc_create): + * gst/elements/gstfakesrc.h: + * gst/elements/gstfilesrc.c: (gst_filesrc_getrange), + (gst_filesrc_open_file), (gst_filesrc_loop), + (gst_filesrc_activate), (filesrc_find_peek), + (gst_filesrc_type_find): + Made base source class, make fakesrc extend it. + Add comments to basesink class. + Some filesrc cleanup. + 2005-03-31 David Schleef * gst/gstplugin.c: (gst_plugin_check_file), (gst_plugin_load_file): diff --git a/gst/base/Makefile.am b/gst/base/Makefile.am index 0c790e8..39c382c 100644 --- a/gst/base/Makefile.am +++ b/gst/base/Makefile.am @@ -8,6 +8,7 @@ libgstbase_@GST_MAJORMINOR@_la_DEPENDENCIES = \ ../libgstreamer-@GST_MAJORMINOR@.la libgstbase_@GST_MAJORMINOR@_la_SOURCES = \ gstbasesink.c \ + gstbasesrc.c \ gstbasetransform.c libgstbase_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS) @@ -20,6 +21,7 @@ libgstbase_@GST_MAJORMINOR@includedir = \ libgstbase_@GST_MAJORMINOR@include_HEADERS = \ gstbasesink.h \ + gstbasesrc.h \ gstbasetransform.h install-data-local: as-libtool-install-data-local diff --git a/gst/base/README b/gst/base/README index f9c1583..3384a24 100644 --- a/gst/base/README +++ b/gst/base/README @@ -25,3 +25,11 @@ GstBaseTransform - does flushing - push mode - pull mode if transform can operate on arbitrary data + +GstBaseSrc + + Base class for getrange based source elements + + - one sinkpad + - handles state changes + - pull/push mode diff --git a/gst/base/gstbasesink.c b/gst/base/gstbasesink.c index 88d7d97..49696c6 100644 --- a/gst/base/gstbasesink.c +++ b/gst/base/gstbasesink.c @@ -190,6 +190,7 @@ gst_basesink_pad_setcaps (GstPad * pad, GstCaps * caps) bsink = GST_BASESINK (GST_PAD_PARENT (pad)); bclass = GST_BASESINK_GET_CLASS (bsink); + if (bclass->set_caps) res = bclass->set_caps (bsink, caps); @@ -206,6 +207,7 @@ gst_basesink_pad_buffer_alloc (GstPad * pad, guint64 offset, guint size, bsink = GST_BASESINK (GST_PAD_PARENT (pad)); bclass = GST_BASESINK_GET_CLASS (bsink); + if (bclass->buffer_alloc) buffer = bclass->buffer_alloc (bsink, offset, size, caps); @@ -571,6 +573,9 @@ gst_basesink_event (GstPad * pad, GstEvent * event) return result; } +/* default implementation to calculate the start and end + * timestamps on a buffer, subclasses cna override + */ static void gst_basesink_get_times (GstBaseSink * basesink, GstBuffer * buffer, GstClockTime * start, GstClockTime * end) @@ -587,6 +592,15 @@ gst_basesink_get_times (GstBaseSink * basesink, GstBuffer * buffer, } } +/* perform synchronisation on a buffer + * + * 1) check if we have a clock, if not, do nothing + * 2) calculate the start and end time of the buffer + * 3) create a single shot notification to wait on + * the clock, save the entry so we can unlock it + * 4) wait on the clock, this blocks + * 5) unref the clockid again + */ static void gst_basesink_do_sync (GstBaseSink * basesink, GstBuffer * buffer) { @@ -615,6 +629,7 @@ gst_basesink_do_sync (GstBaseSink * basesink, GstBuffer * buffer) gst_clock_id_unref (basesink->clock_id); basesink->clock_id = NULL; } + /* FIXME, don't mess with end_time here */ basesink->end_time = GST_CLOCK_TIME_NONE; GST_UNLOCK (basesink); @@ -623,6 +638,12 @@ gst_basesink_do_sync (GstBaseSink * basesink, GstBuffer * buffer) } } +/* handle a buffer + * + * 1) first sync on the buffer + * 2) render the buffer + * 3) unref the buffer + */ static inline void gst_basesink_handle_buffer (GstBaseSink * basesink, GstBuffer * buf) { @@ -662,7 +683,7 @@ gst_basesink_chain_unlocked (GstPad * pad, GstBuffer * buf) return GST_FLOW_UNEXPECTED; default: g_assert_not_reached (); - return GST_FLOW_UNEXPECTED; + return GST_FLOW_ERROR; } } @@ -683,6 +704,8 @@ gst_basesink_chain (GstPad * pad, GstBuffer * buf) return result; } +/* FIXME, not all sinks can operate in pull mode + */ static void gst_basesink_loop (GstPad * pad) { diff --git a/gst/base/gstbasesrc.c b/gst/base/gstbasesrc.c new file mode 100644 index 0000000..4d69e99 --- /dev/null +++ b/gst/base/gstbasesrc.c @@ -0,0 +1,423 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstbasesrc.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 +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstbasesrc.h" +#include + +#define DEFAULT_BLOCKSIZE 4096 + +GST_DEBUG_CATEGORY_STATIC (gst_basesrc_debug); +#define GST_CAT_DEFAULT gst_basesrc_debug + +/* BaseSrc signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_BLOCKSIZE, +}; + +static GstElementClass *parent_class = NULL; + +static void gst_basesrc_base_init (gpointer g_class); +static void gst_basesrc_class_init (GstBaseSrcClass * klass); +static void gst_basesrc_init (GstBaseSrc * src, gpointer g_class); + +GType +gst_basesrc_get_type (void) +{ + static GType basesrc_type = 0; + + if (!basesrc_type) { + static const GTypeInfo basesrc_info = { + sizeof (GstBaseSrcClass), + (GBaseInitFunc) gst_basesrc_base_init, + NULL, + (GClassInitFunc) gst_basesrc_class_init, + NULL, + NULL, + sizeof (GstBaseSrc), + 0, + (GInstanceInitFunc) gst_basesrc_init, + }; + + basesrc_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstBaseSrc", &basesrc_info, G_TYPE_FLAG_ABSTRACT); + } + return basesrc_type; +} + +static gboolean gst_basesrc_activate (GstPad * pad, GstActivateMode mode); +static void gst_basesrc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_basesrc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static gboolean gst_basesrc_event_handler (GstPad * pad, GstEvent * event); +static const GstEventMask *gst_basesrc_get_event_mask (GstPad * pad); +static const GstQueryType *gst_basesrc_get_query_types (GstPad * pad); +static gboolean gst_basesrc_query (GstPad * pad, GstQueryType type, + GstFormat * format, gint64 * value); +static const GstFormat *gst_basesrc_get_formats (GstPad * pad); + +static GstElementStateReturn gst_basesrc_change_state (GstElement * element); + +static void gst_basesrc_loop (GstPad * pad); +static GstFlowReturn gst_basesrc_get_range (GstPad * pad, guint64 offset, + guint length, GstBuffer ** buf); + +static void +gst_basesrc_base_init (gpointer g_class) +{ + GST_DEBUG_CATEGORY_INIT (gst_basesrc_debug, "basesrc", 0, "basesrc element"); +} + +static void +gst_basesrc_class_init (GstBaseSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_basesrc_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_basesrc_get_property); + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BLOCKSIZE, + g_param_spec_ulong ("blocksize", "Block size", + "Size in bytes to read per buffer", 1, G_MAXULONG, DEFAULT_BLOCKSIZE, + G_PARAM_READWRITE)); + + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_basesrc_change_state); +} + +static void +gst_basesrc_init (GstBaseSrc * basesrc, gpointer g_class) +{ + GstPad *pad; + GstPadTemplate *pad_template; + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src"); + g_return_if_fail (pad_template != NULL); + + pad = gst_pad_new_from_template (pad_template, "src"); + + gst_pad_set_activate_function (pad, gst_basesrc_activate); + gst_pad_set_event_function (pad, gst_basesrc_event_handler); + gst_pad_set_event_mask_function (pad, gst_basesrc_get_event_mask); + gst_pad_set_query_function (pad, gst_basesrc_query); + gst_pad_set_query_type_function (pad, gst_basesrc_get_query_types); + gst_pad_set_formats_function (pad, gst_basesrc_get_formats); + gst_pad_set_loop_function (pad, gst_basesrc_loop); + gst_pad_set_getrange_function (pad, gst_basesrc_get_range); + gst_element_add_pad (GST_ELEMENT (basesrc), pad); + + basesrc->segment_start = -1; + basesrc->segment_end = -1; + basesrc->blocksize = DEFAULT_BLOCKSIZE; +} + +static const GstFormat * +gst_basesrc_get_formats (GstPad * pad) +{ + static const GstFormat formats[] = { + GST_FORMAT_DEFAULT, + 0, + }; + + return formats; +} + +static const GstQueryType * +gst_basesrc_get_query_types (GstPad * pad) +{ + static const GstQueryType types[] = { + GST_QUERY_TOTAL, + GST_QUERY_POSITION, + GST_QUERY_START, + GST_QUERY_SEGMENT_END, + 0, + }; + + return types; +} + +static gboolean +gst_basesrc_query (GstPad * pad, GstQueryType type, + GstFormat * format, gint64 * value) +{ + GstBaseSrc *src = GST_BASESRC (GST_PAD_PARENT (pad)); + + switch (type) { + case GST_QUERY_START: + *value = src->segment_start; + break; + case GST_QUERY_SEGMENT_END: + *value = src->segment_end; + break; + default: + return FALSE; + } + return TRUE; +} + +static const GstEventMask * +gst_basesrc_get_event_mask (GstPad * pad) +{ + static const GstEventMask masks[] = { + {GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP}, + {GST_EVENT_FLUSH, 0}, + {0, 0}, + }; + + return masks; +} + +static gboolean +gst_basesrc_event_handler (GstPad * pad, GstEvent * event) +{ + GstBaseSrc *src; + + src = GST_BASESRC (GST_PAD_PARENT (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + src->segment_start = GST_EVENT_SEEK_OFFSET (event); + src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event); + src->segment_loop = + GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP; + break; + case GST_EVENT_FLUSH: + break; + default: + break; + } + gst_event_unref (event); + + return TRUE; +} + +static void +gst_basesrc_set_property (GObject * object, guint prop_id, const GValue * value, + GParamSpec * pspec) +{ + GstBaseSrc *src; + + src = GST_BASESRC (object); + + switch (prop_id) { + case ARG_BLOCKSIZE: + src->blocksize = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_basesrc_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstBaseSrc *src; + + src = GST_BASESRC (object); + + switch (prop_id) { + case ARG_BLOCKSIZE: + g_value_set_int (value, src->blocksize); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstFlowReturn +gst_basesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, + GstBuffer ** buf) +{ + GstFlowReturn ret; + GstBaseSrc *src; + GstBaseSrcClass *bclass; + + src = GST_BASESRC (GST_OBJECT_PARENT (pad)); + bclass = GST_BASESRC_GET_CLASS (src); + + if (bclass->create) + ret = bclass->create (src, offset, length, buf); + else + ret = GST_FLOW_ERROR; + + return ret; +} + +static GstFlowReturn +gst_basesrc_get_range (GstPad * pad, guint64 offset, guint length, + GstBuffer ** ret) +{ + GstFlowReturn fret; + + GST_STREAM_LOCK (pad); + + fret = gst_basesrc_get_range_unlocked (pad, offset, length, ret); + + GST_STREAM_UNLOCK (pad); + + return fret; +} + +static void +gst_basesrc_loop (GstPad * pad) +{ + GstBaseSrc *src; + GstBuffer *buf = NULL; + GstFlowReturn ret; + + src = GST_BASESRC (GST_OBJECT_PARENT (pad)); + + GST_STREAM_LOCK (pad); + + ret = + gst_basesrc_get_range_unlocked (pad, src->offset, DEFAULT_BLOCKSIZE, + &buf); + if (ret != GST_FLOW_OK) + goto pause; + + src->offset += GST_BUFFER_SIZE (buf); + + ret = gst_pad_push (pad, buf); + if (ret != GST_FLOW_OK) + goto pause; + + GST_STREAM_UNLOCK (pad); + return; + +pause: + { + gst_task_pause (GST_RPAD_TASK (pad)); + GST_STREAM_UNLOCK (pad); + return; + } +} + +static gboolean +gst_basesrc_activate (GstPad * pad, GstActivateMode mode) +{ + gboolean result = FALSE; + GstBaseSrc *basesrc; + + basesrc = GST_BASESRC (GST_OBJECT_PARENT (pad)); + + switch (mode) { + case GST_ACTIVATE_PUSH: + /* if we have a scheduler we can start the task */ + if (GST_ELEMENT_SCHEDULER (basesrc)) { + GST_STREAM_LOCK (pad); + GST_RPAD_TASK (pad) = + gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (basesrc), + (GstTaskFunction) gst_basesrc_loop, pad); + + gst_task_start (GST_RPAD_TASK (pad)); + GST_STREAM_UNLOCK (pad); + result = TRUE; + } + break; + case GST_ACTIVATE_PULL: + result = TRUE; + break; + case GST_ACTIVATE_NONE: + /* step 1, unblock clock sync (if any) */ + + /* step 2, make sure streaming finishes */ + GST_STREAM_LOCK (pad); + /* step 3, stop the task */ + if (GST_RPAD_TASK (pad)) { + gst_task_stop (GST_RPAD_TASK (pad)); + gst_object_unref (GST_OBJECT (GST_RPAD_TASK (pad))); + GST_RPAD_TASK (pad) = NULL; + } + GST_STREAM_UNLOCK (pad); + + result = TRUE; + break; + } + return result; +} + +static GstElementStateReturn +gst_basesrc_change_state (GstElement * element) +{ + GstBaseSrc *basesrc; + GstElementStateReturn result = GST_STATE_FAILURE; + GstElementState transition; + + basesrc = GST_BASESRC (element); + + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + case GST_STATE_READY_TO_PAUSED: + { + basesrc->offset = 0; + break; + } + case GST_STATE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_PLAYING_TO_PAUSED: + break; + case GST_STATE_PAUSED_TO_READY: + break; + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + + return result; +} diff --git a/gst/base/gstbasesrc.h b/gst/base/gstbasesrc.h new file mode 100644 index 0000000..a2bfe74 --- /dev/null +++ b/gst/base/gstbasesrc.h @@ -0,0 +1,74 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstbasesrc.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_BASESRC_H__ +#define __GST_BASESRC_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_BASESRC (gst_basesrc_get_type()) +#define GST_BASESRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASESRC,GstBaseSrc)) +#define GST_BASESRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASESRC,GstBaseSrcClass)) +#define GST_BASESRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASESRC, GstBaseSrcClass)) +#define GST_IS_BASESRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASESRC)) +#define GST_IS_BASESRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASESRC)) + +typedef struct _GstBaseSrc GstBaseSrc; +typedef struct _GstBaseSrcClass GstBaseSrcClass; + +struct _GstBaseSrc { + GstElement element; + + gint blocksize; + + gint64 segment_start; + gint64 segment_end; + gboolean segment_loop; + + guint64 offset; +}; + +struct _GstBaseSrcClass { + GstElementClass parent_class; + + GstCaps* (*get_caps) (GstBaseSrc *src); + gboolean (*set_caps) (GstBaseSrc *src, GstCaps *caps); + + gboolean (*start) (GstBaseSrc *src); + gboolean (*stop) (GstBaseSrc *src); + + void (*get_times) (GstBaseSrc *src, GstBuffer *buffer, + GstClockTime *start, GstClockTime *end); + + gboolean (*event) (GstBaseSrc *src, GstEvent *event); + GstFlowReturn (*create) (GstBaseSrc *src, guint64 offset, guint size, + GstBuffer **buf); +}; + +GType gst_basesrc_get_type(void); + +G_END_DECLS + +#endif /* __GST_BASESRC_H__ */ diff --git a/gst/elements/gstfakesrc.c b/gst/elements/gstfakesrc.c index cb5f7dc..3be5c0b 100644 --- a/gst/elements/gstfakesrc.c +++ b/gst/elements/gstfakesrc.c @@ -64,8 +64,6 @@ enum { ARG_0, ARG_NUM_SOURCES, - ARG_HAS_LOOP, - ARG_HAS_GETRANGE, ARG_OUTPUT, ARG_DATA, ARG_SIZETYPE, @@ -84,11 +82,6 @@ enum ARG_LAST_MESSAGE }; -GstStaticPadTemplate fakesrc_src_template = GST_STATIC_PAD_TEMPLATE ("src%d", - GST_PAD_SRC, - GST_PAD_REQUEST, - GST_STATIC_CAPS_ANY); - #define GST_TYPE_FAKESRC_OUTPUT (gst_fakesrc_output_get_type()) static GType gst_fakesrc_output_get_type (void) @@ -175,22 +168,18 @@ gst_fakesrc_filltype_get_type (void) #define _do_init(bla) \ GST_DEBUG_CATEGORY_INIT (gst_fakesrc_debug, "fakesrc", 0, "fakesrc element"); -GST_BOILERPLATE_FULL (GstFakeSrc, gst_fakesrc, GstElement, GST_TYPE_ELEMENT, +GST_BOILERPLATE_FULL (GstFakeSrc, gst_fakesrc, GstBaseSrc, GST_TYPE_BASESRC, _do_init); -static GstPad *gst_fakesrc_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * unused); -static gboolean gst_fakesrc_activate (GstPad * pad, GstActivateMode mode); static void gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static void gst_fakesrc_set_clock (GstElement * element, GstClock * clock); static GstElementStateReturn gst_fakesrc_change_state (GstElement * element); -static void gst_fakesrc_loop (GstPad * pad); -static GstFlowReturn gst_fakesrc_get_range (GstPad * pad, guint64 offset, +static gboolean gst_fakesrc_event_handler (GstBaseSrc * src, GstEvent * event); +static GstFlowReturn gst_fakesrc_create (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buf); static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 }; @@ -202,9 +191,8 @@ gst_fakesrc_base_init (gpointer g_class) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&srctemplate)); + gst_element_class_set_details (gstelement_class, &gst_fakesrc_details); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&fakesrc_src_template)); } static void @@ -212,9 +200,11 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseSrcClass *gstbasesrc_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasesrc_class = (GstBaseSrcClass *) klass; gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property); @@ -222,14 +212,6 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES, g_param_spec_int ("num-sources", "num-sources", "Number of sources", 1, G_MAXINT, 1, G_PARAM_READABLE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_LOOP, - g_param_spec_boolean ("has-loop", "has-loop", - "Enable loop-based operation", TRUE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_GETRANGE, - g_param_spec_boolean ("has-getrange", "has-getrange", - "Enable getrange-based operation", TRUE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_OUTPUT, g_param_spec_enum ("output", "output", "Output method (currently unused)", GST_TYPE_FAKESRC_OUTPUT, FAKESRC_FIRST_LAST_LOOP, G_PARAM_READWRITE)); @@ -287,26 +269,18 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) gst_fakesrc_signals[SIGNAL_HANDOFF] = g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL, - gst_marshal_VOID__BOXED_OBJECT, G_TYPE_NONE, 2, - GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD); + gst_marshal_VOID__BOXED_OBJECT, G_TYPE_NONE, 1, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE); - gstelement_class->request_new_pad = - GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state); - gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_fakesrc_set_clock); + + gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_fakesrc_event_handler); + gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_fakesrc_create); } static void gst_fakesrc_init (GstFakeSrc * fakesrc) { - GstPad *pad; - - /* create our first output pad */ - pad = - gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate), - "src"); - gst_element_add_pad (GST_ELEMENT (fakesrc), pad); - fakesrc->output = FAKESRC_FIRST_LAST_LOOP; fakesrc->segment_start = -1; fakesrc->segment_end = -1; @@ -331,84 +305,12 @@ gst_fakesrc_init (GstFakeSrc * fakesrc) fakesrc->pad_mode = GST_ACTIVATE_NONE; } -static void -gst_fakesrc_set_clock (GstElement * element, GstClock * clock) -{ - GstFakeSrc *src; - - src = GST_FAKESRC (element); - - src->clock = clock; -} - -static const GstFormat * -gst_fakesrc_get_formats (GstPad * pad) -{ - static const GstFormat formats[] = { - GST_FORMAT_DEFAULT, - 0, - }; - - return formats; -} - -static const GstQueryType * -gst_fakesrc_get_query_types (GstPad * pad) -{ - static const GstQueryType types[] = { - GST_QUERY_TOTAL, - GST_QUERY_POSITION, - GST_QUERY_START, - GST_QUERY_SEGMENT_END, - 0, - }; - - return types; -} - -static gboolean -gst_fakesrc_query (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value) -{ - GstFakeSrc *src = GST_FAKESRC (GST_PAD_PARENT (pad)); - - switch (type) { - case GST_QUERY_TOTAL: - *value = src->num_buffers; - break; - case GST_QUERY_POSITION: - *value = src->buffer_count; - break; - case GST_QUERY_START: - *value = src->segment_start; - break; - case GST_QUERY_SEGMENT_END: - *value = src->segment_end; - break; - default: - return FALSE; - } - return TRUE; -} - -static const GstEventMask * -gst_fakesrc_get_event_mask (GstPad * pad) -{ - static const GstEventMask masks[] = { - {GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP}, - {GST_EVENT_FLUSH, 0}, - {0, 0}, - }; - - return masks; -} - static gboolean -gst_fakesrc_event_handler (GstPad * pad, GstEvent * event) +gst_fakesrc_event_handler (GstBaseSrc * basesrc, GstEvent * event) { GstFakeSrc *src; - src = GST_FAKESRC (GST_PAD_PARENT (pad)); + src = GST_FAKESRC (basesrc); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: @@ -431,64 +333,6 @@ gst_fakesrc_event_handler (GstPad * pad, GstEvent * event) } static void -gst_fakesrc_set_pad_functions (GstFakeSrc * src, GstPad * pad) -{ - gst_pad_set_activate_function (pad, gst_fakesrc_activate); - gst_pad_set_event_function (pad, gst_fakesrc_event_handler); - gst_pad_set_event_mask_function (pad, gst_fakesrc_get_event_mask); - gst_pad_set_query_function (pad, gst_fakesrc_query); - gst_pad_set_query_type_function (pad, gst_fakesrc_get_query_types); - gst_pad_set_formats_function (pad, gst_fakesrc_get_formats); - - if (src->has_loop) - gst_pad_set_loop_function (pad, gst_fakesrc_loop); - else - gst_pad_set_loop_function (pad, NULL); - - if (src->has_getrange) - gst_pad_set_getrange_function (pad, gst_fakesrc_get_range); - else - gst_pad_set_getrange_function (pad, NULL); -} - -static void -gst_fakesrc_set_all_pad_functions (GstFakeSrc * src) -{ - GList *l; - - for (l = GST_ELEMENT_PADS (src); l; l = l->next) - gst_fakesrc_set_pad_functions (src, (GstPad *) l->data); -} - -static GstPad * -gst_fakesrc_request_new_pad (GstElement * element, GstPadTemplate * templ, - const gchar * unused) -{ - gchar *name; - GstPad *srcpad; - GstFakeSrc *fakesrc; - - g_return_val_if_fail (GST_IS_FAKESRC (element), NULL); - - if (templ->direction != GST_PAD_SRC) { - g_warning ("gstfakesrc: request new pad that is not a SRC pad\n"); - return NULL; - } - - fakesrc = GST_FAKESRC (element); - - name = g_strdup_printf ("src%d", GST_ELEMENT (fakesrc)->numsrcpads); - - srcpad = gst_pad_new_from_template (templ, name); - gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad); - gst_fakesrc_set_pad_functions (fakesrc, srcpad); - - g_free (name); - - return srcpad; -} - -static void gst_fakesrc_alloc_parent (GstFakeSrc * src) { GstBuffer *buf; @@ -510,14 +354,6 @@ gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value, src = GST_FAKESRC (object); switch (prop_id) { - case ARG_HAS_LOOP: - src->has_loop = g_value_get_boolean (value); - gst_fakesrc_set_all_pad_functions (src); - break; - case ARG_HAS_GETRANGE: - src->has_getrange = g_value_get_boolean (value); - gst_fakesrc_set_all_pad_functions (src); - break; case ARG_OUTPUT: g_warning ("not yet implemented"); break; @@ -594,12 +430,6 @@ gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value, case ARG_NUM_SOURCES: g_value_set_int (value, GST_ELEMENT (src)->numsrcpads); break; - case ARG_HAS_LOOP: - g_value_set_boolean (value, src->has_loop); - break; - case ARG_HAS_GETRANGE: - g_value_set_boolean (value, src->has_getrange); - break; case ARG_OUTPUT: g_value_set_enum (value, src->output); break; @@ -792,26 +622,20 @@ gst_fakesrc_create_buffer (GstFakeSrc * src) } static GstFlowReturn -gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, +gst_fakesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** ret) { GstFakeSrc *src; GstBuffer *buf; GstClockTime time; - src = GST_FAKESRC (GST_OBJECT_PARENT (pad)); + src = GST_FAKESRC (basesrc); if (src->buffer_count == src->segment_end) { - if (src->segment_loop) { - //gst_pad_push_event (pad, gst_event_new (GST_EVENT_SEGMENT_DONE)); - } else { - gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); - return GST_FLOW_UNEXPECTED; - } + return GST_FLOW_UNEXPECTED; } if (src->rt_num_buffers == 0) { - gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); return GST_FLOW_UNEXPECTED; } else { if (src->rt_num_buffers > 0) @@ -820,7 +644,6 @@ gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, if (src->eos) { GST_INFO ("fakesrc is setting eos on pad"); - gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); return GST_FLOW_UNEXPECTED; } @@ -844,8 +667,8 @@ gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, g_free (src->last_message); src->last_message = - g_strdup_printf ("get ******* (%s:%s)> (%d bytes, %" - G_GUINT64_FORMAT " ) %p", GST_DEBUG_PAD_NAME (pad), + g_strdup_printf ("get ******* > (%d bytes, %" + G_GUINT64_FORMAT " ) %p", GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf); g_object_notify (G_OBJECT (src), "last_message"); @@ -853,8 +676,7 @@ gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, if (src->signal_handoffs) { GST_LOG_OBJECT (src, "pre handoff emit"); - g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0, - buf, pad); + g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0, buf); GST_LOG_OBJECT (src, "post handoff emit"); } @@ -864,110 +686,6 @@ gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, return GST_FLOW_OK; } -static GstFlowReturn -gst_fakesrc_get_range (GstPad * pad, guint64 offset, guint length, - GstBuffer ** ret) -{ - GstFlowReturn fret; - - g_assert (GST_FAKESRC (GST_OBJECT_PARENT (pad))->pad_mode == - GST_ACTIVATE_PULL); - - GST_STREAM_LOCK (pad); - - fret = gst_fakesrc_get_range_unlocked (pad, offset, length, ret); - - GST_STREAM_UNLOCK (pad); - - return fret; -} - -static void -gst_fakesrc_loop (GstPad * pad) -{ - GstFakeSrc *src; - GstBuffer *buf = NULL; - GstFlowReturn ret; - - src = GST_FAKESRC (GST_OBJECT_PARENT (pad)); - - g_assert (src->pad_mode == GST_ACTIVATE_PUSH); - - GST_STREAM_LOCK (pad); - if (src->need_flush) { - src->need_flush = FALSE; - gst_pad_push_event (pad, gst_event_new (GST_EVENT_FLUSH)); - } - - ret = gst_fakesrc_get_range_unlocked (pad, src->buffer_count, - DEFAULT_SIZEMAX, &buf); - if (ret != GST_FLOW_OK) { - goto pause; - } - - ret = gst_pad_push (pad, buf); - if (ret != GST_FLOW_OK) { - goto pause; - } - - GST_STREAM_UNLOCK (pad); - return; - -pause: - gst_task_pause (GST_RPAD_TASK (pad)); - GST_STREAM_UNLOCK (pad); - return; -} - -static gboolean -gst_fakesrc_activate (GstPad * pad, GstActivateMode mode) -{ - gboolean result = FALSE; - GstFakeSrc *fakesrc; - - fakesrc = GST_FAKESRC (GST_OBJECT_PARENT (pad)); - - switch (mode) { - case GST_ACTIVATE_PUSH: - /* if we have a scheduler we can start the task */ - g_return_val_if_fail (fakesrc->has_loop, FALSE); - if (GST_ELEMENT_SCHEDULER (fakesrc)) { - GST_STREAM_LOCK (pad); - GST_RPAD_TASK (pad) = - gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (fakesrc), - (GstTaskFunction) gst_fakesrc_loop, pad); - - gst_task_start (GST_RPAD_TASK (pad)); - GST_STREAM_UNLOCK (pad); - result = TRUE; - } - break; - case GST_ACTIVATE_PULL: - g_return_val_if_fail (fakesrc->has_getrange, FALSE); - result = TRUE; - break; - case GST_ACTIVATE_NONE: - /* step 1, unblock clock sync (if any) */ - - /* step 2, make sure streaming finishes */ - GST_STREAM_LOCK (pad); - /* step 3, stop the task */ - if (GST_RPAD_TASK (pad)) { - gst_task_stop (GST_RPAD_TASK (pad)); - gst_object_unref (GST_OBJECT (GST_RPAD_TASK (pad))); - GST_RPAD_TASK (pad) = NULL; - } - GST_STREAM_UNLOCK (pad); - - result = TRUE; - break; - } - - fakesrc->pad_mode = mode; - - return result; -} - static GstElementStateReturn gst_fakesrc_change_state (GstElement * element) { diff --git a/gst/elements/gstfakesrc.h b/gst/elements/gstfakesrc.h index a5251b8..3cda131 100644 --- a/gst/elements/gstfakesrc.h +++ b/gst/elements/gstfakesrc.h @@ -25,10 +25,10 @@ #define __GST_FAKESRC_H__ #include +#include G_BEGIN_DECLS - typedef enum { FAKESRC_FIRST_LAST_LOOP = 1, FAKESRC_LAST_FIRST_LOOP, @@ -74,7 +74,7 @@ typedef struct _GstFakeSrc GstFakeSrc; typedef struct _GstFakeSrcClass GstFakeSrcClass; struct _GstFakeSrc { - GstElement element; + GstBaseSrc element; gboolean has_loop; gboolean has_getrange; @@ -114,7 +114,7 @@ struct _GstFakeSrc { }; struct _GstFakeSrcClass { - GstElementClass parent_class; + GstBaseSrcClass parent_class; /* signals */ void (*handoff) (GstElement *element, GstBuffer *buf, GstPad *pad); diff --git a/gst/elements/gstfilesrc.c b/gst/elements/gstfilesrc.c index ce9354f..4d4b2ff 100644 --- a/gst/elements/gstfilesrc.c +++ b/gst/elements/gstfilesrc.c @@ -910,16 +910,22 @@ gst_filesrc_loop (GstPad * pad) GST_STREAM_LOCK (pad); result = gst_filesrc_get (pad, &buffer); - if (result != GST_FLOW_OK) { - gst_task_pause (GST_RPAD_TASK (pad)); - goto done; - } + if (result != GST_FLOW_OK) + goto need_pause; + result = gst_pad_push (pad, buffer); - if (result != GST_FLOW_OK) { + if (result != GST_FLOW_OK) + goto need_pause; + + GST_STREAM_UNLOCK (pad); + return; + +need_pause: + { gst_task_pause (GST_RPAD_TASK (pad)); + GST_STREAM_UNLOCK (pad); + return; } -done: - GST_STREAM_UNLOCK (pad); } diff --git a/libs/gst/base/Makefile.am b/libs/gst/base/Makefile.am index 0c790e8..39c382c 100644 --- a/libs/gst/base/Makefile.am +++ b/libs/gst/base/Makefile.am @@ -8,6 +8,7 @@ libgstbase_@GST_MAJORMINOR@_la_DEPENDENCIES = \ ../libgstreamer-@GST_MAJORMINOR@.la libgstbase_@GST_MAJORMINOR@_la_SOURCES = \ gstbasesink.c \ + gstbasesrc.c \ gstbasetransform.c libgstbase_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS) @@ -20,6 +21,7 @@ libgstbase_@GST_MAJORMINOR@includedir = \ libgstbase_@GST_MAJORMINOR@include_HEADERS = \ gstbasesink.h \ + gstbasesrc.h \ gstbasetransform.h install-data-local: as-libtool-install-data-local diff --git a/libs/gst/base/README b/libs/gst/base/README index f9c1583..3384a24 100644 --- a/libs/gst/base/README +++ b/libs/gst/base/README @@ -25,3 +25,11 @@ GstBaseTransform - does flushing - push mode - pull mode if transform can operate on arbitrary data + +GstBaseSrc + + Base class for getrange based source elements + + - one sinkpad + - handles state changes + - pull/push mode diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index 88d7d97..49696c6 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -190,6 +190,7 @@ gst_basesink_pad_setcaps (GstPad * pad, GstCaps * caps) bsink = GST_BASESINK (GST_PAD_PARENT (pad)); bclass = GST_BASESINK_GET_CLASS (bsink); + if (bclass->set_caps) res = bclass->set_caps (bsink, caps); @@ -206,6 +207,7 @@ gst_basesink_pad_buffer_alloc (GstPad * pad, guint64 offset, guint size, bsink = GST_BASESINK (GST_PAD_PARENT (pad)); bclass = GST_BASESINK_GET_CLASS (bsink); + if (bclass->buffer_alloc) buffer = bclass->buffer_alloc (bsink, offset, size, caps); @@ -571,6 +573,9 @@ gst_basesink_event (GstPad * pad, GstEvent * event) return result; } +/* default implementation to calculate the start and end + * timestamps on a buffer, subclasses cna override + */ static void gst_basesink_get_times (GstBaseSink * basesink, GstBuffer * buffer, GstClockTime * start, GstClockTime * end) @@ -587,6 +592,15 @@ gst_basesink_get_times (GstBaseSink * basesink, GstBuffer * buffer, } } +/* perform synchronisation on a buffer + * + * 1) check if we have a clock, if not, do nothing + * 2) calculate the start and end time of the buffer + * 3) create a single shot notification to wait on + * the clock, save the entry so we can unlock it + * 4) wait on the clock, this blocks + * 5) unref the clockid again + */ static void gst_basesink_do_sync (GstBaseSink * basesink, GstBuffer * buffer) { @@ -615,6 +629,7 @@ gst_basesink_do_sync (GstBaseSink * basesink, GstBuffer * buffer) gst_clock_id_unref (basesink->clock_id); basesink->clock_id = NULL; } + /* FIXME, don't mess with end_time here */ basesink->end_time = GST_CLOCK_TIME_NONE; GST_UNLOCK (basesink); @@ -623,6 +638,12 @@ gst_basesink_do_sync (GstBaseSink * basesink, GstBuffer * buffer) } } +/* handle a buffer + * + * 1) first sync on the buffer + * 2) render the buffer + * 3) unref the buffer + */ static inline void gst_basesink_handle_buffer (GstBaseSink * basesink, GstBuffer * buf) { @@ -662,7 +683,7 @@ gst_basesink_chain_unlocked (GstPad * pad, GstBuffer * buf) return GST_FLOW_UNEXPECTED; default: g_assert_not_reached (); - return GST_FLOW_UNEXPECTED; + return GST_FLOW_ERROR; } } @@ -683,6 +704,8 @@ gst_basesink_chain (GstPad * pad, GstBuffer * buf) return result; } +/* FIXME, not all sinks can operate in pull mode + */ static void gst_basesink_loop (GstPad * pad) { diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c new file mode 100644 index 0000000..4d69e99 --- /dev/null +++ b/libs/gst/base/gstbasesrc.c @@ -0,0 +1,423 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstbasesrc.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 +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstbasesrc.h" +#include + +#define DEFAULT_BLOCKSIZE 4096 + +GST_DEBUG_CATEGORY_STATIC (gst_basesrc_debug); +#define GST_CAT_DEFAULT gst_basesrc_debug + +/* BaseSrc signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_BLOCKSIZE, +}; + +static GstElementClass *parent_class = NULL; + +static void gst_basesrc_base_init (gpointer g_class); +static void gst_basesrc_class_init (GstBaseSrcClass * klass); +static void gst_basesrc_init (GstBaseSrc * src, gpointer g_class); + +GType +gst_basesrc_get_type (void) +{ + static GType basesrc_type = 0; + + if (!basesrc_type) { + static const GTypeInfo basesrc_info = { + sizeof (GstBaseSrcClass), + (GBaseInitFunc) gst_basesrc_base_init, + NULL, + (GClassInitFunc) gst_basesrc_class_init, + NULL, + NULL, + sizeof (GstBaseSrc), + 0, + (GInstanceInitFunc) gst_basesrc_init, + }; + + basesrc_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstBaseSrc", &basesrc_info, G_TYPE_FLAG_ABSTRACT); + } + return basesrc_type; +} + +static gboolean gst_basesrc_activate (GstPad * pad, GstActivateMode mode); +static void gst_basesrc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_basesrc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static gboolean gst_basesrc_event_handler (GstPad * pad, GstEvent * event); +static const GstEventMask *gst_basesrc_get_event_mask (GstPad * pad); +static const GstQueryType *gst_basesrc_get_query_types (GstPad * pad); +static gboolean gst_basesrc_query (GstPad * pad, GstQueryType type, + GstFormat * format, gint64 * value); +static const GstFormat *gst_basesrc_get_formats (GstPad * pad); + +static GstElementStateReturn gst_basesrc_change_state (GstElement * element); + +static void gst_basesrc_loop (GstPad * pad); +static GstFlowReturn gst_basesrc_get_range (GstPad * pad, guint64 offset, + guint length, GstBuffer ** buf); + +static void +gst_basesrc_base_init (gpointer g_class) +{ + GST_DEBUG_CATEGORY_INIT (gst_basesrc_debug, "basesrc", 0, "basesrc element"); +} + +static void +gst_basesrc_class_init (GstBaseSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_basesrc_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_basesrc_get_property); + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BLOCKSIZE, + g_param_spec_ulong ("blocksize", "Block size", + "Size in bytes to read per buffer", 1, G_MAXULONG, DEFAULT_BLOCKSIZE, + G_PARAM_READWRITE)); + + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_basesrc_change_state); +} + +static void +gst_basesrc_init (GstBaseSrc * basesrc, gpointer g_class) +{ + GstPad *pad; + GstPadTemplate *pad_template; + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src"); + g_return_if_fail (pad_template != NULL); + + pad = gst_pad_new_from_template (pad_template, "src"); + + gst_pad_set_activate_function (pad, gst_basesrc_activate); + gst_pad_set_event_function (pad, gst_basesrc_event_handler); + gst_pad_set_event_mask_function (pad, gst_basesrc_get_event_mask); + gst_pad_set_query_function (pad, gst_basesrc_query); + gst_pad_set_query_type_function (pad, gst_basesrc_get_query_types); + gst_pad_set_formats_function (pad, gst_basesrc_get_formats); + gst_pad_set_loop_function (pad, gst_basesrc_loop); + gst_pad_set_getrange_function (pad, gst_basesrc_get_range); + gst_element_add_pad (GST_ELEMENT (basesrc), pad); + + basesrc->segment_start = -1; + basesrc->segment_end = -1; + basesrc->blocksize = DEFAULT_BLOCKSIZE; +} + +static const GstFormat * +gst_basesrc_get_formats (GstPad * pad) +{ + static const GstFormat formats[] = { + GST_FORMAT_DEFAULT, + 0, + }; + + return formats; +} + +static const GstQueryType * +gst_basesrc_get_query_types (GstPad * pad) +{ + static const GstQueryType types[] = { + GST_QUERY_TOTAL, + GST_QUERY_POSITION, + GST_QUERY_START, + GST_QUERY_SEGMENT_END, + 0, + }; + + return types; +} + +static gboolean +gst_basesrc_query (GstPad * pad, GstQueryType type, + GstFormat * format, gint64 * value) +{ + GstBaseSrc *src = GST_BASESRC (GST_PAD_PARENT (pad)); + + switch (type) { + case GST_QUERY_START: + *value = src->segment_start; + break; + case GST_QUERY_SEGMENT_END: + *value = src->segment_end; + break; + default: + return FALSE; + } + return TRUE; +} + +static const GstEventMask * +gst_basesrc_get_event_mask (GstPad * pad) +{ + static const GstEventMask masks[] = { + {GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP}, + {GST_EVENT_FLUSH, 0}, + {0, 0}, + }; + + return masks; +} + +static gboolean +gst_basesrc_event_handler (GstPad * pad, GstEvent * event) +{ + GstBaseSrc *src; + + src = GST_BASESRC (GST_PAD_PARENT (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + src->segment_start = GST_EVENT_SEEK_OFFSET (event); + src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event); + src->segment_loop = + GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP; + break; + case GST_EVENT_FLUSH: + break; + default: + break; + } + gst_event_unref (event); + + return TRUE; +} + +static void +gst_basesrc_set_property (GObject * object, guint prop_id, const GValue * value, + GParamSpec * pspec) +{ + GstBaseSrc *src; + + src = GST_BASESRC (object); + + switch (prop_id) { + case ARG_BLOCKSIZE: + src->blocksize = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_basesrc_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstBaseSrc *src; + + src = GST_BASESRC (object); + + switch (prop_id) { + case ARG_BLOCKSIZE: + g_value_set_int (value, src->blocksize); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstFlowReturn +gst_basesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, + GstBuffer ** buf) +{ + GstFlowReturn ret; + GstBaseSrc *src; + GstBaseSrcClass *bclass; + + src = GST_BASESRC (GST_OBJECT_PARENT (pad)); + bclass = GST_BASESRC_GET_CLASS (src); + + if (bclass->create) + ret = bclass->create (src, offset, length, buf); + else + ret = GST_FLOW_ERROR; + + return ret; +} + +static GstFlowReturn +gst_basesrc_get_range (GstPad * pad, guint64 offset, guint length, + GstBuffer ** ret) +{ + GstFlowReturn fret; + + GST_STREAM_LOCK (pad); + + fret = gst_basesrc_get_range_unlocked (pad, offset, length, ret); + + GST_STREAM_UNLOCK (pad); + + return fret; +} + +static void +gst_basesrc_loop (GstPad * pad) +{ + GstBaseSrc *src; + GstBuffer *buf = NULL; + GstFlowReturn ret; + + src = GST_BASESRC (GST_OBJECT_PARENT (pad)); + + GST_STREAM_LOCK (pad); + + ret = + gst_basesrc_get_range_unlocked (pad, src->offset, DEFAULT_BLOCKSIZE, + &buf); + if (ret != GST_FLOW_OK) + goto pause; + + src->offset += GST_BUFFER_SIZE (buf); + + ret = gst_pad_push (pad, buf); + if (ret != GST_FLOW_OK) + goto pause; + + GST_STREAM_UNLOCK (pad); + return; + +pause: + { + gst_task_pause (GST_RPAD_TASK (pad)); + GST_STREAM_UNLOCK (pad); + return; + } +} + +static gboolean +gst_basesrc_activate (GstPad * pad, GstActivateMode mode) +{ + gboolean result = FALSE; + GstBaseSrc *basesrc; + + basesrc = GST_BASESRC (GST_OBJECT_PARENT (pad)); + + switch (mode) { + case GST_ACTIVATE_PUSH: + /* if we have a scheduler we can start the task */ + if (GST_ELEMENT_SCHEDULER (basesrc)) { + GST_STREAM_LOCK (pad); + GST_RPAD_TASK (pad) = + gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (basesrc), + (GstTaskFunction) gst_basesrc_loop, pad); + + gst_task_start (GST_RPAD_TASK (pad)); + GST_STREAM_UNLOCK (pad); + result = TRUE; + } + break; + case GST_ACTIVATE_PULL: + result = TRUE; + break; + case GST_ACTIVATE_NONE: + /* step 1, unblock clock sync (if any) */ + + /* step 2, make sure streaming finishes */ + GST_STREAM_LOCK (pad); + /* step 3, stop the task */ + if (GST_RPAD_TASK (pad)) { + gst_task_stop (GST_RPAD_TASK (pad)); + gst_object_unref (GST_OBJECT (GST_RPAD_TASK (pad))); + GST_RPAD_TASK (pad) = NULL; + } + GST_STREAM_UNLOCK (pad); + + result = TRUE; + break; + } + return result; +} + +static GstElementStateReturn +gst_basesrc_change_state (GstElement * element) +{ + GstBaseSrc *basesrc; + GstElementStateReturn result = GST_STATE_FAILURE; + GstElementState transition; + + basesrc = GST_BASESRC (element); + + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + case GST_STATE_READY_TO_PAUSED: + { + basesrc->offset = 0; + break; + } + case GST_STATE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_PLAYING_TO_PAUSED: + break; + case GST_STATE_PAUSED_TO_READY: + break; + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + + return result; +} diff --git a/libs/gst/base/gstbasesrc.h b/libs/gst/base/gstbasesrc.h new file mode 100644 index 0000000..a2bfe74 --- /dev/null +++ b/libs/gst/base/gstbasesrc.h @@ -0,0 +1,74 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstbasesrc.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_BASESRC_H__ +#define __GST_BASESRC_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_BASESRC (gst_basesrc_get_type()) +#define GST_BASESRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASESRC,GstBaseSrc)) +#define GST_BASESRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASESRC,GstBaseSrcClass)) +#define GST_BASESRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASESRC, GstBaseSrcClass)) +#define GST_IS_BASESRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASESRC)) +#define GST_IS_BASESRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASESRC)) + +typedef struct _GstBaseSrc GstBaseSrc; +typedef struct _GstBaseSrcClass GstBaseSrcClass; + +struct _GstBaseSrc { + GstElement element; + + gint blocksize; + + gint64 segment_start; + gint64 segment_end; + gboolean segment_loop; + + guint64 offset; +}; + +struct _GstBaseSrcClass { + GstElementClass parent_class; + + GstCaps* (*get_caps) (GstBaseSrc *src); + gboolean (*set_caps) (GstBaseSrc *src, GstCaps *caps); + + gboolean (*start) (GstBaseSrc *src); + gboolean (*stop) (GstBaseSrc *src); + + void (*get_times) (GstBaseSrc *src, GstBuffer *buffer, + GstClockTime *start, GstClockTime *end); + + gboolean (*event) (GstBaseSrc *src, GstEvent *event); + GstFlowReturn (*create) (GstBaseSrc *src, guint64 offset, guint size, + GstBuffer **buf); +}; + +GType gst_basesrc_get_type(void); + +G_END_DECLS + +#endif /* __GST_BASESRC_H__ */ diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c index cb5f7dc..3be5c0b 100644 --- a/plugins/elements/gstfakesrc.c +++ b/plugins/elements/gstfakesrc.c @@ -64,8 +64,6 @@ enum { ARG_0, ARG_NUM_SOURCES, - ARG_HAS_LOOP, - ARG_HAS_GETRANGE, ARG_OUTPUT, ARG_DATA, ARG_SIZETYPE, @@ -84,11 +82,6 @@ enum ARG_LAST_MESSAGE }; -GstStaticPadTemplate fakesrc_src_template = GST_STATIC_PAD_TEMPLATE ("src%d", - GST_PAD_SRC, - GST_PAD_REQUEST, - GST_STATIC_CAPS_ANY); - #define GST_TYPE_FAKESRC_OUTPUT (gst_fakesrc_output_get_type()) static GType gst_fakesrc_output_get_type (void) @@ -175,22 +168,18 @@ gst_fakesrc_filltype_get_type (void) #define _do_init(bla) \ GST_DEBUG_CATEGORY_INIT (gst_fakesrc_debug, "fakesrc", 0, "fakesrc element"); -GST_BOILERPLATE_FULL (GstFakeSrc, gst_fakesrc, GstElement, GST_TYPE_ELEMENT, +GST_BOILERPLATE_FULL (GstFakeSrc, gst_fakesrc, GstBaseSrc, GST_TYPE_BASESRC, _do_init); -static GstPad *gst_fakesrc_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * unused); -static gboolean gst_fakesrc_activate (GstPad * pad, GstActivateMode mode); static void gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static void gst_fakesrc_set_clock (GstElement * element, GstClock * clock); static GstElementStateReturn gst_fakesrc_change_state (GstElement * element); -static void gst_fakesrc_loop (GstPad * pad); -static GstFlowReturn gst_fakesrc_get_range (GstPad * pad, guint64 offset, +static gboolean gst_fakesrc_event_handler (GstBaseSrc * src, GstEvent * event); +static GstFlowReturn gst_fakesrc_create (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buf); static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 }; @@ -202,9 +191,8 @@ gst_fakesrc_base_init (gpointer g_class) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&srctemplate)); + gst_element_class_set_details (gstelement_class, &gst_fakesrc_details); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&fakesrc_src_template)); } static void @@ -212,9 +200,11 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseSrcClass *gstbasesrc_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasesrc_class = (GstBaseSrcClass *) klass; gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property); @@ -222,14 +212,6 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES, g_param_spec_int ("num-sources", "num-sources", "Number of sources", 1, G_MAXINT, 1, G_PARAM_READABLE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_LOOP, - g_param_spec_boolean ("has-loop", "has-loop", - "Enable loop-based operation", TRUE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_GETRANGE, - g_param_spec_boolean ("has-getrange", "has-getrange", - "Enable getrange-based operation", TRUE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_OUTPUT, g_param_spec_enum ("output", "output", "Output method (currently unused)", GST_TYPE_FAKESRC_OUTPUT, FAKESRC_FIRST_LAST_LOOP, G_PARAM_READWRITE)); @@ -287,26 +269,18 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass) gst_fakesrc_signals[SIGNAL_HANDOFF] = g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL, - gst_marshal_VOID__BOXED_OBJECT, G_TYPE_NONE, 2, - GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD); + gst_marshal_VOID__BOXED_OBJECT, G_TYPE_NONE, 1, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE); - gstelement_class->request_new_pad = - GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state); - gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_fakesrc_set_clock); + + gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_fakesrc_event_handler); + gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_fakesrc_create); } static void gst_fakesrc_init (GstFakeSrc * fakesrc) { - GstPad *pad; - - /* create our first output pad */ - pad = - gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate), - "src"); - gst_element_add_pad (GST_ELEMENT (fakesrc), pad); - fakesrc->output = FAKESRC_FIRST_LAST_LOOP; fakesrc->segment_start = -1; fakesrc->segment_end = -1; @@ -331,84 +305,12 @@ gst_fakesrc_init (GstFakeSrc * fakesrc) fakesrc->pad_mode = GST_ACTIVATE_NONE; } -static void -gst_fakesrc_set_clock (GstElement * element, GstClock * clock) -{ - GstFakeSrc *src; - - src = GST_FAKESRC (element); - - src->clock = clock; -} - -static const GstFormat * -gst_fakesrc_get_formats (GstPad * pad) -{ - static const GstFormat formats[] = { - GST_FORMAT_DEFAULT, - 0, - }; - - return formats; -} - -static const GstQueryType * -gst_fakesrc_get_query_types (GstPad * pad) -{ - static const GstQueryType types[] = { - GST_QUERY_TOTAL, - GST_QUERY_POSITION, - GST_QUERY_START, - GST_QUERY_SEGMENT_END, - 0, - }; - - return types; -} - -static gboolean -gst_fakesrc_query (GstPad * pad, GstQueryType type, - GstFormat * format, gint64 * value) -{ - GstFakeSrc *src = GST_FAKESRC (GST_PAD_PARENT (pad)); - - switch (type) { - case GST_QUERY_TOTAL: - *value = src->num_buffers; - break; - case GST_QUERY_POSITION: - *value = src->buffer_count; - break; - case GST_QUERY_START: - *value = src->segment_start; - break; - case GST_QUERY_SEGMENT_END: - *value = src->segment_end; - break; - default: - return FALSE; - } - return TRUE; -} - -static const GstEventMask * -gst_fakesrc_get_event_mask (GstPad * pad) -{ - static const GstEventMask masks[] = { - {GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP}, - {GST_EVENT_FLUSH, 0}, - {0, 0}, - }; - - return masks; -} - static gboolean -gst_fakesrc_event_handler (GstPad * pad, GstEvent * event) +gst_fakesrc_event_handler (GstBaseSrc * basesrc, GstEvent * event) { GstFakeSrc *src; - src = GST_FAKESRC (GST_PAD_PARENT (pad)); + src = GST_FAKESRC (basesrc); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: @@ -431,64 +333,6 @@ gst_fakesrc_event_handler (GstPad * pad, GstEvent * event) } static void -gst_fakesrc_set_pad_functions (GstFakeSrc * src, GstPad * pad) -{ - gst_pad_set_activate_function (pad, gst_fakesrc_activate); - gst_pad_set_event_function (pad, gst_fakesrc_event_handler); - gst_pad_set_event_mask_function (pad, gst_fakesrc_get_event_mask); - gst_pad_set_query_function (pad, gst_fakesrc_query); - gst_pad_set_query_type_function (pad, gst_fakesrc_get_query_types); - gst_pad_set_formats_function (pad, gst_fakesrc_get_formats); - - if (src->has_loop) - gst_pad_set_loop_function (pad, gst_fakesrc_loop); - else - gst_pad_set_loop_function (pad, NULL); - - if (src->has_getrange) - gst_pad_set_getrange_function (pad, gst_fakesrc_get_range); - else - gst_pad_set_getrange_function (pad, NULL); -} - -static void -gst_fakesrc_set_all_pad_functions (GstFakeSrc * src) -{ - GList *l; - - for (l = GST_ELEMENT_PADS (src); l; l = l->next) - gst_fakesrc_set_pad_functions (src, (GstPad *) l->data); -} - -static GstPad * -gst_fakesrc_request_new_pad (GstElement * element, GstPadTemplate * templ, - const gchar * unused) -{ - gchar *name; - GstPad *srcpad; - GstFakeSrc *fakesrc; - - g_return_val_if_fail (GST_IS_FAKESRC (element), NULL); - - if (templ->direction != GST_PAD_SRC) { - g_warning ("gstfakesrc: request new pad that is not a SRC pad\n"); - return NULL; - } - - fakesrc = GST_FAKESRC (element); - - name = g_strdup_printf ("src%d", GST_ELEMENT (fakesrc)->numsrcpads); - - srcpad = gst_pad_new_from_template (templ, name); - gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad); - gst_fakesrc_set_pad_functions (fakesrc, srcpad); - - g_free (name); - - return srcpad; -} - -static void gst_fakesrc_alloc_parent (GstFakeSrc * src) { GstBuffer *buf; @@ -510,14 +354,6 @@ gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value, src = GST_FAKESRC (object); switch (prop_id) { - case ARG_HAS_LOOP: - src->has_loop = g_value_get_boolean (value); - gst_fakesrc_set_all_pad_functions (src); - break; - case ARG_HAS_GETRANGE: - src->has_getrange = g_value_get_boolean (value); - gst_fakesrc_set_all_pad_functions (src); - break; case ARG_OUTPUT: g_warning ("not yet implemented"); break; @@ -594,12 +430,6 @@ gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value, case ARG_NUM_SOURCES: g_value_set_int (value, GST_ELEMENT (src)->numsrcpads); break; - case ARG_HAS_LOOP: - g_value_set_boolean (value, src->has_loop); - break; - case ARG_HAS_GETRANGE: - g_value_set_boolean (value, src->has_getrange); - break; case ARG_OUTPUT: g_value_set_enum (value, src->output); break; @@ -792,26 +622,20 @@ gst_fakesrc_create_buffer (GstFakeSrc * src) } static GstFlowReturn -gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, +gst_fakesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** ret) { GstFakeSrc *src; GstBuffer *buf; GstClockTime time; - src = GST_FAKESRC (GST_OBJECT_PARENT (pad)); + src = GST_FAKESRC (basesrc); if (src->buffer_count == src->segment_end) { - if (src->segment_loop) { - //gst_pad_push_event (pad, gst_event_new (GST_EVENT_SEGMENT_DONE)); - } else { - gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); - return GST_FLOW_UNEXPECTED; - } + return GST_FLOW_UNEXPECTED; } if (src->rt_num_buffers == 0) { - gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); return GST_FLOW_UNEXPECTED; } else { if (src->rt_num_buffers > 0) @@ -820,7 +644,6 @@ gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, if (src->eos) { GST_INFO ("fakesrc is setting eos on pad"); - gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); return GST_FLOW_UNEXPECTED; } @@ -844,8 +667,8 @@ gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, g_free (src->last_message); src->last_message = - g_strdup_printf ("get ******* (%s:%s)> (%d bytes, %" - G_GUINT64_FORMAT " ) %p", GST_DEBUG_PAD_NAME (pad), + g_strdup_printf ("get ******* > (%d bytes, %" + G_GUINT64_FORMAT " ) %p", GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf); g_object_notify (G_OBJECT (src), "last_message"); @@ -853,8 +676,7 @@ gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, if (src->signal_handoffs) { GST_LOG_OBJECT (src, "pre handoff emit"); - g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0, - buf, pad); + g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0, buf); GST_LOG_OBJECT (src, "post handoff emit"); } @@ -864,110 +686,6 @@ gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, return GST_FLOW_OK; } -static GstFlowReturn -gst_fakesrc_get_range (GstPad * pad, guint64 offset, guint length, - GstBuffer ** ret) -{ - GstFlowReturn fret; - - g_assert (GST_FAKESRC (GST_OBJECT_PARENT (pad))->pad_mode == - GST_ACTIVATE_PULL); - - GST_STREAM_LOCK (pad); - - fret = gst_fakesrc_get_range_unlocked (pad, offset, length, ret); - - GST_STREAM_UNLOCK (pad); - - return fret; -} - -static void -gst_fakesrc_loop (GstPad * pad) -{ - GstFakeSrc *src; - GstBuffer *buf = NULL; - GstFlowReturn ret; - - src = GST_FAKESRC (GST_OBJECT_PARENT (pad)); - - g_assert (src->pad_mode == GST_ACTIVATE_PUSH); - - GST_STREAM_LOCK (pad); - if (src->need_flush) { - src->need_flush = FALSE; - gst_pad_push_event (pad, gst_event_new (GST_EVENT_FLUSH)); - } - - ret = gst_fakesrc_get_range_unlocked (pad, src->buffer_count, - DEFAULT_SIZEMAX, &buf); - if (ret != GST_FLOW_OK) { - goto pause; - } - - ret = gst_pad_push (pad, buf); - if (ret != GST_FLOW_OK) { - goto pause; - } - - GST_STREAM_UNLOCK (pad); - return; - -pause: - gst_task_pause (GST_RPAD_TASK (pad)); - GST_STREAM_UNLOCK (pad); - return; -} - -static gboolean -gst_fakesrc_activate (GstPad * pad, GstActivateMode mode) -{ - gboolean result = FALSE; - GstFakeSrc *fakesrc; - - fakesrc = GST_FAKESRC (GST_OBJECT_PARENT (pad)); - - switch (mode) { - case GST_ACTIVATE_PUSH: - /* if we have a scheduler we can start the task */ - g_return_val_if_fail (fakesrc->has_loop, FALSE); - if (GST_ELEMENT_SCHEDULER (fakesrc)) { - GST_STREAM_LOCK (pad); - GST_RPAD_TASK (pad) = - gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (fakesrc), - (GstTaskFunction) gst_fakesrc_loop, pad); - - gst_task_start (GST_RPAD_TASK (pad)); - GST_STREAM_UNLOCK (pad); - result = TRUE; - } - break; - case GST_ACTIVATE_PULL: - g_return_val_if_fail (fakesrc->has_getrange, FALSE); - result = TRUE; - break; - case GST_ACTIVATE_NONE: - /* step 1, unblock clock sync (if any) */ - - /* step 2, make sure streaming finishes */ - GST_STREAM_LOCK (pad); - /* step 3, stop the task */ - if (GST_RPAD_TASK (pad)) { - gst_task_stop (GST_RPAD_TASK (pad)); - gst_object_unref (GST_OBJECT (GST_RPAD_TASK (pad))); - GST_RPAD_TASK (pad) = NULL; - } - GST_STREAM_UNLOCK (pad); - - result = TRUE; - break; - } - - fakesrc->pad_mode = mode; - - return result; -} - static GstElementStateReturn gst_fakesrc_change_state (GstElement * element) { diff --git a/plugins/elements/gstfakesrc.h b/plugins/elements/gstfakesrc.h index a5251b8..3cda131 100644 --- a/plugins/elements/gstfakesrc.h +++ b/plugins/elements/gstfakesrc.h @@ -25,10 +25,10 @@ #define __GST_FAKESRC_H__ #include +#include G_BEGIN_DECLS - typedef enum { FAKESRC_FIRST_LAST_LOOP = 1, FAKESRC_LAST_FIRST_LOOP, @@ -74,7 +74,7 @@ typedef struct _GstFakeSrc GstFakeSrc; typedef struct _GstFakeSrcClass GstFakeSrcClass; struct _GstFakeSrc { - GstElement element; + GstBaseSrc element; gboolean has_loop; gboolean has_getrange; @@ -114,7 +114,7 @@ struct _GstFakeSrc { }; struct _GstFakeSrcClass { - GstElementClass parent_class; + GstBaseSrcClass parent_class; /* signals */ void (*handoff) (GstElement *element, GstBuffer *buf, GstPad *pad); diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c index ce9354f..4d4b2ff 100644 --- a/plugins/elements/gstfilesrc.c +++ b/plugins/elements/gstfilesrc.c @@ -910,16 +910,22 @@ gst_filesrc_loop (GstPad * pad) GST_STREAM_LOCK (pad); result = gst_filesrc_get (pad, &buffer); - if (result != GST_FLOW_OK) { - gst_task_pause (GST_RPAD_TASK (pad)); - goto done; - } + if (result != GST_FLOW_OK) + goto need_pause; + result = gst_pad_push (pad, buffer); - if (result != GST_FLOW_OK) { + if (result != GST_FLOW_OK) + goto need_pause; + + GST_STREAM_UNLOCK (pad); + return; + +need_pause: + { gst_task_pause (GST_RPAD_TASK (pad)); + GST_STREAM_UNLOCK (pad); + return; } -done: - GST_STREAM_UNLOCK (pad); }